@0xmaxma/claude-gateway 2.0.3 → 2.0.5
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 +11 -1
- package/dist/agent/builtin-commands.d.ts +1 -1
- package/dist/agent/builtin-commands.d.ts.map +1 -1
- package/dist/agent/builtin-commands.js +3 -2
- package/dist/agent/builtin-commands.js.map +1 -1
- package/dist/agent/runner.d.ts +109 -9
- package/dist/agent/runner.d.ts.map +1 -1
- package/dist/agent/runner.js +211 -135
- package/dist/agent/runner.js.map +1 -1
- package/dist/agent/skill-learning/index.d.ts.map +1 -1
- package/dist/agent/skill-learning/index.js +27 -8
- package/dist/agent/skill-learning/index.js.map +1 -1
- package/dist/agent/skill-learning/reviewer.d.ts +3 -1
- package/dist/agent/skill-learning/reviewer.d.ts.map +1 -1
- package/dist/agent/skill-learning/reviewer.js +6 -2
- package/dist/agent/skill-learning/reviewer.js.map +1 -1
- package/dist/agent/turn-stream.d.ts +3 -1
- package/dist/agent/turn-stream.d.ts.map +1 -1
- package/dist/agent/turn-stream.js +8 -4
- package/dist/agent/turn-stream.js.map +1 -1
- package/dist/api/gateway-router.d.ts +2 -0
- package/dist/api/gateway-router.d.ts.map +1 -1
- package/dist/api/gateway-router.js +229 -12
- package/dist/api/gateway-router.js.map +1 -1
- package/dist/api/router.js +11 -11
- package/dist/api/router.js.map +1 -1
- package/dist/api/slack-webhook-router.js +1 -1
- package/dist/api/slack-webhook-router.js.map +1 -1
- package/dist/api/voice-router.d.ts +1 -0
- package/dist/api/voice-router.d.ts.map +1 -1
- package/dist/api/voice-router.js +129 -7
- package/dist/api/voice-router.js.map +1 -1
- package/dist/config/claude-settings.d.ts +14 -0
- package/dist/config/claude-settings.d.ts.map +1 -1
- package/dist/config/claude-settings.js +20 -0
- package/dist/config/claude-settings.js.map +1 -1
- package/dist/orchestration/agent-cli-session.d.ts +46 -0
- package/dist/orchestration/agent-cli-session.d.ts.map +1 -0
- package/dist/orchestration/agent-cli-session.js +121 -0
- package/dist/orchestration/agent-cli-session.js.map +1 -0
- package/dist/orchestration/agent-tool-schemas.d.ts +6 -0
- package/dist/orchestration/agent-tool-schemas.d.ts.map +1 -0
- package/dist/orchestration/agent-tool-schemas.js +23 -0
- package/dist/orchestration/agent-tool-schemas.js.map +1 -0
- package/dist/orchestration/bridge.d.ts +7 -3
- package/dist/orchestration/bridge.d.ts.map +1 -1
- package/dist/orchestration/bridge.js +93 -66
- package/dist/orchestration/bridge.js.map +1 -1
- package/dist/orchestration/browser-voice.d.ts +14 -0
- package/dist/orchestration/browser-voice.d.ts.map +1 -0
- package/dist/orchestration/browser-voice.js +30 -0
- package/dist/orchestration/browser-voice.js.map +1 -0
- package/dist/orchestration/channel-input-media.d.ts +6 -0
- package/dist/orchestration/channel-input-media.d.ts.map +1 -1
- package/dist/orchestration/channel-input-media.js +35 -11
- package/dist/orchestration/channel-input-media.js.map +1 -1
- package/dist/orchestration/channel-media-error.d.ts +11 -0
- package/dist/orchestration/channel-media-error.d.ts.map +1 -0
- package/dist/orchestration/channel-media-error.js +38 -0
- package/dist/orchestration/channel-media-error.js.map +1 -0
- package/dist/orchestration/channel-media.d.ts +1 -1
- package/dist/orchestration/channel-media.d.ts.map +1 -1
- package/dist/orchestration/channel-media.js +37 -7
- package/dist/orchestration/channel-media.js.map +1 -1
- package/dist/orchestration/context-footprint.d.ts +14 -0
- package/dist/orchestration/context-footprint.d.ts.map +1 -0
- package/dist/orchestration/context-footprint.js +57 -0
- package/dist/orchestration/context-footprint.js.map +1 -0
- package/dist/orchestration/conversation-intake.d.ts +1 -1
- package/dist/orchestration/conversation-intake.d.ts.map +1 -1
- package/dist/orchestration/conversation-intake.js +1 -1
- package/dist/orchestration/dashboard-reader-worker.d.ts +2 -0
- package/dist/orchestration/dashboard-reader-worker.d.ts.map +1 -0
- package/dist/orchestration/dashboard-reader-worker.js +155 -0
- package/dist/orchestration/dashboard-reader-worker.js.map +1 -0
- package/dist/orchestration/dashboard-reader.d.ts +15 -0
- package/dist/orchestration/dashboard-reader.d.ts.map +1 -0
- package/dist/orchestration/dashboard-reader.js +87 -0
- package/dist/orchestration/dashboard-reader.js.map +1 -0
- package/dist/orchestration/decision-context.d.ts +15 -0
- package/dist/orchestration/decision-context.d.ts.map +1 -0
- package/dist/orchestration/decision-context.js +57 -0
- package/dist/orchestration/decision-context.js.map +1 -0
- package/dist/orchestration/delivery.d.ts +3 -0
- package/dist/orchestration/delivery.d.ts.map +1 -1
- package/dist/orchestration/delivery.js +14 -5
- package/dist/orchestration/delivery.js.map +1 -1
- package/dist/orchestration/display-stream.d.ts +21 -2
- package/dist/orchestration/display-stream.d.ts.map +1 -1
- package/dist/orchestration/display-stream.js +61 -8
- package/dist/orchestration/display-stream.js.map +1 -1
- package/dist/orchestration/inference-errors.d.ts.map +1 -1
- package/dist/orchestration/inference-errors.js +56 -3
- package/dist/orchestration/inference-errors.js.map +1 -1
- package/dist/orchestration/mutation-recovery.d.ts +12 -0
- package/dist/orchestration/mutation-recovery.d.ts.map +1 -0
- package/dist/orchestration/mutation-recovery.js +41 -0
- package/dist/orchestration/mutation-recovery.js.map +1 -0
- package/dist/orchestration/native-compact.d.ts +5 -0
- package/dist/orchestration/native-compact.d.ts.map +1 -0
- package/dist/orchestration/native-compact.js +29 -0
- package/dist/orchestration/native-compact.js.map +1 -0
- package/dist/orchestration/notification-mailbox.d.ts +3 -1
- package/dist/orchestration/notification-mailbox.d.ts.map +1 -1
- package/dist/orchestration/notification-mailbox.js +4 -2
- package/dist/orchestration/notification-mailbox.js.map +1 -1
- package/dist/orchestration/process-turn.d.ts +15 -2
- package/dist/orchestration/process-turn.d.ts.map +1 -1
- package/dist/orchestration/process-turn.js +103 -16
- package/dist/orchestration/process-turn.js.map +1 -1
- package/dist/orchestration/progress-review.d.ts +8 -18
- package/dist/orchestration/progress-review.d.ts.map +1 -1
- package/dist/orchestration/progress-review.js +12 -14
- package/dist/orchestration/progress-review.js.map +1 -1
- package/dist/orchestration/provider-message.d.ts +7 -0
- package/dist/orchestration/provider-message.d.ts.map +1 -0
- package/dist/orchestration/provider-message.js +63 -0
- package/dist/orchestration/provider-message.js.map +1 -0
- package/dist/orchestration/response-errors.d.ts +6 -0
- package/dist/orchestration/response-errors.d.ts.map +1 -0
- package/dist/orchestration/response-errors.js +88 -0
- package/dist/orchestration/response-errors.js.map +1 -0
- package/dist/orchestration/response-schema.d.ts +33 -0
- package/dist/orchestration/response-schema.d.ts.map +1 -0
- package/dist/orchestration/response-schema.js +61 -0
- package/dist/orchestration/response-schema.js.map +1 -0
- package/dist/orchestration/runtime.d.ts +69 -0
- package/dist/orchestration/runtime.d.ts.map +1 -1
- package/dist/orchestration/runtime.js +347 -98
- package/dist/orchestration/runtime.js.map +1 -1
- package/dist/orchestration/skills.d.ts.map +1 -1
- package/dist/orchestration/skills.js +3 -2
- package/dist/orchestration/skills.js.map +1 -1
- package/dist/orchestration/source-policy.d.ts +1 -1
- package/dist/orchestration/source-policy.d.ts.map +1 -1
- package/dist/orchestration/source-policy.js +1 -1
- package/dist/orchestration/speech.d.ts +15 -17
- package/dist/orchestration/speech.d.ts.map +1 -1
- package/dist/orchestration/speech.js +90 -30
- package/dist/orchestration/speech.js.map +1 -1
- package/dist/orchestration/store.d.ts +19 -0
- package/dist/orchestration/store.d.ts.map +1 -1
- package/dist/orchestration/store.js +44 -1
- package/dist/orchestration/store.js.map +1 -1
- package/dist/orchestration/tasks/driver.d.ts.map +1 -1
- package/dist/orchestration/tasks/driver.js +8 -3
- package/dist/orchestration/tasks/driver.js.map +1 -1
- package/dist/orchestration/tasks/pool.d.ts.map +1 -1
- package/dist/orchestration/tasks/pool.js +8 -4
- package/dist/orchestration/tasks/pool.js.map +1 -1
- package/dist/orchestration/tasks/service.d.ts +48 -1
- package/dist/orchestration/tasks/service.d.ts.map +1 -1
- package/dist/orchestration/tasks/service.js +41 -17
- package/dist/orchestration/tasks/service.js.map +1 -1
- package/dist/orchestration/token-ledger.d.ts +125 -0
- package/dist/orchestration/token-ledger.d.ts.map +1 -0
- package/dist/orchestration/token-ledger.js +232 -0
- package/dist/orchestration/token-ledger.js.map +1 -0
- package/dist/orchestration/token-usage.d.ts +46 -0
- package/dist/orchestration/token-usage.d.ts.map +1 -0
- package/dist/orchestration/token-usage.js +102 -0
- package/dist/orchestration/token-usage.js.map +1 -0
- package/dist/orchestration/tool-activity.d.ts.map +1 -1
- package/dist/orchestration/tool-activity.js +5 -3
- package/dist/orchestration/tool-activity.js.map +1 -1
- package/dist/orchestration/tool-name.d.ts +10 -0
- package/dist/orchestration/tool-name.d.ts.map +1 -0
- package/dist/orchestration/tool-name.js +14 -0
- package/dist/orchestration/tool-name.js.map +1 -0
- package/dist/orchestration/transcript-checkpoint.d.ts +14 -0
- package/dist/orchestration/transcript-checkpoint.d.ts.map +1 -0
- package/dist/orchestration/transcript-checkpoint.js +83 -0
- package/dist/orchestration/transcript-checkpoint.js.map +1 -0
- package/dist/orchestration/unanswered-inputs.d.ts +6 -0
- package/dist/orchestration/unanswered-inputs.d.ts.map +1 -0
- package/dist/orchestration/unanswered-inputs.js +18 -0
- package/dist/orchestration/unanswered-inputs.js.map +1 -0
- package/dist/session/process.d.ts +10 -0
- package/dist/session/process.d.ts.map +1 -1
- package/dist/session/process.js +91 -9
- package/dist/session/process.js.map +1 -1
- package/dist/session/request-tool-capture.d.ts +31 -0
- package/dist/session/request-tool-capture.d.ts.map +1 -0
- package/dist/session/request-tool-capture.js +194 -0
- package/dist/session/request-tool-capture.js.map +1 -0
- package/dist/session/runtime-profile.d.ts +7 -3
- package/dist/session/runtime-profile.d.ts.map +1 -1
- package/dist/session/runtime-profile.js +3 -1
- package/dist/session/runtime-profile.js.map +1 -1
- package/dist/session/store.d.ts +7 -0
- package/dist/session/store.d.ts.map +1 -1
- package/dist/session/store.js +27 -0
- package/dist/session/store.js.map +1 -1
- package/dist/shell/tailer.d.ts +7 -5
- package/dist/shell/tailer.d.ts.map +1 -1
- package/dist/shell/tailer.js +6 -17
- package/dist/shell/tailer.js.map +1 -1
- package/dist/ui/cli-viewer-ui.js +1 -1
- package/dist/ui/dashboard-client.d.ts +3 -0
- package/dist/ui/dashboard-client.d.ts.map +1 -0
- package/dist/ui/dashboard-client.js +188 -0
- package/dist/ui/dashboard-client.js.map +1 -0
- package/dist/ui/dashboard-presentation.d.ts +9 -0
- package/dist/ui/dashboard-presentation.d.ts.map +1 -0
- package/dist/ui/dashboard-presentation.js +56 -0
- package/dist/ui/dashboard-presentation.js.map +1 -0
- package/dist/ui/dashboard-range.d.ts +5 -0
- package/dist/ui/dashboard-range.d.ts.map +1 -0
- package/dist/ui/dashboard-range.js +20 -0
- package/dist/ui/dashboard-range.js.map +1 -0
- package/dist/ui/dashboard-theme.d.ts +4 -0
- package/dist/ui/dashboard-theme.d.ts.map +1 -0
- package/dist/ui/dashboard-theme.js +485 -0
- package/dist/ui/dashboard-theme.js.map +1 -0
- package/dist/ui/token-report-client.d.ts +3 -0
- package/dist/ui/token-report-client.d.ts.map +1 -0
- package/dist/ui/token-report-client.js +34 -0
- package/dist/ui/token-report-client.js.map +1 -0
- package/dist/ui/token-report.d.ts +89 -0
- package/dist/ui/token-report.d.ts.map +1 -0
- package/dist/ui/token-report.js +200 -0
- package/dist/ui/token-report.js.map +1 -0
- package/dist/ui/web-ui.d.ts.map +1 -1
- package/dist/ui/web-ui.js +124 -181
- package/dist/ui/web-ui.js.map +1 -1
- package/dist/voice/replay.d.ts +8 -0
- package/dist/voice/replay.d.ts.map +1 -0
- package/dist/voice/replay.js +48 -0
- package/dist/voice/replay.js.map +1 -0
- package/dist/voice/session.d.ts +9 -0
- package/dist/voice/session.d.ts.map +1 -1
- package/dist/voice/session.js +72 -14
- package/dist/voice/session.js.map +1 -1
- package/mcp/lazy-connector.test.ts +58 -0
- package/mcp/lazy-connector.ts +67 -0
- package/mcp/lazy-tools.test.ts +152 -0
- package/mcp/lazy-tools.ts +41 -0
- package/mcp/server.ts +53 -34
- package/mcp/tools/discord/commands.ts +2 -0
- package/mcp/tools/discord/inbound.ts +1 -1
- package/mcp/tools/discord/receiver-server.ts +1 -1
- package/mcp/tools/discord/types.ts +1 -1
- package/mcp/tools/receiver-spool.test.ts +8 -2
- package/mcp/tools/receiver-spool.ts +198 -25
- package/mcp/tools/tasks/module.ts +1 -12
- package/mcp/tools/telegram/media-group.ts +3 -3
- package/mcp/tools/telegram/receiver-server.ts +15 -15
- package/mcp/types.ts +1 -1
- package/package.json +2 -1
- package/resource/dashboard/OFL.txt +93 -0
- package/resource/dashboard/poppins-300.woff2 +0 -0
- package/resource/dashboard/poppins-400.woff2 +0 -0
- package/resource/dashboard/poppins-500.woff2 +0 -0
- package/resource/dashboard/poppins-600.woff2 +0 -0
|
@@ -7,5 +7,11 @@ export declare function channelInputMedia(agent: AgentConfig, root: string, sour
|
|
|
7
7
|
name?: string;
|
|
8
8
|
quoted: boolean;
|
|
9
9
|
}[];
|
|
10
|
+
unavailable: {
|
|
11
|
+
code: string;
|
|
12
|
+
name?: string;
|
|
13
|
+
quoted: boolean;
|
|
14
|
+
}[];
|
|
15
|
+
primaryDirectMedia: string | undefined;
|
|
10
16
|
}>;
|
|
11
17
|
//# sourceMappingURL=channel-input-media.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-input-media.d.ts","sourceRoot":"","sources":["../../src/orchestration/channel-input-media.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"channel-input-media.d.ts","sourceRoot":"","sources":["../../src/orchestration/channel-input-media.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAK5C,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,IAAI,EAAC,MAAM,KAAG,IAAI;;;;aAgBhG,MAAM;eAAO,MAAM;gBAAQ,OAAO;;;cACpE,MAAM;eAAO,MAAM;gBAAQ,OAAO;;;GA+BlE"}
|
|
@@ -4,25 +4,36 @@ exports.channelInputMedia = channelInputMedia;
|
|
|
4
4
|
const media_1 = require("./media");
|
|
5
5
|
const channel_media_1 = require("./channel-media");
|
|
6
6
|
const types_1 = require("./types");
|
|
7
|
+
const channel_media_error_1 = require("./channel-media-error");
|
|
7
8
|
async function channelInputMedia(agent, root, source, chatId, meta, discard) {
|
|
8
9
|
const items = [];
|
|
9
10
|
if (meta.attachments_json) {
|
|
10
|
-
|
|
11
|
+
let parsed;
|
|
12
|
+
try {
|
|
13
|
+
parsed = JSON.parse(meta.attachments_json);
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
throw new types_1.OrchestrationError('INVALID_ATTACHMENT');
|
|
17
|
+
}
|
|
11
18
|
if (!Array.isArray(parsed) || parsed.length > 20 || parsed.some(a => !a || typeof a !== 'object' || (a.path !== undefined && typeof a.path !== 'string') || (a.ref !== undefined && typeof a.ref !== 'string') || (a.name !== undefined && typeof a.name !== 'string') || (a.kind !== undefined && typeof a.kind !== 'string') || (a.quoted !== undefined && typeof a.quoted !== 'boolean') || (!a.path && !a.ref)))
|
|
12
19
|
throw new types_1.OrchestrationError('INVALID_ATTACHMENT');
|
|
13
20
|
items.push(...parsed);
|
|
14
21
|
}
|
|
15
22
|
else {
|
|
16
23
|
if (meta.image_path || meta.document_path || meta.sticker_path)
|
|
17
|
-
items.push({ path: meta.image_path || meta.document_path || meta.sticker_path, name: meta.attachment_name });
|
|
24
|
+
items.push({ path: meta.image_path || meta.document_path || meta.sticker_path, name: meta.attachment_name, size: meta.attachment_size === undefined ? undefined : Number(meta.attachment_size) });
|
|
18
25
|
else if (meta.attachment_file_id)
|
|
19
|
-
items.push({ ref: meta.attachment_file_id, name: meta.attachment_name });
|
|
26
|
+
items.push({ ref: meta.attachment_file_id, name: meta.attachment_name, size: meta.attachment_size === undefined ? undefined : Number(meta.attachment_size) });
|
|
20
27
|
}
|
|
21
28
|
if (meta.replied_image_path)
|
|
22
29
|
items.push({ path: meta.replied_image_path, quoted: true });
|
|
23
30
|
else if (meta.replied_attachment_file_id)
|
|
24
|
-
items.push({ ref: meta.replied_attachment_file_id, name: meta.replied_attachment_name, quoted: true });
|
|
31
|
+
items.push({ ref: meta.replied_attachment_file_id, name: meta.replied_attachment_name, size: meta.replied_attachment_size === undefined ? undefined : Number(meta.replied_attachment_size), quoted: true });
|
|
32
|
+
const primaryDirect = items.find(item => !item.quoted);
|
|
33
|
+
let primaryDirectMedia;
|
|
25
34
|
const media = [], quoted = [], details = [];
|
|
35
|
+
const unavailable = [];
|
|
36
|
+
const discardPaths = new Set();
|
|
26
37
|
const seen = new Map();
|
|
27
38
|
for (const item of items) {
|
|
28
39
|
const key = item.path ?? item.ref;
|
|
@@ -31,24 +42,37 @@ async function channelInputMedia(agent, root, source, chatId, meta, discard) {
|
|
|
31
42
|
let ref = seen.get(key);
|
|
32
43
|
if (!ref) {
|
|
33
44
|
try {
|
|
34
|
-
|
|
45
|
+
if (item.size !== undefined && (!Number.isSafeInteger(item.size) || item.size < 0))
|
|
46
|
+
throw new types_1.OrchestrationError('INVALID_ATTACHMENT');
|
|
47
|
+
if (item.size !== undefined && item.size > (source === 'telegram' ? 20 : 50) * 1024 * 1024)
|
|
48
|
+
throw new types_1.OrchestrationError('ATTACHMENT_TOO_LARGE');
|
|
49
|
+
ref = item.path ? (0, media_1.ingestOrchestrationMedia)(root, agent.id, `${source}-${chatId}`, item.path) : await (0, channel_media_1.receiveChannelMedia)(agent, root, source, chatId, item.ref, fetch, item.size);
|
|
35
50
|
}
|
|
36
51
|
catch (error) {
|
|
37
|
-
|
|
38
|
-
if (
|
|
39
|
-
throw
|
|
40
|
-
|
|
52
|
+
const failure = (0, channel_media_error_1.classifyChannelMediaError)(error);
|
|
53
|
+
if (failure.retryable)
|
|
54
|
+
throw failure;
|
|
55
|
+
const name = item.name?.replace(/[\x00-\x1f\x7f]/g, '').slice(0, 200);
|
|
56
|
+
unavailable.push({ code: failure.code, ...(name ? { name } : {}), quoted: Boolean(item.quoted) });
|
|
41
57
|
continue;
|
|
42
58
|
}
|
|
43
59
|
seen.set(key, ref);
|
|
44
60
|
media.push(ref);
|
|
45
61
|
if (item.path && meta.media_ephemeral === '1')
|
|
46
|
-
|
|
62
|
+
discardPaths.add(item.path);
|
|
47
63
|
}
|
|
64
|
+
if (item === primaryDirect)
|
|
65
|
+
primaryDirectMedia = ref;
|
|
48
66
|
if (item.quoted)
|
|
49
67
|
quoted.push(ref);
|
|
50
68
|
details.push({ ref, name: item.name, quoted: Boolean(item.quoted) });
|
|
51
69
|
}
|
|
52
|
-
|
|
70
|
+
if (unavailable.length) {
|
|
71
|
+
const diagnostic = unavailable.some(item => item.quoted) ? 'A quoted attachment is unavailable. Do not claim to have read it.' : 'An attachment is unavailable. Do not claim to have read it.';
|
|
72
|
+
meta.attachment_error = [meta.attachment_error, diagnostic].filter(Boolean).join(' ');
|
|
73
|
+
}
|
|
74
|
+
for (const path of discardPaths)
|
|
75
|
+
discard(path);
|
|
76
|
+
return { media, quoted: [...new Set(quoted)], details, unavailable, primaryDirectMedia };
|
|
53
77
|
}
|
|
54
78
|
//# sourceMappingURL=channel-input-media.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-input-media.js","sourceRoot":"","sources":["../../src/orchestration/channel-input-media.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"channel-input-media.js","sourceRoot":"","sources":["../../src/orchestration/channel-input-media.ts"],"names":[],"mappings":";;AAKA,8CAgDC;AApDD,mCAAmD;AACnD,mDAAsD;AACtD,mCAA6C;AAC7C,+DAAkE;AAC3D,KAAK,UAAU,iBAAiB,CAAC,KAAkB,EAAE,IAAY,EAAE,MAAc,EAAE,MAAc,EAAE,IAA2B,EAAE,OAA4B;IAEjK,MAAM,KAAK,GAAiB,EAAE,CAAC;IAC/B,IAAG,IAAI,CAAC,gBAAgB,EAAC,CAAC;QACxB,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YAAC,MAAM,GAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,MAAM,IAAI,0BAAkB,CAAC,oBAAoB,CAAC,CAAC;QAAC,CAAC;QAC/G,IAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAE,MAAM,CAAC,MAAM,GAAC,EAAE,IAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA,EAAE,CAAA,CAAC,CAAC,IAAE,OAAO,CAAC,KAAG,QAAQ,IAAE,CAAC,CAAC,CAAC,IAAI,KAAG,SAAS,IAAE,OAAO,CAAC,CAAC,IAAI,KAAG,QAAQ,CAAC,IAAE,CAAC,CAAC,CAAC,GAAG,KAAG,SAAS,IAAE,OAAO,CAAC,CAAC,GAAG,KAAG,QAAQ,CAAC,IAAE,CAAC,CAAC,CAAC,IAAI,KAAG,SAAS,IAAE,OAAO,CAAC,CAAC,IAAI,KAAG,QAAQ,CAAC,IAAE,CAAC,CAAC,CAAC,IAAI,KAAG,SAAS,IAAE,OAAO,CAAC,CAAC,IAAI,KAAG,QAAQ,CAAC,IAAE,CAAC,CAAC,CAAC,MAAM,KAAG,SAAS,IAAE,OAAO,CAAC,CAAC,MAAM,KAAG,SAAS,CAAC,IAAE,CAAC,CAAC,CAAC,CAAC,IAAI,IAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YAAC,MAAM,IAAI,0BAAkB,CAAC,oBAAoB,CAAC,CAAC;QAC9Y,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;IACxB,CAAC;SAAM,CAAC;QACN,IAAG,IAAI,CAAC,UAAU,IAAE,IAAI,CAAC,aAAa,IAAE,IAAI,CAAC,YAAY;YAAC,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAC,IAAI,CAAC,UAAU,IAAE,IAAI,CAAC,aAAa,IAAE,IAAI,CAAC,YAAY,EAAC,IAAI,EAAC,IAAI,CAAC,eAAe,EAAC,IAAI,EAAC,IAAI,CAAC,eAAe,KAAG,SAAS,CAAA,CAAC,CAAA,SAAS,CAAA,CAAC,CAAA,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,EAAC,CAAC,CAAC;aACtO,IAAG,IAAI,CAAC,kBAAkB;YAAC,KAAK,CAAC,IAAI,CAAC,EAAC,GAAG,EAAC,IAAI,CAAC,kBAAkB,EAAC,IAAI,EAAC,IAAI,CAAC,eAAe,EAAC,IAAI,EAAC,IAAI,CAAC,eAAe,KAAG,SAAS,CAAA,CAAC,CAAA,SAAS,CAAA,CAAC,CAAA,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,EAAC,CAAC,CAAC;IACnL,CAAC;IACD,IAAG,IAAI,CAAC,kBAAkB;QAAC,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAC,IAAI,CAAC,kBAAkB,EAAC,MAAM,EAAC,IAAI,EAAC,CAAC,CAAC;SAC7E,IAAG,IAAI,CAAC,0BAA0B;QAAC,KAAK,CAAC,IAAI,CAAC,EAAC,GAAG,EAAC,IAAI,CAAC,0BAA0B,EAAC,IAAI,EAAC,IAAI,CAAC,uBAAuB,EAAC,IAAI,EAAC,IAAI,CAAC,uBAAuB,KAAG,SAAS,CAAA,CAAC,CAAA,SAAS,CAAA,CAAC,CAAA,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,EAAC,MAAM,EAAC,IAAI,EAAC,CAAC,CAAC;IACrO,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAA,EAAE,CAAA,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrD,IAAI,kBAAsC,CAAC;IAC3C,MAAM,KAAK,GAAW,EAAE,EAAC,MAAM,GAAW,EAAE,EAAC,OAAO,GAAkD,EAAE,CAAC;IACzG,MAAM,WAAW,GAAmD,EAAE,CAAC;IACvE,MAAM,YAAY,GAAC,IAAI,GAAG,EAAU,CAAC;IACrC,MAAM,IAAI,GAAC,IAAI,GAAG,EAAiB,CAAC;IACpC,KAAI,MAAM,IAAI,IAAI,KAAK,EAAC,CAAC;QACvB,MAAM,GAAG,GAAC,IAAI,CAAC,IAAI,IAAE,IAAI,CAAC,GAAG,CAAC;QAAA,IAAG,CAAC,GAAG;YAAC,SAAS;QAC/C,IAAI,GAAG,GAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACtB,IAAG,CAAC,GAAG,EAAC,CAAC;YACP,IAAI,CAAC;gBACH,IAAG,IAAI,CAAC,IAAI,KAAG,SAAS,IAAE,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAE,IAAI,CAAC,IAAI,GAAC,CAAC,CAAC;oBAAC,MAAM,IAAI,0BAAkB,CAAC,oBAAoB,CAAC,CAAC;gBAC7H,IAAG,IAAI,CAAC,IAAI,KAAG,SAAS,IAAE,IAAI,CAAC,IAAI,GAAC,CAAC,MAAM,KAAG,UAAU,CAAA,CAAC,CAAA,EAAE,CAAA,CAAC,CAAA,EAAE,CAAC,GAAC,IAAI,GAAC,IAAI;oBAAC,MAAM,IAAI,0BAAkB,CAAC,sBAAsB,CAAC,CAAC;gBAC/H,GAAG,GAAC,IAAI,CAAC,IAAI,CAAA,CAAC,CAAA,IAAA,gCAAwB,EAAC,IAAI,EAAC,KAAK,CAAC,EAAE,EAAC,GAAG,MAAM,IAAI,MAAM,EAAE,EAAC,IAAI,CAAC,IAAI,CAAC,CAAA,CAAC,CAAA,MAAM,IAAA,mCAAmB,EAAC,KAAK,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,IAAI,CAAC,GAAI,EAAC,KAAK,EAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACtK,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,OAAO,GAAC,IAAA,+CAAyB,EAAC,KAAK,CAAC,CAAC;gBAC/C,IAAG,OAAO,CAAC,SAAS;oBAAC,MAAM,OAAO,CAAC;gBACnC,MAAM,IAAI,GAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,kBAAkB,EAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAC,GAAG,CAAC,CAAC;gBAClE,WAAW,CAAC,IAAI,CAAC,EAAC,IAAI,EAAC,OAAO,CAAC,IAAI,EAAC,GAAG,CAAC,IAAI,CAAA,CAAC,CAAA,EAAC,IAAI,EAAC,CAAA,CAAC,CAAA,EAAE,CAAC,EAAC,MAAM,EAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAC,CAAC,CAAC;gBACtF,SAAS;YACX,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,GAAG,EAAC,GAAG,CAAC,CAAC;YAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACnC,IAAG,IAAI,CAAC,IAAI,IAAE,IAAI,CAAC,eAAe,KAAG,GAAG;gBAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvE,CAAC;QACD,IAAG,IAAI,KAAG,aAAa;YAAC,kBAAkB,GAAC,GAAG,CAAC;QAC/C,IAAG,IAAI,CAAC,MAAM;YAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChC,OAAO,CAAC,IAAI,CAAC,EAAC,GAAG,EAAC,IAAI,EAAC,IAAI,CAAC,IAAI,EAAC,MAAM,EAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAC,CAAC,CAAC;IACjE,CAAC;IACD,IAAG,WAAW,CAAC,MAAM,EAAE,CAAC;QACtB,MAAM,UAAU,GAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAA,EAAE,CAAA,IAAI,CAAC,MAAM,CAAC,CAAA,CAAC,CAAA,mEAAmE,CAAA,CAAC,CAAA,6DAA6D,CAAC;QACvL,IAAI,CAAC,gBAAgB,GAAC,CAAC,IAAI,CAAC,gBAAgB,EAAC,UAAU,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrF,CAAC;IACD,KAAI,MAAM,IAAI,IAAI,YAAY;QAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,OAAO,EAAC,KAAK,EAAC,MAAM,EAAC,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,EAAC,OAAO,EAAC,WAAW,EAAC,kBAAkB,EAAC,CAAC;AACpF,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { OrchestrationError } from './types';
|
|
2
|
+
/** Safe admission diagnostics: never expose provider URLs, bodies, or credentials. */
|
|
3
|
+
export declare class ChannelMediaError extends OrchestrationError {
|
|
4
|
+
readonly retryable: boolean;
|
|
5
|
+
readonly status?: number | undefined;
|
|
6
|
+
readonly retryAfterMs?: number | undefined;
|
|
7
|
+
constructor(code: string, retryable: boolean, status?: number | undefined, retryAfterMs?: number | undefined);
|
|
8
|
+
}
|
|
9
|
+
export declare function classifyChannelMediaError(error: unknown): ChannelMediaError;
|
|
10
|
+
export declare function channelMediaHttpError(status: number, retryAfter?: string | null): ChannelMediaError;
|
|
11
|
+
//# sourceMappingURL=channel-media-error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-media-error.d.ts","sourceRoot":"","sources":["../../src/orchestration/channel-media-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE7C,sFAAsF;AACtF,qBAAa,iBAAkB,SAAQ,kBAAkB;IAC7B,QAAQ,CAAC,SAAS,EAAE,OAAO;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;IAAE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM;gBAAnG,IAAI,EAAE,MAAM,EAAW,SAAS,EAAE,OAAO,EAAW,MAAM,CAAC,EAAE,MAAM,YAAA,EAAW,YAAY,CAAC,EAAE,MAAM,YAAA;CAGhH;AAED,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,CAS3E;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,iBAAiB,CAQnG"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChannelMediaError = void 0;
|
|
4
|
+
exports.classifyChannelMediaError = classifyChannelMediaError;
|
|
5
|
+
exports.channelMediaHttpError = channelMediaHttpError;
|
|
6
|
+
const types_1 = require("./types");
|
|
7
|
+
/** Safe admission diagnostics: never expose provider URLs, bodies, or credentials. */
|
|
8
|
+
class ChannelMediaError extends types_1.OrchestrationError {
|
|
9
|
+
constructor(code, retryable, status, retryAfterMs) {
|
|
10
|
+
super(code);
|
|
11
|
+
this.retryable = retryable;
|
|
12
|
+
this.status = status;
|
|
13
|
+
this.retryAfterMs = retryAfterMs;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.ChannelMediaError = ChannelMediaError;
|
|
17
|
+
function classifyChannelMediaError(error) {
|
|
18
|
+
if (error instanceof ChannelMediaError)
|
|
19
|
+
return error;
|
|
20
|
+
if (error instanceof types_1.OrchestrationError && ['INVALID_ATTACHMENT', 'ATTACHMENT_TOO_LARGE', 'ATTACHMENT_NOT_CONFIGURED'].includes(error.code)) {
|
|
21
|
+
return new ChannelMediaError(error.code, false);
|
|
22
|
+
}
|
|
23
|
+
const code = error?.code;
|
|
24
|
+
// Missing source files cannot be recovered by retrying the same reference.
|
|
25
|
+
// Disk, permission and reconciliation errors may recover after operator action.
|
|
26
|
+
return new ChannelMediaError('ATTACHMENT_UNAVAILABLE', !['ENOENT', 'ENOTDIR', 'EISDIR'].includes(code ?? ''));
|
|
27
|
+
}
|
|
28
|
+
function channelMediaHttpError(status, retryAfter) {
|
|
29
|
+
let retryAfterMs;
|
|
30
|
+
if (retryAfter) {
|
|
31
|
+
const seconds = Number(retryAfter);
|
|
32
|
+
const delay = Number.isFinite(seconds) ? seconds * 1000 : Date.parse(retryAfter) - Date.now();
|
|
33
|
+
if (Number.isFinite(delay) && delay >= 0)
|
|
34
|
+
retryAfterMs = Math.min(delay, 24 * 60 * 60 * 1000);
|
|
35
|
+
}
|
|
36
|
+
return new ChannelMediaError('ATTACHMENT_UNAVAILABLE', status === 408 || status === 429 || status >= 500, status, retryAfterMs);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=channel-media-error.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-media-error.js","sourceRoot":"","sources":["../../src/orchestration/channel-media-error.ts"],"names":[],"mappings":";;;AASA,8DASC;AAED,sDAQC;AA5BD,mCAA6C;AAE7C,sFAAsF;AACtF,MAAa,iBAAkB,SAAQ,0BAAkB;IACvD,YAAY,IAAY,EAAW,SAAkB,EAAW,MAAe,EAAW,YAAqB;QAC7G,KAAK,CAAC,IAAI,CAAC,CAAC;QADqB,cAAS,GAAT,SAAS,CAAS;QAAW,WAAM,GAAN,MAAM,CAAS;QAAW,iBAAY,GAAZ,YAAY,CAAS;IAE/G,CAAC;CACF;AAJD,8CAIC;AAED,SAAgB,yBAAyB,CAAC,KAAc;IACtD,IAAI,KAAK,YAAY,iBAAiB;QAAE,OAAO,KAAK,CAAC;IACrD,IAAI,KAAK,YAAY,0BAAkB,IAAI,CAAC,oBAAoB,EAAE,sBAAsB,EAAE,2BAA2B,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5I,OAAO,IAAI,iBAAiB,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC;IACD,MAAM,IAAI,GAAI,KAA2C,EAAE,IAAI,CAAC;IAChE,2EAA2E;IAC3E,gFAAgF;IAChF,OAAO,IAAI,iBAAiB,CAAC,wBAAwB,EAAE,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC;AAChH,CAAC;AAED,SAAgB,qBAAqB,CAAC,MAAc,EAAE,UAA0B;IAC9E,IAAI,YAAgC,CAAC;IACrC,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9F,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;YAAE,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,IAAI,iBAAiB,CAAC,wBAAwB,EAAE,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,IAAI,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;AAClI,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { AgentConfig } from '../types';
|
|
2
2
|
/** Resolve provider-only attachment references before acknowledging receiver ingress. */
|
|
3
|
-
export declare function receiveChannelMedia(agent: AgentConfig, agentsRoot: string, source: string, chatId: string, ref: string, request?: typeof fetch): Promise<string>;
|
|
3
|
+
export declare function receiveChannelMedia(agent: AgentConfig, agentsRoot: string, source: string, chatId: string, ref: string, request?: typeof fetch, size?: number): Promise<string>;
|
|
4
4
|
//# sourceMappingURL=channel-media.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-media.d.ts","sourceRoot":"","sources":["../../src/orchestration/channel-media.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"channel-media.d.ts","sourceRoot":"","sources":["../../src/orchestration/channel-media.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAKvC,yFAAyF;AACzF,wBAAsB,mBAAmB,CAAC,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,OAAO,KAAa,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAI5L"}
|
|
@@ -6,16 +6,39 @@ const path_1 = require("path");
|
|
|
6
6
|
const crypto_1 = require("crypto");
|
|
7
7
|
const types_1 = require("./types");
|
|
8
8
|
const media_1 = require("./media");
|
|
9
|
+
const channel_media_error_1 = require("./channel-media-error");
|
|
9
10
|
/** Resolve provider-only attachment references before acknowledging receiver ingress. */
|
|
10
|
-
async function receiveChannelMedia(agent, agentsRoot, source, chatId, ref, request = fetch) {
|
|
11
|
+
async function receiveChannelMedia(agent, agentsRoot, source, chatId, ref, request = fetch, size) {
|
|
12
|
+
try {
|
|
13
|
+
return await receive(agent, agentsRoot, source, chatId, ref, request, size);
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
throw (0, channel_media_error_1.classifyChannelMediaError)(error);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async function receive(agent, agentsRoot, source, chatId, ref, request, size) {
|
|
20
|
+
const limit = (source === 'telegram' ? 20 : 50) * 1024 * 1024;
|
|
21
|
+
if (size !== undefined && (!Number.isSafeInteger(size) || size < 0))
|
|
22
|
+
throw new types_1.OrchestrationError('INVALID_ATTACHMENT');
|
|
23
|
+
if (size !== undefined && size > limit)
|
|
24
|
+
throw new types_1.OrchestrationError('ATTACHMENT_TOO_LARGE');
|
|
11
25
|
if (!ref || ref.length > 8192)
|
|
12
26
|
throw new types_1.OrchestrationError('INVALID_ATTACHMENT');
|
|
13
27
|
let url;
|
|
14
28
|
if (source === 'telegram' && agent.telegram?.botToken) {
|
|
15
29
|
const response = await request(`https://api.telegram.org/bot${agent.telegram.botToken}/getFile`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ file_id: ref }), signal: AbortSignal.timeout(10000) });
|
|
16
|
-
if (!response.ok)
|
|
17
|
-
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
const errorBody = await response.json().catch(() => undefined);
|
|
32
|
+
const retryAfter = response.headers.get('retry-after') ?? (typeof errorBody?.parameters?.retry_after === 'number' ? String(errorBody.parameters.retry_after) : undefined);
|
|
33
|
+
throw (0, channel_media_error_1.channelMediaHttpError)(response.status, retryAfter);
|
|
34
|
+
}
|
|
18
35
|
const body = await response.json();
|
|
36
|
+
if (!body.ok) {
|
|
37
|
+
const status = body.error_code;
|
|
38
|
+
throw status && Number.isInteger(status) && status >= 400 && status <= 599
|
|
39
|
+
? (0, channel_media_error_1.channelMediaHttpError)(status, body.parameters?.retry_after === undefined ? undefined : String(body.parameters.retry_after))
|
|
40
|
+
: new channel_media_error_1.ChannelMediaError('ATTACHMENT_UNAVAILABLE', true);
|
|
41
|
+
}
|
|
19
42
|
const path = body.result?.file_path;
|
|
20
43
|
if (!body.ok || !path || path.split('/').some(part => part === '..') || !/^[A-Za-z0-9_./-]+$/.test(path))
|
|
21
44
|
throw new types_1.OrchestrationError('INVALID_ATTACHMENT');
|
|
@@ -24,7 +47,13 @@ async function receiveChannelMedia(agent, agentsRoot, source, chatId, ref, reque
|
|
|
24
47
|
url = `https://api.telegram.org/file/bot${agent.telegram.botToken}/${path}`;
|
|
25
48
|
}
|
|
26
49
|
else if (source === 'discord') {
|
|
27
|
-
|
|
50
|
+
let parsed;
|
|
51
|
+
try {
|
|
52
|
+
parsed = new URL(ref);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
throw new types_1.OrchestrationError('INVALID_ATTACHMENT');
|
|
56
|
+
}
|
|
28
57
|
if (parsed.protocol !== 'https:' || parsed.username || parsed.password || !['cdn.discordapp.com', 'media.discordapp.net'].includes(parsed.hostname))
|
|
29
58
|
throw new types_1.OrchestrationError('INVALID_ATTACHMENT');
|
|
30
59
|
url = parsed.href;
|
|
@@ -32,9 +61,10 @@ async function receiveChannelMedia(agent, agentsRoot, source, chatId, ref, reque
|
|
|
32
61
|
else
|
|
33
62
|
throw new types_1.OrchestrationError('ATTACHMENT_NOT_CONFIGURED');
|
|
34
63
|
const response = await request(url, { redirect: 'error', signal: AbortSignal.timeout(30000) });
|
|
35
|
-
if (!response.ok
|
|
36
|
-
throw
|
|
37
|
-
|
|
64
|
+
if (!response.ok)
|
|
65
|
+
throw (0, channel_media_error_1.channelMediaHttpError)(response.status, response.headers.get('retry-after'));
|
|
66
|
+
if (!response.body)
|
|
67
|
+
throw new channel_media_error_1.ChannelMediaError('ATTACHMENT_UNAVAILABLE', true);
|
|
38
68
|
const reader = response.body.getReader(), chunks = [];
|
|
39
69
|
let bytes = 0;
|
|
40
70
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel-media.js","sourceRoot":"","sources":["../../src/orchestration/channel-media.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"channel-media.js","sourceRoot":"","sources":["../../src/orchestration/channel-media.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare function referenceTokens(text: string): number;
|
|
2
|
+
export interface ContextFootprint {
|
|
3
|
+
observedAt: number;
|
|
4
|
+
rows: Array<{
|
|
5
|
+
name: string;
|
|
6
|
+
tokens: number | null;
|
|
7
|
+
characters: number | null;
|
|
8
|
+
hasContent?: boolean;
|
|
9
|
+
note: string;
|
|
10
|
+
}>;
|
|
11
|
+
}
|
|
12
|
+
/** Run in the dashboard reader thread. Never launch a CLI/model or return file content. */
|
|
13
|
+
export declare function contextFootprint(workspace: string | undefined): ContextFootprint;
|
|
14
|
+
//# sourceMappingURL=context-footprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-footprint.d.ts","sourceRoot":"","sources":["../../src/orchestration/context-footprint.ts"],"names":[],"mappings":"AAOA,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGpD;AACD,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,KAAK,CAAC;QAAC,IAAI,EAAC,MAAM,CAAC;QAAA,MAAM,EAAC,MAAM,GAAC,IAAI,CAAC;QAAA,UAAU,EAAC,MAAM,GAAC,IAAI,CAAC;QAAA,UAAU,CAAC,EAAC,OAAO,CAAC;QAAA,IAAI,EAAC,MAAM,CAAA;KAAC,CAAC,CAAC;CACtG;AACD,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,gBAAgB,CA2BhF"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.referenceTokens = referenceTokens;
|
|
4
|
+
exports.contextFootprint = contextFootprint;
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const js_tiktoken_1 = require("js-tiktoken");
|
|
8
|
+
const agent_tool_schemas_1 = require("./agent-tool-schemas");
|
|
9
|
+
const cache = new Map();
|
|
10
|
+
let encoder;
|
|
11
|
+
function referenceTokens(text) {
|
|
12
|
+
encoder ?? (encoder = (0, js_tiktoken_1.getEncoding)('cl100k_base'));
|
|
13
|
+
return encoder.encode(text, [], []).length;
|
|
14
|
+
}
|
|
15
|
+
/** Run in the dashboard reader thread. Never launch a CLI/model or return file content. */
|
|
16
|
+
function contextFootprint(workspace) {
|
|
17
|
+
if (!workspace)
|
|
18
|
+
return { observedAt: Date.now(), rows: [] };
|
|
19
|
+
const key = workspace, previous = cache.get(key);
|
|
20
|
+
if (previous && Date.now() - previous.at < 30000)
|
|
21
|
+
return previous.value;
|
|
22
|
+
const rows = [];
|
|
23
|
+
const read = (name) => {
|
|
24
|
+
try {
|
|
25
|
+
const filename = (0, path_1.join)(workspace, name);
|
|
26
|
+
if ((0, fs_1.statSync)(filename).size > 1024 * 1024)
|
|
27
|
+
return undefined;
|
|
28
|
+
return (0, fs_1.readFileSync)(filename, 'utf8');
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const add = (name, text, note) => rows.push({ name, tokens: text === undefined ? null : referenceTokens(text), characters: text === undefined ? null : [...text].length, hasContent: Boolean(text?.trim()), note });
|
|
35
|
+
const composed = read('CLAUDE.md');
|
|
36
|
+
add('CLAUDE.md · composed workspace context', composed, 'Current generated file after workspace budgets. Parent total; do not add its sections again. Not the complete CLI prompt.');
|
|
37
|
+
const labels = { 'AGENT IDENTITY': 'AGENTS.md', 'IDENTITY': 'IDENTITY.md', 'SOUL': 'SOUL.md', 'USER PROFILE': 'USER.md', 'LONG-TERM MEMORY': 'MEMORY.md', 'HEARTBEAT CONFIG': 'HEARTBEAT.md', 'AVAILABLE SKILLS': 'Skill catalog', 'MEMORY RULE': 'Memory rules', 'MEMORY RETRIEVAL': 'Memory retrieval instructions' };
|
|
38
|
+
if (composed) {
|
|
39
|
+
const markers = [...composed.matchAll(/^--- ([A-Z -]+) ---\n/gm)];
|
|
40
|
+
for (let i = 0; i < markers.length; i++) {
|
|
41
|
+
const marker = markers[i], name = labels[marker[1]] || marker[1];
|
|
42
|
+
const text = composed.slice(marker.index + marker[0].length, markers[i + 1]?.index ?? composed.length);
|
|
43
|
+
add('↳ ' + name, text, 'Section found in generated CLAUDE.md; includes section whitespace. Boundary tokenization can differ from parent total.');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
for (const name of ['AGENTS.md', 'IDENTITY.md', 'SOUL.md', 'USER.md', 'MEMORY.md', 'HEARTBEAT.md'])
|
|
47
|
+
add(name + ' · source file', read(name), 'Current file on disk before budget/index/truncation. Reference only; not added to composed context.');
|
|
48
|
+
// Every agent tool is declared on every turn, so the measured schema cost does not
|
|
49
|
+
// depend on any feature flag. Filtering one out here would under-report the real prefix.
|
|
50
|
+
add('Agent gateway tool schemas (' + agent_tool_schemas_1.AGENT_TASK_TOOLS.length + ')', JSON.stringify(agent_tool_schemas_1.AGENT_TASK_TOOLS), 'Current host Agent MCP definitions: name, description and inputSchema. Excludes native CLI tools, worker tools and provider framing.');
|
|
51
|
+
const value = { observedAt: Date.now(), rows };
|
|
52
|
+
if (cache.size >= 32)
|
|
53
|
+
cache.delete(cache.keys().next().value);
|
|
54
|
+
cache.set(key, { at: Date.now(), value });
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=context-footprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-footprint.js","sourceRoot":"","sources":["../../src/orchestration/context-footprint.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@ export interface IntakeChoice {
|
|
|
7
7
|
clarification?: string;
|
|
8
8
|
task_id?: string;
|
|
9
9
|
}
|
|
10
|
-
export declare const INTAKE_OVERLAY = "Use conversation_intake only for executable work, incomplete materials, or amendments to an existing task. Greetings, introductions, casual conversation and questions you can answer directly need one normal answer: do not call conversation_intake or emit a separate acknowledgement for them.\nBefore any work mutation, use conversation_intake to decide how to handle the user's latest input together with pending materials and current tasks.\nready: the requested executable action and required material are complete. Supply a brief, specific acknowledgement addressed directly to the user, in their language and your existing persona. This text is immediately displayed and
|
|
10
|
+
export declare const INTAKE_OVERLAY = "Use conversation_intake only for executable work, incomplete materials, or amendments to an existing task. Greetings, introductions, casual conversation and questions you can answer directly need one normal answer: do not call conversation_intake or emit a separate acknowledgement for them.\nBefore any work mutation, use conversation_intake to decide how to handle the user's latest input together with pending materials and current tasks.\nready: the requested executable action and required material are complete. Supply a brief, specific acknowledgement addressed directly to the user, in their language and your existing persona. This text is immediately displayed to the user and speech is attempted when enabled; it is not a private classification, instruction to yourself, or reasoning field. Do not add a waiting period. A successful acknowledgement permits dispatch even when audio is unavailable. If a task tool fails, explain the failure and never claim work started without a successful receipt.\nwait: the user is supplying materials without an action, promises an attachment that has not arrived, or says the instruction will follow. Inspect available images now. Preserve useful facts in preparation, clearly distinguishing observed contents from instructions. Supply one short clarification to ask only if no further input arrives for the configured intake wait interval. Do not speculate about unavailable link contents. End this turn without user-facing text; the gateway owns the waiting timer. Each new item will be read as it arrives.\nupdate: the user changes or supplements a specific existing task. Supply its exact task_id and acknowledge the change; use task_update/task_answer, not an independent duplicate. If the target is ambiguous, ask a precise question instead of guessing.\nNever create work merely to acknowledge material. A complete instruction arriving after materials is ready now; do not request another waiting interval. Preserve all unchanged requirements and refer to the original input/attachment IDs. Urgent stop or prohibition may call task_cancel before acknowledgement; do not delay fencing unsafe work for speech playback.";
|
|
11
11
|
/** Durable preparation is scoped by conversation AND authenticated principal.
|
|
12
12
|
* Source inputs remain canonical; this cache only supplements their full contents. */
|
|
13
13
|
export declare class ConversationIntake {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation-intake.d.ts","sourceRoot":"","sources":["../../src/orchestration/conversation-intake.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAe,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAsB,MAAM,SAAS,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"conversation-intake.d.ts","sourceRoot":"","sources":["../../src/orchestration/conversation-intake.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAe,MAAM,SAAS,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAsB,MAAM,SAAS,CAAC;AAE7D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;IAClC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AACD,eAAO,MAAM,cAAc,ioEAKgV,CAAC;AAE5W;sFACsF;AACtF,qBAAa,kBAAkB;IACjB,OAAO,CAAC,KAAK;gBAAL,KAAK,EAAE,kBAAkB;IAQ7C,OAAO,CAAC,cAAc,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM;IAMvE,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAO5B;sEACkE;IAClE,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM9B,MAAM,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,YAAY;;;;;;cA7C9C,OAAO,GAAG,MAAM,GAAG,QAAQ;kBAIvB,MAAM;;IAqEhB,GAAG,CAAC,MAAM,SAAO,EAAE,GAAG,SAAa;CAUpC"}
|
|
@@ -5,7 +5,7 @@ const store_1 = require("./store");
|
|
|
5
5
|
const types_1 = require("./types");
|
|
6
6
|
exports.INTAKE_OVERLAY = `Use conversation_intake only for executable work, incomplete materials, or amendments to an existing task. Greetings, introductions, casual conversation and questions you can answer directly need one normal answer: do not call conversation_intake or emit a separate acknowledgement for them.
|
|
7
7
|
Before any work mutation, use conversation_intake to decide how to handle the user's latest input together with pending materials and current tasks.
|
|
8
|
-
ready: the requested executable action and required material are complete. Supply a brief, specific acknowledgement addressed directly to the user, in their language and your existing persona. This text is immediately displayed and
|
|
8
|
+
ready: the requested executable action and required material are complete. Supply a brief, specific acknowledgement addressed directly to the user, in their language and your existing persona. This text is immediately displayed to the user and speech is attempted when enabled; it is not a private classification, instruction to yourself, or reasoning field. Do not add a waiting period. A successful acknowledgement permits dispatch even when audio is unavailable. If a task tool fails, explain the failure and never claim work started without a successful receipt.
|
|
9
9
|
wait: the user is supplying materials without an action, promises an attachment that has not arrived, or says the instruction will follow. Inspect available images now. Preserve useful facts in preparation, clearly distinguishing observed contents from instructions. Supply one short clarification to ask only if no further input arrives for the configured intake wait interval. Do not speculate about unavailable link contents. End this turn without user-facing text; the gateway owns the waiting timer. Each new item will be read as it arrives.
|
|
10
10
|
update: the user changes or supplements a specific existing task. Supply its exact task_id and acknowledge the change; use task_update/task_answer, not an independent duplicate. If the target is ambiguous, ask a precise question instead of guessing.
|
|
11
11
|
Never create work merely to acknowledge material. A complete instruction arriving after materials is ready now; do not request another waiting interval. Preserve all unchanged requirements and refer to the original input/attachment IDs. Urgent stop or prohibition may call task_cancel before acknowledgement; do not delay fencing unsafe work for speech playback.`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-reader-worker.d.ts","sourceRoot":"","sources":["../../src/orchestration/dashboard-reader-worker.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const context_footprint_1 = require("./context-footprint");
|
|
4
|
+
const worker_threads_1 = require("worker_threads");
|
|
5
|
+
const node_sqlite_1 = require("node:sqlite");
|
|
6
|
+
const fs_1 = require("fs");
|
|
7
|
+
const token_ledger_1 = require("./token-ledger");
|
|
8
|
+
const task_directive_1 = require("./tasks/task-directive");
|
|
9
|
+
/**
|
|
10
|
+
* Conversation activity status — the single source shared by the dashboard
|
|
11
|
+
* Conversations "Status" column and the Session token report header, so the two
|
|
12
|
+
* views can never disagree (thinking → working → waiting_input → queued → idle).
|
|
13
|
+
* `thinking` is returned alongside so callers keep the existing isRunning signal
|
|
14
|
+
* without re-querying. Display-only; does not touch token accounting.
|
|
15
|
+
*/
|
|
16
|
+
function conversationActivityStatus(get, all, conversationId) {
|
|
17
|
+
const thinking = Boolean(get("SELECT id FROM conversation_decisions WHERE conversation_id=? AND state IN ('running','interrupting') LIMIT 1", conversationId));
|
|
18
|
+
const states = all("SELECT DISTINCT state FROM tasks WHERE conversation_id=? AND state NOT IN ('completed','failed','cancelled')", conversationId).map(t => t.state);
|
|
19
|
+
const lastTurn = get('SELECT MAX(ended_at) ended_at FROM conversation_decisions WHERE conversation_id=?', conversationId)?.ended_at;
|
|
20
|
+
const resting = lastTurn != null && Date.now() - Number(lastTurn) <= 3600000 ? 'idle' : 'stopped';
|
|
21
|
+
const status = thinking ? 'thinking' : states.includes('needs_reconciliation') ? 'needs_reconciliation' : states.some(s => ['starting', 'running', 'interrupting', 'cancel_requested', 'recovering'].includes(s)) ? 'working' : states.includes('waiting_input') ? 'waiting_input' : states.includes('queued') ? 'queued' : resting;
|
|
22
|
+
return { status, thinking };
|
|
23
|
+
}
|
|
24
|
+
const connections = new Map();
|
|
25
|
+
function database(filename) {
|
|
26
|
+
if (!(0, fs_1.existsSync)(filename))
|
|
27
|
+
return undefined;
|
|
28
|
+
let db = connections.get(filename);
|
|
29
|
+
if (!db) {
|
|
30
|
+
if (connections.size >= 32) {
|
|
31
|
+
const key = connections.keys().next().value;
|
|
32
|
+
connections.get(key).close();
|
|
33
|
+
connections.delete(key);
|
|
34
|
+
}
|
|
35
|
+
db = new node_sqlite_1.DatabaseSync(filename, { readOnly: true });
|
|
36
|
+
db.exec('PRAGMA query_only=ON; PRAGMA busy_timeout=1000');
|
|
37
|
+
connections.set(filename, db);
|
|
38
|
+
}
|
|
39
|
+
connections.delete(filename);
|
|
40
|
+
connections.set(filename, db);
|
|
41
|
+
return db;
|
|
42
|
+
}
|
|
43
|
+
function read(filename, operation, options) {
|
|
44
|
+
const db = database(filename);
|
|
45
|
+
if (!db)
|
|
46
|
+
return undefined;
|
|
47
|
+
const all = (sql, ...params) => db.prepare(sql).all(...params);
|
|
48
|
+
const get = (sql, ...params) => db.prepare(sql).get(...params);
|
|
49
|
+
const exists = (table) => Boolean(get("SELECT name FROM sqlite_master WHERE type='table' AND name=?", table));
|
|
50
|
+
if (!exists('conversations'))
|
|
51
|
+
return undefined;
|
|
52
|
+
const since = Math.max(0, Number(options.since) || 0);
|
|
53
|
+
// A read transaction makes the session/task/attempt relationships consistent.
|
|
54
|
+
db.exec('BEGIN');
|
|
55
|
+
try {
|
|
56
|
+
const adapter = { all, get, attempt: (id) => { const row = get('SELECT payload_json FROM task_attempts WHERE id=?', id); return row ? JSON.parse(row.payload_json) : undefined; } };
|
|
57
|
+
if (operation === 'report' || operation === 'session') {
|
|
58
|
+
if (!get('SELECT id FROM conversations WHERE agent_session_id=?', options.sessionId))
|
|
59
|
+
return undefined;
|
|
60
|
+
// Before the ledger table exists (an agent whose very first turn has not recorded
|
|
61
|
+
// usage yet) a queued input still has to be visible, so derive the pending rows
|
|
62
|
+
// without the token_turns lookup instead of returning an empty list.
|
|
63
|
+
const report = exists('token_turns') ? (0, token_ledger_1.readTokenReport)(adapter, options.sessionId, true, { offset: Math.max(0, Number(options.offset) || 0), limit: operation === 'report' ? 25 : 50, since, newestFirst: true }) : { sessionId: options.sessionId, turns: (0, token_ledger_1.pendingInputTurns)(adapter, options.sessionId, since, false), totals: { agentTokens: null, workerTokens: null, totalTokens: null }, coverage: 'recorded-turns-only' };
|
|
64
|
+
if (operation === 'session') {
|
|
65
|
+
const session = get('SELECT * FROM conversations WHERE agent_session_id=?', options.sessionId);
|
|
66
|
+
const offset = Math.max(0, Number(options.offset) || 0);
|
|
67
|
+
const tasks = all('SELECT id,state,snapshot_json,updated_at FROM tasks WHERE conversation_id=? AND updated_at>=? ORDER BY updated_at DESC,id LIMIT 50 OFFSET ?', session.id, since, offset).map(t => ({ taskId: t.id, state: t.state, title: JSON.parse(t.snapshot_json).title, updatedAt: t.updated_at }));
|
|
68
|
+
// Same activity status the Conversations column shows, so the session drawer's
|
|
69
|
+
// Context window box can use the same idle-vs-stopped disambiguation as the report page.
|
|
70
|
+
const activityStatus = conversationActivityStatus(get, all, session.id).status;
|
|
71
|
+
return { ...report, session: { sessionId: session.agent_session_id, source: session.source, chatId: session.chat_id, createdAt: session.created_at, updatedAt: session.updated_at }, tasks, totalTasks: Number(get('SELECT COUNT(*) n FROM tasks WHERE conversation_id=? AND updated_at>=?', session.id, since).n), offset, activityStatus };
|
|
72
|
+
}
|
|
73
|
+
const session = get('SELECT id,source,chat_id FROM conversations WHERE agent_session_id=?', options.sessionId);
|
|
74
|
+
// Same activity status the Conversations column shows, so the report header mirrors it.
|
|
75
|
+
const activityStatus = conversationActivityStatus(get, all, session.id).status;
|
|
76
|
+
return { ...report, source: session.source, chatId: session.chat_id, activityStatus, since, contextFootprint: (0, context_footprint_1.contextFootprint)(options.workspace) };
|
|
77
|
+
}
|
|
78
|
+
if (operation === 'task') {
|
|
79
|
+
const row = get('SELECT t.*,c.agent_session_id FROM tasks t JOIN conversations c ON c.id=t.conversation_id WHERE t.id=? AND c.agent_session_id=?', options.taskId, options.sessionId);
|
|
80
|
+
if (!row)
|
|
81
|
+
return undefined;
|
|
82
|
+
const snapshot = JSON.parse(row.snapshot_json);
|
|
83
|
+
// The assignment text is never stored on the task snapshot — it lives in task_revisions.
|
|
84
|
+
// Read the revisions the worker actually received (appliedRevision, or the newest authored
|
|
85
|
+
// one before the first claim) and normalize them exactly like TaskService.revision() does,
|
|
86
|
+
// so a revision > 1 shows the effective brief instead of append-only answer text.
|
|
87
|
+
const effectiveRevision = Number(snapshot.appliedRevision) || Number(snapshot.revision) || Number.MAX_SAFE_INTEGER;
|
|
88
|
+
const revisions = all('SELECT payload_json FROM task_revisions WHERE task_id=? AND revision<=? ORDER BY revision', options.taskId, effectiveRevision)
|
|
89
|
+
.map(r => JSON.parse(String(r.payload_json)));
|
|
90
|
+
const instructions = revisions.length ? (0, task_directive_1.normalizeTaskRevisions)(revisions).instructions : undefined;
|
|
91
|
+
const offset = Math.max(0, Number(options.offset) || 0);
|
|
92
|
+
const attempts = all(`SELECT payload_json FROM task_attempts WHERE task_id=? AND COALESCE(json_extract(payload_json,'$.startedAt'),0)>=? ORDER BY generation DESC LIMIT 25 OFFSET ?`, options.taskId, since, offset).map(r => {
|
|
93
|
+
const attempt = JSON.parse(r.payload_json);
|
|
94
|
+
const metrics = exists('token_turns') ? get('SELECT payload_json FROM token_turns WHERE id=? AND session_id=?', attempt.attemptId, options.sessionId) : undefined;
|
|
95
|
+
const events = all('SELECT type,payload_json,occurred_at FROM worker_events WHERE attempt_id=? ORDER BY local_seq DESC LIMIT 30', attempt.attemptId).map(e => ({ type: e.type, at: e.occurred_at, payload: JSON.parse(e.payload_json) }));
|
|
96
|
+
return { ...attempt, metrics: metrics ? JSON.parse(metrics.payload_json) : null, events };
|
|
97
|
+
});
|
|
98
|
+
return { snapshot, instructions, attempts, totalAttempts: Number(get("SELECT COUNT(*) n FROM task_attempts WHERE task_id=? AND COALESCE(json_extract(payload_json,'$.startedAt'),0)>=?", options.taskId, since).n), offset };
|
|
99
|
+
}
|
|
100
|
+
const offset = Math.max(0, Number(options.offset) || 0), limit = 25;
|
|
101
|
+
const conversations = all('SELECT c.* FROM conversations c WHERE c.updated_at>=? ORDER BY c.updated_at DESC,c.id DESC LIMIT ? OFFSET ?', since, limit, offset);
|
|
102
|
+
const sessions = conversations.map(c => {
|
|
103
|
+
const turns = exists('token_turn_metrics')
|
|
104
|
+
? all("SELECT COALESCE(m.payload_json,json_remove(t.payload_json,'$.requests','$.inputTexts','$.responseText')) payload_json FROM token_turns t LEFT JOIN token_turn_metrics m ON m.id=t.id WHERE t.session_id=? AND t.started_at>=? ORDER BY t.started_at,t.id", c.agent_session_id, since).map(r => JSON.parse(r.payload_json))
|
|
105
|
+
: exists('token_turns') ? all(`SELECT id,role,task_id,started_at,json_extract(payload_json,'$.usage') usage,
|
|
106
|
+
json_extract(payload_json,'$.loadedTools') loadedTools,json_extract(payload_json,'$.usedTools') usedTools,
|
|
107
|
+
json_extract(payload_json,'$.model') model FROM token_turns WHERE session_id=? AND started_at>=? ORDER BY started_at,id`, c.agent_session_id, since).map(r => ({ ...r, taskId: r.task_id, startedAt: r.started_at, sessionId: c.agent_session_id, usage: r.usage ? JSON.parse(r.usage) : null, loadedTools: r.loadedTools ? JSON.parse(r.loadedTools) : null, usedTools: r.usedTools ? JSON.parse(r.usedTools) : [] })) : [];
|
|
108
|
+
const agent = (0, token_ledger_1.summarizeTokenTurns)(turns.filter(t => t.role === 'agent')), workers = (0, token_ledger_1.summarizeTokenTurns)(turns.filter(t => t.role === 'worker'));
|
|
109
|
+
const tasks = all(`SELECT * FROM tasks WHERE conversation_id=? AND updated_at>=? ORDER BY updated_at DESC,id DESC LIMIT 100`, c.id, since).map(t => {
|
|
110
|
+
const snapshot = JSON.parse(t.snapshot_json);
|
|
111
|
+
const last = t.active_attempt_id ? { id: t.active_attempt_id } : get('SELECT id FROM task_attempts WHERE task_id=? ORDER BY generation DESC LIMIT 1', t.id);
|
|
112
|
+
const attempt = last ? adapter.attempt(last.id) : undefined;
|
|
113
|
+
const metrics = (0, token_ledger_1.summarizeTokenTurns)(turns.filter(turn => turn.id === attempt?.attemptId));
|
|
114
|
+
const total = (0, token_ledger_1.summarizeTokenTurns)(turns.filter(turn => turn.taskId === t.id));
|
|
115
|
+
const lastTool = get("SELECT payload_json,occurred_at FROM conversation_events WHERE json_extract(payload_json,'$.task_id')=? AND type='tool.activity' ORDER BY seq DESC LIMIT 1", t.id);
|
|
116
|
+
const tool = lastTool ? JSON.parse(lastTool.payload_json).payload : undefined;
|
|
117
|
+
return { taskId: t.id, sessionId: c.agent_session_id, title: snapshot.title, state: t.state, updatedAt: t.updated_at,
|
|
118
|
+
createdAt: t.created_at, execution: snapshot.execution, workerId: attempt?.workerId, attemptId: attempt?.attemptId,
|
|
119
|
+
workerSessionId: attempt?.sessionId, resumed: attempt?.resumeSession, workstreamId: snapshot.workstreamId,
|
|
120
|
+
continueTaskId: snapshot.continueTaskId, hostProcessId: t.active_attempt_id ? attempt?.processIdentity?.pid : undefined,
|
|
121
|
+
tokenSummary: { totalTokens: metrics.totalTokens, allAttemptsTokens: total.totalTokens }, contextTools: metrics.contextTools, loadedTools: metrics.loadedTools, usedTools: metrics.usedTools,
|
|
122
|
+
lastTool: tool ? { name: tool.name, type: tool.type, is_error: tool.is_error, at: lastTool.occurred_at } : undefined };
|
|
123
|
+
});
|
|
124
|
+
const { status: state, thinking } = conversationActivityStatus(get, all, c.id);
|
|
125
|
+
const totalTokens = agent.totalTokens === null && workers.totalTokens === null ? null : (agent.totalTokens ?? 0) + (workers.totalTokens ?? 0);
|
|
126
|
+
return { sessionId: c.agent_session_id, chatId: c.chat_id, source: c.source, orchestration: true, mode: 'headless', status: state, isRunning: thinking,
|
|
127
|
+
model: turns.filter(t => t.role === 'agent' && t.model).at(-1)?.model ?? '', updatedAt: c.updated_at, createdAt: c.created_at,
|
|
128
|
+
tokenSummary: { agentTokens: agent.totalTokens, workerTokens: workers.totalTokens, totalTokens }, contextTools: agent.contextTools, loadedTools: agent.loadedTools, usedTools: agent.usedTools,
|
|
129
|
+
tasks, totalTasks: Number(get('SELECT COUNT(*) n FROM tasks WHERE conversation_id=? AND updated_at>=?', c.id, since).n),
|
|
130
|
+
workerIds: all('SELECT id FROM worker_pool WHERE conversation_id=?', c.id).map(w => w.id), spawnedAt: 0, uptimeSec: 0, tokens: 0 };
|
|
131
|
+
});
|
|
132
|
+
const today = Date.now() - Date.now() % 86400000;
|
|
133
|
+
const usageToday = exists('token_turns') ? all(`SELECT role,CAST((started_at-?)/3600000 AS INTEGER) hour,SUM(json_extract(payload_json,'$.usage.totalTokens')) tokens FROM token_turns WHERE started_at>=? AND json_type(payload_json,'$.usage')='object' GROUP BY role,hour`, today, Math.max(today, since)) : [];
|
|
134
|
+
const attention = all(`SELECT t.id taskId,t.state,t.snapshot_json,c.agent_session_id sessionId FROM tasks t JOIN conversations c ON c.id=t.conversation_id WHERE t.updated_at>=? AND t.state IN ('waiting_input','needs_reconciliation') ORDER BY t.updated_at DESC LIMIT 8`, since).map(t => ({ taskId: t.taskId, state: t.state, sessionId: t.sessionId, title: JSON.parse(t.snapshot_json).title }));
|
|
135
|
+
const recentWork = all(`SELECT t.id taskId,t.state,t.snapshot_json,t.updated_at updatedAt,c.agent_session_id sessionId FROM tasks t JOIN conversations c ON c.id=t.conversation_id WHERE t.updated_at>=? ORDER BY t.updated_at DESC,t.id DESC LIMIT 6`, today).map(t => ({ taskId: t.taskId, state: t.state, sessionId: t.sessionId, updatedAt: t.updatedAt, title: JSON.parse(t.snapshot_json).title }));
|
|
136
|
+
const pool = exists('worker_pool') ? all('SELECT * FROM worker_pool') : [];
|
|
137
|
+
return { usageToday, attention, recentWork, managedLegacyIds: all('SELECT agent_session_id FROM conversations WHERE agent_session_id IN (SELECT value FROM json_each(?))', JSON.stringify(options.legacyIds ?? [])).map(c => c.agent_session_id), enabled: true, backend: 'headless', workspaceMode: options.workspaceMode, sessions, tasks: sessions.flatMap(s => s.tasks),
|
|
138
|
+
pagination: { offset, limit, total: Number(get('SELECT COUNT(*) n FROM conversations WHERE updated_at>=?', since).n) },
|
|
139
|
+
counts: { sessions: Number(get('SELECT COUNT(*) n FROM conversations WHERE updated_at>=?', since).n), tasks: all('SELECT state,COUNT(*) count FROM tasks WHERE updated_at>=? GROUP BY state', since) },
|
|
140
|
+
activeAgentSessions: sessions.filter(s => s.isRunning).map(s => s.sessionId),
|
|
141
|
+
workerPool: { maxWorkers: options.maxWorkers, idleTtlMs: options.idleTtlMs, workers: pool.map(w => ({ workerId: w.id, sessionId: w.session_id, workstreamId: w.workstream_id, state: w.active_task_id ? 'busy' : 'idle', taskId: w.active_task_id, expiresAt: w.active_task_id ? undefined : Number(w.idle_since) + Number(options.idleTtlMs) })) } };
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
db.exec('ROLLBACK');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
worker_threads_1.parentPort.on('message', ({ id, operation, filename, options }) => {
|
|
148
|
+
try {
|
|
149
|
+
worker_threads_1.parentPort.postMessage({ id, value: read(filename, operation, options) });
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
worker_threads_1.parentPort.postMessage({ id, error: 'Unable to read dashboard data' });
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
//# sourceMappingURL=dashboard-reader-worker.js.map
|