@co0ontty/wand 4.89.5 → 4.90.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/README.md +5 -3
- package/dist/agent-dispatch.js +4 -9
- package/dist/ai-team-employee-binding.js +10 -9
- package/dist/ai-team-runner.d.ts +2 -1
- package/dist/ai-team-runner.js +38 -2
- package/dist/ai-team-types.js +3 -2
- package/dist/ai-text-runner.d.ts +61 -0
- package/dist/ai-text-runner.js +653 -0
- package/dist/avatar-input.d.ts +2 -0
- package/dist/avatar-input.js +19 -0
- package/dist/bounded-process-output.d.ts +5 -0
- package/dist/bounded-process-output.js +9 -0
- package/dist/build-info.json +3 -3
- package/dist/command-error.d.ts +6 -0
- package/dist/command-error.js +8 -0
- package/dist/config.js +11 -42
- package/dist/conversation-service.d.ts +12 -2
- package/dist/conversation-service.js +104 -25
- package/dist/conversation-session-preview.d.ts +2 -0
- package/dist/conversation-session-preview.js +4 -0
- package/dist/decision-client.js +22 -6
- package/dist/decision-expert-employee.js +2 -2
- package/dist/decision-expert-identity.d.ts +1 -1
- package/dist/decision-expert-identity.js +1 -1
- package/dist/decision-expert-service.d.ts +1 -0
- package/dist/decision-expert-service.js +82 -76
- package/dist/decision-hardware.js +4 -3
- package/dist/decision-types.d.ts +4 -0
- package/dist/decision-types.js +4 -0
- package/dist/deployment-lock.d.ts +13 -0
- package/dist/deployment-lock.js +189 -0
- package/dist/employee-text.js +1 -1
- package/dist/fixed-employee-avatar.d.ts +7 -0
- package/dist/fixed-employee-avatar.js +13 -0
- package/dist/git-quick-commit.d.ts +5 -40
- package/dist/git-quick-commit.js +8 -636
- package/dist/hr-employee-identity.d.ts +5 -0
- package/dist/hr-employee-identity.js +5 -0
- package/dist/hr-employee.d.ts +5 -0
- package/dist/hr-employee.js +21 -0
- package/dist/middleware/path-safety.js +1 -1
- package/dist/milestone-scope.js +1 -1
- package/dist/model-auto-assign.d.ts +1 -1
- package/dist/model-auto-assign.js +1 -1
- package/dist/models.d.ts +4 -0
- package/dist/models.js +21 -1
- package/dist/npm-update-utils.js +5 -44
- package/dist/pi-auto-resources.js +6 -3
- package/dist/plush-avatar.d.ts +10 -1
- package/dist/plush-avatar.js +13 -1
- package/dist/plush-cat-appearance.d.ts +97 -0
- package/dist/plush-cat-appearance.js +118 -0
- package/dist/plush-cat-whiskers.d.ts +6 -0
- package/dist/plush-cat-whiskers.js +42 -0
- package/dist/process-manager.d.ts +22 -21
- package/dist/process-manager.js +49 -83
- package/dist/prompt-optimizer.d.ts +1 -1
- package/dist/prompt-optimizer.js +1 -1
- package/dist/render-host.js +1 -19
- package/dist/scheduled-task-service.d.ts +41 -0
- package/dist/scheduled-task-service.js +294 -0
- package/dist/scheduled-task-state.d.ts +11 -0
- package/dist/scheduled-task-state.js +65 -0
- package/dist/scheduled-task-time.d.ts +4 -0
- package/dist/scheduled-task-time.js +82 -0
- package/dist/scheduled-task-types.d.ts +71 -0
- package/dist/scheduled-task-types.js +1 -0
- package/dist/server-ai-team-routes.js +3 -17
- package/dist/server-employee-routes.d.ts +3 -0
- package/dist/server-employee-routes.js +20 -38
- package/dist/server-file-routes.js +44 -1
- package/dist/server-pi-recommendation-routes.js +13 -4
- package/dist/server-request.d.ts +2 -0
- package/dist/server-request.js +9 -0
- package/dist/server-resume-routes.js +1 -1
- package/dist/server-scheduled-task-routes.d.ts +4 -0
- package/dist/server-scheduled-task-routes.js +34 -0
- package/dist/server-session-routes.d.ts +5 -13
- package/dist/server-session-routes.js +35 -70
- package/dist/server-task-routes.d.ts +6 -21
- package/dist/server-task-routes.js +25 -120
- package/dist/server-team-dispatch-routes.js +12 -2
- package/dist/server-workspace-routes.d.ts +1 -1
- package/dist/server-workspace-routes.js +33 -78
- package/dist/server.js +55 -20
- package/dist/session-model.d.ts +15 -0
- package/dist/session-model.js +23 -0
- package/dist/session-registry.d.ts +5 -1
- package/dist/session-registry.js +20 -11
- package/dist/session-request.d.ts +9 -0
- package/dist/session-request.js +27 -0
- package/dist/session-topic.d.ts +1 -1
- package/dist/session-topic.js +1 -1
- package/dist/session-transport.d.ts +3 -1
- package/dist/session-transport.js +11 -5
- package/dist/silicon-employee-draft.d.ts +2 -2
- package/dist/silicon-employee-draft.js +3 -3
- package/dist/socket-probe.d.ts +2 -0
- package/dist/socket-probe.js +20 -0
- package/dist/storage-schedules.d.ts +20 -0
- package/dist/storage-schedules.js +78 -0
- package/dist/storage-schema.d.ts +3 -0
- package/dist/storage-schema.js +702 -0
- package/dist/storage.d.ts +42 -8
- package/dist/storage.js +182 -715
- package/dist/structured-claude-adapter.js +12 -0
- package/dist/structured-claude-protocol.d.ts +4 -0
- package/dist/structured-claude-protocol.js +18 -4
- package/dist/structured-codex-adapter.js +11 -0
- package/dist/structured-exec-pump.js +79 -38
- package/dist/structured-failure.d.ts +21 -0
- package/dist/structured-failure.js +14 -0
- package/dist/structured-gemini-adapter.js +12 -2
- package/dist/structured-grok-adapter.js +12 -2
- package/dist/structured-opencode-adapter.js +8 -1
- package/dist/structured-qoder-adapter.js +14 -0
- package/dist/structured-session-manager.d.ts +13 -18
- package/dist/structured-session-manager.js +147 -517
- package/dist/system-employee.d.ts +1 -1
- package/dist/system-employee.js +1 -1
- package/dist/task-archive-policy.js +1 -1
- package/dist/task-read-model.d.ts +27 -0
- package/dist/task-read-model.js +47 -0
- package/dist/task-retention.d.ts +1 -1
- package/dist/task-retention.js +1 -1
- package/dist/task-title-service.d.ts +30 -0
- package/dist/task-title-service.js +122 -0
- package/dist/task-title.d.ts +1 -1
- package/dist/task-title.js +1 -1
- package/dist/terminal-daemon-client.js +1 -18
- package/dist/user-memory.js +1 -1
- package/dist/web-ui/asset-runtime.d.ts +12 -0
- package/dist/web-ui/asset-runtime.js +6 -0
- package/dist/web-ui/composer-avatar-activity.d.ts +6 -0
- package/dist/web-ui/composer-avatar-activity.js +29 -0
- package/dist/web-ui/content/ai-teams.js +13 -13
- package/dist/web-ui/content/module-manifest.json +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chat-render-PY6DIXNZ.js +24 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-2YZLCGYN.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-6CFHW3FA.js +111 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-6XQEBIEX.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-DDSO7OX7.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-G3CXNMA2.js +20 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-LGVAPHRS.js +36 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-NURCNMRU.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-PCMFGZKX.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-QRNA4D7E.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-TMRPHNJO.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-WC7RK7LP.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-YOXXNXOX.js +2 -0
- package/dist/web-ui/content/modules/5478be410b112154/chunk-YX475LXO.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/employee-card-MDWKU4V3.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-56WPSON2.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-5QOHKHNC.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-AWIJ5L2K.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-BOZLGIT5.js +69 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-EZV22Q7Y.js +4 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-IW43Z5ZF.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-JT7NIUQL.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-JWEIDB55.js +3 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-OU5TRYH6.js +2 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-PRSTCPVE.js +5 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-TWPJI3HE.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-WZGJSNML.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-X6KQVFD6.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-YKCQFMQR.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/host-bridge-2LZX6UUZ.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/library-bridge-MQFJGTGY.js +4 -0
- package/dist/web-ui/content/modules/5478be410b112154/page-T3VUCU2W.js +3 -0
- package/dist/web-ui/content/modules/5478be410b112154/panel-HJBGBBPY.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/runtime.js +920 -0
- package/dist/web-ui/content/modules/5478be410b112154/sha256-ANXV72UC.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/task-board-host-AVMDIHIV.js +2 -0
- package/dist/web-ui/content/modules/5478be410b112154/workspace-agent-picker-KI7QVSK3.js +1 -0
- package/dist/web-ui/content/modules/5478be410b112154/workspace-window-L542FGP2.js +1 -0
- package/dist/web-ui/content/plush-avatar.js +177 -177
- package/dist/web-ui/content/scripts.js +1 -994
- 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 +32 -0
- package/dist/web-ui/embedded-assets.js +10 -8
- package/dist/web-ui/markdown.d.ts +3 -2
- package/dist/web-ui/markdown.js +61 -48
- package/dist/web-ui/message-file-target.d.ts +13 -0
- package/dist/web-ui/message-file-target.js +85 -0
- package/dist/web-ui/provider-identity.d.ts +1 -1
- package/dist/web-ui/provider-identity.js +3 -4
- package/dist/web-ui/react/local-preview/controller.d.ts +2 -0
- package/dist/web-ui/react/local-preview/controller.js +12 -0
- package/dist/web-ui/scripts.d.ts +10 -0
- package/dist/web-ui/scripts.js +42 -5
- package/package.json +6 -3
- package/browser-extension/icons/wand-128.png +0 -0
- package/browser-extension/icons/wand-16.png +0 -0
- package/browser-extension/icons/wand-32.png +0 -0
- package/browser-extension/icons/wand-48.png +0 -0
- package/dist/web-ui/content/licenses/codex-LICENSE.txt +0 -21
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Diagnostic tails are not protocol payloads; only diagnostics may be truncated. */
|
|
2
|
+
export declare const MAX_DIAGNOSTIC_CHARS: number;
|
|
3
|
+
export declare const MAX_PROTOCOL_LINE_BYTES: number;
|
|
4
|
+
export declare const MAX_AI_TEXT_BYTES: number;
|
|
5
|
+
export declare function appendDiagnosticTail(previous: string, text: string): string;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Diagnostic tails are not protocol payloads; only diagnostics may be truncated. */
|
|
2
|
+
export const MAX_DIAGNOSTIC_CHARS = 64 * 1024;
|
|
3
|
+
export const MAX_PROTOCOL_LINE_BYTES = 8 * 1024 * 1024;
|
|
4
|
+
export const MAX_AI_TEXT_BYTES = 4 * 1024 * 1024;
|
|
5
|
+
export function appendDiagnosticTail(previous, text) {
|
|
6
|
+
const tail = (previous + text).slice(-MAX_DIAGNOSTIC_CHARS);
|
|
7
|
+
const first = tail.charCodeAt(0);
|
|
8
|
+
return first >= 0xdc00 && first <= 0xdfff ? tail.slice(1) : tail;
|
|
9
|
+
}
|
package/dist/build-info.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"commit": "
|
|
3
|
-
"builtAt": "2026-10-
|
|
4
|
-
"version": "4.
|
|
2
|
+
"commit": "c19f50516469789583ace432959dd7519a952f19",
|
|
3
|
+
"builtAt": "2026-10-11T15:04:29.304Z",
|
|
4
|
+
"version": "4.90.0",
|
|
5
5
|
"channel": "stable"
|
|
6
6
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Shared command failure shape; public legacy names/codes stay compatible. */
|
|
2
|
+
export type QuickCommitErrorCode = "CWD_MISSING" | "NO_CWD" | "NOT_A_GIT_REPO" | "NO_COMMIT" | "NOTHING_TO_COMMIT" | "NOTHING_TO_PUSH" | "EMPTY_MESSAGE" | "EMPTY_TAG" | "EMPTY_AI_MESSAGE" | "AI_FALLBACK_FAILED" | "INVALID_AI_TAG" | "TAG_EXISTS" | "GIT_ADD_FAILED" | "GIT_DIFF_FAILED" | "GIT_COMMIT_FAILED" | "GIT_TAG_FAILED" | "CLAUDE_CLI_MISSING" | "CLAUDE_CLI_FAILED" | "CLAUDE_TIMEOUT";
|
|
3
|
+
export declare class QuickCommitError extends Error {
|
|
4
|
+
readonly code: QuickCommitErrorCode;
|
|
5
|
+
constructor(message: string, code: QuickCommitErrorCode);
|
|
6
|
+
}
|
package/dist/config.js
CHANGED
|
@@ -61,9 +61,10 @@ export const PROVIDER_MODEL_PREFERENCE_FIELDS = {
|
|
|
61
61
|
gemini: "defaultGeminiModel",
|
|
62
62
|
};
|
|
63
63
|
const PROVIDER_MODEL_FIELDS = Object.values(PROVIDER_MODEL_PREFERENCE_FIELDS);
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
const TRIMMED_STRING_FIELDS = [...PROVIDER_MODEL_FIELDS, "commitModel", "systemAiModel", "language"];
|
|
65
|
+
const TRIMMED_STRING_FIELD_SET = new Set(TRIMMED_STRING_FIELDS);
|
|
66
|
+
function isTrimmedStringField(key) {
|
|
67
|
+
return TRIMMED_STRING_FIELD_SET.has(key);
|
|
67
68
|
}
|
|
68
69
|
const PREFERENCE_KEY_SET = new Set(PREFERENCE_KEYS);
|
|
69
70
|
function preferenceStorageKey(key) {
|
|
@@ -244,8 +245,8 @@ export async function loadConfigWithStorage(configPath, storage) {
|
|
|
244
245
|
reconcileAppSecret(config, storage);
|
|
245
246
|
// password: DB 优先映射到 runtime config,让 config:show 与 server.ts 都看到真值
|
|
246
247
|
applyStoragePassword(config, storage);
|
|
247
|
-
//
|
|
248
|
-
//
|
|
248
|
+
// 内置「系统运维」员工负责 commit message / 标题 / 提示词优化;招聘由 HR 负责。
|
|
249
|
+
// 这里只做幂等补齐——首次按用户已有的系统 AI 工具与默认
|
|
249
250
|
// provider 建首条候选,之后候选由用户在员工设置里维护,不再回写 config。
|
|
250
251
|
storage.ensureSystemSiliconEmployee({
|
|
251
252
|
cli: config.systemAiCli,
|
|
@@ -256,6 +257,7 @@ export async function loadConfigWithStorage(configPath, storage) {
|
|
|
256
257
|
storage.ensureDefaultSiliconEmployee(config.defaultProvider);
|
|
257
258
|
storage.ensureDecisionExpertEmployee();
|
|
258
259
|
storage.ensureSpeechPolisherEmployee();
|
|
260
|
+
storage.ensureHrEmployee(storage.getSystemSiliconEmployee()?.agents);
|
|
259
261
|
// 如果 JSON 里有偏好字段(说明是老版本配置或刚迁移),重写一次干净版本
|
|
260
262
|
const hasLegacyPrefs = PREFERENCE_KEYS.some((key) => key in rawInput);
|
|
261
263
|
const hasLegacySecrets = "password" in rawInput || "appSecret" in rawInput;
|
|
@@ -372,7 +374,7 @@ export function applyStoragePreferences(config, storage) {
|
|
|
372
374
|
if (typeof v === "string" && v.trim())
|
|
373
375
|
config.defaultCwd = v;
|
|
374
376
|
}
|
|
375
|
-
for (const field of
|
|
377
|
+
for (const field of TRIMMED_STRING_FIELDS) {
|
|
376
378
|
const dbKey = preferenceStorageKey(field);
|
|
377
379
|
if (!storage.hasPreference(dbKey))
|
|
378
380
|
continue;
|
|
@@ -388,31 +390,16 @@ export function applyStoragePreferences(config, storage) {
|
|
|
388
390
|
if (v === "claude" || v === "codex" || v === "opencode")
|
|
389
391
|
config.commitCli = v;
|
|
390
392
|
}
|
|
391
|
-
if (storage.hasPreference(preferenceStorageKey("commitModel"))) {
|
|
392
|
-
const v = storage.getPreference(preferenceStorageKey("commitModel"), defaults.commitModel ?? "");
|
|
393
|
-
if (typeof v === "string")
|
|
394
|
-
config.commitModel = v.trim();
|
|
395
|
-
}
|
|
396
393
|
if (storage.hasPreference(preferenceStorageKey("systemAiCli"))) {
|
|
397
394
|
const v = storage.getPreference(preferenceStorageKey("systemAiCli"), defaults.systemAiCli);
|
|
398
395
|
if (isSessionProvider(v))
|
|
399
396
|
config.systemAiCli = v;
|
|
400
397
|
}
|
|
401
|
-
if (storage.hasPreference(preferenceStorageKey("systemAiModel"))) {
|
|
402
|
-
const v = storage.getPreference(preferenceStorageKey("systemAiModel"), defaults.systemAiModel);
|
|
403
|
-
if (typeof v === "string")
|
|
404
|
-
config.systemAiModel = v.trim();
|
|
405
|
-
}
|
|
406
398
|
if (storage.hasPreference(preferenceStorageKey("defaultThinkingEffort"))) {
|
|
407
399
|
const v = storage.getPreference(preferenceStorageKey("defaultThinkingEffort"), defaults.defaultThinkingEffort ?? "off");
|
|
408
400
|
if (isThinkingEffort(v))
|
|
409
401
|
config.defaultThinkingEffort = v;
|
|
410
402
|
}
|
|
411
|
-
if (storage.hasPreference(preferenceStorageKey("language"))) {
|
|
412
|
-
const v = storage.getPreference(preferenceStorageKey("language"), defaults.language ?? "");
|
|
413
|
-
if (typeof v === "string")
|
|
414
|
-
config.language = v.trim();
|
|
415
|
-
}
|
|
416
403
|
if (storage.hasPreference(preferenceStorageKey("cardDefaults"))) {
|
|
417
404
|
const v = storage.getPreference(preferenceStorageKey("cardDefaults"), defaults.cardDefaults);
|
|
418
405
|
config.cardDefaults = normalizeCardDefaults(v);
|
|
@@ -440,9 +427,9 @@ export function applyStoragePreferences(config, storage) {
|
|
|
440
427
|
/** Write a single preference value to DB and (in-place) update the live config object. */
|
|
441
428
|
export function writePreferenceToStorage(config, storage, key, value) {
|
|
442
429
|
const dbKey = preferenceStorageKey(key);
|
|
443
|
-
//
|
|
444
|
-
//
|
|
445
|
-
if (
|
|
430
|
+
// Identical string policies share one typed field set for both read and write.
|
|
431
|
+
// Strict enums/booleans and legacy read tolerance deliberately remain distinct.
|
|
432
|
+
if (isTrimmedStringField(key)) {
|
|
446
433
|
const v = typeof value === "string" ? value.trim() : "";
|
|
447
434
|
storage.setPreference(dbKey, v);
|
|
448
435
|
config[key] = v;
|
|
@@ -509,12 +496,6 @@ export function writePreferenceToStorage(config, storage, key, value) {
|
|
|
509
496
|
config.commitCli = value;
|
|
510
497
|
break;
|
|
511
498
|
}
|
|
512
|
-
case "commitModel": {
|
|
513
|
-
const v = typeof value === "string" ? value.trim() : "";
|
|
514
|
-
storage.setPreference(dbKey, v);
|
|
515
|
-
config.commitModel = v;
|
|
516
|
-
break;
|
|
517
|
-
}
|
|
518
499
|
case "systemAiCli": {
|
|
519
500
|
if (!isSessionProvider(value))
|
|
520
501
|
throw new Error(`无效系统 AI CLI: ${String(value)}`);
|
|
@@ -522,12 +503,6 @@ export function writePreferenceToStorage(config, storage, key, value) {
|
|
|
522
503
|
config.systemAiCli = value;
|
|
523
504
|
break;
|
|
524
505
|
}
|
|
525
|
-
case "systemAiModel": {
|
|
526
|
-
const v = typeof value === "string" ? value.trim() : "";
|
|
527
|
-
storage.setPreference(dbKey, v);
|
|
528
|
-
config.systemAiModel = v;
|
|
529
|
-
break;
|
|
530
|
-
}
|
|
531
506
|
case "defaultThinkingEffort": {
|
|
532
507
|
if (!isThinkingEffort(value))
|
|
533
508
|
throw new Error(`无效思考深度: ${String(value)}`);
|
|
@@ -536,12 +511,6 @@ export function writePreferenceToStorage(config, storage, key, value) {
|
|
|
536
511
|
config.defaultThinkingEffort = v;
|
|
537
512
|
break;
|
|
538
513
|
}
|
|
539
|
-
case "language": {
|
|
540
|
-
const v = typeof value === "string" ? value.trim() : "";
|
|
541
|
-
storage.setPreference(dbKey, v);
|
|
542
|
-
config.language = v;
|
|
543
|
-
break;
|
|
544
|
-
}
|
|
545
514
|
case "cardDefaults": {
|
|
546
515
|
const normalized = normalizeCardDefaults(value);
|
|
547
516
|
storage.setPreference(dbKey, normalized);
|
|
@@ -20,6 +20,12 @@ interface ConversationDispatchInput {
|
|
|
20
20
|
memberVersion?: number;
|
|
21
21
|
continueTaskId?: string;
|
|
22
22
|
}
|
|
23
|
+
/** Internal execution context; HTTP conversation input does not expose this override. */
|
|
24
|
+
interface ConversationExecutionTarget {
|
|
25
|
+
workspaceId?: string;
|
|
26
|
+
title?: string;
|
|
27
|
+
scheduled?: true;
|
|
28
|
+
}
|
|
23
29
|
/** Business coordination only; all execution remains in StructuredSessionManager / AiTeamRunner. */
|
|
24
30
|
export declare class ConversationService {
|
|
25
31
|
private readonly deps;
|
|
@@ -49,7 +55,11 @@ export declare class ConversationService {
|
|
|
49
55
|
private selfName;
|
|
50
56
|
private memberReasons;
|
|
51
57
|
private turns;
|
|
52
|
-
|
|
58
|
+
/** Same ordering as turns(), so a source tail is enough when timestamps are append-only. */
|
|
59
|
+
private laterTurn;
|
|
60
|
+
private tailTurn;
|
|
61
|
+
private previewTurn;
|
|
62
|
+
summary(instance: ConversationInstance, knownTurns?: ConversationTurn[]): ConversationSummary;
|
|
53
63
|
list(): ConversationSummary[];
|
|
54
64
|
updateListState(id: string, patch: {
|
|
55
65
|
pinned?: boolean;
|
|
@@ -75,7 +85,7 @@ export declare class ConversationService {
|
|
|
75
85
|
/** Explicit resource action may prepare a channel; it never sends or starts a model. */
|
|
76
86
|
prepare(id: string, requestId: string, explicitCwd?: string): Promise<ConversationReceipt>;
|
|
77
87
|
private communicationChannel;
|
|
78
|
-
send(id: string, requestId: string, input: string, target: ConversationTarget, explicitCwd?: string, echo?: boolean): Promise<ConversationReceipt>;
|
|
88
|
+
send(id: string, requestId: string, input: string, target: ConversationTarget, explicitCwd?: string, echo?: boolean, executionTarget?: ConversationExecutionTarget): Promise<ConversationReceipt>;
|
|
79
89
|
/** One IM message is one fresh model context. No task, team, relay or previous DM history. */
|
|
80
90
|
private startMessageSession;
|
|
81
91
|
private requireTarget;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { statSync, rmSync, existsSync, realpathSync } from "node:fs";
|
|
3
|
-
import { resolve, sep } from "node:path";
|
|
3
|
+
import { isAbsolute, resolve, sep } from "node:path";
|
|
4
4
|
import { AI_TEAM_ACTIVE_RUN_STATUSES, AI_TEAM_DEFAULT_MAX_STEPS, AI_TEAM_MAX_MEMBERS, memberAgents } from "./ai-team-types.js";
|
|
5
5
|
import { freezeTeamEmployees, projectTeamEmployees, requireTeamEmployee } from "./ai-team-employee-binding.js";
|
|
6
6
|
import { AiTeamConflictError } from "./ai-team-runner.js";
|
|
7
7
|
import { CONVERSATION_OWNER, CONVERSATION_RELAY_PREFIX, employeeConversationId } from "./conversation-types.js";
|
|
8
8
|
import { conversationLeaderMention, conversationMessageBody } from "./conversation-mentions.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { compactTransportAvatar } from "./fixed-employee-avatar.js";
|
|
10
|
+
import { fallbackProviderModel } from "./session-model.js";
|
|
11
11
|
import { getErrorMessage } from "./error-utils.js";
|
|
12
12
|
import { resolveSessionCwd } from "./session-cwd.js";
|
|
13
|
-
import { resolveWorkspaceIdForNewSession } from "./workspace-binding.js";
|
|
13
|
+
import { isGlobalWorkspace, normalizeProjectCwd, resolveWorkspaceIdForNewSession } from "./workspace-binding.js";
|
|
14
14
|
import { CONVERSATION_SESSION_PREFIX, conversationSessionPreview } from "./conversation-session-preview.js";
|
|
15
15
|
import { conversationTaskLiveText } from "./conversation-task-preview.js";
|
|
16
16
|
import { selectEmployeeCandidate } from "./silicon-employee-dispatch.js";
|
|
@@ -162,7 +162,7 @@ export class ConversationService {
|
|
|
162
162
|
...(turn.role === "assistant" && !turn.author ? { author: {
|
|
163
163
|
id: channel?.employeeId ?? instance.team?.members.find((m) => m.isLeader)?.id ?? "leader",
|
|
164
164
|
name: channel?.employeeName ?? instance.team?.members.find((m) => m.isLeader)?.name ?? instance.name,
|
|
165
|
-
avatar: channel?.employeeAvatar, sessionId: id,
|
|
165
|
+
avatar: compactTransportAvatar(channel?.employeeAvatar), sessionId: id,
|
|
166
166
|
leader: instance.kind === "group" || undefined,
|
|
167
167
|
} } : {}),
|
|
168
168
|
}));
|
|
@@ -174,7 +174,62 @@ export class ConversationService {
|
|
|
174
174
|
return [...base, ...this.storage.conversationEvents(instance.id), ...communication].map(withSelf)
|
|
175
175
|
.sort((a, b) => (a.createdAt ?? "").localeCompare(b.createdAt ?? "") || (instance.kind === "dm" ? 0 : (a.role === "user" ? -1 : 0) - (b.role === "user" ? -1 : 0)));
|
|
176
176
|
}
|
|
177
|
-
|
|
177
|
+
/** Same ordering as turns(), so a source tail is enough when timestamps are append-only. */
|
|
178
|
+
laterTurn(instance, left, right) {
|
|
179
|
+
const time = (left.createdAt ?? "").localeCompare(right.createdAt ?? "");
|
|
180
|
+
if (time)
|
|
181
|
+
return time > 0 ? left : right;
|
|
182
|
+
if (instance.kind === "dm" || left.role === right.role)
|
|
183
|
+
return right;
|
|
184
|
+
return left.role === "user" ? right : left;
|
|
185
|
+
}
|
|
186
|
+
tailTurn(id, role) {
|
|
187
|
+
const live = this.deps.structured.get(id);
|
|
188
|
+
if (live) {
|
|
189
|
+
const messages = live.messages ?? [];
|
|
190
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
191
|
+
const turn = messages[index];
|
|
192
|
+
if (turn && (!role || turn.role === role))
|
|
193
|
+
return turn;
|
|
194
|
+
}
|
|
195
|
+
return undefined;
|
|
196
|
+
}
|
|
197
|
+
return this.storage.lastSessionTurn(id, role) ?? undefined;
|
|
198
|
+
}
|
|
199
|
+
previewTurn(instance) {
|
|
200
|
+
const candidates = [];
|
|
201
|
+
if (instance.kind !== "dm" && instance.sessionId) {
|
|
202
|
+
const relay = this.tailTurn(instance.sessionId);
|
|
203
|
+
if (relay)
|
|
204
|
+
candidates.push({ ...relay, messageId: relay.messageId ?? `${instance.sessionId}:0`, conversationId: instance.id });
|
|
205
|
+
}
|
|
206
|
+
const event = this.storage.lastConversationEvent(instance.id);
|
|
207
|
+
if (event)
|
|
208
|
+
candidates.push(event);
|
|
209
|
+
const channelIds = [...(instance.historySessionIds ?? []), instance.communicationSessionId]
|
|
210
|
+
.filter((id) => !!id && (instance.kind === "dm" || id !== instance.sessionId));
|
|
211
|
+
for (const id of new Set(channelIds)) {
|
|
212
|
+
const turn = this.tailTurn(id, "assistant");
|
|
213
|
+
if (!turn)
|
|
214
|
+
continue;
|
|
215
|
+
const channel = this.deps.structured.get(id) ?? this.storage.getSessionSlim(id);
|
|
216
|
+
candidates.push({
|
|
217
|
+
...turn,
|
|
218
|
+
messageId: turn.messageId ?? `${id}:preview`,
|
|
219
|
+
conversationId: instance.id,
|
|
220
|
+
conversationTarget: null,
|
|
221
|
+
...(turn.author ? {} : { author: {
|
|
222
|
+
id: channel?.employeeId ?? instance.team?.members.find((member) => member.isLeader)?.id ?? "leader",
|
|
223
|
+
name: channel?.employeeName ?? instance.team?.members.find((member) => member.isLeader)?.name ?? instance.name,
|
|
224
|
+
avatar: compactTransportAvatar(channel?.employeeAvatar),
|
|
225
|
+
sessionId: id,
|
|
226
|
+
leader: instance.kind === "group" || undefined,
|
|
227
|
+
} }),
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
return candidates.reduce((latest, turn) => latest ? this.laterTurn(instance, latest, turn) : turn, undefined);
|
|
231
|
+
}
|
|
232
|
+
summary(instance, knownTurns) {
|
|
178
233
|
const tasks = this.storage.conversationTasks(instance.id).flatMap((link) => {
|
|
179
234
|
const task = this.storage.getWandTask(link.taskId);
|
|
180
235
|
const receipt = task ? this.storage.conversationTaskStartup(task.id) : null;
|
|
@@ -193,16 +248,21 @@ export class ConversationService {
|
|
|
193
248
|
unavailableReason = getErrorMessage(error);
|
|
194
249
|
}
|
|
195
250
|
}
|
|
196
|
-
const
|
|
197
|
-
const last = messages.at(-1);
|
|
251
|
+
const last = knownTurns ? knownTurns.at(-1) : this.previewTurn(instance);
|
|
198
252
|
const lastText = last?.sessionLink ? conversationSessionPreview(this.snapshot(last.sessionLink.sessionId), last.requestId ? this.receipt(last.requestId) ?? undefined : undefined).text
|
|
199
253
|
: last?.content.map((b) => b.type === "text" ? b.text : "").join(" ") ?? "";
|
|
200
254
|
const messageAt = [instance.updatedAt, last?.createdAt ?? "", ...tasks.flatMap((t) => t.runs.map((r) => r.updatedAt))].sort().at(-1) ?? "";
|
|
201
255
|
const title = instance.kind === "dm" ? employee?.name ?? instance.name
|
|
202
256
|
: instance.nameSource === "custom" ? instance.name : tasks.at(-1)?.task.title ?? instance.name;
|
|
203
|
-
|
|
257
|
+
// 私聊标题已说明对方身份;只保留自己的署名,群聊仍需区分发言人。
|
|
258
|
+
const previewAuthor = last?.role === "user" ? `${this.selfName()}:`
|
|
259
|
+
: instance.kind === "group" && last ? `${last.author?.name ?? "系统"}:` : "";
|
|
260
|
+
const team = instance.team ? projectTeamEmployees(instance.team, this.storage) : null;
|
|
261
|
+
return { ...instance, ...lifecycle, team: team ? { ...team, members: team.members.map((member) => ({
|
|
262
|
+
...member, avatar: compactTransportAvatar(member.avatar) ?? "",
|
|
263
|
+
})) } : null,
|
|
204
264
|
title, unavailableReason, memberUnavailableReasons: this.memberReasons(instance), tasks,
|
|
205
|
-
preview: last ? `${
|
|
265
|
+
preview: last ? `${previewAuthor}${lastText.slice(0, 160)}`
|
|
206
266
|
: instance.kind === "group" ? "群已建立,尚未派任务" : "还没有消息", messageAt };
|
|
207
267
|
}
|
|
208
268
|
list() {
|
|
@@ -295,8 +355,9 @@ export class ConversationService {
|
|
|
295
355
|
history(id) { return this.turns(this.requireInstance(id)); }
|
|
296
356
|
detail(id) {
|
|
297
357
|
const instance = this.requireInstance(id);
|
|
298
|
-
const
|
|
299
|
-
|
|
358
|
+
const turns = this.turns(instance);
|
|
359
|
+
const summary = this.summary(instance, turns);
|
|
360
|
+
return { ...summary, messages: turns.map(turn => turn.sessionLink
|
|
300
361
|
? { ...turn, sessionPreview: conversationSessionPreview(this.snapshot(turn.sessionLink.sessionId), turn.requestId ? this.receipt(turn.requestId) ?? undefined : undefined),
|
|
301
362
|
// Older clients can still open the exact source session without understanding sessionLink.
|
|
302
363
|
author: turn.author ? { ...turn.author, sessionId: turn.sessionLink.sessionId } : turn.author,
|
|
@@ -514,9 +575,7 @@ export class ConversationService {
|
|
|
514
575
|
if (!session) {
|
|
515
576
|
if (instance.communicationSessionId)
|
|
516
577
|
instance.historySessionIds = [...(instance.historySessionIds ?? []), instance.communicationSessionId];
|
|
517
|
-
const model = agent.model === "default"
|
|
518
|
-
? defaultModelGroupSelector(this.deps.config.modelGroups, agent.provider, getDefaultModelForProvider(this.deps.config, agent.provider))
|
|
519
|
-
|| getDefaultModelForProvider(this.deps.config, agent.provider) || undefined : agent.model;
|
|
578
|
+
const model = agent.model === "default" ? fallbackProviderModel(this.deps.config, agent.provider) : agent.model;
|
|
520
579
|
session = this.deps.structured.createSession({ cwd, provider: agent.provider, mode: agent.mode, model,
|
|
521
580
|
thinkingEffort: agent.thinkingEffort, worktreeEnabled: false, sessionSource: "interactive",
|
|
522
581
|
automationId: `conversation-talk:${instance.id}`, employeeId: employee?.id,
|
|
@@ -533,10 +592,31 @@ export class ConversationService {
|
|
|
533
592
|
this.storage.saveConversation(instance);
|
|
534
593
|
return session;
|
|
535
594
|
}
|
|
536
|
-
send(id, requestId, input, target, explicitCwd, echo = true) {
|
|
537
|
-
return this.request(requestId, "send", { input, target, explicitCwd, echo
|
|
595
|
+
send(id, requestId, input, target, explicitCwd, echo = true, executionTarget) {
|
|
596
|
+
return this.request(requestId, "send", { input, target, explicitCwd, echo,
|
|
597
|
+
...(executionTarget?.workspaceId ? { workspaceId: executionTarget.workspaceId } : {}),
|
|
598
|
+
...(executionTarget?.title !== undefined ? { title: executionTarget.title } : {}),
|
|
599
|
+
...(executionTarget?.scheduled ? { scheduled: true } : {}) }, id, async (receipt, commit) => {
|
|
538
600
|
const text = shortText(input, "消息", 256_000, true);
|
|
539
601
|
const instance = this.requireInstance(id);
|
|
602
|
+
let workspaceId;
|
|
603
|
+
if (executionTarget) {
|
|
604
|
+
if (instance.kind !== "dm" || target)
|
|
605
|
+
throw new Error("指定工作项目仅用于员工执行。");
|
|
606
|
+
}
|
|
607
|
+
if (executionTarget?.workspaceId !== undefined) {
|
|
608
|
+
workspaceId = shortText(executionTarget.workspaceId, "执行项目", 160, true);
|
|
609
|
+
const workspace = this.storage.getWorkspace(workspaceId);
|
|
610
|
+
if (!workspace || isGlobalWorkspace(workspace))
|
|
611
|
+
throw new Error("执行项目不存在或不可用,请重新选择项目。");
|
|
612
|
+
if (!explicitCwd?.trim() || !workspace.cwd.trim() || !isAbsolute(workspace.cwd.trim())) {
|
|
613
|
+
throw new Error("指定工作项目需要有效的绝对执行目录。");
|
|
614
|
+
}
|
|
615
|
+
const cwd = this.cwd(explicitCwd);
|
|
616
|
+
const workspaceCwd = resolveSessionCwd(workspace.cwd, undefined);
|
|
617
|
+
if (normalizeProjectCwd(cwd) !== normalizeProjectCwd(workspaceCwd))
|
|
618
|
+
throw new Error("执行项目目录已变更,请核对执行位置。");
|
|
619
|
+
}
|
|
540
620
|
if (target) {
|
|
541
621
|
const run = this.requireTarget(instance, target);
|
|
542
622
|
if (!AI_TEAM_ACTIVE_RUN_STATUSES.includes(run.status))
|
|
@@ -555,7 +635,7 @@ export class ConversationService {
|
|
|
555
635
|
return;
|
|
556
636
|
}
|
|
557
637
|
if (instance.kind === "dm") {
|
|
558
|
-
this.startMessageSession(instance, requestId, text, explicitCwd, receipt, commit);
|
|
638
|
+
this.startMessageSession(instance, requestId, text, explicitCwd, receipt, commit, executionTarget ? { ...executionTarget, workspaceId } : undefined);
|
|
559
639
|
return;
|
|
560
640
|
}
|
|
561
641
|
if (instance.kind === "group" && instance.team) {
|
|
@@ -599,21 +679,20 @@ export class ConversationService {
|
|
|
599
679
|
});
|
|
600
680
|
}
|
|
601
681
|
/** One IM message is one fresh model context. No task, team, relay or previous DM history. */
|
|
602
|
-
startMessageSession(instance, requestId, input, explicitCwd, receipt, commit) {
|
|
682
|
+
startMessageSession(instance, requestId, input, explicitCwd, receipt, commit, executionTarget) {
|
|
603
683
|
requireTeamEmployee(this.storage, instance.peerEmployeeId ?? "");
|
|
604
684
|
const employee = this.storage.getSiliconEmployee(instance.peerEmployeeId);
|
|
605
685
|
const selected = selectEmployeeCandidate(employee), agent = selected.agent;
|
|
606
686
|
const cwd = this.cwd(explicitCwd);
|
|
607
|
-
const model = agent.model === "default"
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
const title = provisionalTaskTitleFromDescription(conversationMessageBody(input)) || "新会话";
|
|
687
|
+
const model = agent.model === "default" ? fallbackProviderModel(this.deps.config, agent.provider) : agent.model;
|
|
688
|
+
const title = shortText(executionTarget?.title, "会话标题", 200)
|
|
689
|
+
|| provisionalTaskTitleFromDescription(conversationMessageBody(input)) || "新会话";
|
|
611
690
|
let session;
|
|
612
691
|
try {
|
|
613
692
|
this.storage.acceptConversationSession(instance, () => {
|
|
614
693
|
session = this.deps.structured.createSession({ title, cwd, provider: agent.provider, mode: agent.mode, model,
|
|
615
|
-
thinkingEffort: agent.thinkingEffort, worktreeEnabled: false, sessionSource: "interactive",
|
|
616
|
-
workspaceId: resolveWorkspaceIdForNewSession(this.storage, cwd),
|
|
694
|
+
thinkingEffort: agent.thinkingEffort, worktreeEnabled: false, sessionSource: executionTarget?.scheduled ? "automation" : "interactive",
|
|
695
|
+
workspaceId: resolveWorkspaceIdForNewSession(this.storage, cwd, executionTarget?.workspaceId),
|
|
617
696
|
automationId: `${CONVERSATION_SESSION_PREFIX}${requestId}`, employeeId: employee.id,
|
|
618
697
|
employeeName: employee.name, employeeAvatar: employee.avatar, employeeCandidates: employee.agents,
|
|
619
698
|
employeeCandidateIndex: selected.index, systemPrompt: employee.prompt });
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ConversationSessionPreview, SessionSnapshot } from "./types.js";
|
|
2
2
|
export declare const CONVERSATION_SESSION_PREFIX = "conversation-message:";
|
|
3
|
+
/** Scheduled occurrences already have a plan title. Identify them from durable metadata, never prompt text. */
|
|
4
|
+
export declare function isScheduledConversationSession(session: Pick<SessionSnapshot, "sessionSource" | "automationId">): boolean;
|
|
3
5
|
export declare const CONVERSATION_PREVIEW_LIMIT = 4000;
|
|
4
6
|
export declare const conversationSessionPreviewLabels: Record<ConversationSessionPreview["status"], string>;
|
|
5
7
|
/** The session owns the transcript. IM only reads a bounded tail; never copies it into message history. */
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
export const CONVERSATION_SESSION_PREFIX = "conversation-message:";
|
|
2
|
+
/** Scheduled occurrences already have a plan title. Identify them from durable metadata, never prompt text. */
|
|
3
|
+
export function isScheduledConversationSession(session) {
|
|
4
|
+
return session.sessionSource === "automation" && session.automationId?.startsWith(`${CONVERSATION_SESSION_PREFIX}scheduled:`) === true;
|
|
5
|
+
}
|
|
2
6
|
export const CONVERSATION_PREVIEW_LIMIT = 4000;
|
|
3
7
|
export const conversationSessionPreviewLabels = {
|
|
4
8
|
starting: "正在启动", running: "正在回复", waiting_user: "等待你确认", done: "已完成",
|
package/dist/decision-client.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import { request as httpRequest } from "node:http";
|
|
3
3
|
import { request as httpsRequest } from "node:https";
|
|
4
|
-
import { DECISION_MAX_BYTES, DecisionError, parseDecisionRequest, parseDecisionResult } from "./decision-types.js";
|
|
4
|
+
import { DECISION_CHAIN_WAIT_MS, DECISION_MAX_BYTES, DecisionError, parseDecisionRequest, parseDecisionResult } from "./decision-types.js";
|
|
5
5
|
/** No admin/password lookup, redirects, or implicit remote fallback. Credentials stay in headers. */
|
|
6
6
|
export async function callDecisionService(request, env = process.env) {
|
|
7
7
|
const endpoint = env.WAND_DECISION_URL;
|
|
@@ -49,15 +49,31 @@ export async function callDecisionService(request, env = process.env) {
|
|
|
49
49
|
const code = typeof value?.code === "string" && /^[A-Z_]{1,40}$/.test(value.code) ? value.code : "HTTP_ERROR";
|
|
50
50
|
reject(new DecisionError(code, `决策调用失败 (${code}, HTTP ${res.statusCode})。`, res.statusCode));
|
|
51
51
|
}
|
|
52
|
-
else
|
|
53
|
-
resolve(
|
|
52
|
+
else if (!request)
|
|
53
|
+
resolve(value);
|
|
54
|
+
else {
|
|
55
|
+
// A configured backup is a text evaluator, not LAYA (and can have output tokens).
|
|
56
|
+
if (typeof value?.model !== "string" || !value.model || value.model.length > 512
|
|
57
|
+
|| !["laya-mlx", "decision-expert"].includes(value.runtime))
|
|
58
|
+
throw new Error("identity");
|
|
59
|
+
const result = parseDecisionResult(value, request, { model: value.model, runtime: value.runtime });
|
|
60
|
+
if (value.executor !== undefined) {
|
|
61
|
+
const executor = value.executor;
|
|
62
|
+
if (!executor || typeof executor.employeeId !== "string" || executor.employeeId.length > 128
|
|
63
|
+
|| !Number.isSafeInteger(executor.candidate) || executor.candidate < 0 || executor.candidate > 3
|
|
64
|
+
|| !["local", "free-group", "cli", "sdk"].includes(executor.source))
|
|
65
|
+
throw new Error("executor");
|
|
66
|
+
result.executor = { employeeId: executor.employeeId, candidate: executor.candidate, source: executor.source };
|
|
67
|
+
}
|
|
68
|
+
resolve(result);
|
|
69
|
+
}
|
|
54
70
|
}
|
|
55
|
-
catch {
|
|
56
|
-
reject(new DecisionError("INVALID_RESULT", "决策服务返回了无效结果。", 502));
|
|
71
|
+
catch (error) {
|
|
72
|
+
reject(error instanceof DecisionError ? error : new DecisionError("INVALID_RESULT", "决策服务返回了无效结果。", 502));
|
|
57
73
|
}
|
|
58
74
|
});
|
|
59
75
|
});
|
|
60
|
-
const deadline = setTimeout(() => req.destroy(new Error("deadline")), 50_000);
|
|
76
|
+
const deadline = setTimeout(() => req.destroy(new Error("deadline")), request ? DECISION_CHAIN_WAIT_MS : 50_000);
|
|
61
77
|
req.once("close", () => clearTimeout(deadline));
|
|
62
78
|
req.once("error", () => reject(new DecisionError("CONNECTION_FAILED", "连接决策服务失败或超时。", 502)));
|
|
63
79
|
req.end(data);
|
|
@@ -3,11 +3,11 @@ import { DECISION_EXPERT_ID, DECISION_EXPERT_KEY, DECISION_EXPERT_NAME, WAND_LOC
|
|
|
3
3
|
import { OPENROUTER_FREE_SELECTOR } from "./openrouter-free-selection.js";
|
|
4
4
|
export const DECISION_EXPERT_DUTY = "Wand 决策专家:根据最少必要证据做有界选择、评分与是非判断;按已配置工具与模型顺序调用;本地决策先核对本机能力。";
|
|
5
5
|
export const DECISION_EXPERT_PROMPT = [
|
|
6
|
-
|
|
6
|
+
`你是 Wand 内置系统员工「${DECISION_EXPERT_NAME}」,担任决策专家。你的职责是基于用户提供的证据,做有界候选选择、评分与是非判断。`,
|
|
7
7
|
"按员工调用链的配置顺序调用工具与模型;初始候选为 LAYA 和 Wand 免费分组。LAYA 不生成开放式文本,不伪装成聊天模型。",
|
|
8
8
|
"先核对机器的 CPU、内存、Apple Silicon / Metal 和运行时健康。性能/平台不足时明确说明原因,建议配置你的调用链,不能捏造可以运行。",
|
|
9
9
|
"只使用输入中已授权的最少证据,不读取别人的知识/私聊。概率不是正确性保证,更不是权限、删除、发布或付款批准。",
|
|
10
|
-
"
|
|
10
|
+
"严格输出任务要求的格式;不编造选项、解释、执行结果或事实。任一决策候选失败时按已配置顺序尝试后续候选,直到成功、全部失败或用户取消;这仅适用于无工具判断,不重放实际任务或操作。",
|
|
11
11
|
"免费分组在每次请求前重新核对价格;免费候选不可用时依调用链处理,不把免费选择器替换成付费模型。",
|
|
12
12
|
].join("\n");
|
|
13
13
|
export function decisionExpertSeedAgents() {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Pure identity shared by server and clients; LAYA is a bounded decision source, never a chat model. */
|
|
2
2
|
export declare const DECISION_EXPERT_KEY = "wand-decision-expert";
|
|
3
3
|
export declare const DECISION_EXPERT_ID = "e_wand_decision_expert";
|
|
4
|
-
export declare const DECISION_EXPERT_NAME = "\
|
|
4
|
+
export declare const DECISION_EXPERT_NAME = "\u77F3\u4E00";
|
|
5
5
|
export declare const WAND_LOCAL_DECISION_MODEL = "wand-decision/laya";
|
|
6
6
|
export declare const WAND_LOCAL_DECISION_LABEL = "Wand \u672C\u5730\u51B3\u7B56\u6A21\u578B \u00B7 LAYA";
|
|
7
7
|
export declare function isLocalDecisionModel(value: string | null | undefined): boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Pure identity shared by server and clients; LAYA is a bounded decision source, never a chat model. */
|
|
2
2
|
export const DECISION_EXPERT_KEY = "wand-decision-expert";
|
|
3
3
|
export const DECISION_EXPERT_ID = "e_wand_decision_expert";
|
|
4
|
-
export const DECISION_EXPERT_NAME = "
|
|
4
|
+
export const DECISION_EXPERT_NAME = "石一";
|
|
5
5
|
export const WAND_LOCAL_DECISION_MODEL = "wand-decision/laya";
|
|
6
6
|
export const WAND_LOCAL_DECISION_LABEL = "Wand 本地决策模型 · LAYA";
|
|
7
7
|
export function isLocalDecisionModel(value) { return value === WAND_LOCAL_DECISION_MODEL; }
|
|
@@ -11,6 +11,7 @@ interface DecisionExpertDeps {
|
|
|
11
11
|
free: Pick<OpenRouterFreeModelsService, "status" | "resolveForCall">;
|
|
12
12
|
config: WandConfig;
|
|
13
13
|
hardware?: () => DecisionHardwareAssessment;
|
|
14
|
+
/** Budget per saved slot; expanded group members share it, not later slots. */
|
|
14
15
|
timeoutMs?: number;
|
|
15
16
|
/** A prepared adapter has accepted no input yet. Tests never call real models. */
|
|
16
17
|
prepare?: (agent: WandTaskAgent, request: AiTextRequest, signal: AbortSignal) => Promise<() => Promise<string>>;
|