evolcore 0.0.4 → 0.0.6
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 +65 -3
- package/README.md +4 -12
- package/dist/agents/baseagent.js +39 -0
- package/dist/agents/claude-runner.js +10 -2
- package/dist/agents/codex-runner.js +37 -8
- package/dist/agents/ecagent-runner.js +1159 -0
- package/dist/agents/gemini-runner.js +4 -1
- package/dist/agents/runner-types.js +20 -4
- package/dist/aun/msg/history.js +32 -9
- package/dist/aun/outbox.js +4 -9
- package/dist/channels/aun.js +32 -6
- package/dist/channels/daemon.js +7 -4
- package/dist/channels/dingtalk.js +3 -5
- package/dist/channels/feishu.js +16 -108
- package/dist/channels/wechat.js +4 -4
- package/dist/channels/wecom.js +4 -6
- package/dist/cli/agent-command.js +1 -1
- package/dist/cli/agent.js +42 -11
- package/dist/cli/aun-commands.js +50 -3
- package/dist/cli/daemon-commands.js +127 -21
- package/dist/cli/data-command.js +132 -0
- package/dist/cli/index.js +11 -3
- package/dist/cli/init.js +116 -37
- package/dist/cli/net-check.js +9 -20
- package/dist/cli/restart-monitor.js +11 -2
- package/dist/cli/trigger-command.js +1 -1
- package/dist/cli/watch-msg.js +12 -25
- package/dist/config/access-policy-domain.js +0 -20
- package/dist/config/access-policy.js +5 -29
- package/dist/config/builtin-roles.js +3 -1
- package/dist/config/config-field-policy.js +1 -1
- package/dist/config/gateway-config.js +21 -4
- package/dist/config/resolved-config-op.js +10 -0
- package/dist/core/auth/operation-catalog.js +1 -1
- package/dist/core/command/command-handler.js +2 -2
- package/dist/core/command/connect-menu.js +20 -42
- package/dist/core/command/menu-handler.js +11 -9
- package/dist/core/command/role-menu.js +27 -0
- package/dist/core/command/slash-handler.js +18 -14
- package/dist/core/data-migration.js +1434 -0
- package/dist/core/handoff/store.js +14 -4
- package/dist/core/inference/text-inference.js +42 -1
- package/dist/core/message/inbound-admission.js +23 -13
- package/dist/core/message/pending-hints.js +1 -1
- package/dist/core/message/response-engine.js +406 -167
- package/dist/core/message/retry-scheduler.js +71 -0
- package/dist/core/model/model-catalog.js +7 -2
- package/dist/core/model/model-fallback.js +81 -0
- package/dist/core/protected-paths.js +41 -8
- package/dist/core/session/adapters/ecagent-session-file-adapter.js +112 -0
- package/dist/core/session/session-fs-store.js +300 -61
- package/dist/core/session/session-manager.js +225 -21
- package/dist/core/session/session-title.js +1 -0
- package/dist/core/session/session-turn-coordinator.js +8 -1
- package/dist/core/system-channels.js +1 -0
- package/dist/index.js +10 -9
- package/dist/paths.js +35 -27
- package/dist/trigger/feedback.js +16 -0
- package/dist/trigger/legacy-session-history.js +19 -0
- package/dist/trigger/manager.js +12 -1
- package/dist/trigger/parser.js +4 -2
- package/dist/trigger/scheduler.js +185 -15
- package/dist/trigger/session-lock.js +62 -0
- package/dist/trigger/state.js +64 -0
- package/dist/trigger/validation.js +32 -2
- package/dist/utils/aid-bind.js +1 -1
- package/dist/utils/cross-platform.js +8 -2
- package/dist/utils/error-utils.js +9 -0
- package/dist/utils/process-introspect.js +19 -3
- package/dist/utils/welcome.js +2 -3
- package/ecagent/LICENSE +21 -0
- package/ecagent/NOTICE +11 -0
- package/ecagent/README.md +61 -0
- package/ecagent/dist/agent-loop.d.ts +24 -0
- package/ecagent/dist/agent-loop.d.ts.map +1 -0
- package/ecagent/dist/agent-loop.js +547 -0
- package/ecagent/dist/agent-loop.js.map +1 -0
- package/ecagent/dist/agent.d.ts +127 -0
- package/ecagent/dist/agent.d.ts.map +1 -0
- package/ecagent/dist/agent.js +386 -0
- package/ecagent/dist/agent.js.map +1 -0
- package/ecagent/dist/harness/agent-harness.d.ts +95 -0
- package/ecagent/dist/harness/agent-harness.d.ts.map +1 -0
- package/ecagent/dist/harness/agent-harness.js +926 -0
- package/ecagent/dist/harness/agent-harness.js.map +1 -0
- package/ecagent/dist/harness/compaction/branch-summarization.d.ts +51 -0
- package/ecagent/dist/harness/compaction/branch-summarization.d.ts.map +1 -0
- package/ecagent/dist/harness/compaction/branch-summarization.js +174 -0
- package/ecagent/dist/harness/compaction/branch-summarization.js.map +1 -0
- package/ecagent/dist/harness/compaction/compaction.d.ts +95 -0
- package/ecagent/dist/harness/compaction/compaction.d.ts.map +1 -0
- package/ecagent/dist/harness/compaction/compaction.js +528 -0
- package/ecagent/dist/harness/compaction/compaction.js.map +1 -0
- package/ecagent/dist/harness/compaction/utils.d.ts +25 -0
- package/ecagent/dist/harness/compaction/utils.d.ts.map +1 -0
- package/ecagent/dist/harness/compaction/utils.js +131 -0
- package/ecagent/dist/harness/compaction/utils.js.map +1 -0
- package/ecagent/dist/harness/env/nodejs.d.ts +51 -0
- package/ecagent/dist/harness/env/nodejs.d.ts.map +1 -0
- package/ecagent/dist/harness/env/nodejs.js +513 -0
- package/ecagent/dist/harness/env/nodejs.js.map +1 -0
- package/ecagent/dist/harness/messages.d.ts +51 -0
- package/ecagent/dist/harness/messages.d.ts.map +1 -0
- package/ecagent/dist/harness/messages.js +102 -0
- package/ecagent/dist/harness/messages.js.map +1 -0
- package/ecagent/dist/harness/prompt-templates.d.ts +48 -0
- package/ecagent/dist/harness/prompt-templates.d.ts.map +1 -0
- package/ecagent/dist/harness/prompt-templates.js +230 -0
- package/ecagent/dist/harness/prompt-templates.js.map +1 -0
- package/ecagent/dist/harness/session/jsonl-repo.d.ts +26 -0
- package/ecagent/dist/harness/session/jsonl-repo.d.ts.map +1 -0
- package/ecagent/dist/harness/session/jsonl-repo.js +100 -0
- package/ecagent/dist/harness/session/jsonl-repo.js.map +1 -0
- package/ecagent/dist/harness/session/jsonl-storage.d.ts +34 -0
- package/ecagent/dist/harness/session/jsonl-storage.d.ts.map +1 -0
- package/ecagent/dist/harness/session/jsonl-storage.js +234 -0
- package/ecagent/dist/harness/session/jsonl-storage.js.map +1 -0
- package/ecagent/dist/harness/session/memory-repo.d.ts +18 -0
- package/ecagent/dist/harness/session/memory-repo.d.ts.map +1 -0
- package/ecagent/dist/harness/session/memory-repo.js +44 -0
- package/ecagent/dist/harness/session/memory-repo.js.map +1 -0
- package/ecagent/dist/harness/session/memory-storage.d.ts +25 -0
- package/ecagent/dist/harness/session/memory-storage.d.ts.map +1 -0
- package/ecagent/dist/harness/session/memory-storage.js +111 -0
- package/ecagent/dist/harness/session/memory-storage.js.map +1 -0
- package/ecagent/dist/harness/session/repo-utils.d.ts +11 -0
- package/ecagent/dist/harness/session/repo-utils.d.ts.map +1 -0
- package/ecagent/dist/harness/session/repo-utils.js +39 -0
- package/ecagent/dist/harness/session/repo-utils.js.map +1 -0
- package/ecagent/dist/harness/session/session.d.ts +47 -0
- package/ecagent/dist/harness/session/session.d.ts.map +1 -0
- package/ecagent/dist/harness/session/session.js +245 -0
- package/ecagent/dist/harness/session/session.js.map +1 -0
- package/ecagent/dist/harness/session/uuid.d.ts +2 -0
- package/ecagent/dist/harness/session/uuid.d.ts.map +1 -0
- package/ecagent/dist/harness/session/uuid.js +50 -0
- package/ecagent/dist/harness/session/uuid.js.map +1 -0
- package/ecagent/dist/harness/skills.d.ts +44 -0
- package/ecagent/dist/harness/skills.d.ts.map +1 -0
- package/ecagent/dist/harness/skills.js +311 -0
- package/ecagent/dist/harness/skills.js.map +1 -0
- package/ecagent/dist/harness/system-prompt.d.ts +3 -0
- package/ecagent/dist/harness/system-prompt.d.ts.map +1 -0
- package/ecagent/dist/harness/system-prompt.js +30 -0
- package/ecagent/dist/harness/system-prompt.js.map +1 -0
- package/ecagent/dist/harness/types.d.ts +619 -0
- package/ecagent/dist/harness/types.d.ts.map +1 -0
- package/ecagent/dist/harness/types.js +81 -0
- package/ecagent/dist/harness/types.js.map +1 -0
- package/ecagent/dist/harness/utils/shell-output.d.ts +14 -0
- package/ecagent/dist/harness/utils/shell-output.d.ts.map +1 -0
- package/ecagent/dist/harness/utils/shell-output.js +126 -0
- package/ecagent/dist/harness/utils/shell-output.js.map +1 -0
- package/ecagent/dist/harness/utils/truncate.d.ts +70 -0
- package/ecagent/dist/harness/utils/truncate.d.ts.map +1 -0
- package/ecagent/dist/harness/utils/truncate.js +290 -0
- package/ecagent/dist/harness/utils/truncate.js.map +1 -0
- package/ecagent/dist/index.d.ts +22 -0
- package/ecagent/dist/index.d.ts.map +1 -0
- package/ecagent/dist/index.js +27 -0
- package/ecagent/dist/index.js.map +1 -0
- package/ecagent/dist/node.d.ts +3 -0
- package/ecagent/dist/node.d.ts.map +1 -0
- package/ecagent/dist/node.js +3 -0
- package/ecagent/dist/node.js.map +1 -0
- package/ecagent/dist/proxy.d.ts +69 -0
- package/ecagent/dist/proxy.d.ts.map +1 -0
- package/ecagent/dist/proxy.js +278 -0
- package/ecagent/dist/proxy.js.map +1 -0
- package/ecagent/dist/runtime/api/lazy.d.ts +15 -0
- package/ecagent/dist/runtime/api/lazy.d.ts.map +1 -0
- package/ecagent/dist/runtime/api/lazy.js +59 -0
- package/ecagent/dist/runtime/api/lazy.js.map +1 -0
- package/ecagent/dist/runtime/api/pi-messages.d.ts +97 -0
- package/ecagent/dist/runtime/api/pi-messages.d.ts.map +1 -0
- package/ecagent/dist/runtime/api/pi-messages.js +307 -0
- package/ecagent/dist/runtime/api/pi-messages.js.map +1 -0
- package/ecagent/dist/runtime/api/pi-messages.lazy.d.ts +3 -0
- package/ecagent/dist/runtime/api/pi-messages.lazy.d.ts.map +1 -0
- package/ecagent/dist/runtime/api/pi-messages.lazy.js +3 -0
- package/ecagent/dist/runtime/api/pi-messages.lazy.js.map +1 -0
- package/ecagent/dist/runtime/auth/context.d.ts +7 -0
- package/ecagent/dist/runtime/auth/context.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/context.js +42 -0
- package/ecagent/dist/runtime/auth/context.js.map +1 -0
- package/ecagent/dist/runtime/auth/credential-store.d.ts +16 -0
- package/ecagent/dist/runtime/auth/credential-store.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/credential-store.js +39 -0
- package/ecagent/dist/runtime/auth/credential-store.js.map +1 -0
- package/ecagent/dist/runtime/auth/helpers.d.ts +20 -0
- package/ecagent/dist/runtime/auth/helpers.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/helpers.js +46 -0
- package/ecagent/dist/runtime/auth/helpers.js.map +1 -0
- package/ecagent/dist/runtime/auth/resolve.d.ts +26 -0
- package/ecagent/dist/runtime/auth/resolve.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/resolve.js +100 -0
- package/ecagent/dist/runtime/auth/resolve.js.map +1 -0
- package/ecagent/dist/runtime/auth/types.d.ts +180 -0
- package/ecagent/dist/runtime/auth/types.d.ts.map +1 -0
- package/ecagent/dist/runtime/auth/types.js +2 -0
- package/ecagent/dist/runtime/auth/types.js.map +1 -0
- package/ecagent/dist/runtime/compat.d.ts +28 -0
- package/ecagent/dist/runtime/compat.d.ts.map +1 -0
- package/ecagent/dist/runtime/compat.js +86 -0
- package/ecagent/dist/runtime/compat.js.map +1 -0
- package/ecagent/dist/runtime/index.d.ts +20 -0
- package/ecagent/dist/runtime/index.d.ts.map +1 -0
- package/ecagent/dist/runtime/index.js +17 -0
- package/ecagent/dist/runtime/index.js.map +1 -0
- package/ecagent/dist/runtime/models.d.ts +142 -0
- package/ecagent/dist/runtime/models.d.ts.map +1 -0
- package/ecagent/dist/runtime/models.js +245 -0
- package/ecagent/dist/runtime/models.js.map +1 -0
- package/ecagent/dist/runtime/oauth.d.ts +2 -0
- package/ecagent/dist/runtime/oauth.d.ts.map +1 -0
- package/ecagent/dist/runtime/oauth.js +2 -0
- package/ecagent/dist/runtime/oauth.js.map +1 -0
- package/ecagent/dist/runtime/providers/faux.d.ts +97 -0
- package/ecagent/dist/runtime/providers/faux.d.ts.map +1 -0
- package/ecagent/dist/runtime/providers/faux.js +395 -0
- package/ecagent/dist/runtime/providers/faux.js.map +1 -0
- package/ecagent/dist/runtime/types.d.ts +607 -0
- package/ecagent/dist/runtime/types.d.ts.map +1 -0
- package/ecagent/dist/runtime/types.js +2 -0
- package/ecagent/dist/runtime/types.js.map +1 -0
- package/ecagent/dist/runtime/utils/diagnostics.d.ts +19 -0
- package/ecagent/dist/runtime/utils/diagnostics.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/diagnostics.js +25 -0
- package/ecagent/dist/runtime/utils/diagnostics.js.map +1 -0
- package/ecagent/dist/runtime/utils/event-stream.d.ts +21 -0
- package/ecagent/dist/runtime/utils/event-stream.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/event-stream.js +77 -0
- package/ecagent/dist/runtime/utils/event-stream.js.map +1 -0
- package/ecagent/dist/runtime/utils/headers.d.ts +4 -0
- package/ecagent/dist/runtime/utils/headers.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/headers.js +18 -0
- package/ecagent/dist/runtime/utils/headers.js.map +1 -0
- package/ecagent/dist/runtime/utils/json-parse.d.ts +16 -0
- package/ecagent/dist/runtime/utils/json-parse.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/json-parse.js +113 -0
- package/ecagent/dist/runtime/utils/json-parse.js.map +1 -0
- package/ecagent/dist/runtime/utils/oauth/types.d.ts +64 -0
- package/ecagent/dist/runtime/utils/oauth/types.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/oauth/types.js +2 -0
- package/ecagent/dist/runtime/utils/oauth/types.js.map +1 -0
- package/ecagent/dist/runtime/utils/overflow.d.ts +58 -0
- package/ecagent/dist/runtime/utils/overflow.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/overflow.js +158 -0
- package/ecagent/dist/runtime/utils/overflow.js.map +1 -0
- package/ecagent/dist/runtime/utils/provider-env.d.ts +7 -0
- package/ecagent/dist/runtime/utils/provider-env.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/provider-env.js +44 -0
- package/ecagent/dist/runtime/utils/provider-env.js.map +1 -0
- package/ecagent/dist/runtime/utils/retry.d.ts +12 -0
- package/ecagent/dist/runtime/utils/retry.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/retry.js +90 -0
- package/ecagent/dist/runtime/utils/retry.js.map +1 -0
- package/ecagent/dist/runtime/utils/typebox-helpers.d.ts +17 -0
- package/ecagent/dist/runtime/utils/typebox-helpers.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/typebox-helpers.js +21 -0
- package/ecagent/dist/runtime/utils/typebox-helpers.js.map +1 -0
- package/ecagent/dist/runtime/utils/validation.d.ts +18 -0
- package/ecagent/dist/runtime/utils/validation.d.ts.map +1 -0
- package/ecagent/dist/runtime/utils/validation.js +269 -0
- package/ecagent/dist/runtime/utils/validation.js.map +1 -0
- package/ecagent/dist/types.d.ts +401 -0
- package/ecagent/dist/types.d.ts.map +1 -0
- package/ecagent/dist/types.js +2 -0
- package/ecagent/dist/types.js.map +1 -0
- package/ecagent/package.json +93 -0
- package/ecagent/src/agent-loop.ts +792 -0
- package/ecagent/src/agent.ts +575 -0
- package/ecagent/src/harness/agent-harness.ts +1029 -0
- package/ecagent/src/harness/compaction/branch-summarization.ts +261 -0
- package/ecagent/src/harness/compaction/compaction.ts +753 -0
- package/ecagent/src/harness/compaction/utils.ts +144 -0
- package/ecagent/src/harness/env/nodejs.ts +569 -0
- package/ecagent/src/harness/messages.ts +164 -0
- package/ecagent/src/harness/prompt-templates.ts +267 -0
- package/ecagent/src/harness/session/jsonl-repo.ts +179 -0
- package/ecagent/src/harness/session/jsonl-storage.ts +314 -0
- package/ecagent/src/harness/session/memory-repo.ts +50 -0
- package/ecagent/src/harness/session/memory-storage.ts +133 -0
- package/ecagent/src/harness/session/repo-utils.ts +51 -0
- package/ecagent/src/harness/session/session.ts +338 -0
- package/ecagent/src/harness/session/uuid.ts +54 -0
- package/ecagent/src/harness/skills.ts +375 -0
- package/ecagent/src/harness/system-prompt.ts +34 -0
- package/ecagent/src/harness/types.ts +838 -0
- package/ecagent/src/harness/utils/shell-output.ts +135 -0
- package/ecagent/src/harness/utils/truncate.ts +344 -0
- package/ecagent/src/index.ts +46 -0
- package/ecagent/src/node.ts +2 -0
- package/ecagent/src/proxy.ts +367 -0
- package/ecagent/src/runtime/api/lazy.ts +70 -0
- package/ecagent/src/runtime/api/pi-messages.lazy.ts +4 -0
- package/ecagent/src/runtime/api/pi-messages.ts +436 -0
- package/ecagent/src/runtime/auth/context.ts +45 -0
- package/ecagent/src/runtime/auth/credential-store.ts +47 -0
- package/ecagent/src/runtime/auth/helpers.ts +46 -0
- package/ecagent/src/runtime/auth/resolve.ts +141 -0
- package/ecagent/src/runtime/auth/types.ts +182 -0
- package/ecagent/src/runtime/compat.ts +158 -0
- package/ecagent/src/runtime/index.ts +31 -0
- package/ecagent/src/runtime/models.ts +452 -0
- package/ecagent/src/runtime/oauth.ts +1 -0
- package/ecagent/src/runtime/providers/faux.ts +538 -0
- package/ecagent/src/runtime/types.ts +718 -0
- package/ecagent/src/runtime/utils/diagnostics.ts +45 -0
- package/ecagent/src/runtime/utils/event-stream.ts +88 -0
- package/ecagent/src/runtime/utils/headers.ts +18 -0
- package/ecagent/src/runtime/utils/json-parse.ts +124 -0
- package/ecagent/src/runtime/utils/oauth/types.ts +79 -0
- package/ecagent/src/runtime/utils/overflow.ts +165 -0
- package/ecagent/src/runtime/utils/provider-env.ts +52 -0
- package/ecagent/src/runtime/utils/retry.ts +101 -0
- package/ecagent/src/runtime/utils/typebox-helpers.ts +24 -0
- package/ecagent/src/runtime/utils/validation.ts +310 -0
- package/ecagent/src/types.ts +430 -0
- package/ecagent/tsconfig.build.json +32 -0
- package/kits/docs/evolcore/config.md +4 -4
- package/kits/docs/evolcore/contact.md +2 -1
- package/kits/schemas/_meta.json +7 -4
- package/kits/schemas/agent-config.schema.10.json +370 -0
- package/kits/schemas/agent-config.schema.9.json +2 -12
- package/kits/schemas/defaults.schema.4.json +93 -0
- package/kits/schemas/relation-config.schema.8.json +69 -0
- package/kits/templates/roles/admin.json +1 -1
- package/package.json +22 -6
- package/skills/eclink/SKILL.md +70 -0
- package/skills/eclink/agents/openai.yaml +4 -0
- package/assets/.env.template +0 -4
|
@@ -10,22 +10,108 @@ function encodeSegment(s) {
|
|
|
10
10
|
function decodeSegment(s) {
|
|
11
11
|
return s.replace(/%([0-9A-Fa-f]{2})/g, (_, hex) => String.fromCharCode(parseInt(hex, 16)));
|
|
12
12
|
}
|
|
13
|
+
function resolveAunSelfAID(selfAID, channelKey) {
|
|
14
|
+
const direct = selfAID?.trim();
|
|
15
|
+
if (direct && direct !== '_unknown')
|
|
16
|
+
return direct;
|
|
17
|
+
const parts = channelKey?.split('#');
|
|
18
|
+
const inferred = parts?.length === 3 && parts[0] === 'aun' ? parts[1]?.trim() : undefined;
|
|
19
|
+
if (inferred && inferred !== '_unknown')
|
|
20
|
+
return inferred;
|
|
21
|
+
throw new Error('[SessionFsStore] AUN chat directory requires selfAID or an aun channel key.');
|
|
22
|
+
}
|
|
23
|
+
function resolveSessionChannelKey(channelType, selfAID, channelKey) {
|
|
24
|
+
if (channelKey?.trim())
|
|
25
|
+
return channelKey.trim();
|
|
26
|
+
return `${channelType}#${selfAID}#main`;
|
|
27
|
+
}
|
|
28
|
+
function encodeChannelSessionComponent(value) {
|
|
29
|
+
// encodeURIComponent leaves `*` untouched, but it is illegal in a Windows
|
|
30
|
+
// filename. A trailing dot is also rejected by Windows filesystems.
|
|
31
|
+
const encoded = encodeURIComponent(value).replace(/\*/g, '%2A');
|
|
32
|
+
return encoded.endsWith('.') ? `${encoded.slice(0, -1)}%2E` : encoded;
|
|
33
|
+
}
|
|
34
|
+
const MAX_CHANNEL_SESSION_KEY_BYTES = 255;
|
|
35
|
+
function formatChannelSessionKeyParts(channelType, channelName, channelId) {
|
|
36
|
+
if (!channelType || !channelName || !channelId) {
|
|
37
|
+
throw new Error('[SessionFsStore] channel session key components must not be empty.');
|
|
38
|
+
}
|
|
39
|
+
const key = [channelType, channelName, channelId]
|
|
40
|
+
.map(encodeChannelSessionComponent)
|
|
41
|
+
.join('#');
|
|
42
|
+
const bytes = Buffer.byteLength(key, 'utf8');
|
|
43
|
+
if (bytes > MAX_CHANNEL_SESSION_KEY_BYTES) {
|
|
44
|
+
throw new Error(`[SessionFsStore] channel session key is ${bytes} bytes; filesystem limit is ${MAX_CHANNEL_SESSION_KEY_BYTES} bytes.`);
|
|
45
|
+
}
|
|
46
|
+
return key;
|
|
47
|
+
}
|
|
13
48
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
49
|
+
* Session 的磁盘路由键。它将实例名和会话路由 ID 合并为一个目录段;
|
|
50
|
+
* Agent 身份由父目录 `agents/<aid>/` 提供,不能省略这个父目录。
|
|
51
|
+
*
|
|
52
|
+
* This is intentionally distinct from SessionFile.sessionKey, which includes
|
|
53
|
+
* the thread ID and is used as the agent-internal session routing key.
|
|
18
54
|
*/
|
|
19
|
-
export function
|
|
20
|
-
|
|
21
|
-
|
|
55
|
+
export function formatChannelSessionKey(channelType, channelId, channelKey) {
|
|
56
|
+
const parts = channelKey?.split('#');
|
|
57
|
+
const channelName = parts?.length === 3 && parts[0] === channelType && parts[2]?.trim()
|
|
58
|
+
? parts[2].trim()
|
|
59
|
+
: 'main';
|
|
60
|
+
return formatChannelSessionKeyParts(channelType, channelName, channelId);
|
|
61
|
+
}
|
|
62
|
+
function parseChannelSessionKeyComponents(key) {
|
|
63
|
+
const parts = key.split('#');
|
|
64
|
+
if (parts.length !== 3 || !parts[0] || !parts[1] || !parts[2])
|
|
65
|
+
return undefined;
|
|
66
|
+
try {
|
|
67
|
+
const channelType = decodeURIComponent(parts[0]);
|
|
68
|
+
const channelName = decodeURIComponent(parts[1]);
|
|
69
|
+
const channelId = decodeURIComponent(parts[2]);
|
|
70
|
+
if (!channelType || !channelName || !channelId)
|
|
71
|
+
return undefined;
|
|
72
|
+
return { channelType, channelName, channelId };
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return undefined;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/** Parse only the canonical channelSessionKey emitted by the current formatter. */
|
|
79
|
+
export function tryParseChannelSessionKey(key) {
|
|
80
|
+
const parsed = parseChannelSessionKeyComponents(key);
|
|
81
|
+
if (!parsed)
|
|
82
|
+
return undefined;
|
|
83
|
+
try {
|
|
84
|
+
return formatChannelSessionKeyParts(parsed.channelType, parsed.channelName, parsed.channelId) === key
|
|
85
|
+
? parsed
|
|
86
|
+
: undefined;
|
|
22
87
|
}
|
|
23
|
-
|
|
24
|
-
return
|
|
88
|
+
catch {
|
|
89
|
+
return undefined;
|
|
25
90
|
}
|
|
26
|
-
return path.join(sessionsDir, channelType, encodeSegment(channelId));
|
|
27
91
|
}
|
|
28
|
-
/**
|
|
92
|
+
/** Parse the immediately preceding v3 encoding for explicit migration only. */
|
|
93
|
+
export function tryParseLegacyChannelSessionKey(key) {
|
|
94
|
+
return parseChannelSessionKeyComponents(key);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 计算 chat 目录的完整路径。
|
|
98
|
+
* - agents/<selfAID>/sessions/<channelSessionKey>/
|
|
99
|
+
*
|
|
100
|
+
* The relation peerKey intentionally is not used here: it omits the channel
|
|
101
|
+
* instance. channelSessionKey retains the configured instance name and the
|
|
102
|
+
* chat route in one path segment.
|
|
103
|
+
*/
|
|
104
|
+
export function chatDirPath(sessionsRoot, channelType, channelId, selfAID, channelKey) {
|
|
105
|
+
const aid = channelType === 'aun'
|
|
106
|
+
? resolveAunSelfAID(selfAID, channelKey)
|
|
107
|
+
: (selfAID?.trim() || trySelfAIDFromChannelKey(channelKey) || '_unknown');
|
|
108
|
+
return path.join(sessionsRoot, encodeSegment(aid), 'sessions', formatChannelSessionKey(channelType, channelId, resolveSessionChannelKey(channelType, aid, channelKey)));
|
|
109
|
+
}
|
|
110
|
+
function trySelfAIDFromChannelKey(channelKey) {
|
|
111
|
+
const parts = channelKey?.split('#');
|
|
112
|
+
return parts?.length === 3 && parts[1]?.trim() ? parts[1].trim() : undefined;
|
|
113
|
+
}
|
|
114
|
+
/** 解码目录段(用于扫描时把目录名还原为逻辑路径键) */
|
|
29
115
|
export function decodeDirSegment(seg) {
|
|
30
116
|
return decodeSegment(seg);
|
|
31
117
|
}
|
|
@@ -47,9 +133,8 @@ export function formatTimestamp(epochMs) {
|
|
|
47
133
|
const ss = String(d.getSeconds()).padStart(2, '0');
|
|
48
134
|
return `${yyyy}-${mo}-${dd} ${hh}:${mi}:${ss}`;
|
|
49
135
|
}
|
|
50
|
-
|
|
136
|
+
function atomicWrite(filePath, content) {
|
|
51
137
|
const tmpPath = filePath + '.tmp';
|
|
52
|
-
const content = JSON.stringify(data, null, 2) + '\n';
|
|
53
138
|
const fd = fs.openSync(tmpPath, 'w');
|
|
54
139
|
fs.writeSync(fd, content);
|
|
55
140
|
fs.fsyncSync(fd);
|
|
@@ -63,6 +148,12 @@ export function atomicWriteJson(filePath, data) {
|
|
|
63
148
|
}
|
|
64
149
|
fs.renameSync(tmpPath, filePath);
|
|
65
150
|
}
|
|
151
|
+
export function atomicWriteJson(filePath, data) {
|
|
152
|
+
atomicWrite(filePath, JSON.stringify(data, null, 2) + '\n');
|
|
153
|
+
}
|
|
154
|
+
export function atomicWriteText(filePath, content) {
|
|
155
|
+
atomicWrite(filePath, content);
|
|
156
|
+
}
|
|
66
157
|
export function appendJsonl(filePath, record) {
|
|
67
158
|
const line = JSON.stringify(record) + '\n';
|
|
68
159
|
const fd = fs.openSync(filePath, 'a');
|
|
@@ -128,22 +219,193 @@ export function readAllJsonlLines(filePath) {
|
|
|
128
219
|
}
|
|
129
220
|
}
|
|
130
221
|
/**
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
* - wecom: channelType / channelKey / channelId (3层;兼容旧的2层目录)
|
|
134
|
-
* - 其它: channelType / channelId (2层)
|
|
222
|
+
* Scan the current per-Agent layout:
|
|
223
|
+
* `agents/<aid>/sessions/<channelSessionKey>/`.
|
|
135
224
|
*/
|
|
136
|
-
export function scanChatDirs(
|
|
225
|
+
export function scanChatDirs(sessionsRoot) {
|
|
137
226
|
const results = [];
|
|
138
|
-
let
|
|
227
|
+
let agentEntries;
|
|
139
228
|
try {
|
|
140
|
-
|
|
229
|
+
agentEntries = fs.readdirSync(sessionsRoot, { withFileTypes: true });
|
|
141
230
|
}
|
|
142
231
|
catch (e) {
|
|
143
232
|
if (e.code === 'ENOENT')
|
|
144
233
|
return [];
|
|
145
234
|
throw e;
|
|
146
235
|
}
|
|
236
|
+
const hasAgentLayout = agentEntries.some(entry => entry.isDirectory() && (fs.existsSync(path.join(sessionsRoot, entry.name, 'config.json'))
|
|
237
|
+
|| fs.existsSync(path.join(sessionsRoot, entry.name, 'sessions'))));
|
|
238
|
+
if (!hasAgentLayout)
|
|
239
|
+
return [];
|
|
240
|
+
for (const agentEntry of agentEntries) {
|
|
241
|
+
if (!agentEntry.isDirectory())
|
|
242
|
+
continue;
|
|
243
|
+
const sessionsDir = path.join(sessionsRoot, agentEntry.name, 'sessions');
|
|
244
|
+
let sessionEntries;
|
|
245
|
+
try {
|
|
246
|
+
sessionEntries = fs.readdirSync(sessionsDir, { withFileTypes: true });
|
|
247
|
+
}
|
|
248
|
+
catch {
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
const selfAID = decodeSegment(agentEntry.name);
|
|
252
|
+
for (const sessionEntry of sessionEntries) {
|
|
253
|
+
if (!sessionEntry.isDirectory())
|
|
254
|
+
continue;
|
|
255
|
+
const channelSessionKey = sessionEntry.name;
|
|
256
|
+
const parsed = tryParseChannelSessionKey(channelSessionKey);
|
|
257
|
+
if (!parsed)
|
|
258
|
+
continue;
|
|
259
|
+
const dirPath = path.join(sessionsDir, sessionEntry.name);
|
|
260
|
+
if (!hasSessionPayload(dirPath))
|
|
261
|
+
continue;
|
|
262
|
+
results.push({
|
|
263
|
+
channelType: parsed.channelType,
|
|
264
|
+
selfAID,
|
|
265
|
+
channelId: parsed.channelId,
|
|
266
|
+
channelKey: parsed.channelType === 'daemon'
|
|
267
|
+
? 'daemon'
|
|
268
|
+
: `${parsed.channelType}#${selfAID}#${parsed.channelName}`,
|
|
269
|
+
channelSessionKey,
|
|
270
|
+
dirPath,
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
return results.sort((left, right) => left.dirPath < right.dirPath ? -1 : left.dirPath > right.dirPath ? 1 : 0);
|
|
275
|
+
}
|
|
276
|
+
function hasSessionPayload(dirPath) {
|
|
277
|
+
try {
|
|
278
|
+
return fs.readdirSync(dirPath, { withFileTypes: true }).some(entry => (entry.isFile() && (entry.name === 'active.json'
|
|
279
|
+
|| entry.name === 'messages.jsonl'
|
|
280
|
+
|| (entry.name.startsWith('meta_') && entry.name.endsWith('.jsonl')))) || (entry.isDirectory() && entry.name === '_threads'));
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Scan non-canonical single-level v3 keys. The runtime ignores these entries;
|
|
288
|
+
* only the explicit migration planner may copy them into their canonical key.
|
|
289
|
+
*/
|
|
290
|
+
export function scanNonCanonicalAgentChatDirs(sessionsRoot) {
|
|
291
|
+
const results = [];
|
|
292
|
+
let agentEntries;
|
|
293
|
+
try {
|
|
294
|
+
agentEntries = fs.readdirSync(sessionsRoot, { withFileTypes: true });
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
return results;
|
|
298
|
+
}
|
|
299
|
+
for (const agentEntry of agentEntries) {
|
|
300
|
+
if (!agentEntry.isDirectory())
|
|
301
|
+
continue;
|
|
302
|
+
const selfAID = decodeSegment(agentEntry.name);
|
|
303
|
+
const sessionsDir = path.join(sessionsRoot, agentEntry.name, 'sessions');
|
|
304
|
+
let sessionEntries;
|
|
305
|
+
try {
|
|
306
|
+
sessionEntries = fs.readdirSync(sessionsDir, { withFileTypes: true });
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
continue;
|
|
310
|
+
}
|
|
311
|
+
for (const sessionEntry of sessionEntries) {
|
|
312
|
+
if (!sessionEntry.isDirectory() || tryParseChannelSessionKey(sessionEntry.name))
|
|
313
|
+
continue;
|
|
314
|
+
const parsed = tryParseLegacyChannelSessionKey(sessionEntry.name);
|
|
315
|
+
const dirPath = path.join(sessionsDir, sessionEntry.name);
|
|
316
|
+
if (!parsed || !hasSessionPayload(dirPath))
|
|
317
|
+
continue;
|
|
318
|
+
results.push({
|
|
319
|
+
...parsed,
|
|
320
|
+
selfAID,
|
|
321
|
+
channelKey: parsed.channelType === 'daemon'
|
|
322
|
+
? 'daemon'
|
|
323
|
+
: `${parsed.channelType}#${selfAID}#${parsed.channelName}`,
|
|
324
|
+
channelSessionKey: sessionEntry.name,
|
|
325
|
+
dirPath,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return results.sort((left, right) => left.dirPath < right.dirPath ? -1 : left.dirPath > right.dirPath ? 1 : 0);
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Scan the immediately preceding per-Agent layout:
|
|
333
|
+
* `agents/<aid>/sessions/<channelKey>/<channelId>/`.
|
|
334
|
+
*
|
|
335
|
+
* The runtime must not use this scanner. It exists solely for the explicit
|
|
336
|
+
* migration that copies the old two-level layout into channelSessionKey.
|
|
337
|
+
*/
|
|
338
|
+
export function scanNestedAgentChatDirs(sessionsRoot) {
|
|
339
|
+
const results = [];
|
|
340
|
+
let agentEntries;
|
|
341
|
+
try {
|
|
342
|
+
agentEntries = fs.readdirSync(sessionsRoot, { withFileTypes: true });
|
|
343
|
+
}
|
|
344
|
+
catch {
|
|
345
|
+
return results;
|
|
346
|
+
}
|
|
347
|
+
for (const agentEntry of agentEntries) {
|
|
348
|
+
if (!agentEntry.isDirectory())
|
|
349
|
+
continue;
|
|
350
|
+
const selfAID = decodeSegment(agentEntry.name);
|
|
351
|
+
const sessionsDir = path.join(sessionsRoot, agentEntry.name, 'sessions');
|
|
352
|
+
let channelEntries;
|
|
353
|
+
try {
|
|
354
|
+
channelEntries = fs.readdirSync(sessionsDir, { withFileTypes: true });
|
|
355
|
+
}
|
|
356
|
+
catch {
|
|
357
|
+
continue;
|
|
358
|
+
}
|
|
359
|
+
for (const channelEntry of channelEntries) {
|
|
360
|
+
if (!channelEntry.isDirectory())
|
|
361
|
+
continue;
|
|
362
|
+
const channelKey = decodeSegment(channelEntry.name);
|
|
363
|
+
const parts = channelKey.split('#');
|
|
364
|
+
const isDaemon = channelKey === 'daemon';
|
|
365
|
+
const isCurrentKey = parts.length === 3 && parts[1] === selfAID && !!parts[0] && !!parts[2];
|
|
366
|
+
const isReversedLegacyKey = parts.length === 3 && parts[0] === selfAID && !!parts[1] && !!parts[2];
|
|
367
|
+
const isAgentChannel = isCurrentKey || isReversedLegacyKey;
|
|
368
|
+
if (!isDaemon && !isAgentChannel)
|
|
369
|
+
continue;
|
|
370
|
+
const channelDir = path.join(sessionsDir, channelEntry.name);
|
|
371
|
+
// A single-level channelSessionKey can look superficially like a legacy
|
|
372
|
+
// key when an AID happens to match an instance name. Its own active.json
|
|
373
|
+
// proves it is a current chat directory, not a legacy channel parent.
|
|
374
|
+
if (fs.existsSync(path.join(channelDir, 'active.json')))
|
|
375
|
+
continue;
|
|
376
|
+
const channelType = isDaemon ? 'daemon' : (isCurrentKey ? parts[0] : parts[1]);
|
|
377
|
+
let chatEntries;
|
|
378
|
+
try {
|
|
379
|
+
chatEntries = fs.readdirSync(channelDir, { withFileTypes: true });
|
|
380
|
+
}
|
|
381
|
+
catch {
|
|
382
|
+
continue;
|
|
383
|
+
}
|
|
384
|
+
for (const chatEntry of chatEntries) {
|
|
385
|
+
if (!chatEntry.isDirectory())
|
|
386
|
+
continue;
|
|
387
|
+
results.push({
|
|
388
|
+
channelType,
|
|
389
|
+
selfAID,
|
|
390
|
+
channelKey,
|
|
391
|
+
channelId: decodeSegment(chatEntry.name),
|
|
392
|
+
dirPath: path.join(channelDir, chatEntry.name),
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return results.sort((left, right) => left.dirPath < right.dirPath ? -1 : left.dirPath > right.dirPath ? 1 : 0);
|
|
398
|
+
}
|
|
399
|
+
/** Scan the pre-migration data/sessions layout without changing it. */
|
|
400
|
+
export function scanLegacyChatDirs(sessionsDir) {
|
|
401
|
+
const results = [];
|
|
402
|
+
let typeEntries;
|
|
403
|
+
try {
|
|
404
|
+
typeEntries = fs.readdirSync(sessionsDir, { withFileTypes: true });
|
|
405
|
+
}
|
|
406
|
+
catch {
|
|
407
|
+
return results;
|
|
408
|
+
}
|
|
147
409
|
for (const typeEntry of typeEntries) {
|
|
148
410
|
if (!typeEntry.isDirectory())
|
|
149
411
|
continue;
|
|
@@ -157,7 +419,6 @@ export function scanChatDirs(sessionsDir) {
|
|
|
157
419
|
continue;
|
|
158
420
|
}
|
|
159
421
|
if (channelType === 'aun') {
|
|
160
|
-
// 3-layer: aun/selfAID/channelId
|
|
161
422
|
for (const selfEntry of level2Entries) {
|
|
162
423
|
if (!selfEntry.isDirectory())
|
|
163
424
|
continue;
|
|
@@ -169,19 +430,15 @@ export function scanChatDirs(sessionsDir) {
|
|
|
169
430
|
catch {
|
|
170
431
|
continue;
|
|
171
432
|
}
|
|
172
|
-
for (const chatEntry of chatEntries)
|
|
173
|
-
if (
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
selfAID: decodeSegment(selfEntry.name),
|
|
178
|
-
channelId: decodeSegment(chatEntry.name),
|
|
179
|
-
dirPath: path.join(selfDir, chatEntry.name),
|
|
180
|
-
});
|
|
181
|
-
}
|
|
433
|
+
for (const chatEntry of chatEntries)
|
|
434
|
+
if (chatEntry.isDirectory())
|
|
435
|
+
results.push({
|
|
436
|
+
channelType, selfAID: decodeSegment(selfEntry.name), channelId: decodeSegment(chatEntry.name), dirPath: path.join(selfDir, chatEntry.name),
|
|
437
|
+
});
|
|
182
438
|
}
|
|
439
|
+
continue;
|
|
183
440
|
}
|
|
184
|
-
|
|
441
|
+
if (channelType === 'wecom') {
|
|
185
442
|
for (const entry of level2Entries) {
|
|
186
443
|
if (!entry.isDirectory())
|
|
187
444
|
continue;
|
|
@@ -195,43 +452,25 @@ export function scanChatDirs(sessionsDir) {
|
|
|
195
452
|
catch {
|
|
196
453
|
continue;
|
|
197
454
|
}
|
|
198
|
-
for (const chatEntry of chatEntries)
|
|
199
|
-
if (
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
selfAID: '',
|
|
204
|
-
channelKey: decoded,
|
|
205
|
-
channelId: decodeSegment(chatEntry.name),
|
|
206
|
-
dirPath: path.join(entryDir, chatEntry.name),
|
|
207
|
-
});
|
|
208
|
-
}
|
|
455
|
+
for (const chatEntry of chatEntries)
|
|
456
|
+
if (chatEntry.isDirectory())
|
|
457
|
+
results.push({
|
|
458
|
+
channelType, selfAID: '', channelKey: decoded, channelId: decodeSegment(chatEntry.name), dirPath: path.join(entryDir, chatEntry.name),
|
|
459
|
+
});
|
|
209
460
|
}
|
|
210
461
|
else {
|
|
211
|
-
results.push({
|
|
212
|
-
channelType,
|
|
213
|
-
selfAID: '',
|
|
214
|
-
channelId: decoded,
|
|
215
|
-
dirPath: entryDir,
|
|
216
|
-
});
|
|
462
|
+
results.push({ channelType, selfAID: '', channelId: decoded, dirPath: entryDir });
|
|
217
463
|
}
|
|
218
464
|
}
|
|
465
|
+
continue;
|
|
219
466
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
for (const chatEntry of level2Entries) {
|
|
223
|
-
if (!chatEntry.isDirectory())
|
|
224
|
-
continue;
|
|
467
|
+
for (const chatEntry of level2Entries)
|
|
468
|
+
if (chatEntry.isDirectory())
|
|
225
469
|
results.push({
|
|
226
|
-
channelType,
|
|
227
|
-
selfAID: '',
|
|
228
|
-
channelId: decodeSegment(chatEntry.name),
|
|
229
|
-
dirPath: path.join(typeDir, chatEntry.name),
|
|
470
|
+
channelType, selfAID: '', channelId: decodeSegment(chatEntry.name), dirPath: path.join(typeDir, chatEntry.name),
|
|
230
471
|
});
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
472
|
}
|
|
234
|
-
return results;
|
|
473
|
+
return results.sort((left, right) => left.dirPath < right.dirPath ? -1 : left.dirPath > right.dirPath ? 1 : 0);
|
|
235
474
|
}
|
|
236
475
|
export function scanMetaFiles(chatDir) {
|
|
237
476
|
try {
|