feat: prepare Zhinian desktop pilot
This commit is contained in:
26
electron/api/routes/apps.ts
Normal file
26
electron/api/routes/apps.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import type { IncomingMessage, ServerResponse } from 'http';
|
||||
import type { HostApiContext } from '../context';
|
||||
import { sendJson } from '../route-utils';
|
||||
import {
|
||||
ensureNianxxPlayServiceStarted,
|
||||
getNianxxPlayServiceStatus,
|
||||
} from '../../utils/nianxx-play-service';
|
||||
|
||||
export async function handleAppIntegrationRoutes(
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
url: URL,
|
||||
_ctx: HostApiContext,
|
||||
): Promise<boolean> {
|
||||
if (url.pathname === '/api/apps/nianxx-play/status' && req.method === 'GET') {
|
||||
sendJson(res, 200, await getNianxxPlayServiceStatus());
|
||||
return true;
|
||||
}
|
||||
|
||||
if (url.pathname === '/api/apps/nianxx-play/start' && req.method === 'POST') {
|
||||
sendJson(res, 200, await ensureNianxxPlayServiceStarted());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -27,10 +27,7 @@ import {
|
||||
listAgentsSnapshotFromConfig,
|
||||
} from '../../utils/agent-config';
|
||||
import {
|
||||
ensureDingTalkPluginInstalled,
|
||||
ensureFeishuPluginInstalled,
|
||||
ensureWeChatPluginInstalled,
|
||||
ensureWeComPluginInstalled,
|
||||
} from '../../utils/plugin-install';
|
||||
import {
|
||||
computeChannelRuntimeStatus,
|
||||
@@ -83,6 +80,7 @@ import type { HostApiContext } from '../context';
|
||||
import { parseJsonBody, sendJson } from '../route-utils';
|
||||
|
||||
const WECHAT_QR_TIMEOUT_MS = 8 * 60 * 1000;
|
||||
const DISABLED_PLUGIN_CHANNEL_TYPES = new Set(['dingtalk', 'wecom', 'feishu']);
|
||||
const activeQrLogins = new Map<string, string>();
|
||||
|
||||
interface WebLoginStartResult {
|
||||
@@ -1559,27 +1557,9 @@ export async function handleChannelRoutes(
|
||||
return true;
|
||||
}
|
||||
const storedChannelType = resolveStoredChannelType(body.channelType);
|
||||
if (storedChannelType === 'dingtalk') {
|
||||
const installResult = await ensureDingTalkPluginInstalled();
|
||||
if (!installResult.installed) {
|
||||
sendJson(res, 500, { success: false, error: installResult.warning || 'DingTalk plugin install failed' });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (storedChannelType === 'wecom') {
|
||||
const installResult = await ensureWeComPluginInstalled();
|
||||
if (!installResult.installed) {
|
||||
sendJson(res, 500, { success: false, error: installResult.warning || 'WeCom plugin install failed' });
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// QQBot is a built-in channel since OpenClaw 3.31 — no plugin install needed
|
||||
if (storedChannelType === 'feishu') {
|
||||
const installResult = await ensureFeishuPluginInstalled();
|
||||
if (!installResult.installed) {
|
||||
sendJson(res, 500, { success: false, error: installResult.warning || 'Feishu plugin install failed' });
|
||||
return true;
|
||||
}
|
||||
if (DISABLED_PLUGIN_CHANNEL_TYPES.has(storedChannelType)) {
|
||||
sendJson(res, 400, { success: false, error: '当前内测版本未启用该渠道' });
|
||||
return true;
|
||||
}
|
||||
if (storedChannelType === OPENCLAW_WECHAT_CHANNEL_TYPE) {
|
||||
const installResult = await ensureWeChatPluginInstalled();
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { IncomingMessage, ServerResponse } from 'http';
|
||||
import { logger } from '../../utils/logger';
|
||||
import { getOpenClawConfigDir } from '../../utils/paths';
|
||||
import { buildGatewayHealthSummary } from '../../utils/gateway-health';
|
||||
import { buildYinianModelConfigDiagnostics, ensureYinianModelRuntimeConfigured } from '../../utils/model-diagnostics';
|
||||
import type { HostApiContext } from '../context';
|
||||
import { sendJson } from '../route-utils';
|
||||
import { buildChannelAccountsView, getChannelStatusDiagnostics } from './channels';
|
||||
@@ -82,5 +83,17 @@ export async function handleDiagnosticsRoutes(
|
||||
return true;
|
||||
}
|
||||
|
||||
if (url.pathname === '/api/diagnostics/model-config' && req.method === 'GET') {
|
||||
try {
|
||||
if (url.searchParams.get('repair') === '1') {
|
||||
await ensureYinianModelRuntimeConfigured();
|
||||
}
|
||||
sendJson(res, 200, await buildYinianModelConfigDiagnostics());
|
||||
} catch (error) {
|
||||
sendJson(res, 500, { success: false, error: String(error) });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ export async function handleGatewayRoutes(
|
||||
if (imageAttachments.length > 0) {
|
||||
rpcParams.attachments = imageAttachments;
|
||||
}
|
||||
const result = await ctx.gatewayManager.rpc('chat.send', rpcParams, 120000);
|
||||
const result = await ctx.gatewayManager.rpc('chat.send', rpcParams, 330000);
|
||||
sendJson(res, 200, { success: true, result });
|
||||
} catch (error) {
|
||||
sendJson(res, 500, { success: false, error: String(error) });
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { IncomingMessage, ServerResponse } from 'node:http';
|
||||
import crypto from 'node:crypto';
|
||||
import { basename, extname, join } from 'node:path';
|
||||
import { mkdir, readFile, stat, writeFile, copyFile } from 'node:fs/promises';
|
||||
import { mkdir, readFile, stat, writeFile, copyFile, rm } from 'node:fs/promises';
|
||||
import type { HostApiContext } from '../context';
|
||||
import { parseJsonBody, sendJson } from '../route-utils';
|
||||
import { getDataDir } from '../../utils/paths';
|
||||
@@ -225,6 +225,27 @@ export async function buildKnowledgeContext(params: {
|
||||
};
|
||||
}
|
||||
|
||||
async function deleteKnowledgeDocument(params: {
|
||||
workspaceId?: string;
|
||||
documentId: string;
|
||||
}): Promise<{ deleted: KnowledgeDocument | null }> {
|
||||
const workspaceId = sanitizeWorkspaceId(params.workspaceId);
|
||||
const documentId = params.documentId.trim();
|
||||
if (!documentId) return { deleted: null };
|
||||
|
||||
const registry = await readRegistry(workspaceId);
|
||||
const target = registry.find((doc) => doc.id === documentId);
|
||||
if (!target) return { deleted: null };
|
||||
|
||||
await Promise.all([
|
||||
target.storedPath ? rm(target.storedPath, { force: true }).catch(() => undefined) : Promise.resolve(),
|
||||
target.textPath ? rm(target.textPath, { force: true }).catch(() => undefined) : Promise.resolve(),
|
||||
]);
|
||||
await writeRegistry(workspaceId, registry.filter((doc) => doc.id !== documentId));
|
||||
|
||||
return { deleted: target };
|
||||
}
|
||||
|
||||
export async function handleKnowledgeRoutes(
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
@@ -238,6 +259,22 @@ export async function handleKnowledgeRoutes(
|
||||
return true;
|
||||
}
|
||||
|
||||
if (url.pathname.startsWith('/api/knowledge/files/') && req.method === 'DELETE') {
|
||||
try {
|
||||
const documentId = decodeURIComponent(url.pathname.slice('/api/knowledge/files/'.length));
|
||||
const workspaceId = sanitizeWorkspaceId(url.searchParams.get('workspaceId') ?? undefined);
|
||||
const result = await deleteKnowledgeDocument({ workspaceId, documentId });
|
||||
if (!result.deleted) {
|
||||
sendJson(res, 404, { success: false, error: 'Knowledge document not found' });
|
||||
return true;
|
||||
}
|
||||
sendJson(res, 200, { success: true, document: result.deleted });
|
||||
} catch (error) {
|
||||
sendJson(res, 500, { success: false, error: String(error) });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (url.pathname === '/api/knowledge/import-paths' && req.method === 'POST') {
|
||||
try {
|
||||
const body = await parseJsonBody<{ workspaceId?: string; filePaths?: string[] }>(req);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { logger } from '../utils/logger';
|
||||
import { extensionRegistry } from '../extensions/registry';
|
||||
import type { HostApiContext } from './context';
|
||||
import { handleAppRoutes } from './routes/app';
|
||||
import { handleAppIntegrationRoutes } from './routes/apps';
|
||||
import { handleGatewayRoutes } from './routes/gateway';
|
||||
import { handleSettingsRoutes } from './routes/settings';
|
||||
import { handleProviderRoutes } from './routes/providers';
|
||||
@@ -29,6 +30,7 @@ type RouteHandler = (
|
||||
|
||||
const coreRouteHandlers: RouteHandler[] = [
|
||||
handleAppRoutes,
|
||||
handleAppIntegrationRoutes,
|
||||
handleGatewayRoutes,
|
||||
handleSettingsRoutes,
|
||||
handleProviderRoutes,
|
||||
|
||||
Reference in New Issue
Block a user