@co0ontty/wand 4.89.0-beta.gde0b3cd → 4.89.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-dispatch.d.ts +0 -5
- package/dist/agent-dispatch.js +0 -8
- package/dist/ai-team-runner.d.ts +1 -1
- package/dist/ai-team-runner.js +5 -13
- package/dist/ai-team-types.js +2 -3
- package/dist/build-info.json +4 -4
- package/dist/commit-task-archive.d.ts +0 -3
- package/dist/commit-task-archive.js +0 -15
- package/dist/config.js +0 -1
- package/dist/decision-expert-employee.d.ts +1 -1
- package/dist/decision-expert-employee.js +3 -3
- package/dist/decision-expert-service.d.ts +5 -6
- package/dist/decision-expert-service.js +49 -75
- package/dist/decision-types.d.ts +1 -2
- package/dist/git-quick-commit.d.ts +4 -13
- package/dist/git-quick-commit.js +33 -112
- package/dist/local-model-setup.d.ts +1 -7
- package/dist/local-model-setup.js +7 -54
- package/dist/local-model-types.d.ts +1 -2
- package/dist/process-manager.d.ts +1 -4
- package/dist/process-manager.js +6 -5
- package/dist/server-employee-routes.d.ts +0 -2
- package/dist/server-employee-routes.js +45 -19
- package/dist/server-file-routes.js +25 -61
- package/dist/server-local-model-routes.js +0 -12
- package/dist/server-session-routes.d.ts +1 -2
- package/dist/server-session-routes.js +10 -13
- package/dist/server-speech-routes.d.ts +0 -2
- package/dist/server-speech-routes.js +1 -7
- package/dist/server-task-routes.d.ts +0 -3
- package/dist/server-task-routes.js +10 -13
- package/dist/server.js +8 -20
- package/dist/session-ai-context.d.ts +4 -6
- package/dist/session-ai-context.js +9 -10
- package/dist/silicon-employee-dispatch.d.ts +6 -4
- package/dist/silicon-employee-dispatch.js +6 -9
- package/dist/speech-service.d.ts +1 -3
- package/dist/speech-service.js +3 -14
- package/dist/speech-types.d.ts +0 -5
- package/dist/storage.d.ts +0 -2
- package/dist/storage.js +1 -18
- package/dist/structured-session-manager.d.ts +2 -3
- package/dist/structured-session-manager.js +7 -11
- package/dist/system-employee.d.ts +4 -6
- package/dist/system-employee.js +5 -8
- package/dist/types.d.ts +1 -3
- package/dist/user-memory.d.ts +0 -2
- package/dist/user-memory.js +1 -1
- package/dist/web-ui/content/ai-teams.js +10 -10
- package/dist/web-ui/content/scripts.js +204 -316
- package/dist/web-ui/content/styles.css +1 -1
- package/dist/web-ui/content/tailwind.css +1 -1
- package/dist/web-ui/embedded-assets.d.ts +0 -1
- package/dist/web-ui/embedded-assets.js +3 -4
- package/dist/web-ui/index.js +3 -3
- package/dist/web-ui/provider-identity.d.ts +0 -2
- package/dist/web-ui/provider-identity.js +1 -7
- package/dist/web-ui/scripts.d.ts +0 -2
- package/dist/web-ui/scripts.js +0 -5
- package/package.json +1 -1
- package/dist/employee-text.d.ts +0 -28
- package/dist/employee-text.js +0 -124
- package/dist/speech-polisher-employee.d.ts +0 -6
- package/dist/speech-polisher-employee.js +0 -23
- package/dist/speech-polisher-identity.d.ts +0 -4
- package/dist/speech-polisher-identity.js +0 -4
- package/dist/speech-polisher-service.d.ts +0 -31
- package/dist/speech-polisher-service.js +0 -88
- package/dist/speech-support.d.ts +0 -6
- package/dist/speech-support.js +0 -26
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { randomUUID } from "node:crypto";
|
|
2
2
|
import { AI_TEAM_MAX_CANDIDATES, SILICON_EMPLOYEE_AVATAR_MAX_CHARS, agentKey, isBuiltinSiliconEmployee, parseSiliconEmployeeTags, siliconEmployeeTags, } from "./ai-team-types.js";
|
|
3
3
|
import { getErrorMessage } from "./error-utils.js";
|
|
4
|
+
import { DECISION_EXPERT_KEY, isLocalDecisionModel } from "./decision-expert-identity.js";
|
|
5
|
+
import { OPENROUTER_FREE_SELECTOR, isOpenRouterFreeSelector } from "./openrouter-free-selection.js";
|
|
4
6
|
import { asyncRoute } from "./express-async.js";
|
|
5
7
|
import { bodyObject, sendRouteError, text } from "./server-request.js";
|
|
6
8
|
import { parseTaskAgent } from "./server-task-routes.js";
|
|
@@ -12,7 +14,7 @@ import { SESSION_PROVIDERS } from "./session-provider.js";
|
|
|
12
14
|
import { DEFAULT_WAND_TASK_AGENT_KIND } from "./task-types.js";
|
|
13
15
|
import { EMPLOYEE_KNOWLEDGE_MAX_ENTRIES } from "./employee-knowledge-types.js";
|
|
14
16
|
/** 员工起草没有会话上下文,按「默认 provider」解析,与任务标题 / 提示词优化一致。 */
|
|
15
|
-
function employeeDraftAiOptions(storage, config
|
|
17
|
+
function employeeDraftAiOptions(storage, config) {
|
|
16
18
|
if (!config)
|
|
17
19
|
return {};
|
|
18
20
|
const provider = config.defaultProvider ?? "claude";
|
|
@@ -23,7 +25,7 @@ function employeeDraftAiOptions(storage, config, free) {
|
|
|
23
25
|
command: provider === "qoder" ? "qodercli" : provider,
|
|
24
26
|
selectedModel: null,
|
|
25
27
|
thinkingEffort: config.defaultThinkingEffort,
|
|
26
|
-
}, config, storage.getSystemSiliconEmployee()
|
|
28
|
+
}, config, storage.getSystemSiliconEmployee());
|
|
27
29
|
}
|
|
28
30
|
function sendEmployeeError(res, error, context) {
|
|
29
31
|
const message = getErrorMessage(error, "硅基员工操作失败。");
|
|
@@ -97,23 +99,23 @@ export function parseSystemEmployeeAgents(value, existing) {
|
|
|
97
99
|
if (body.systemKey !== undefined && body.systemKey !== existing.systemKey) {
|
|
98
100
|
throw new Error("该员工是内置的,身份不可修改。");
|
|
99
101
|
}
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
/** One validation owner for every employee candidate list, including legacy single agents. */
|
|
103
|
-
function parseEmployeeAgents(value) {
|
|
104
|
-
if (!Array.isArray(value))
|
|
102
|
+
if (!Array.isArray(body.agents))
|
|
105
103
|
throw new Error("请提供执行候选数组(CLI / SDK)。");
|
|
106
|
-
if (
|
|
104
|
+
if (body.agents.length === 0)
|
|
107
105
|
throw new Error("至少需要一个执行候选。");
|
|
108
|
-
if (
|
|
106
|
+
if (body.agents.length > AI_TEAM_MAX_CANDIDATES) {
|
|
109
107
|
throw new Error(`最多 ${AI_TEAM_MAX_CANDIDATES} 个执行候选。`);
|
|
110
108
|
}
|
|
111
|
-
const agents =
|
|
109
|
+
const agents = body.agents.map((rawAgent) => {
|
|
112
110
|
const parsed = parseTaskAgent(rawAgent ?? {});
|
|
113
111
|
if (!parsed)
|
|
114
112
|
throw new Error("请选择有效的 CLI 工具或 Wand Agent。");
|
|
115
113
|
if (parsed.kind !== "structured")
|
|
116
114
|
throw new Error("硅基员工只支持结构化会话。");
|
|
115
|
+
if (existing.systemKey === DECISION_EXPERT_KEY && (parsed.provider !== "pi" || parsed.engine !== "sdk"
|
|
116
|
+
|| !(isLocalDecisionModel(parsed.model) || parsed.model === OPENROUTER_FREE_SELECTOR || isOpenRouterFreeSelector(parsed.model)))) {
|
|
117
|
+
throw new Error("决策专家仅支持 LAYA 或 Wand 免费分组的决策候选;请使用 Wand 内部执行入口。");
|
|
118
|
+
}
|
|
117
119
|
return parsed;
|
|
118
120
|
});
|
|
119
121
|
if (new Set(agents.map(agentKey)).size !== agents.length) {
|
|
@@ -130,16 +132,40 @@ export function parseSiliconEmployeeInput(value, existing, now) {
|
|
|
130
132
|
const prompt = text(body.prompt);
|
|
131
133
|
if (prompt.length > 20_000)
|
|
132
134
|
throw new Error("员工设定 Prompt 不能超过 20000 个字符。");
|
|
133
|
-
let
|
|
134
|
-
if (Array.isArray(body.agents))
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
let agents;
|
|
136
|
+
if (Array.isArray(body.agents)) {
|
|
137
|
+
if (body.agents.length === 0)
|
|
138
|
+
throw new Error("至少需要一个执行候选。");
|
|
139
|
+
if (body.agents.length > AI_TEAM_MAX_CANDIDATES) {
|
|
140
|
+
throw new Error(`最多 ${AI_TEAM_MAX_CANDIDATES} 个执行候选。`);
|
|
141
|
+
}
|
|
142
|
+
agents = body.agents.map((rawAgent) => {
|
|
143
|
+
const parsed = parseTaskAgent(rawAgent ?? {});
|
|
144
|
+
if (!parsed)
|
|
145
|
+
throw new Error("请选择有效的 CLI 工具或 Wand Agent。");
|
|
146
|
+
if (parsed.kind !== "structured")
|
|
147
|
+
throw new Error("硅基员工只支持结构化会话。");
|
|
148
|
+
return parsed;
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
else if (body.agents !== undefined && body.agents !== null) {
|
|
137
152
|
throw new Error("候选执行配置必须是数组。");
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
153
|
+
}
|
|
154
|
+
else if (body.agent !== undefined && body.agent !== null) {
|
|
155
|
+
const singleAgent = parseTaskAgent(body.agent);
|
|
156
|
+
if (!singleAgent)
|
|
157
|
+
throw new Error("请选择有效的 CLI 工具或 Wand Agent。");
|
|
158
|
+
if (singleAgent.kind !== "structured")
|
|
159
|
+
throw new Error("硅基员工只支持结构化会话。");
|
|
160
|
+
agents = [singleAgent];
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
141
163
|
throw new Error("至少需要一个执行候选。");
|
|
142
|
-
|
|
164
|
+
}
|
|
165
|
+
const seenKeys = new Set(agents.map(agentKey));
|
|
166
|
+
if (seenKeys.size !== agents.length) {
|
|
167
|
+
throw new Error("执行候选存在重复。");
|
|
168
|
+
}
|
|
143
169
|
const avatar = parseAvatar(body.avatar, name);
|
|
144
170
|
const tags = parseSiliconEmployeeTags(body.tags === undefined ? existing?.tags ?? [] : body.tags);
|
|
145
171
|
const id = existing?.id ?? `e_${randomUUID().replace(/-/g, "")}`;
|
|
@@ -177,7 +203,7 @@ export function registerSiliconEmployeeRoutes(app, deps) {
|
|
|
177
203
|
const available = availableEmployeeProviders(resolveDefaults().provider, isProviderAvailable);
|
|
178
204
|
return available.length ? available : [...SESSION_PROVIDERS];
|
|
179
205
|
};
|
|
180
|
-
const generateDraft = deps.generateDraft ?? ((request) => generateSiliconEmployeeDraft(request.expectation, employeeDraftAiOptions(storage, config
|
|
206
|
+
const generateDraft = deps.generateDraft ?? ((request) => generateSiliconEmployeeDraft(request.expectation, employeeDraftAiOptions(storage, config), {
|
|
181
207
|
cwd: config?.defaultCwd || process.cwd(),
|
|
182
208
|
language: config?.language ?? "",
|
|
183
209
|
existingNames: request.existingNames,
|
|
@@ -10,7 +10,6 @@ import { asyncRoute } from "./express-async.js";
|
|
|
10
10
|
import { sendRouteError } from "./server-request.js";
|
|
11
11
|
import { isBlockedFolderPath, isPathWithinBase, normalizeFolderPath } from "./middleware/path-safety.js";
|
|
12
12
|
import { parseBoundedInteger } from "./request-limits.js";
|
|
13
|
-
import { runGitRawAsync } from "./git-utils.js";
|
|
14
13
|
const execAsync = promisify(exec);
|
|
15
14
|
const DIRECTORY_MAX_ITEMS = 200;
|
|
16
15
|
const MAX_TEXT_PREVIEW_SIZE = 512 * 1024;
|
|
@@ -594,10 +593,7 @@ export function registerFileRoutes(app, deps) {
|
|
|
594
593
|
const cwd = typeof req.query.cwd === "string" ? req.query.cwd : defaultCwd;
|
|
595
594
|
const maxDepth = parseBoundedInteger(req.query.depth, 5, 0, 8);
|
|
596
595
|
const maxResults = parseBoundedInteger(req.query.limit, 50, 1, 200);
|
|
597
|
-
const
|
|
598
|
-
// Internal metadata remains excluded even when the user opts into generated files.
|
|
599
|
-
const ignoredDirectories = new Set([".git", ".wand", ".wand-uploads", ".wand-team"]);
|
|
600
|
-
const generatedDirectories = new Set(["node_modules", ".next", "dist", "build", "coverage"]);
|
|
596
|
+
const ignoredDirectories = new Set([".git", "node_modules", ".next", "dist", "build", "coverage", ".wand-uploads", ".wand-team"]);
|
|
601
597
|
const maxVisitedEntries = 20_000;
|
|
602
598
|
let resolvedCwd;
|
|
603
599
|
try {
|
|
@@ -616,70 +612,38 @@ export function registerFileRoutes(app, deps) {
|
|
|
616
612
|
return;
|
|
617
613
|
}
|
|
618
614
|
try {
|
|
619
|
-
let gitIgnored = new Set();
|
|
620
|
-
try {
|
|
621
|
-
const ignored = await runGitRawAsync(["ls-files", "--others", "--ignored", "--exclude-standard", "--directory", "-z"], resolvedCwd, { timeout: 2_000, maxBuffer: 2 * 1024 * 1024 });
|
|
622
|
-
gitIgnored = new Set(ignored.split("\0").filter(Boolean).map((entry) => path.resolve(resolvedCwd, entry.replace(/\/$/, ""))));
|
|
623
|
-
}
|
|
624
|
-
catch {
|
|
625
|
-
// Ordinary directories and hosts without Git still retain the existing known-directory exclusions.
|
|
626
|
-
}
|
|
627
615
|
const results = [];
|
|
628
|
-
const deferred = [];
|
|
629
616
|
const queryLower = query.toLowerCase();
|
|
630
617
|
let visitedEntries = 0;
|
|
631
|
-
async function searchDir(dirPath, currentDepth
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
618
|
+
async function searchDir(dirPath, currentDepth) {
|
|
619
|
+
if (currentDepth > maxDepth || results.length >= maxResults || visitedEntries >= maxVisitedEntries)
|
|
620
|
+
return;
|
|
621
|
+
const entries = await readdir(dirPath, { withFileTypes: true });
|
|
622
|
+
for (const entry of entries) {
|
|
623
|
+
if (results.length >= maxResults || visitedEntries >= maxVisitedEntries)
|
|
624
|
+
break;
|
|
625
|
+
visitedEntries += 1;
|
|
626
|
+
if (entry.isDirectory() && ignoredDirectories.has(entry.name))
|
|
636
627
|
continue;
|
|
637
|
-
const
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
if (includeGenerated)
|
|
647
|
-
deferred.push({ path: entryPath, name: entry.name, depth: directory.depth + 1 });
|
|
648
|
-
continue;
|
|
649
|
-
}
|
|
650
|
-
if (!generated && gitIgnored.has(entryPath))
|
|
651
|
-
continue;
|
|
652
|
-
const matchIndex = entry.name.toLowerCase().indexOf(queryLower);
|
|
653
|
-
if (matchIndex !== -1) {
|
|
654
|
-
results.push({
|
|
655
|
-
path: entryPath,
|
|
656
|
-
name: entry.name,
|
|
657
|
-
type: entry.isDirectory() ? "dir" : "file",
|
|
658
|
-
matchScore: matchIndex,
|
|
659
|
-
generated,
|
|
660
|
-
depth: directory.depth,
|
|
661
|
-
});
|
|
662
|
-
}
|
|
663
|
-
if (entry.isDirectory() && directory.depth < maxDepth)
|
|
664
|
-
directories.push({ path: entryPath, depth: directory.depth + 1 });
|
|
628
|
+
const entryPath = path.join(dirPath, entry.name);
|
|
629
|
+
const matchIndex = entry.name.toLowerCase().indexOf(queryLower);
|
|
630
|
+
if (matchIndex !== -1) {
|
|
631
|
+
results.push({
|
|
632
|
+
path: entryPath,
|
|
633
|
+
name: entry.name,
|
|
634
|
+
type: entry.isDirectory() ? "dir" : "file",
|
|
635
|
+
matchScore: matchIndex,
|
|
636
|
+
});
|
|
665
637
|
}
|
|
638
|
+
if (entry.isDirectory())
|
|
639
|
+
await searchDir(entryPath, currentDepth + 1);
|
|
666
640
|
}
|
|
667
641
|
}
|
|
668
642
|
await searchDir(resolvedCwd, 0);
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
const matchScore = directory.name.toLowerCase().indexOf(queryLower);
|
|
674
|
-
if (matchScore !== -1)
|
|
675
|
-
results.push({ path: directory.path, name: directory.name, type: "dir", matchScore, generated: true, depth: directory.depth - 1 });
|
|
676
|
-
await searchDir(directory.path, directory.depth, true);
|
|
677
|
-
}
|
|
678
|
-
results.sort((a, b) => Number(a.generated) - Number(b.generated)
|
|
679
|
-
|| Number(b.name.toLowerCase() === queryLower) - Number(a.name.toLowerCase() === queryLower)
|
|
680
|
-
|| a.depth - b.depth || a.matchScore - b.matchScore || a.name.localeCompare(b.name));
|
|
681
|
-
res.json({ results: results.slice(0, maxResults), query, cwd: resolvedCwd,
|
|
682
|
-
truncated: results.length > maxResults || visitedEntries >= maxVisitedEntries });
|
|
643
|
+
results.sort((a, b) => a.matchScore !== b.matchScore
|
|
644
|
+
? a.matchScore - b.matchScore
|
|
645
|
+
: a.name.localeCompare(b.name));
|
|
646
|
+
res.json({ results: results.slice(0, maxResults), query, cwd: resolvedCwd });
|
|
683
647
|
}
|
|
684
648
|
catch (error) {
|
|
685
649
|
sendRouteError(res, error, "搜索失败。可能原因:路径不存在或权限不足。");
|
|
@@ -51,18 +51,6 @@ export function registerLocalModelRoutes(app, deps) {
|
|
|
51
51
|
next(error);
|
|
52
52
|
}
|
|
53
53
|
});
|
|
54
|
-
app.patch("/api/local-models/speech/settings", deps.requireAdmin, async (req, res, next) => {
|
|
55
|
-
try {
|
|
56
|
-
if (!req.body || Array.isArray(req.body) || Object.keys(req.body).length !== 1 || typeof req.body.enabled !== "boolean") {
|
|
57
|
-
throw new DecisionError("INVALID_REQUEST", "仅允许修改语音启用状态。");
|
|
58
|
-
}
|
|
59
|
-
await deps.models.setSpeechEnabled(req.body.enabled);
|
|
60
|
-
res.status(202).json(await deps.models.status());
|
|
61
|
-
}
|
|
62
|
-
catch (error) {
|
|
63
|
-
next(error);
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
54
|
const errors = (error, _req, res, _next) => {
|
|
67
55
|
if (error instanceof DecisionError || error instanceof SpeechError) {
|
|
68
56
|
res.status(error.status).json({ error: error.message, code: error.code });
|
|
@@ -3,7 +3,6 @@ import { ProcessManager } from "./process-manager.js";
|
|
|
3
3
|
import { StructuredSessionManager } from "./structured-session-manager.js";
|
|
4
4
|
import { WandStorage } from "./storage.js";
|
|
5
5
|
import { ExecutionMode, ProcessEvent, SessionSnapshot, SessionSource, WandConfig } from "./types.js";
|
|
6
|
-
import type { OpenRouterFreeModelsService } from "./openrouter-free-models.js";
|
|
7
6
|
import { toSessionListItemDTO } from "./session-transport.js";
|
|
8
7
|
import { type ProviderHistoryDeleter, SessionRegistry } from "./session-registry.js";
|
|
9
8
|
import { type PiRecommendationRuntime } from "./server-pi-recommendation-routes.js";
|
|
@@ -47,6 +46,6 @@ export interface SessionDirectoryTreeResponse {
|
|
|
47
46
|
}
|
|
48
47
|
export declare function buildSessionListPage(sessions: SessionSnapshot[], offset: number, limit: number): SessionListPage;
|
|
49
48
|
export declare function buildSessionDirectoryTree(sessions: SessionSnapshot[], customNames?: ReadonlyMap<string, string>): SessionDirectoryTreeResponse;
|
|
50
|
-
export declare function registerSessionRoutes(app: Express, processes: ProcessManager, structured: StructuredSessionManager, storage: WandStorage, defaultMode: ExecutionMode, config: WandConfig, sessions: SessionRegistry, onSessionCreated?: (cwd: string | undefined | null) => void, onCompletionViewed?: (event: ProcessEvent) => void, decisions?: PiRecommendationRuntime
|
|
49
|
+
export declare function registerSessionRoutes(app: Express, processes: ProcessManager, structured: StructuredSessionManager, storage: WandStorage, defaultMode: ExecutionMode, config: WandConfig, sessions: SessionRegistry, onSessionCreated?: (cwd: string | undefined | null) => void, onCompletionViewed?: (event: ProcessEvent) => void, decisions?: PiRecommendationRuntime): void;
|
|
51
50
|
export declare function registerClaudeHistoryRoutes(app: Express, processes: ProcessManager, storage: WandStorage): void;
|
|
52
51
|
export {};
|
|
@@ -11,7 +11,7 @@ import { resolveSessionCwd } from "./session-cwd.js";
|
|
|
11
11
|
import { resolveSystemAiContext } from "./session-ai-context.js";
|
|
12
12
|
import { getGitStatusAsync, QuickCommitError, runQuickCommitWithFallback, runTagHead, runPush, generateCommitMessageOnly, } from "./git-quick-commit.js";
|
|
13
13
|
import { getErrorMessage } from "./error-utils.js";
|
|
14
|
-
import { archiveCommitTasks
|
|
14
|
+
import { archiveCommitTasks } from "./commit-task-archive.js";
|
|
15
15
|
import { buildIterationCommitContext, COMMIT_CONTEXT_MODE_PREF_KEY, isCommitContextMode, readCommitContextMode, resolveCommitContextInput, } from "./iteration-log.js";
|
|
16
16
|
import { inferProviderFromCommand, isSessionProvider, providerCliCommand, SESSION_PROVIDERS } from "./session-provider.js";
|
|
17
17
|
import { selectEmployeeCandidate } from "./silicon-employee-dispatch.js";
|
|
@@ -366,7 +366,7 @@ function canMergeSession(snapshot) {
|
|
|
366
366
|
function isMergeActionAllowed(snapshot) {
|
|
367
367
|
return snapshot.status !== "running";
|
|
368
368
|
}
|
|
369
|
-
export function registerSessionRoutes(app, processes, structured, storage, defaultMode, config, sessions, onSessionCreated, onCompletionViewed, decisions
|
|
369
|
+
export function registerSessionRoutes(app, processes, structured, storage, defaultMode, config, sessions, onSessionCreated, onCompletionViewed, decisions) {
|
|
370
370
|
registerPiRecommendationRoute(app, { structured, sessions, config, decisions });
|
|
371
371
|
const wantsCompactTools = (req) => req.get("X-Wand-Tool-Projection") === "compact" || req.query.compactTools === "1";
|
|
372
372
|
const sessionResponseDTO = (snapshot, req) => {
|
|
@@ -497,9 +497,9 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
497
497
|
res.status(400).json({ error: "请选择有效的执行引擎。" });
|
|
498
498
|
return;
|
|
499
499
|
}
|
|
500
|
-
const requestedEngine = employee && !requestedProvider
|
|
501
|
-
?
|
|
502
|
-
: rawEngine
|
|
500
|
+
const requestedEngine = (employee && !requestedProvider) || !rawEngine
|
|
501
|
+
? undefined
|
|
502
|
+
: rawEngine;
|
|
503
503
|
if (requestedEngine === "sdk" && provider !== "pi") {
|
|
504
504
|
res.status(400).json({ error: "Wand Agent 只支持 Pi 结构化会话。" });
|
|
505
505
|
return;
|
|
@@ -1100,7 +1100,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1100
1100
|
}
|
|
1101
1101
|
const body = (req.body ?? {});
|
|
1102
1102
|
try {
|
|
1103
|
-
const ai = resolveSystemAiContext(snapshot, config, storage.getSystemSiliconEmployee()
|
|
1103
|
+
const ai = resolveSystemAiContext(snapshot, config, storage.getSystemSiliconEmployee());
|
|
1104
1104
|
// 自动 message + 迭代模式:拿本轮提示词当输入;提交成功后标记已用掉。
|
|
1105
1105
|
const context = await iterationCommitInput(storage, snapshot, body);
|
|
1106
1106
|
const result = await runQuickCommitWithFallback({
|
|
@@ -1120,7 +1120,6 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1120
1120
|
? storage.markIterationPromptsConsumed(context.entryIds, result.commit.hash)
|
|
1121
1121
|
: 0;
|
|
1122
1122
|
let archivedTaskIds = [];
|
|
1123
|
-
const archivedSessionIds = [];
|
|
1124
1123
|
let archiveError;
|
|
1125
1124
|
if (body.archiveRelatedTasks === true && result.ok && result.commit?.hash) {
|
|
1126
1125
|
try {
|
|
@@ -1130,17 +1129,15 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1130
1129
|
archivedTaskIds = archiveCommitTasks(storage, snapshot, context.entryIds, {
|
|
1131
1130
|
workspaceTaskId: openedTaskId || null,
|
|
1132
1131
|
});
|
|
1133
|
-
archiveCommitStandaloneSessions(storage, sessions, snapshot, archivedSessionIds);
|
|
1134
1132
|
}
|
|
1135
1133
|
catch (error) {
|
|
1136
|
-
archiveError = getErrorMessage(error, "
|
|
1134
|
+
archiveError = getErrorMessage(error, "归档关联任务失败。");
|
|
1137
1135
|
console.error("[QuickCommit] Failed to archive related tasks:", archiveError);
|
|
1138
1136
|
}
|
|
1139
1137
|
}
|
|
1140
1138
|
res.json({
|
|
1141
1139
|
...result,
|
|
1142
1140
|
archivedTaskIds,
|
|
1143
|
-
archivedSessionIds,
|
|
1144
1141
|
...(archiveError ? { archiveError } : {}),
|
|
1145
1142
|
commitContext: {
|
|
1146
1143
|
source: commitMessageFromIteration(body) && context.digest ? "iteration" : "diff",
|
|
@@ -1202,7 +1199,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1202
1199
|
}
|
|
1203
1200
|
const body = (req.body ?? {});
|
|
1204
1201
|
try {
|
|
1205
|
-
const ai = resolveSystemAiContext(snapshot, config, storage.getSystemSiliconEmployee()
|
|
1202
|
+
const ai = resolveSystemAiContext(snapshot, config, storage.getSystemSiliconEmployee());
|
|
1206
1203
|
const context = await iterationCommitInput(storage, snapshot, body);
|
|
1207
1204
|
const result = await generateCommitMessageOnly(snapshot.cwd, config.language ?? "", {
|
|
1208
1205
|
...ai,
|
|
@@ -1239,7 +1236,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1239
1236
|
}
|
|
1240
1237
|
const body = (req.body ?? {});
|
|
1241
1238
|
try {
|
|
1242
|
-
const ai = resolveSystemAiContext(snapshot, config, storage.getSystemSiliconEmployee()
|
|
1239
|
+
const ai = resolveSystemAiContext(snapshot, config, storage.getSystemSiliconEmployee());
|
|
1243
1240
|
const result = await runTagHead({
|
|
1244
1241
|
cwd: snapshot.cwd,
|
|
1245
1242
|
language: config.language ?? "",
|
|
@@ -1736,7 +1733,7 @@ export function registerSessionRoutes(app, processes, structured, storage, defau
|
|
|
1736
1733
|
sendRouteError(res, error, "无法停止会话。");
|
|
1737
1734
|
}
|
|
1738
1735
|
});
|
|
1739
|
-
//
|
|
1736
|
+
// 归档会停止会话,但保留 Wand 会话 ID 和 provider session id。恢复时用这个 ID 续上。
|
|
1740
1737
|
app.post("/api/sessions/:id/archive", (req, res) => {
|
|
1741
1738
|
try {
|
|
1742
1739
|
const updated = sessions.setArchived(req.params.id, true);
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import { type Express, type RequestHandler } from "express";
|
|
2
2
|
import { type SpeechService } from "./speech-service.js";
|
|
3
|
-
import type { SpeechPolisherService } from "./speech-polisher-service.js";
|
|
4
3
|
/** Mounted behind /api authentication. Clients may transcribe, only admins configure/download. */
|
|
5
4
|
export declare function registerSpeechRoutes(app: Express, deps: {
|
|
6
5
|
speech: SpeechService;
|
|
7
6
|
requireSessions: RequestHandler;
|
|
8
7
|
requireAdmin: RequestHandler;
|
|
9
|
-
polisher?: Pick<SpeechPolisherService, "polish">;
|
|
10
8
|
}): void;
|
|
@@ -53,7 +53,6 @@ export function registerSpeechRoutes(app, deps) {
|
|
|
53
53
|
next();
|
|
54
54
|
};
|
|
55
55
|
app.post("/api/speech/transcribe", admission, express.raw({ type: "audio/wav", limit: SPEECH_MAX_WAV_BYTES }), async (req, res, next) => {
|
|
56
|
-
const started = Date.now();
|
|
57
56
|
const abort = new AbortController();
|
|
58
57
|
const disconnected = () => { if (!res.writableEnded)
|
|
59
58
|
abort.abort(); };
|
|
@@ -62,13 +61,8 @@ export function registerSpeechRoutes(app, deps) {
|
|
|
62
61
|
if (!Buffer.isBuffer(req.body))
|
|
63
62
|
throw new SpeechError("INVALID_AUDIO", "未收到 WAV 音频。");
|
|
64
63
|
const result = await deps.speech.transcribe(req.body, abort.signal);
|
|
65
|
-
const polished = deps.polisher ? await deps.polisher.polish(result.text, abort.signal, Math.min(45_000, 123_000 - (Date.now() - started))).catch(() => {
|
|
66
|
-
abort.signal.throwIfAborted();
|
|
67
|
-
return { text: result.text, originalText: result.text, optimized: false,
|
|
68
|
-
optimizationError: "口述整理暂不可用,已保留原始转写。" };
|
|
69
|
-
}) : null;
|
|
70
64
|
if (!res.destroyed)
|
|
71
|
-
res.json(
|
|
65
|
+
res.json(result);
|
|
72
66
|
}
|
|
73
67
|
catch (error) {
|
|
74
68
|
if (!res.destroyed)
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Express } from "express";
|
|
2
2
|
import { type WandStorage } from "./storage.js";
|
|
3
3
|
import { generateWandTaskTitle } from "./task-title.js";
|
|
4
|
-
import type { OpenRouterFreeModelsService } from "./openrouter-free-models.js";
|
|
5
4
|
import type { SessionRegistry } from "./session-registry.js";
|
|
6
5
|
import type { StructuredSessionManager } from "./structured-session-manager.js";
|
|
7
6
|
import type { ProcessManager } from "./process-manager.js";
|
|
@@ -18,7 +17,6 @@ export interface TaskRouteDependencies {
|
|
|
18
17
|
/** PTY 会话创建入口;派发 `kind: "pty"` 的任务时使用。测试里可换成同步桩。 */
|
|
19
18
|
processes?: ProcessManager;
|
|
20
19
|
config?: WandConfig;
|
|
21
|
-
free?: Pick<OpenRouterFreeModelsService, "resolveForCall">;
|
|
22
20
|
aiTeams?: AiTeamRunner;
|
|
23
21
|
/** 可注入的任务标题生成器;测试里换成同步桩,避免真的起 CLI。 */
|
|
24
22
|
generateTitle?: typeof generateWandTaskTitle;
|
|
@@ -35,7 +33,6 @@ export declare function parseTaskAgent(value: unknown, fallbackMode?: WandTaskAg
|
|
|
35
33
|
export declare function whenWandTaskTitlesSettled(): Promise<void>;
|
|
36
34
|
export interface AutoTaskTitleOptions {
|
|
37
35
|
config?: WandConfig;
|
|
38
|
-
free?: Pick<OpenRouterFreeModelsService, "resolveForCall">;
|
|
39
36
|
/** 可注入的标题生成器;测试里换成同步桩,避免真的起 CLI。 */
|
|
40
37
|
generateTitle?: typeof generateWandTaskTitle;
|
|
41
38
|
/** 未从任务所属工作区解析到目录时的兜底 cwd。 */
|
|
@@ -41,7 +41,6 @@ export function writeTaskBoardLastAgent(storage, agent) {
|
|
|
41
41
|
thinkingEffort: agent.thinkingEffort,
|
|
42
42
|
mode: agent.mode,
|
|
43
43
|
kind: agent.kind,
|
|
44
|
-
...(agent.engine ? { engine: agent.engine } : {}),
|
|
45
44
|
});
|
|
46
45
|
}
|
|
47
46
|
function parseExecutionSubject(storage, value) {
|
|
@@ -251,7 +250,7 @@ function scheduleWandTaskTitleGeneration(storage, taskId, source, signature, opt
|
|
|
251
250
|
const cwd = options.cwd || options.config?.defaultCwd || process.cwd();
|
|
252
251
|
const run = async () => {
|
|
253
252
|
try {
|
|
254
|
-
const title = await generateTitle(source, cwd, options.config?.language ?? "", taskTitleAiOptions(options.config, storage
|
|
253
|
+
const title = await generateTitle(source, cwd, options.config?.language ?? "", taskTitleAiOptions(options.config, storage));
|
|
255
254
|
const current = storage.getWandTask(taskId);
|
|
256
255
|
// 用户已经自己写了标题(原生端 / 面板编辑)就不要覆盖。
|
|
257
256
|
if (!current || current.titleSource !== "auto")
|
|
@@ -305,12 +304,11 @@ export function refreshAutoBoardTaskTitles(storage, options = {}) {
|
|
|
305
304
|
cwd,
|
|
306
305
|
config: options.config,
|
|
307
306
|
generateTitle: options.generateTitle,
|
|
308
|
-
free: options.free,
|
|
309
307
|
});
|
|
310
308
|
}
|
|
311
309
|
}
|
|
312
310
|
/** 自动生成标题没有会话上下文,按「默认 provider + 默认模型」解析,与提示词优化一致。 */
|
|
313
|
-
function taskTitleAiOptions(config, storage
|
|
311
|
+
function taskTitleAiOptions(config, storage) {
|
|
314
312
|
if (!config)
|
|
315
313
|
return {};
|
|
316
314
|
const provider = config.defaultProvider ?? "claude";
|
|
@@ -322,7 +320,8 @@ function taskTitleAiOptions(config, storage, free) {
|
|
|
322
320
|
selectedModel: null,
|
|
323
321
|
thinkingEffort: config.defaultThinkingEffort,
|
|
324
322
|
};
|
|
325
|
-
|
|
323
|
+
// resolveSystemAiContext 按系统运维员工的 CLI 候选链解析(首个已安装的优先)。
|
|
324
|
+
return resolveSystemAiContext(defaultSession, config, storage?.getSystemSiliconEmployee() ?? null);
|
|
326
325
|
}
|
|
327
326
|
export function registerTaskRoutes(app, deps) {
|
|
328
327
|
const { storage, sessions, structured, processes, config, aiTeams } = deps;
|
|
@@ -330,7 +329,7 @@ export function registerTaskRoutes(app, deps) {
|
|
|
330
329
|
app.get("/api/wand-tasks", (req, res) => {
|
|
331
330
|
try {
|
|
332
331
|
// 侧栏建的任务 / 后续新增的会话都会在这里补上自动标题。
|
|
333
|
-
refreshAutoBoardTaskTitles(storage, { config, generateTitle: deps.generateTitle
|
|
332
|
+
refreshAutoBoardTaskTitles(storage, { config, generateTitle: deps.generateTitle });
|
|
334
333
|
}
|
|
335
334
|
catch (error) {
|
|
336
335
|
console.error("[WandTask] Failed to refresh auto task titles:", getErrorMessage(error));
|
|
@@ -484,15 +483,13 @@ export function registerTaskRoutes(app, deps) {
|
|
|
484
483
|
agent: assignedAgent,
|
|
485
484
|
executionSubject,
|
|
486
485
|
});
|
|
487
|
-
|
|
488
|
-
if (body.rememberAgentDefaults === true && agent)
|
|
486
|
+
if (agent)
|
|
489
487
|
writeTaskBoardLastAgent(storage, agent);
|
|
490
488
|
if (titleSource === "auto") {
|
|
491
489
|
refreshAutoBoardTaskTitles(storage, {
|
|
492
490
|
cwd: workspaceId ? storage.getWorkspace(workspaceId)?.cwd : undefined,
|
|
493
491
|
config,
|
|
494
492
|
generateTitle: deps.generateTitle,
|
|
495
|
-
free: deps.free,
|
|
496
493
|
});
|
|
497
494
|
}
|
|
498
495
|
res.status(201).json(dto(storage.getWandTask(task.id) ?? task));
|
|
@@ -586,7 +583,7 @@ export function registerTaskRoutes(app, deps) {
|
|
|
586
583
|
res.status(404).json({ error: "未找到该任务。" });
|
|
587
584
|
return;
|
|
588
585
|
}
|
|
589
|
-
if (body.
|
|
586
|
+
if (body.agent !== undefined && patch.agent)
|
|
590
587
|
writeTaskBoardLastAgent(storage, patch.agent);
|
|
591
588
|
res.json(dto(storage.getWandTask(task.id) ?? task));
|
|
592
589
|
}
|
|
@@ -744,12 +741,12 @@ export function registerTaskRoutes(app, deps) {
|
|
|
744
741
|
if (subject?.type === "employee" && (!employee || employee.archivedAt)) {
|
|
745
742
|
throw new Error("硅基员工不存在或已归档。");
|
|
746
743
|
}
|
|
747
|
-
const selected = employee ? selectEmployeeCandidate(employee) : null;
|
|
744
|
+
const selected = employee ? selectEmployeeCandidate(employee, undefined, { skipSdk: true }) : null;
|
|
748
745
|
const cliDefault = subject?.type === "cli"
|
|
749
746
|
? parseTaskAgent({ ...cliAgentForSubject(subject, task.agent), ...(body.kind === "pty" ? { kind: "pty" } : {}) })
|
|
750
747
|
: null;
|
|
751
748
|
const fallbackCandidate = !subject && body.agent === undefined && !task.agent
|
|
752
|
-
&& !body.provider ? selectEmployeeCandidate(defaultRoleForCli(storage, config.defaultProvider)).agent : null;
|
|
749
|
+
&& !body.provider ? selectEmployeeCandidate(defaultRoleForCli(storage, config.defaultProvider), undefined, { skipSdk: true }).agent : null;
|
|
753
750
|
const fallbackAgent = fallbackCandidate && body.kind === "pty"
|
|
754
751
|
? { ...fallbackCandidate, kind: "pty" } : fallbackCandidate;
|
|
755
752
|
const agent = selected?.agent ?? (body.agent === undefined
|
|
@@ -783,7 +780,7 @@ export function registerTaskRoutes(app, deps) {
|
|
|
783
780
|
executionSubject: usedSubject,
|
|
784
781
|
status: task.status === "todo" ? "doing" : task.status,
|
|
785
782
|
});
|
|
786
|
-
if (
|
|
783
|
+
if (!employee)
|
|
787
784
|
writeTaskBoardLastAgent(storage, agent);
|
|
788
785
|
// 派发也算一轮迭代里的改动意图:直接把任务的标题 / 描述记进迭代记录。
|
|
789
786
|
recordIterationPromptForTask(storage, {
|
package/dist/server.js
CHANGED
|
@@ -29,8 +29,6 @@ import { recordRecentPath, registerFileRoutes } from "./server-file-routes.js";
|
|
|
29
29
|
import { registerLocalPreviewRoutes } from "./server-local-preview-routes.js";
|
|
30
30
|
import { registerSettingsRoutes } from "./server-settings-routes.js";
|
|
31
31
|
import { registerSpeechRoutes } from "./server-speech-routes.js";
|
|
32
|
-
import { SpeechPolisherService } from "./speech-polisher-service.js";
|
|
33
|
-
import { SPEECH_POLISHER_KEY } from "./speech-polisher-identity.js";
|
|
34
32
|
import { registerLocalModelRoutes } from "./server-local-model-routes.js";
|
|
35
33
|
import { LocalModelSetupService } from "./local-model-setup.js";
|
|
36
34
|
import { DecisionExpertService } from "./decision-expert-service.js";
|
|
@@ -81,7 +79,7 @@ import { DistributionManager } from "./distribution-manager.js";
|
|
|
81
79
|
import { isLogBusActive, wandTuiLog } from "./tui/log-bus.js";
|
|
82
80
|
import { EMBEDDED_WEB_ASSETS } from "./web-ui/embedded-assets.js";
|
|
83
81
|
import { renderApp } from "./web-ui/index.js";
|
|
84
|
-
import { getAiTeamsChunk, getScriptAsset
|
|
82
|
+
import { getAiTeamsChunk, getScriptAsset } from "./web-ui/scripts.js";
|
|
85
83
|
import { getStylesAsset } from "./web-ui/styles.js";
|
|
86
84
|
import { WsBroadcastManager } from "./ws-broadcast.js";
|
|
87
85
|
import { TerminalDaemonClient } from "./terminal-daemon-client.js";
|
|
@@ -327,8 +325,6 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
327
325
|
const storage = new WandStorage(resolveDatabasePath(configPath));
|
|
328
326
|
const runtimeConfig = new RuntimeConfigState(config);
|
|
329
327
|
const openRouter = new OpenRouterFreeModelsService(storage, options.openRouterFetch);
|
|
330
|
-
const speechPolisher = new SpeechPolisherService({ config, free: openRouter,
|
|
331
|
-
employee: () => storage.getSystemSiliconEmployee(SPEECH_POLISHER_KEY) });
|
|
332
328
|
const authService = new AuthService(storage);
|
|
333
329
|
const settingsAccess = new SettingsWebAccess();
|
|
334
330
|
const decisions = new DecisionService(config.localDecision);
|
|
@@ -402,7 +398,7 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
402
398
|
const terminalHost = daemonAdmission.terminal(ptyHosts.host);
|
|
403
399
|
let decisionRuntime = null;
|
|
404
400
|
let autoAssignEvaluate;
|
|
405
|
-
const processes = new ProcessManager(config, storage, configDir, terminalHost, { resolveDecisionEvaluate: () => autoAssignEvaluate
|
|
401
|
+
const processes = new ProcessManager(config, storage, configDir, terminalHost, { resolveDecisionEvaluate: () => autoAssignEvaluate });
|
|
406
402
|
const structuredLogger = new SessionLogger(configDir, config.shortcutLogMaxBytes);
|
|
407
403
|
// Production startup provides a daemon-backed host for structured CLI runs
|
|
408
404
|
// even when Render owns every PTY. In-process hosts are for test injection.
|
|
@@ -554,11 +550,6 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
554
550
|
setAssetCache(req, res, asset.hash, "public");
|
|
555
551
|
res.type("text/css").send(asset.content);
|
|
556
552
|
});
|
|
557
|
-
app.get("/assets/theme.js", (req, res) => {
|
|
558
|
-
const asset = getThemePreloadAsset();
|
|
559
|
-
setAssetCache(req, res, asset.hash, "public");
|
|
560
|
-
res.type("application/javascript").send(asset.content);
|
|
561
|
-
});
|
|
562
553
|
app.get("/assets/app.js", (req, res) => {
|
|
563
554
|
const asset = getScriptAsset(configPath, requestedHash(req));
|
|
564
555
|
setAssetCache(req, res, asset.hash, "private");
|
|
@@ -773,7 +764,7 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
773
764
|
app.use("/api/silicon-employees/:employeeId/knowledge", requireSessions);
|
|
774
765
|
app.use(userMemoryOperationLog(storage));
|
|
775
766
|
const userMemory = new UserMemoryService({
|
|
776
|
-
storage, config,
|
|
767
|
+
storage, config,
|
|
777
768
|
notifyChanged: (employeeId) => notifyAiTeamRun({ kind: "silicon-employee-definition", employeeId }),
|
|
778
769
|
});
|
|
779
770
|
registerUserMemoryRoutes(app, {
|
|
@@ -850,7 +841,7 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
850
841
|
});
|
|
851
842
|
registerGithubRoutes(app, { storage, requireAdmin, sessions: sessionRegistry });
|
|
852
843
|
// 任务管理与 Missions 一样只需登录:原生 connected-app 也要能列/建/派发。
|
|
853
|
-
registerTaskRoutes(app, { storage, sessions: sessionRegistry, structured: structuredSessions, processes, config, aiTeams
|
|
844
|
+
registerTaskRoutes(app, { storage, sessions: sessionRegistry, structured: structuredSessions, processes, config, aiTeams });
|
|
854
845
|
registerAiTeamRoutes(app, {
|
|
855
846
|
storage,
|
|
856
847
|
runner: aiTeams,
|
|
@@ -861,7 +852,6 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
861
852
|
registerSiliconEmployeeRoutes(app, {
|
|
862
853
|
storage,
|
|
863
854
|
config,
|
|
864
|
-
free: openRouter,
|
|
865
855
|
notifyEmployeeChanged: (employeeId) => notifyAiTeamRun({ kind: "silicon-employee-definition", employeeId }),
|
|
866
856
|
});
|
|
867
857
|
registerAttentionRoutes(app, { sessions: sessionRegistry, runner: aiTeams });
|
|
@@ -892,12 +882,12 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
892
882
|
}
|
|
893
883
|
registerSessionRoutes(app, processes, structuredSessions, storage, config.defaultMode, config, sessionRegistry, (cwd) => {
|
|
894
884
|
recordRecentPath(storage, cwd);
|
|
895
|
-
}, (event) => wsManager.emitEvent(event), decisionExpert
|
|
885
|
+
}, (event) => wsManager.emitEvent(event), decisionExpert);
|
|
896
886
|
registerClaudeHistoryRoutes(app, processes, storage);
|
|
897
887
|
registerWorkspaceRoutes(app, storage, sessionRegistry, { config });
|
|
898
888
|
registerMissionRoutes(app, missions);
|
|
899
889
|
registerUploadRoutes(app, sessionRegistry);
|
|
900
|
-
registerSpeechRoutes(app, { speech, requireSessions, requireAdmin
|
|
890
|
+
registerSpeechRoutes(app, { speech, requireSessions, requireAdmin });
|
|
901
891
|
registerLocalModelRoutes(app, { models: localModels, requireSessions, requireAdmin });
|
|
902
892
|
app.post("/api/optimize-prompt", asyncRoute(async (req, res) => {
|
|
903
893
|
const body = (req.body ?? {});
|
|
@@ -909,7 +899,7 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
909
899
|
if (snapshot?.cwd)
|
|
910
900
|
cwd = snapshot.cwd;
|
|
911
901
|
if (snapshot)
|
|
912
|
-
ai = resolveSystemAiContext(snapshot, config, storage.getSystemSiliconEmployee()
|
|
902
|
+
ai = resolveSystemAiContext(snapshot, config, storage.getSystemSiliconEmployee());
|
|
913
903
|
}
|
|
914
904
|
if (!ai) {
|
|
915
905
|
const defaultSession = {
|
|
@@ -920,7 +910,7 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
920
910
|
selectedModel: null,
|
|
921
911
|
thinkingEffort: config.defaultThinkingEffort,
|
|
922
912
|
};
|
|
923
|
-
ai = resolveSystemAiContext(defaultSession, config, storage.getSystemSiliconEmployee()
|
|
913
|
+
ai = resolveSystemAiContext(defaultSession, config, storage.getSystemSiliconEmployee());
|
|
924
914
|
}
|
|
925
915
|
try {
|
|
926
916
|
const optimized = await optimizePrompt(text, config.language ?? "", cwd, ai);
|
|
@@ -1190,7 +1180,6 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
1190
1180
|
conversationService.dispose();
|
|
1191
1181
|
localModels.dispose();
|
|
1192
1182
|
speech.dispose();
|
|
1193
|
-
speechPolisher.dispose();
|
|
1194
1183
|
try {
|
|
1195
1184
|
structuredSessions.dispose();
|
|
1196
1185
|
}
|
|
@@ -1511,7 +1500,6 @@ export async function startServer(config, configPath, options = {}) {
|
|
|
1511
1500
|
conversationService.dispose();
|
|
1512
1501
|
localModels.dispose();
|
|
1513
1502
|
speech.dispose();
|
|
1514
|
-
speechPolisher.dispose();
|
|
1515
1503
|
try {
|
|
1516
1504
|
structuredSessions.dispose();
|
|
1517
1505
|
}
|