evolcore 0.0.28 → 0.0.29
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/CHANGELOG.md +12 -0
- package/bin/ec-safe-output.js +270 -54
- package/dist/agents/baseagent-availability.js +37 -1
- package/dist/agents/baseagent.js +19 -9
- package/dist/agents/claude-runner.js +171 -13
- package/dist/agents/codex/app-server-client.js +6 -2
- package/dist/agents/codex/diagnostics.js +4 -3
- package/dist/agents/codex-runner.js +396 -95
- package/dist/agents/gemini-runner.js +35 -17
- package/dist/aun/group/history.js +130 -90
- package/dist/aun/group/operations.js +1 -3
- package/dist/aun/menu/transport.js +5 -3
- package/dist/aun/msg/managed-operation.js +70 -0
- package/dist/aun/msg/p2p.js +1 -3
- package/dist/aun/msg/upload.js +2 -2
- package/dist/aun/outbox.js +1 -37
- package/dist/channels/aun.js +249 -89
- package/dist/channels/daemon.js +18 -1
- package/dist/channels/feishu.js +1 -2
- package/dist/cli/agent-command.js +23 -3
- package/dist/cli/agent-create.js +68 -2
- package/dist/cli/agent.js +12 -2
- package/dist/cli/aun-commands.js +87 -13
- package/dist/cli/cli-argv.js +26 -0
- package/dist/cli/daemon-commands.js +40 -10
- package/dist/cli/data-command.js +4 -4
- package/dist/cli/handoff-command.js +2 -0
- package/dist/cli/index.js +18 -1
- package/dist/cli/managed-command-guard.js +10 -0
- package/dist/cli/memory-command.js +441 -0
- package/dist/cli/restart-monitor.js +62 -6
- package/dist/cli/skill-command.js +41 -0
- package/dist/cli/task-context.js +2 -23
- package/dist/cli/trigger-command.js +9 -1
- package/dist/cli/watch-msg-diag.js +209 -0
- package/dist/config/config-field-policy.js +52 -3
- package/dist/config/config-manager.js +17 -4
- package/dist/config/contact-book-store.js +2 -2
- package/dist/config/mention-mode.js +7 -2
- package/dist/config/merge.js +28 -9
- package/dist/config/resolved-config-op.js +1 -1
- package/dist/config/runtime-env.js +137 -0
- package/dist/config/schema-registry.js +11 -1
- package/dist/config-store.js +10 -10
- package/dist/core/audit/event-key.js +3 -1
- package/dist/core/audit/log-integrity.js +4 -0
- package/dist/core/auth/agent-delegation.js +2 -1
- package/dist/core/auth/auth-gateway.js +13 -6
- package/dist/core/auth/authorization-audit.js +54 -19
- package/dist/core/auth/operation-authorizer.js +17 -0
- package/dist/core/auth/operation-catalog.js +9 -0
- package/dist/core/causation/context.js +5 -1
- package/dist/core/command/agent-control.js +1 -2
- package/dist/core/command/command-handler.js +51 -23
- package/dist/core/command/memory-slash.js +270 -0
- package/dist/core/command/menu-catalog.js +1 -0
- package/dist/core/command/menu-handler.js +315 -60
- package/dist/core/command/menu-protocol.js +42 -4
- package/dist/core/command/slash-gate.js +10 -10
- package/dist/core/command/slash-handler.js +206 -64
- package/dist/core/data-migration.js +282 -505
- package/dist/core/event-catalog.js +26 -0
- package/dist/core/evolagent-registry.js +6 -0
- package/dist/core/evolagent.js +0 -10
- package/dist/core/handoff/store.js +1 -20
- package/dist/core/inference/text-inference.js +57 -1
- package/dist/core/memory/consolidation-context.js +505 -0
- package/dist/core/memory/consolidation-ops-records.js +124 -0
- package/dist/core/memory/consolidation-trigger.js +394 -0
- package/dist/core/memory/index-manager.js +308 -0
- package/dist/core/memory/launch-consolidation.js +395 -0
- package/dist/core/memory/memory-admin.js +234 -0
- package/dist/core/memory/memory-document.js +100 -0
- package/dist/core/memory/memory-session-policy.js +41 -0
- package/dist/core/memory/memory-signature.js +257 -0
- package/dist/core/memory/memory-writer.js +432 -0
- package/dist/core/memory/staleness.js +117 -0
- package/dist/core/message/auto-mention-gate.js +454 -0
- package/dist/core/message/im-renderer.js +69 -16
- package/dist/core/message/message-bridge.js +287 -21
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/message-queue.js +114 -27
- package/dist/core/message/pending-hints.js +329 -161
- package/dist/core/message/response-engine.js +567 -80
- package/dist/core/permission/ec-command-parser.js +1029 -80
- package/dist/core/permission/protected-paths.js +376 -126
- package/dist/core/permission/sandbox-runtime.js +40 -12
- package/dist/core/permission/tool-error-code.js +96 -13
- package/dist/core/permission/tool-policy.js +276 -23
- package/dist/core/role/runtime-policy.js +3 -7
- package/dist/core/session/{runner-task-history.js → runner-event-summary.js} +1 -1
- package/dist/core/session/session-fs-store.js +0 -76
- package/dist/core/session/session-idle-monitor.js +355 -0
- package/dist/core/session/session-manager.js +478 -17
- package/dist/core/session/session-mapper.js +33 -16
- package/dist/core/session/session-renew.js +217 -155
- package/dist/core/session/{session-turns.js → session-transcript.js} +35 -6
- package/dist/core/skill/global-watcher.js +282 -0
- package/dist/core/skill/index-generator.js +84 -0
- package/dist/core/skill/startup.js +73 -0
- package/dist/core/skill/switch-resolver.js +115 -0
- package/dist/core/task/task-activity-store.js +219 -0
- package/dist/eck/kit-renderer.js +30 -3
- package/dist/eck/manifest-engine.js +26 -4
- package/dist/index.js +708 -18
- package/dist/ipc.js +564 -2
- package/dist/paths.js +30 -9
- package/dist/response-system/engines/v1/proactive-flow.js +116 -15
- package/dist/response-system/modes/single-session/index.js +3 -0
- package/dist/trigger/feedback.js +1 -0
- package/dist/trigger/manager.js +0 -10
- package/dist/trigger/scheduler.js +11 -0
- package/dist/trigger/validation.js +22 -0
- package/dist/utils/avatar-upload.js +59 -18
- package/dist/utils/error-dict.json +6 -3
- package/dist/utils/error-utils.js +27 -0
- package/dist/utils/logger.js +32 -10
- package/dist/utils/media-cache.js +84 -0
- package/dist/utils/msg-diag.js +97 -0
- package/dist/utils/welcome.js +37 -8
- package/kits/docs/AUTHORING.md +314 -0
- package/kits/docs/GUIDE.md +2 -0
- package/kits/docs/INDEX.md +2 -0
- package/kits/docs/aun/CHEATSHEET.md +4 -0
- package/kits/docs/aun/SDK.md +60 -0
- package/kits/docs/context-assembly.md +10 -6
- package/kits/docs/evolcore/INDEX.md +17 -3
- package/kits/docs/evolcore/agent-create.md +24 -0
- package/kits/docs/evolcore/agent.md +5 -2
- package/kits/docs/evolcore/config.md +1 -1
- package/kits/docs/evolcore/ec-capabilities.md +364 -0
- package/kits/docs/evolcore/group.md +34 -18
- package/kits/docs/evolcore/memory-architecture.md +78 -0
- package/kits/docs/evolcore/memory-consolidation-batches.md +133 -0
- package/kits/docs/evolcore/memory-consolidation.md +263 -0
- package/kits/docs/evolcore/memory-tags.md +63 -0
- package/kits/docs/evolcore/memory.md +110 -0
- package/kits/docs/evolcore/menu-client.md +27 -11
- package/kits/{schemas → docs/evolcore}/menu-exec-schema-commands.md +12 -6
- package/kits/docs/evolcore/menu-protocol.md +213 -0
- package/kits/docs/evolcore/msg.md +2 -0
- package/kits/docs/evolcore/trigger.md +7 -5
- package/kits/docs/path-registry.md +6 -8
- package/kits/docs/prompt-loading-architecture.md +5 -3
- package/kits/docs/venues/group.md +5 -4
- package/kits/eck_manifest.json +294 -88
- package/kits/eck_manifest.memory.json +257 -0
- package/kits/rules/03-identity.md +8 -8
- package/kits/rules/05-venue.md +4 -2
- package/kits/rules/06-channel.md +1 -1
- package/kits/schemas/_meta.json +276 -47
- package/kits/schemas/agent-config.schema.12.json +38 -2
- package/kits/schemas/agent-config.schema.13.json +591 -0
- package/kits/schemas/daemon.schema.6.json +9 -9
- package/kits/schemas/defaults.schema.5.json +29 -0
- package/kits/schemas/relation-config.schema.8.json +14 -1
- package/kits/schemas/relation-config.schema.9.json +129 -0
- package/kits/schemas/role-config.schema.1.json +3 -3
- package/kits/skills/.switches.json +3 -0
- package/kits/skills/ec-skill/SKILL.md +217 -0
- package/kits/skills/ec-skill/scripts/cli.mjs +128 -0
- package/kits/skills/ec-skill/scripts/deps.mjs +107 -0
- package/kits/skills/ec-skill/scripts/frontmatter.mjs +104 -0
- package/kits/skills/ec-skill/scripts/skill.mjs +629 -0
- package/kits/skills/ec-skill/scripts/template/SKILL.md.tmpl +30 -0
- package/kits/templates/decision/auto-mention.md +25 -0
- package/kits/templates/decision/session-renew.md +22 -0
- package/kits/templates/memory-consolidation/forget.md +104 -0
- package/kits/templates/memory-consolidation/generalize.md +76 -0
- package/kits/templates/memory-consolidation/notes.md +133 -0
- package/kits/templates/memory-consolidation/profile.md +58 -0
- package/kits/templates/memory-consolidation/promote.md +72 -0
- package/kits/templates/memory-consolidation/workflow.md +75 -0
- package/kits/templates/system-fragments/bootstrap.md +14 -5
- package/kits/templates/system-fragments/commands.md +1 -0
- package/kits/templates/system-fragments/group-history.md +6 -0
- package/kits/templates/system-fragments/identity.md +0 -3
- package/kits/templates/system-fragments/memory.md +79 -0
- package/kits/templates/system-fragments/reply.md +1 -0
- package/kits/templates/system-fragments/venue.md +1 -1
- package/package.json +4 -6
- package/dist/trigger/legacy-session-history.js +0 -19
- package/kits/templates/system-fragments/group-unread-history.md +0 -7
package/dist/paths.js
CHANGED
|
@@ -26,11 +26,11 @@ export function resolvePaths() {
|
|
|
26
26
|
const agentsDir = path.join(root, 'agents');
|
|
27
27
|
return {
|
|
28
28
|
root,
|
|
29
|
-
// Session storage is partitioned by owning Agent.
|
|
30
|
-
// location separately so the explicit data migration can inventory it.
|
|
29
|
+
// Session storage is partitioned by owning Agent.
|
|
31
30
|
sessionsDir: agentsDir,
|
|
32
|
-
legacySessionsDir: path.join(root, 'data', 'sessions'),
|
|
33
31
|
instanceDir: path.join(root, 'data', 'instance'),
|
|
32
|
+
// Historical outbox root. Runtime writes use agentOutboxPath() below;
|
|
33
|
+
// this directory is retained only for explicit data migration.
|
|
34
34
|
outboxDir: path.join(root, 'data', 'outbox'),
|
|
35
35
|
dataDir: path.join(root, 'data'),
|
|
36
36
|
claudeModelCache: path.join(root, 'data', 'claude-model-cache.json'),
|
|
@@ -89,7 +89,13 @@ export function agentContactConfig(aid) {
|
|
|
89
89
|
return path.join(agentDir(aid), 'contact.json');
|
|
90
90
|
}
|
|
91
91
|
export function agentContactOperations(aid) {
|
|
92
|
-
return path.join(
|
|
92
|
+
return path.join(agentDataDir(aid), 'contact', 'operations.jsonl');
|
|
93
|
+
}
|
|
94
|
+
export function agentContactDataDir(aid) {
|
|
95
|
+
return path.join(agentDataDir(aid), 'contact');
|
|
96
|
+
}
|
|
97
|
+
export function agentContactAuditPath(aid) {
|
|
98
|
+
return path.join(agentContactDataDir(aid), 'audit.jsonl');
|
|
93
99
|
}
|
|
94
100
|
export function agentPersonalDir(aid) {
|
|
95
101
|
return path.join(agentDir(aid), 'personal');
|
|
@@ -132,28 +138,44 @@ export function agentSessionsDir(aid) {
|
|
|
132
138
|
export function agentDataDir(aid) {
|
|
133
139
|
return path.join(agentDir(aid), 'data');
|
|
134
140
|
}
|
|
141
|
+
export function agentTaskActivityDir(aid) {
|
|
142
|
+
return path.join(agentDataDir(aid), 'task-activity');
|
|
143
|
+
}
|
|
135
144
|
export function agentDataCacheDir(aid) {
|
|
136
145
|
return path.join(agentDataDir(aid), 'cache');
|
|
137
146
|
}
|
|
138
147
|
export function agentHandoffDir(aid) {
|
|
139
148
|
return path.join(agentDataDir(aid), 'handoff');
|
|
140
149
|
}
|
|
150
|
+
export function agentCodexTokensDir(aid) {
|
|
151
|
+
return path.join(agentDataDir(aid), 'codex-tokens');
|
|
152
|
+
}
|
|
153
|
+
export function agentCodexTokenPath(aid, threadId) {
|
|
154
|
+
return path.join(agentCodexTokensDir(aid), `${encodeURIComponent(threadId)}.json`);
|
|
155
|
+
}
|
|
141
156
|
export function agentGroupInviteReviewsPath(aid) {
|
|
142
157
|
return path.join(agentDataDir(aid), 'aun', 'group-invite-reviews.json');
|
|
143
158
|
}
|
|
144
159
|
export function agentOutboxPath(aid) {
|
|
145
|
-
return path.join(
|
|
160
|
+
return path.join(agentDataDir(aid), 'outbox', 'delivery.jsonl');
|
|
146
161
|
}
|
|
147
162
|
export function agentActivityOutboxPath(aid) {
|
|
148
|
-
return path.join(
|
|
163
|
+
return path.join(agentDataDir(aid), 'outbox', 'activity.jsonl');
|
|
149
164
|
}
|
|
150
|
-
/**
|
|
165
|
+
/** Historical per-Agent outbox paths used only by the explicit migration. */
|
|
151
166
|
export function legacyAgentOutboxPath(aid) {
|
|
152
167
|
return path.join(agentDataDir(aid), 'outbox.jsonl');
|
|
153
168
|
}
|
|
154
169
|
export function legacyAgentActivityOutboxPath(aid) {
|
|
155
170
|
return path.join(agentDataDir(aid), 'activity-outbox.jsonl');
|
|
156
171
|
}
|
|
172
|
+
/** Historical shared per-Agent outbox directory layout. */
|
|
173
|
+
export function legacySharedOutboxPath(aid) {
|
|
174
|
+
return path.join(resolvePaths().outboxDir, encodeURIComponent(aid), 'outbox.jsonl');
|
|
175
|
+
}
|
|
176
|
+
export function legacySharedActivityOutboxPath(aid) {
|
|
177
|
+
return path.join(resolvePaths().outboxDir, encodeURIComponent(aid), 'activity-outbox.jsonl');
|
|
178
|
+
}
|
|
157
179
|
/** Earliest global outbox layout: data/outbox/<aid>.jsonl. */
|
|
158
180
|
export function legacyFlatOutboxPath(aid) {
|
|
159
181
|
return path.join(resolvePaths().outboxDir, `${aid}.jsonl`);
|
|
@@ -261,7 +283,7 @@ export function getWindowsInstanceSocketPathCandidates(root) {
|
|
|
261
283
|
}
|
|
262
284
|
return candidates;
|
|
263
285
|
}
|
|
264
|
-
function resolveInstanceSocketPath(root) {
|
|
286
|
+
export function resolveInstanceSocketPath(root) {
|
|
265
287
|
if (isWindows)
|
|
266
288
|
return getWindowsInstanceSocketPathCandidates(root)[0];
|
|
267
289
|
const filesystemPath = path.join(root, 'data', 'instance', INSTANCE_SOCKET_FILENAME);
|
|
@@ -291,7 +313,6 @@ export function ensureDataDirs() {
|
|
|
291
313
|
fs.mkdirSync(p.agentsDir, { recursive: true });
|
|
292
314
|
fs.mkdirSync(p.sessionsDir, { recursive: true });
|
|
293
315
|
fs.mkdirSync(p.instanceDir, { recursive: true });
|
|
294
|
-
fs.mkdirSync(p.outboxDir, { recursive: true });
|
|
295
316
|
fs.mkdirSync(p.eckDir, { recursive: true });
|
|
296
317
|
fs.mkdirSync(aidsDir(), { recursive: true });
|
|
297
318
|
migrateLegacyAgentJsonlLogs(p.agentsDir, p.logs);
|
|
@@ -9,7 +9,10 @@
|
|
|
9
9
|
* 依赖全部由调用点显式传入。
|
|
10
10
|
*/
|
|
11
11
|
const STATE_KEY = 'proactive';
|
|
12
|
-
const
|
|
12
|
+
const SNAPSHOT_KEY = 'proactive:continuation';
|
|
13
|
+
const OWNER_KEY = 'proactive:owner';
|
|
14
|
+
const SNAPSHOT_MAX_AGE_MS = 30 * 60 * 1_000;
|
|
15
|
+
const TOOL_REPORT_INTERVAL = 20;
|
|
13
16
|
const SEND_RECEIPT_RE = /["']?(?:message[_ -]?id|handoff[_ -]?id)["']?\s*[:=]\s*["']?([A-Za-z0-9][A-Za-z0-9._:-]*)/gi;
|
|
14
17
|
const HANDOFF_TEXT_RECEIPT_RE = /\bhandoff\s+(h-[A-Za-z0-9._-]+)/i;
|
|
15
18
|
const RETURN_CONTENT_RE = /["']?(?:return[_ -]?content|returnContent)["']?\s*[:=]\s*["']?([^}\n,]*)/i;
|
|
@@ -161,6 +164,79 @@ function buildState(message, cfg) {
|
|
|
161
164
|
toolReportPending: false,
|
|
162
165
|
};
|
|
163
166
|
}
|
|
167
|
+
function normalizedThread(threadId) {
|
|
168
|
+
return threadId && threadId !== 'main' ? threadId : '';
|
|
169
|
+
}
|
|
170
|
+
function isResumableTerminal(terminal) {
|
|
171
|
+
return terminal?.status === 'interrupted' && terminal.reason === 'daemon_restart'
|
|
172
|
+
|| terminal?.status === 'cancelled' && (terminal.reason === 'stop' || terminal.reason === 'explicit_cancel');
|
|
173
|
+
}
|
|
174
|
+
function canRestoreSnapshot(ctx, state, snapshot) {
|
|
175
|
+
const previous = ctx.previousTurnState;
|
|
176
|
+
const terminal = previous?.lastTerminal;
|
|
177
|
+
const continuation = ctx.continuation;
|
|
178
|
+
if (!continuation || !previous || previous.active || !isResumableTerminal(terminal))
|
|
179
|
+
return false;
|
|
180
|
+
if (!snapshot.agentSessionId || !snapshot.baseagent)
|
|
181
|
+
return false;
|
|
182
|
+
const age = Date.now() - snapshot.finishedAt;
|
|
183
|
+
if (!Number.isFinite(age) || age < 0 || age > SNAPSHOT_MAX_AGE_MS
|
|
184
|
+
|| !Number.isSafeInteger(snapshot.toolCount) || snapshot.toolCount < 0
|
|
185
|
+
|| typeof snapshot.firstToolDone !== 'boolean' || typeof snapshot.toolReportPending !== 'boolean'
|
|
186
|
+
|| snapshot.sessionId !== ctx.session.id || snapshot.selfAid !== ctx.session.selfAID
|
|
187
|
+
|| snapshot.channel !== ctx.session.channel || snapshot.channelId !== ctx.session.channelId
|
|
188
|
+
|| snapshot.chatType !== ctx.message.chatType || snapshot.chatType !== ctx.session.chatType
|
|
189
|
+
|| snapshot.threadId !== normalizedThread(ctx.session.threadId)
|
|
190
|
+
|| snapshot.threadId !== normalizedThread(continuation.threadId)
|
|
191
|
+
|| snapshot.baseagent !== ctx.session.baseagent || snapshot.agentSessionId !== ctx.session.agentSessionId
|
|
192
|
+
|| snapshot.firstSendRequired !== state.firstSendRequired
|
|
193
|
+
|| snapshot.toolReportRequired !== state.toolReportRequired
|
|
194
|
+
|| snapshot.toolReportInterval !== state.toolReportInterval
|
|
195
|
+
|| snapshot.turnId !== terminal.turnId || snapshot.taskId !== terminal.taskId
|
|
196
|
+
|| snapshot.generation !== terminal.generation || snapshot.finishedAt !== terminal.finishedAt)
|
|
197
|
+
return false;
|
|
198
|
+
if (state.chatType === 'group' && continuation.groupId !== snapshot.channelId)
|
|
199
|
+
return false;
|
|
200
|
+
if (continuation.kind === 'taskRecovery') {
|
|
201
|
+
return continuation.taskId === snapshot.taskId && continuation.generation === previous.generation;
|
|
202
|
+
}
|
|
203
|
+
return continuation.kind === 'restartResume'
|
|
204
|
+
&& terminal.status === 'interrupted' && terminal.reason === 'daemon_restart';
|
|
205
|
+
}
|
|
206
|
+
function saveContinuation(ctx) {
|
|
207
|
+
const state = ctx.state.get(STATE_KEY);
|
|
208
|
+
if (!state || !ctx.sessionState || ctx.sessionState.get(OWNER_KEY) !== state)
|
|
209
|
+
return;
|
|
210
|
+
ctx.sessionState.delete(OWNER_KEY);
|
|
211
|
+
const terminal = ctx.terminal;
|
|
212
|
+
if (!terminal || terminal.turnId !== ctx.turn.turnId || terminal.taskId !== ctx.turn.taskId
|
|
213
|
+
|| terminal.generation !== ctx.turn.generation)
|
|
214
|
+
return;
|
|
215
|
+
ctx.sessionState.delete(SNAPSHOT_KEY);
|
|
216
|
+
if (!isResumableTerminal(terminal))
|
|
217
|
+
return;
|
|
218
|
+
const snapshot = {
|
|
219
|
+
sessionId: ctx.session.id,
|
|
220
|
+
selfAid: ctx.session.selfAID,
|
|
221
|
+
channel: ctx.session.channel,
|
|
222
|
+
channelId: ctx.session.channelId,
|
|
223
|
+
chatType: state.chatType,
|
|
224
|
+
threadId: normalizedThread(ctx.session.threadId),
|
|
225
|
+
baseagent: ctx.session.baseagent,
|
|
226
|
+
agentSessionId: ctx.session.agentSessionId,
|
|
227
|
+
turnId: terminal.turnId,
|
|
228
|
+
taskId: terminal.taskId,
|
|
229
|
+
generation: terminal.generation,
|
|
230
|
+
finishedAt: terminal.finishedAt,
|
|
231
|
+
firstToolDone: state.firstToolDone,
|
|
232
|
+
toolCount: state.toolCount,
|
|
233
|
+
toolReportPending: state.toolReportPending,
|
|
234
|
+
firstSendRequired: state.firstSendRequired,
|
|
235
|
+
toolReportRequired: state.toolReportRequired,
|
|
236
|
+
toolReportInterval: state.toolReportInterval,
|
|
237
|
+
};
|
|
238
|
+
ctx.sessionState.set(SNAPSHOT_KEY, snapshot);
|
|
239
|
+
}
|
|
164
240
|
export const proactiveFlow = {
|
|
165
241
|
chatMode: 'proactive',
|
|
166
242
|
// ─── 入站决策:构造 runtimeState ───
|
|
@@ -187,7 +263,15 @@ export const proactiveFlow = {
|
|
|
187
263
|
// ─── beforeProcess:把 runtimeState 落入 ctx.state,供后续钩子共享 ───
|
|
188
264
|
beforeProcess(ctx) {
|
|
189
265
|
const state = buildState(ctx.message, ctx.modeConfig ?? {});
|
|
266
|
+
const snapshot = ctx.sessionState?.get(SNAPSHOT_KEY);
|
|
267
|
+
ctx.sessionState?.delete(SNAPSHOT_KEY);
|
|
268
|
+
if (snapshot && canRestoreSnapshot(ctx, state, snapshot)) {
|
|
269
|
+
state.firstToolDone = snapshot.firstToolDone;
|
|
270
|
+
state.toolCount = snapshot.toolCount;
|
|
271
|
+
state.toolReportPending = state.toolReportRequired && snapshot.toolReportPending;
|
|
272
|
+
}
|
|
190
273
|
ctx.state.set(STATE_KEY, state);
|
|
274
|
+
ctx.sessionState?.set(OWNER_KEY, state);
|
|
191
275
|
},
|
|
192
276
|
// ─── configureRun:policyHook 只判定,不推进状态 ───
|
|
193
277
|
configureRun(ctx) {
|
|
@@ -240,29 +324,43 @@ export const proactiveFlow = {
|
|
|
240
324
|
const isAllowedTool = ctx.isSendCommand(ctx.toolName, ctx.toolInput);
|
|
241
325
|
if (!state.toolUseReminder)
|
|
242
326
|
return;
|
|
243
|
-
// 队列未读变化提醒
|
|
244
|
-
const queueLen = ctx.getQueueLength();
|
|
245
|
-
if (queueLen !== state.lastQueueReminderLen) {
|
|
246
|
-
state.lastQueueReminderLen = queueLen;
|
|
247
|
-
if (queueLen > 0) {
|
|
248
|
-
const queueMsg = queueLen >= 5
|
|
249
|
-
? `⚠️ 有 ${queueLen} 条消息未读,请尽快完成当前任务,或使用 ec ctl queue 读取后同步处理。`
|
|
250
|
-
: `⚠️ 有 ${queueLen} 条消息未读,可使用 ec ctl queue 读取。`;
|
|
251
|
-
ctx.recordReminder?.({ kind: 'queue_unread', text: queueMsg, queueLength: queueLen });
|
|
252
|
-
ctx.injectToModel(queueMsg);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
327
|
// 工具计数(排除表态命令白名单)
|
|
256
328
|
if (state.toolReportRequired && !isAllowedTool)
|
|
257
329
|
state.toolCount++;
|
|
330
|
+
// 队列未读变化提醒:首次达到 3 条立即提醒,后续复用工具汇报的计数间隔,
|
|
331
|
+
// 避免连续工具调用时每次队列数量变化都重复注入。
|
|
332
|
+
const queueLen = ctx.getQueueLength();
|
|
333
|
+
const queueChanged = queueLen !== state.lastQueueReminderLen;
|
|
334
|
+
const toolReportDue = state.toolReportRequired
|
|
335
|
+
&& !isAllowedTool
|
|
336
|
+
&& state.toolCount > 0
|
|
337
|
+
&& state.toolCount % state.toolReportInterval === 0;
|
|
338
|
+
let queueReminder;
|
|
339
|
+
const queueReminderDue = state.lastQueueReminderLen === 0
|
|
340
|
+
? queueLen >= 3
|
|
341
|
+
: toolReportDue;
|
|
342
|
+
if (queueLen === 0) {
|
|
343
|
+
state.lastQueueReminderLen = 0;
|
|
344
|
+
}
|
|
345
|
+
else if (queueChanged && queueReminderDue) {
|
|
346
|
+
state.lastQueueReminderLen = queueLen;
|
|
347
|
+
queueReminder = queueLen >= 5
|
|
348
|
+
? `⚠️ 有 ${queueLen} 条消息未读,请尽快完成当前任务,或使用 ec ctl queue 读取后同步处理。`
|
|
349
|
+
: `⚠️ 有 ${queueLen} 条消息未读,可使用 ec ctl queue 读取。`;
|
|
350
|
+
ctx.recordReminder?.({ kind: 'queue_unread', text: queueReminder, queueLength: queueLen });
|
|
351
|
+
}
|
|
352
|
+
if (queueReminder && !toolReportDue) {
|
|
353
|
+
ctx.injectToModel(queueReminder);
|
|
354
|
+
}
|
|
258
355
|
// 每 N 次工具调用警告
|
|
259
|
-
|
|
356
|
+
// 只有计数推进到新阈值时才提醒;发送工具不能重新打开已解除的汇报门禁。
|
|
357
|
+
if (toolReportDue) {
|
|
260
358
|
state.toolReportPending = true;
|
|
261
359
|
const cmdHint = state.chatType === 'group' ? 'ec group send' : 'ec msg send';
|
|
262
360
|
const target = state.chatType === 'group' ? '群里' : '对方';
|
|
263
361
|
const reportMsg = `⚠️ 工具调用已达到 ${state.toolCount} 次,请立即用 ${cmdHint} 向${target}汇报当前情况和下一步意图。`;
|
|
264
362
|
ctx.recordReminder?.({ kind: 'tool_report', text: reportMsg, toolCount: state.toolCount });
|
|
265
|
-
ctx.injectToModel(reportMsg);
|
|
363
|
+
ctx.injectToModel(queueReminder ? `${queueReminder}\n${reportMsg}` : reportMsg);
|
|
266
364
|
}
|
|
267
365
|
},
|
|
268
366
|
// ─── onToolResult:成功发送回执后解除门禁 ───
|
|
@@ -291,6 +389,9 @@ export const proactiveFlow = {
|
|
|
291
389
|
await ctx.updateSessionMeta({ lastProactiveFlag: true });
|
|
292
390
|
}
|
|
293
391
|
},
|
|
392
|
+
onTurnEnd(ctx) {
|
|
393
|
+
saveContinuation(ctx);
|
|
394
|
+
},
|
|
294
395
|
// ─── afterProcess:Unknown skill 兜底 ───
|
|
295
396
|
async afterProcess(ctx) {
|
|
296
397
|
if (!ctx.streamResult.hasReceivedText && /^Unknown skill:\s+\S+/i.test(ctx.fullText.trim())) {
|
package/dist/trigger/feedback.js
CHANGED
|
@@ -274,6 +274,7 @@ export class TriggerFeedbackDispatcher {
|
|
|
274
274
|
?? (input.trigger.origin?.channelKey ? channelTypeFromKey(input.trigger.origin.channelKey) : undefined),
|
|
275
275
|
...(eventSession ? { originChatType: messageChatType, originConversationId: target.channelId } : {}),
|
|
276
276
|
originControl: !eventSession && input.trigger.origin?.channelKey === 'daemon',
|
|
277
|
+
noopSentinel: input.trigger.execution.noopSentinel,
|
|
277
278
|
authorizedBy: input.trigger.authorizedBy,
|
|
278
279
|
},
|
|
279
280
|
};
|
package/dist/trigger/manager.js
CHANGED
|
@@ -4,7 +4,6 @@ import { agentTriggersDir } from '../paths.js';
|
|
|
4
4
|
import { assertExplicitAunDeliveryRoutes, definitionRevision, normalizeTriggerDefinition, resolveScriptPath, safeRelativePath, } from './validation.js';
|
|
5
5
|
import { atomicWriteJson } from '../core/session/session-fs-store.js';
|
|
6
6
|
import { TriggerHistoryStore } from './history.js';
|
|
7
|
-
import { rewriteLegacyTriggerSessionPaths } from './legacy-session-history.js';
|
|
8
7
|
export class TriggerDefinitionManager {
|
|
9
8
|
agentAid;
|
|
10
9
|
rootDir;
|
|
@@ -42,15 +41,6 @@ export class TriggerDefinitionManager {
|
|
|
42
41
|
this.writeDefinition(definition);
|
|
43
42
|
this.history.recordDefinition('trigger.updated', definition, { reason: 'legacy-aun-target-chat-type' });
|
|
44
43
|
}
|
|
45
|
-
if (typeof definition.execution.prompt === 'string') {
|
|
46
|
-
const rewritten = rewriteLegacyTriggerSessionPaths(definition.execution.prompt, definition.agentAid);
|
|
47
|
-
if (rewritten !== definition.execution.prompt) {
|
|
48
|
-
definition.execution = { ...definition.execution, prompt: rewritten };
|
|
49
|
-
definition.updatedAt = Date.now();
|
|
50
|
-
this.writeDefinition(definition);
|
|
51
|
-
this.history.recordDefinition('trigger.updated', definition, { reason: 'legacy-session-history-paths' });
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
44
|
return definition;
|
|
55
45
|
}
|
|
56
46
|
require(triggerId) {
|
|
@@ -193,6 +193,17 @@ export class TriggerRuntimeScheduler {
|
|
|
193
193
|
history(triggerId, limit = 100) {
|
|
194
194
|
return this.manager.history.events(triggerId, limit);
|
|
195
195
|
}
|
|
196
|
+
recentRuns(triggerId, limit = 50) {
|
|
197
|
+
return this.audit.recent(triggerId, limit).map(run => ({
|
|
198
|
+
runId: run.runId,
|
|
199
|
+
status: run.status,
|
|
200
|
+
...(run.reason ? { reason: run.reason } : {}),
|
|
201
|
+
startedAt: run.startedAt,
|
|
202
|
+
finishedAt: run.finishedAt,
|
|
203
|
+
durationMs: Math.max(0, run.finishedAt - run.startedAt),
|
|
204
|
+
...(run.error?.code ? { errorCode: run.error.code } : {}),
|
|
205
|
+
}));
|
|
206
|
+
}
|
|
196
207
|
scriptPreview(definition) {
|
|
197
208
|
if (definition.execution.type !== 'script' || !definition.execution.script)
|
|
198
209
|
return undefined;
|
|
@@ -452,12 +452,34 @@ function normalizeExecution(value, _opts) {
|
|
|
452
452
|
permissionMode: normalizeTriggerPermissionMode(raw.permissionMode),
|
|
453
453
|
onError: normalizeOnError(raw.onError),
|
|
454
454
|
noopSentinel: optionalString(raw.noopSentinel) ?? DEFAULT_NOOP_SENTINEL,
|
|
455
|
+
memoryMode: normalizeMemoryMode(raw.memoryMode),
|
|
456
|
+
memoryScope: normalizeMemoryScope(raw.memoryScope),
|
|
457
|
+
consolidationBatchDir: optionalString(raw.consolidationBatchDir ?? raw.consolidationLogBase),
|
|
458
|
+
consolidationChatDir: optionalString(raw.consolidationChatDir),
|
|
459
|
+
consolidationMemoryDir: optionalString(raw.consolidationMemoryDir),
|
|
455
460
|
};
|
|
456
461
|
if (execution.type === 'script' && execution.permissionMode === 'fullaccess') {
|
|
457
462
|
throw new Error('script Trigger already executes as the daemon OS user and cannot declare execution.permissionMode=fullaccess');
|
|
458
463
|
}
|
|
459
464
|
return execution;
|
|
460
465
|
}
|
|
466
|
+
const MEMORY_MODES = ['notes', 'generalize', 'promote', 'profile', 'forget'];
|
|
467
|
+
function normalizeMemoryMode(value) {
|
|
468
|
+
if (value === undefined)
|
|
469
|
+
return undefined;
|
|
470
|
+
if (typeof value !== 'string' || !MEMORY_MODES.includes(value)) {
|
|
471
|
+
throw new Error(`execution.memoryMode must be one of ${MEMORY_MODES.join(', ')}`);
|
|
472
|
+
}
|
|
473
|
+
return value;
|
|
474
|
+
}
|
|
475
|
+
function normalizeMemoryScope(value) {
|
|
476
|
+
if (value === undefined)
|
|
477
|
+
return undefined;
|
|
478
|
+
if (value !== 'relation' && value !== 'agent' && value !== 'owner') {
|
|
479
|
+
throw new Error('execution.memoryScope must be relation, agent, or owner');
|
|
480
|
+
}
|
|
481
|
+
return value;
|
|
482
|
+
}
|
|
461
483
|
function normalizeExecutionBaseagent(value) {
|
|
462
484
|
if (value === undefined)
|
|
463
485
|
return undefined;
|
|
@@ -5,8 +5,10 @@ import net from 'net';
|
|
|
5
5
|
import { agentmdGet, agentmdPut, updateAgentMdFrontmatterAvatar } from '../aun/aid/agentmd.js';
|
|
6
6
|
import { storageRm, storageUpload } from '../aun/storage/index.js';
|
|
7
7
|
import { logger } from './logger.js';
|
|
8
|
+
import sharp from 'sharp';
|
|
8
9
|
import { validateImage } from './media-cache.js';
|
|
9
10
|
const MAX_AVATAR_BYTES = 500 * 1024;
|
|
11
|
+
export const MAX_AVATAR_SOURCE_BYTES = 10 * 1024 * 1024;
|
|
10
12
|
const MIN_AVATAR_DIMENSION = 128;
|
|
11
13
|
const MAX_AVATAR_DIMENSION = 2048;
|
|
12
14
|
const MIN_AVATAR_RATIO = 0.8;
|
|
@@ -20,6 +22,29 @@ const MIME_EXT = {
|
|
|
20
22
|
'image/jpeg': 'jpg',
|
|
21
23
|
'image/webp': 'webp',
|
|
22
24
|
};
|
|
25
|
+
export async function normalizeAvatarImage(buffer) {
|
|
26
|
+
if (buffer.length > MAX_AVATAR_SOURCE_BYTES)
|
|
27
|
+
throw new Error('头像源文件超过 10 MiB 限制');
|
|
28
|
+
const input = sharp(buffer, { failOn: 'error', limitInputPixels: 80_000_000, animated: false });
|
|
29
|
+
const metadata = await input.metadata();
|
|
30
|
+
const sourceMimeType = metadata.format === 'jpeg' ? 'image/jpeg' : `image/${metadata.format ?? ''}`;
|
|
31
|
+
if (!['image/jpeg', 'image/png', 'image/webp'].includes(sourceMimeType)) {
|
|
32
|
+
throw new Error(`头像格式不支持:${sourceMimeType || 'unknown'};请提供 PNG、JPEG 或 WebP 图片`);
|
|
33
|
+
}
|
|
34
|
+
if (!metadata.width || !metadata.height)
|
|
35
|
+
throw new Error('无法读取头像尺寸');
|
|
36
|
+
const sizes = [512, 384, 256, 192, 128];
|
|
37
|
+
const qualities = [82, 74, 66, 58, 50];
|
|
38
|
+
for (let i = 0; i < sizes.length; i++) {
|
|
39
|
+
const output = await sharp(buffer, { failOn: 'error', limitInputPixels: 80_000_000, animated: false })
|
|
40
|
+
.rotate().resize(sizes[i], sizes[i], { fit: 'contain', background: '#ffffff' })
|
|
41
|
+
.jpeg({ mozjpeg: true, quality: qualities[i] }).toBuffer();
|
|
42
|
+
if (output.length <= MAX_AVATAR_BYTES) {
|
|
43
|
+
return { buffer: output, mimeType: 'image/jpeg', width: sizes[i], height: sizes[i], sourceWidth: metadata.width, sourceHeight: metadata.height };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
throw new Error('图片经过缩放和压缩后仍超过头像 500 KiB 上限');
|
|
47
|
+
}
|
|
23
48
|
function fail(error, code) {
|
|
24
49
|
return { ok: false, error, code };
|
|
25
50
|
}
|
|
@@ -50,12 +75,12 @@ function parseAvatarDataUrl(dataUrl) {
|
|
|
50
75
|
return fail('avatar base64 编码无效', 'INVALID_ARGS');
|
|
51
76
|
}
|
|
52
77
|
const estimatedSize = estimateDecodedBytes(base64);
|
|
53
|
-
if (estimatedSize >
|
|
54
|
-
return fail(
|
|
78
|
+
if (estimatedSize > MAX_AVATAR_SOURCE_BYTES) {
|
|
79
|
+
return fail(`头像源文件超过 ${formatKb(MAX_AVATAR_SOURCE_BYTES)} 限制(当前: ${formatKb(estimatedSize)})`, 'INVALID_ARGS');
|
|
55
80
|
}
|
|
56
81
|
const buffer = Buffer.from(base64, 'base64');
|
|
57
|
-
if (buffer.length >
|
|
58
|
-
return fail(
|
|
82
|
+
if (buffer.length > MAX_AVATAR_SOURCE_BYTES) {
|
|
83
|
+
return fail(`头像源文件超过 ${formatKb(MAX_AVATAR_SOURCE_BYTES)} 限制(当前: ${formatKb(buffer.length)})`, 'INVALID_ARGS');
|
|
59
84
|
}
|
|
60
85
|
return { mime: declaredMime, buffer };
|
|
61
86
|
}
|
|
@@ -71,13 +96,16 @@ export async function uploadAvatar(aid, dataUrl, opts) {
|
|
|
71
96
|
const parsed = parseAvatarDataUrl(dataUrl);
|
|
72
97
|
if ('ok' in parsed)
|
|
73
98
|
return parsed;
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
99
|
+
const detected = await validateImage(parsed.buffer, {
|
|
100
|
+
maxSize: MAX_AVATAR_SOURCE_BYTES,
|
|
101
|
+
allowedMimes: ALLOWED_AVATAR_MIMES,
|
|
102
|
+
});
|
|
103
|
+
if (detected.mime === null)
|
|
104
|
+
return fail(`头像格式验证失败:${detected.reason}`, 'INVALID_ARGS');
|
|
105
|
+
if (detected.mime !== parsed.mime) {
|
|
106
|
+
return fail(`头像格式验证失败:声明 ${parsed.mime},实际 ${detected.mime}`, 'INVALID_ARGS');
|
|
79
107
|
}
|
|
80
|
-
return
|
|
108
|
+
return uploadAvatarBuffer(aid, parsed.buffer, opts);
|
|
81
109
|
}
|
|
82
110
|
function parseJpegDimensions(buffer) {
|
|
83
111
|
let offset = 2;
|
|
@@ -258,9 +286,9 @@ async function downloadAvatarBuffer(sourceUrl) {
|
|
|
258
286
|
return fail(`头像 URL 返回 HTTP ${response.status}`, 'UPLOAD_FAILED');
|
|
259
287
|
}
|
|
260
288
|
const length = Number(response.headers.get('content-length') || 0);
|
|
261
|
-
if (length >
|
|
289
|
+
if (length > MAX_AVATAR_SOURCE_BYTES) {
|
|
262
290
|
clearTimeout(timeout);
|
|
263
|
-
return fail('
|
|
291
|
+
return fail('头像源文件超过 10 MiB 限制', 'INVALID_ARGS');
|
|
264
292
|
}
|
|
265
293
|
if (!response.body) {
|
|
266
294
|
clearTimeout(timeout);
|
|
@@ -276,9 +304,9 @@ async function downloadAvatarBuffer(sourceUrl) {
|
|
|
276
304
|
break;
|
|
277
305
|
const chunk = Buffer.from(part.value);
|
|
278
306
|
total += chunk.length;
|
|
279
|
-
if (total >
|
|
307
|
+
if (total > MAX_AVATAR_SOURCE_BYTES) {
|
|
280
308
|
await reader.cancel();
|
|
281
|
-
return fail('
|
|
309
|
+
return fail('头像源文件超过 10 MiB 限制', 'INVALID_ARGS');
|
|
282
310
|
}
|
|
283
311
|
chunks.push(chunk);
|
|
284
312
|
}
|
|
@@ -344,7 +372,7 @@ async function uploadValidatedAvatar(aid, buffer, mime, dimensions, opts) {
|
|
|
344
372
|
}
|
|
345
373
|
async function validateAvatarBuffer(buffer) {
|
|
346
374
|
const validated = await validateImage(buffer, {
|
|
347
|
-
maxSize:
|
|
375
|
+
maxSize: MAX_AVATAR_SOURCE_BYTES,
|
|
348
376
|
allowedMimes: ALLOWED_AVATAR_MIMES,
|
|
349
377
|
});
|
|
350
378
|
if (validated.mime === null)
|
|
@@ -367,9 +395,22 @@ export async function uploadAvatarFile(aid, filePath, opts) {
|
|
|
367
395
|
/** Upload already-read image bytes; callers can use this after secure fd validation. */
|
|
368
396
|
export async function uploadAvatarBuffer(aid, buffer, opts) {
|
|
369
397
|
const validated = await validateAvatarBuffer(buffer);
|
|
370
|
-
if (
|
|
371
|
-
return validated;
|
|
372
|
-
|
|
398
|
+
if ('dimensions' in validated && buffer.length <= MAX_AVATAR_BYTES) {
|
|
399
|
+
return uploadValidatedAvatar(aid, buffer, validated.mime, validated.dimensions, opts);
|
|
400
|
+
}
|
|
401
|
+
try {
|
|
402
|
+
const normalized = await normalizeAvatarImage(buffer);
|
|
403
|
+
const uploaded = await uploadValidatedAvatar(aid, normalized.buffer, normalized.mimeType, { width: normalized.width, height: normalized.height }, opts);
|
|
404
|
+
return uploaded.ok ? {
|
|
405
|
+
...uploaded,
|
|
406
|
+
normalized: true,
|
|
407
|
+
sourceWidth: normalized.sourceWidth,
|
|
408
|
+
sourceHeight: normalized.sourceHeight,
|
|
409
|
+
} : uploaded;
|
|
410
|
+
}
|
|
411
|
+
catch (error) {
|
|
412
|
+
return fail(`${'error' in validated && validated.error ? validated.error : '头像不符合规范'};自动规范化失败: ${messageOf(error)}`, 'INVALID_ARGS');
|
|
413
|
+
}
|
|
373
414
|
}
|
|
374
415
|
/** Download an HTTPS image with redirect/SSRF/size guards, then upload it. */
|
|
375
416
|
export async function uploadAvatarUrl(aid, url, opts) {
|
|
@@ -109,19 +109,22 @@
|
|
|
109
109
|
"id": "api-error-502",
|
|
110
110
|
"match": "api error: 502",
|
|
111
111
|
"action": "retry",
|
|
112
|
-
"type": "api_error"
|
|
112
|
+
"type": "api_error",
|
|
113
|
+
"message": "❌ API 网关异常,请稍后重试"
|
|
113
114
|
},
|
|
114
115
|
{
|
|
115
116
|
"id": "api-error-503",
|
|
116
117
|
"match": "api error: 503",
|
|
117
118
|
"action": "retry",
|
|
118
|
-
"type": "api_error"
|
|
119
|
+
"type": "api_error",
|
|
120
|
+
"message": "❌ API 服务暂时不可用,请稍后重试"
|
|
119
121
|
},
|
|
120
122
|
{
|
|
121
123
|
"id": "api-error-504",
|
|
122
124
|
"match": "api error: 504",
|
|
123
125
|
"action": "retry",
|
|
124
|
-
"type": "api_error"
|
|
126
|
+
"type": "api_error",
|
|
127
|
+
"message": "❌ API 请求超时,请稍后重试"
|
|
125
128
|
},
|
|
126
129
|
{
|
|
127
130
|
"id": "not-valid-json",
|
|
@@ -25,6 +25,7 @@ export function isExecutionFailure(error) {
|
|
|
25
25
|
return error instanceof ExecutionTimeoutError || error instanceof OrphanedTargetSessionError;
|
|
26
26
|
}
|
|
27
27
|
export const CLAUDE_STARTUP_ARGUMENTS_TOO_LONG = 'claude_startup_arguments_too_long';
|
|
28
|
+
export const CLAUDE_CODE_STARTUP_FAILED = 'claude_code_startup_failed';
|
|
28
29
|
/** A completed provider response exhausted its output budget, rather than a transport failure. */
|
|
29
30
|
export function isOutputTokenLimitError(error) {
|
|
30
31
|
const record = error && typeof error === 'object' ? error : undefined;
|
|
@@ -58,6 +59,22 @@ export function createClaudeStartupArgumentsTooLongError(error) {
|
|
|
58
59
|
wrapped.cause = error;
|
|
59
60
|
return wrapped;
|
|
60
61
|
}
|
|
62
|
+
export function isClaudeCodeStartupProcessError(error) {
|
|
63
|
+
const record = error && typeof error === 'object' ? error : undefined;
|
|
64
|
+
const code = String(record?.code ?? '').toLowerCase();
|
|
65
|
+
const message = String(record?.message ?? error ?? '').toLowerCase();
|
|
66
|
+
return code === 'eftype'
|
|
67
|
+
|| message.includes('spawn eftype')
|
|
68
|
+
|| message.includes('not a valid application for this os platform');
|
|
69
|
+
}
|
|
70
|
+
export function createClaudeCodeStartupError(error) {
|
|
71
|
+
const wrapped = new Error(`${CLAUDE_CODE_STARTUP_FAILED}: Claude Code SDK 本地运行时启动失败,任务未执行`);
|
|
72
|
+
wrapped.name = 'ClaudeCodeStartupError';
|
|
73
|
+
wrapped.code = CLAUDE_CODE_STARTUP_FAILED;
|
|
74
|
+
if (error !== undefined)
|
|
75
|
+
wrapped.cause = error;
|
|
76
|
+
return wrapped;
|
|
77
|
+
}
|
|
61
78
|
export var ErrorType;
|
|
62
79
|
(function (ErrorType) {
|
|
63
80
|
ErrorType["SDK_TIMEOUT"] = "sdk_timeout";
|
|
@@ -71,6 +88,7 @@ export var ErrorType;
|
|
|
71
88
|
ErrorType["SESSION_UNAVAILABLE"] = "session_unavailable";
|
|
72
89
|
ErrorType["SANDBOX_INITIALIZATION_FAILED"] = "sandbox_initialization_failed";
|
|
73
90
|
ErrorType["CLAUDE_STARTUP_ARGUMENTS_TOO_LONG"] = "claude_startup_arguments_too_long";
|
|
91
|
+
ErrorType["CLAUDE_CODE_STARTUP_FAILED"] = "claude_code_startup_failed";
|
|
74
92
|
ErrorType["UNKNOWN"] = "unknown";
|
|
75
93
|
})(ErrorType || (ErrorType = {}));
|
|
76
94
|
/**
|
|
@@ -329,6 +347,9 @@ export function classifyError(error) {
|
|
|
329
347
|
if (isClaudeStartupArgumentsTooLong(error)) {
|
|
330
348
|
return ErrorType.CLAUDE_STARTUP_ARGUMENTS_TOO_LONG;
|
|
331
349
|
}
|
|
350
|
+
if (error?.code === CLAUDE_CODE_STARTUP_FAILED) {
|
|
351
|
+
return ErrorType.CLAUDE_CODE_STARTUP_FAILED;
|
|
352
|
+
}
|
|
332
353
|
// 字典优先 — 命中则直接返回
|
|
333
354
|
const rule = matchErrorRule(msg);
|
|
334
355
|
if (rule) {
|
|
@@ -410,6 +431,10 @@ export function getErrorMessage(error, terminalReason, includeEmoji = true) {
|
|
|
410
431
|
const prefix = includeEmoji ? '⚠️ ' : '';
|
|
411
432
|
return `${prefix}当前 Claude 启动参数过长,任务未执行`;
|
|
412
433
|
}
|
|
434
|
+
if (error?.code === CLAUDE_CODE_STARTUP_FAILED) {
|
|
435
|
+
const prefix = includeEmoji ? '❌ ' : '';
|
|
436
|
+
return `${prefix}Claude Code SDK 本地运行时启动失败(${CLAUDE_CODE_STARTUP_FAILED}),当前任务未执行。请重新安装并对齐 Claude Code SDK 与 Windows 原生组件版本,然后重启 EvolCore 后重试`;
|
|
437
|
+
}
|
|
413
438
|
// terminalReason 提供更精确的错误提示(SDK 0.2.100+)
|
|
414
439
|
if (terminalReason) {
|
|
415
440
|
const prefix = includeEmoji ? '❌ ' : '';
|
|
@@ -433,6 +458,8 @@ export function getErrorMessage(error, terminalReason, includeEmoji = true) {
|
|
|
433
458
|
return `${warnPrefix}执行沙箱启动失败(sandbox_initialization_failed),当前操作未执行;请检查文件系统挂载规则及 user namespace/seccomp 配置`;
|
|
434
459
|
case 'claude_startup_arguments_too_long':
|
|
435
460
|
return `${warnPrefix}当前 Claude 启动参数过长,任务未执行`;
|
|
461
|
+
case 'claude_code_startup_failed':
|
|
462
|
+
return `${prefix}Claude Code SDK 本地运行时启动失败(${CLAUDE_CODE_STARTUP_FAILED}),当前任务未执行。请重新安装并对齐 Claude Code SDK 与 Windows 原生组件版本,然后重启 EvolCore 后重试`;
|
|
436
463
|
case 'aborted_streaming':
|
|
437
464
|
case 'aborted_tools':
|
|
438
465
|
return `${prefix}任务已中断`;
|