agentenkit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +226 -0
- package/dist/adapters/inline.d.ts +27 -0
- package/dist/adapters/inline.d.ts.map +1 -0
- package/dist/adapters/inline.js +41 -0
- package/dist/adapters/inline.js.map +1 -0
- package/dist/adapters/memory.d.ts +74 -0
- package/dist/adapters/memory.d.ts.map +1 -0
- package/dist/adapters/memory.js +194 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/adapters/prisma.d.ts +176 -0
- package/dist/adapters/prisma.d.ts.map +1 -0
- package/dist/adapters/prisma.js +107 -0
- package/dist/adapters/prisma.js.map +1 -0
- package/dist/adapters/qstash.d.ts +36 -0
- package/dist/adapters/qstash.d.ts.map +1 -0
- package/dist/adapters/qstash.js +26 -0
- package/dist/adapters/qstash.js.map +1 -0
- package/dist/adapters/redis.d.ts +49 -0
- package/dist/adapters/redis.d.ts.map +1 -0
- package/dist/adapters/redis.js +60 -0
- package/dist/adapters/redis.js.map +1 -0
- package/dist/adapters/sqlite.d.ts +67 -0
- package/dist/adapters/sqlite.d.ts.map +1 -0
- package/dist/adapters/sqlite.js +199 -0
- package/dist/adapters/sqlite.js.map +1 -0
- package/dist/adapters/upstash.d.ts +48 -0
- package/dist/adapters/upstash.d.ts.map +1 -0
- package/dist/adapters/upstash.js +46 -0
- package/dist/adapters/upstash.js.map +1 -0
- package/dist/admin/default.d.ts +15 -0
- package/dist/admin/default.d.ts.map +1 -0
- package/dist/admin/default.js +22 -0
- package/dist/admin/default.js.map +1 -0
- package/dist/admin/memory.d.ts +29 -0
- package/dist/admin/memory.d.ts.map +1 -0
- package/dist/admin/memory.js +83 -0
- package/dist/admin/memory.js.map +1 -0
- package/dist/admin/postgres.d.ts +43 -0
- package/dist/admin/postgres.d.ts.map +1 -0
- package/dist/admin/postgres.js +201 -0
- package/dist/admin/postgres.js.map +1 -0
- package/dist/admin/sqlite.d.ts +35 -0
- package/dist/admin/sqlite.d.ts.map +1 -0
- package/dist/admin/sqlite.js +187 -0
- package/dist/admin/sqlite.js.map +1 -0
- package/dist/core/admin.d.ts +88 -0
- package/dist/core/admin.d.ts.map +1 -0
- package/dist/core/admin.js +147 -0
- package/dist/core/admin.js.map +1 -0
- package/dist/core/agent.d.ts +29 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +41 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/cache.d.ts +37 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +68 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/context.d.ts +13 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +87 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/deleteThread.d.ts +14 -0
- package/dist/core/deleteThread.d.ts.map +1 -0
- package/dist/core/deleteThread.js +34 -0
- package/dist/core/deleteThread.js.map +1 -0
- package/dist/core/engine.d.ts +79 -0
- package/dist/core/engine.d.ts.map +1 -0
- package/dist/core/engine.js +489 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/follow.d.ts +50 -0
- package/dist/core/follow.d.ts.map +1 -0
- package/dist/core/follow.js +153 -0
- package/dist/core/follow.js.map +1 -0
- package/dist/core/hitl.d.ts +98 -0
- package/dist/core/hitl.d.ts.map +1 -0
- package/dist/core/hitl.js +199 -0
- package/dist/core/hitl.js.map +1 -0
- package/dist/core/keys.d.ts +26 -0
- package/dist/core/keys.d.ts.map +1 -0
- package/dist/core/keys.js +32 -0
- package/dist/core/keys.js.map +1 -0
- package/dist/core/loop.d.ts +105 -0
- package/dist/core/loop.d.ts.map +1 -0
- package/dist/core/loop.js +234 -0
- package/dist/core/loop.js.map +1 -0
- package/dist/core/publish.d.ts +18 -0
- package/dist/core/publish.d.ts.map +1 -0
- package/dist/core/publish.js +34 -0
- package/dist/core/publish.js.map +1 -0
- package/dist/core/reclaim.d.ts +20 -0
- package/dist/core/reclaim.d.ts.map +1 -0
- package/dist/core/reclaim.js +56 -0
- package/dist/core/reclaim.js.map +1 -0
- package/dist/core/run.d.ts +8 -0
- package/dist/core/run.d.ts.map +1 -0
- package/dist/core/run.js +102 -0
- package/dist/core/run.js.map +1 -0
- package/dist/core/state.d.ts +50 -0
- package/dist/core/state.d.ts.map +1 -0
- package/dist/core/state.js +39 -0
- package/dist/core/state.js.map +1 -0
- package/dist/core/stop.d.ts +7 -0
- package/dist/core/stop.d.ts.map +1 -0
- package/dist/core/stop.js +15 -0
- package/dist/core/stop.js.map +1 -0
- package/dist/core/stream.d.ts +12 -0
- package/dist/core/stream.d.ts.map +1 -0
- package/dist/core/stream.js +21 -0
- package/dist/core/stream.js.map +1 -0
- package/dist/core/subagent.d.ts +77 -0
- package/dist/core/subagent.d.ts.map +1 -0
- package/dist/core/subagent.js +261 -0
- package/dist/core/subagent.js.map +1 -0
- package/dist/core/tools.d.ts +36 -0
- package/dist/core/tools.d.ts.map +1 -0
- package/dist/core/tools.js +22 -0
- package/dist/core/tools.js.map +1 -0
- package/dist/core/types.d.ts +286 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +49 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/usage.d.ts +40 -0
- package/dist/core/usage.d.ts.map +1 -0
- package/dist/core/usage.js +43 -0
- package/dist/core/usage.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/ports/admin.d.ts +102 -0
- package/dist/ports/admin.d.ts.map +1 -0
- package/dist/ports/admin.js +2 -0
- package/dist/ports/admin.js.map +1 -0
- package/dist/ports/bus.d.ts +13 -0
- package/dist/ports/bus.d.ts.map +1 -0
- package/dist/ports/bus.js +2 -0
- package/dist/ports/bus.js.map +1 -0
- package/dist/ports/kv.d.ts +16 -0
- package/dist/ports/kv.d.ts.map +1 -0
- package/dist/ports/kv.js +2 -0
- package/dist/ports/kv.js.map +1 -0
- package/dist/ports/queue.d.ts +18 -0
- package/dist/ports/queue.d.ts.map +1 -0
- package/dist/ports/queue.js +2 -0
- package/dist/ports/queue.js.map +1 -0
- package/dist/ports/runtime.d.ts +260 -0
- package/dist/ports/runtime.d.ts.map +1 -0
- package/dist/ports/runtime.js +2 -0
- package/dist/ports/runtime.js.map +1 -0
- package/dist/ports/storage.d.ts +72 -0
- package/dist/ports/storage.d.ts.map +1 -0
- package/dist/ports/storage.js +2 -0
- package/dist/ports/storage.js.map +1 -0
- package/dist/runtime.d.ts +5 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +177 -0
- package/dist/runtime.js.map +1 -0
- package/package.json +126 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
const EMPTY = {
|
|
2
|
+
inputTokens: 0, cachedInputTokens: 0, outputTokens: 0, totalTokens: 0,
|
|
3
|
+
};
|
|
4
|
+
function percentiles(values) {
|
|
5
|
+
if (values.length === 0)
|
|
6
|
+
return null;
|
|
7
|
+
const s = [...values].sort((a, b) => a - b);
|
|
8
|
+
const at = (q) => s[Math.min(s.length - 1, Math.floor(q * s.length))];
|
|
9
|
+
return { p50: at(0.5), p95: at(0.95), max: s[s.length - 1] };
|
|
10
|
+
}
|
|
11
|
+
export function summarise(runs) {
|
|
12
|
+
const byState = {};
|
|
13
|
+
const byStopReason = {};
|
|
14
|
+
const tokens = { ...EMPTY };
|
|
15
|
+
const durations = [];
|
|
16
|
+
const queued = [];
|
|
17
|
+
let failed = 0;
|
|
18
|
+
for (const r of runs) {
|
|
19
|
+
byState[r.state] = (byState[r.state] ?? 0) + 1;
|
|
20
|
+
if (r.stopReason)
|
|
21
|
+
byStopReason[r.stopReason] = (byStopReason[r.stopReason] ?? 0) + 1;
|
|
22
|
+
tokens.inputTokens += r.inputTokens;
|
|
23
|
+
tokens.cachedInputTokens += r.cachedInputTokens;
|
|
24
|
+
tokens.outputTokens += r.outputTokens;
|
|
25
|
+
tokens.totalTokens += r.totalTokens;
|
|
26
|
+
if (typeof r.durationMs === 'number')
|
|
27
|
+
durations.push(r.durationMs);
|
|
28
|
+
if (typeof r.queuedMs === 'number')
|
|
29
|
+
queued.push(r.queuedMs);
|
|
30
|
+
if (r.state === 'FAILED')
|
|
31
|
+
failed += 1;
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
total: runs.length,
|
|
35
|
+
byState,
|
|
36
|
+
byStopReason,
|
|
37
|
+
tokens,
|
|
38
|
+
duration: percentiles(durations),
|
|
39
|
+
queued: percentiles(queued),
|
|
40
|
+
failed,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/** Default window for a dashboard read: enough to be useful, bounded enough
|
|
44
|
+
* that "show me everything" can never become a table scan. */
|
|
45
|
+
const DEFAULT_LIMIT = 200;
|
|
46
|
+
export async function listRuns(deps, filter = {}) {
|
|
47
|
+
return deps.admin.runs.list({ ...filter, limit: filter.limit ?? DEFAULT_LIMIT });
|
|
48
|
+
}
|
|
49
|
+
export async function runStats(deps, range = {}) {
|
|
50
|
+
// Percentiles are computed here rather than pushed into the adapter, so an
|
|
51
|
+
// adapter only ever writes filters it can express in one indexed query.
|
|
52
|
+
return summarise(await listRuns(deps, { ...range, limit: range.limit ?? 1_000 }));
|
|
53
|
+
}
|
|
54
|
+
export async function overview(deps, range = {}) {
|
|
55
|
+
const [threads, runsByState, recent, active] = await Promise.all([
|
|
56
|
+
deps.admin.threads.countByState(),
|
|
57
|
+
deps.admin.runs.countByState(),
|
|
58
|
+
listRuns(deps, { since: range.since, limit: 1_000 }),
|
|
59
|
+
deps.admin.runs.list({ state: ['RUNNING', 'WAITING_FOR_INPUT'], limit: 50 }),
|
|
60
|
+
]);
|
|
61
|
+
return { runs: summarise(recent), threads, runsByState, active };
|
|
62
|
+
}
|
|
63
|
+
/** A run's steps, in order (§2.9). Rows in the platform's own store rather
|
|
64
|
+
* than a scan of the caller's event log. */
|
|
65
|
+
export async function listSteps(deps, runId) {
|
|
66
|
+
return deps.admin.steps.listByRun(runId);
|
|
67
|
+
}
|
|
68
|
+
const addTokens = (into, from) => {
|
|
69
|
+
into.inputTokens += from.inputTokens;
|
|
70
|
+
into.cachedInputTokens += from.cachedInputTokens;
|
|
71
|
+
into.outputTokens += from.outputTokens;
|
|
72
|
+
into.totalTokens += from.totalTokens;
|
|
73
|
+
};
|
|
74
|
+
function rollUp(thread, runs) {
|
|
75
|
+
const tokens = { ...EMPTY };
|
|
76
|
+
let steps = 0;
|
|
77
|
+
let durationMs = 0;
|
|
78
|
+
for (const r of runs) {
|
|
79
|
+
addTokens(tokens, r);
|
|
80
|
+
steps += r.steps;
|
|
81
|
+
durationMs += r.durationMs ?? 0;
|
|
82
|
+
}
|
|
83
|
+
// The dispatched run is the one a person started; a nested run's prompt is
|
|
84
|
+
// a brief the model wrote.
|
|
85
|
+
const root = runs.filter((r) => r.depth === 0).sort((a, b) => a.startedAt.getTime() - b.startedAt.getTime())[0];
|
|
86
|
+
return { ...thread, runs: runs.length, steps, tokens, durationMs, prompt: root?.prompt ?? null };
|
|
87
|
+
}
|
|
88
|
+
/** Threads with their runs rolled up, newest activity first (§2.9). One pass
|
|
89
|
+
* over the window's runs rather than a query per thread. */
|
|
90
|
+
export async function listThreads(deps, filter = {}) {
|
|
91
|
+
const [threads, runs] = await Promise.all([
|
|
92
|
+
deps.admin.threads.list({ ...filter, limit: filter.limit ?? DEFAULT_LIMIT }),
|
|
93
|
+
deps.admin.runs.list({ since: filter.since, limit: 5_000 }),
|
|
94
|
+
]);
|
|
95
|
+
const byThread = new Map();
|
|
96
|
+
for (const r of runs) {
|
|
97
|
+
const list = byThread.get(r.threadId) ?? [];
|
|
98
|
+
list.push(r);
|
|
99
|
+
byThread.set(r.threadId, list);
|
|
100
|
+
}
|
|
101
|
+
return threads.map((t) => rollUp(t, byThread.get(t.id) ?? []));
|
|
102
|
+
}
|
|
103
|
+
/** One thread opened up: its runs and every step across them (§2.9). */
|
|
104
|
+
export async function getThread(deps, threadId) {
|
|
105
|
+
const [runs, steps] = await Promise.all([
|
|
106
|
+
deps.admin.runs.listByThread(threadId),
|
|
107
|
+
deps.admin.steps.listByThread(threadId),
|
|
108
|
+
]);
|
|
109
|
+
const rows = await deps.admin.threads.list({ limit: 5_000 });
|
|
110
|
+
const thread = rows.find((t) => t.id === threadId);
|
|
111
|
+
if (!thread && runs.length === 0)
|
|
112
|
+
return null;
|
|
113
|
+
const base = thread ?? {
|
|
114
|
+
id: threadId,
|
|
115
|
+
state: (runs[0]?.state ?? 'IDLE'),
|
|
116
|
+
model: runs[0]?.model ?? 'unknown',
|
|
117
|
+
firstSeenAt: runs.at(-1)?.startedAt ?? new Date(),
|
|
118
|
+
updatedAt: runs[0]?.startedAt ?? new Date(),
|
|
119
|
+
};
|
|
120
|
+
return { thread: rollUp(base, runs), runs, steps };
|
|
121
|
+
}
|
|
122
|
+
export async function getRun(deps, runId) {
|
|
123
|
+
const run = await deps.admin.runs.get(runId);
|
|
124
|
+
if (!run)
|
|
125
|
+
return null;
|
|
126
|
+
const [steps, siblings, events] = await Promise.all([
|
|
127
|
+
listSteps(deps, runId),
|
|
128
|
+
deps.admin.runs.listByThread(run.threadId),
|
|
129
|
+
deps.storage.events.listSince(run.threadId, -1),
|
|
130
|
+
]);
|
|
131
|
+
const from = new Date(run.startedAt).getTime();
|
|
132
|
+
const to = run.endedAt ? new Date(run.endedAt).getTime() : Infinity;
|
|
133
|
+
return {
|
|
134
|
+
run,
|
|
135
|
+
steps,
|
|
136
|
+
// Its children: same table, distinguished by depth (§2.7).
|
|
137
|
+
subagents: siblings.filter((c) => c.parentRunId === runId),
|
|
138
|
+
// CHUNK is the token firehose; a timeline wants the spine.
|
|
139
|
+
events: events.filter((e) => {
|
|
140
|
+
if (e.type === 'CHUNK' || e.type === 'SUBAGENT_CHUNK')
|
|
141
|
+
return false;
|
|
142
|
+
const at = new Date(e.createdAt).getTime();
|
|
143
|
+
return at >= from && at <= to;
|
|
144
|
+
}),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=admin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin.js","sourceRoot":"","sources":["../../src/core/admin.ts"],"names":[],"mappings":"AA4EA,MAAM,KAAK,GAAgB;IACzB,WAAW,EAAE,CAAC,EAAE,iBAAiB,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC;CACtE,CAAC;AAEF,SAAS,WAAW,CAAC,MAAgB;IACnC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC5C,MAAM,EAAE,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC;IAC/E,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAE,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAiB;IACzC,MAAM,OAAO,GAA4C,EAAE,CAAC;IAC5D,MAAM,YAAY,GAA2B,EAAE,CAAC;IAChD,MAAM,MAAM,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;IAC5B,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,MAAM,GAAG,CAAC,CAAC;IAEf,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC/C,IAAI,CAAC,CAAC,UAAU;YAAE,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACrF,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,CAAC;QACpC,MAAM,CAAC,iBAAiB,IAAI,CAAC,CAAC,iBAAiB,CAAC;QAChD,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC,YAAY,CAAC;QACtC,MAAM,CAAC,WAAW,IAAI,CAAC,CAAC,WAAW,CAAC;QACpC,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ;YAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QACnE,IAAI,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ;YAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;QAC5D,IAAI,CAAC,CAAC,KAAK,KAAK,QAAQ;YAAE,MAAM,IAAI,CAAC,CAAC;IACxC,CAAC;IAED,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,MAAM;QAClB,OAAO;QACP,YAAY;QACZ,MAAM;QACN,QAAQ,EAAE,WAAW,CAAC,SAAS,CAAC;QAChC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC;QAC3B,MAAM;KACP,CAAC;AACJ,CAAC;AAED;+DAC+D;AAC/D,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,IAAkB,EAClB,SAAoB,EAAE;IAEtB,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,aAAa,EAAE,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,IAAkB,EAClB,QAAwD,EAAE;IAE1D,2EAA2E;IAC3E,wEAAwE;IACxE,OAAO,SAAS,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,IAAkB,EAClB,QAA0B,EAAE;IAE5B,MAAM,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC/D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,EAAE;QACjC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE;QAC9B,QAAQ,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACpD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,SAAS,EAAE,mBAAmB,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;KAC7E,CAAC,CAAC;IACH,OAAO,EAAE,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC;AACnE,CAAC;AAED;6CAC6C;AAC7C,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAkB,EAAE,KAAa;IAC/D,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,SAAS,GAAG,CAAC,IAAiB,EAAE,IAAiB,EAAE,EAAE;IACzD,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC;IACrC,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,iBAAiB,CAAC;IACjD,IAAI,CAAC,YAAY,IAAI,IAAI,CAAC,YAAY,CAAC;IACvC,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC;AACvC,CAAC,CAAC;AAEF,SAAS,MAAM,CAAC,MAEf,EAAE,IAAiB;IAClB,MAAM,MAAM,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;IAC5B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACrB,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC;QACjB,UAAU,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC;IAClC,CAAC;IACD,2EAA2E;IAC3E,2BAA2B;IAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CACjD,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,CACxD,CAAC,CAAC,CAAC,CAAC;IACL,OAAO,EAAE,GAAG,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,IAAI,EAAE,CAAC;AACnG,CAAC;AAED;6DAC6D;AAC7D,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAkB,EAClB,SAAqE,EAAE;IAEvE,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACxC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,aAAa,EAAE,CAAC;QAC5E,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;KAC5D,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IAChD,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACrB,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACb,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,wEAAwE;AACxE,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,IAAkB,EAClB,QAAgB;IAEhB,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACtC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC;QACtC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC;KACxC,CAAC,CAAC;IACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;IAC7D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;IACnD,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9C,MAAM,IAAI,GAAG,MAAM,IAAI;QACrB,EAAE,EAAE,QAAQ;QACZ,KAAK,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,MAAM,CAAmB;QACnD,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,SAAS;QAClC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,IAAI,IAAI,IAAI,EAAE;QACjD,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,IAAI,IAAI,IAAI,EAAE;KAC5C,CAAC;IACF,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAkB,EAAE,KAAa;IAC5D,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7C,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAClD,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC;QACtB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC;QAC1C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;KAChD,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;IAC/C,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC;IACpE,OAAO;QACL,GAAG;QACH,KAAK;QACL,2DAA2D;QAC3D,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAY,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,KAAK,KAAK,CAAC;QACrE,2DAA2D;QAC3D,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAa,EAAE,EAAE;YACtC,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,IAAI,KAAK,gBAAgB;gBAAE,OAAO,KAAK,CAAC;YACpE,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;YAC3C,OAAO,EAAE,IAAI,IAAI,IAAI,EAAE,IAAI,EAAE,CAAC;QAChC,CAAC,CAAC;KACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { RuntimePorts } from '../ports/runtime.js';
|
|
2
|
+
import type { AgentRunState } from './state.js';
|
|
3
|
+
import type { AgentHandle, AgentKind, GenerateTextAgentSpec, ProviderOptions, StreamTextAgentSpec, SubagentsConfig } from '../ports/runtime.js';
|
|
4
|
+
import { Semaphore } from './subagent.js';
|
|
5
|
+
/** The registry entry behind a handle: the bound generation flavor, the
|
|
6
|
+
* spec-level defaults the engine reads, and the user's generation args
|
|
7
|
+
* (spread first, platform keys last — §3.1). */
|
|
8
|
+
export interface RegisteredAgent {
|
|
9
|
+
name: string;
|
|
10
|
+
kind: AgentKind;
|
|
11
|
+
spec: {
|
|
12
|
+
model?: string;
|
|
13
|
+
subagents?: boolean | SubagentsConfig;
|
|
14
|
+
tokenBudget?: number;
|
|
15
|
+
/** Additional provider-specific options (§3.1) — merged per run. */
|
|
16
|
+
providerOptions?: ProviderOptions;
|
|
17
|
+
};
|
|
18
|
+
/** The user's generation args — spread first, platform keys last (§3.1). */
|
|
19
|
+
args: Record<string, any>;
|
|
20
|
+
sem: Semaphore;
|
|
21
|
+
}
|
|
22
|
+
/** Normalize the delegation config: `false`/`undefined` = off; `true` = defaults. */
|
|
23
|
+
export declare function normalizeSubagents(spec: boolean | SubagentsConfig | undefined): SubagentsConfig | null;
|
|
24
|
+
/** Resolves the ports for one call, binding that call's state to storage
|
|
25
|
+
* (§2.10). A handle outlives many runs, so it cannot hold fixed ports. */
|
|
26
|
+
export type ScopeFn = (state?: AgentRunState, runId?: string) => RuntimePorts;
|
|
27
|
+
export declare function createStreamTextAgent(scope: ScopeFn, spec: StreamTextAgentSpec): AgentHandle;
|
|
28
|
+
export declare function createGenerateTextAgent(scope: ScopeFn, spec: GenerateTextAgentSpec): AgentHandle;
|
|
29
|
+
//# sourceMappingURL=agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,eAAe,EAEf,mBAAmB,EACnB,eAAe,EAChB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI1C;;iDAEiD;AACjD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE;QACJ,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,OAAO,GAAG,eAAe,CAAC;QACtC,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,oEAAoE;QACpE,eAAe,CAAC,EAAE,eAAe,CAAC;KACnC,CAAC;IACF,4EAA4E;IAC5E,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC1B,GAAG,EAAE,SAAS,CAAC;CAChB;AAED,qFAAqF;AACrF,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,GAC1C,eAAe,GAAG,IAAI,CAGxB;AAED;2EAC2E;AAC3E,MAAM,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,YAAY,CAAC;AAc9E,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,mBAAmB,GACxB,WAAW,CASb;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,IAAI,EAAE,qBAAqB,GAC1B,WAAW,CASb"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { execute, executeWithPolicy } from './engine.js';
|
|
2
|
+
import { Semaphore } from './subagent.js';
|
|
3
|
+
import { run } from './run.js';
|
|
4
|
+
import { stop } from './stop.js';
|
|
5
|
+
/** Normalize the delegation config: `false`/`undefined` = off; `true` = defaults. */
|
|
6
|
+
export function normalizeSubagents(spec) {
|
|
7
|
+
if (!spec)
|
|
8
|
+
return null;
|
|
9
|
+
return spec === true ? {} : spec;
|
|
10
|
+
}
|
|
11
|
+
function createHandle(scope, agent) {
|
|
12
|
+
return {
|
|
13
|
+
name: agent.name,
|
|
14
|
+
kind: agent.kind,
|
|
15
|
+
execute: (input) => execute(scope(input.state, input.runId), agent, input),
|
|
16
|
+
executeWithPolicy: (input, policy) => executeWithPolicy(scope(input.state, input.runId), agent, input, policy),
|
|
17
|
+
run: (input) => run(scope(input.state), agent, input),
|
|
18
|
+
stop: (threadId, state) => stop(scope(state), threadId),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function createStreamTextAgent(scope, spec) {
|
|
22
|
+
const { name, model, subagents, tokenBudget, providerOptions, ...args } = spec;
|
|
23
|
+
return createHandle(scope, {
|
|
24
|
+
name,
|
|
25
|
+
kind: 'stream-text',
|
|
26
|
+
spec: { model, subagents, tokenBudget, providerOptions },
|
|
27
|
+
args: args,
|
|
28
|
+
sem: new Semaphore(scope().config.subagentMaxConcurrent),
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export function createGenerateTextAgent(scope, spec) {
|
|
32
|
+
const { name, model, subagents, tokenBudget, providerOptions, ...args } = spec;
|
|
33
|
+
return createHandle(scope, {
|
|
34
|
+
name,
|
|
35
|
+
kind: 'generate-text',
|
|
36
|
+
spec: { model, subagents, tokenBudget, providerOptions },
|
|
37
|
+
args: args,
|
|
38
|
+
sem: new Semaphore(scope().config.subagentMaxConcurrent),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/core/agent.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAC/B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAoBjC,qFAAqF;AACrF,MAAM,UAAU,kBAAkB,CAChC,IAA2C;IAE3C,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,OAAO,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACnC,CAAC;AAMD,SAAS,YAAY,CAAC,KAAc,EAAE,KAAsB;IAC1D,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,CAAC,KAAmB,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC;QACxF,iBAAiB,EAAE,CAAC,KAAmB,EAAE,MAAiC,EAAE,EAAE,CAC5E,iBAAiB,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC;QAC1E,GAAG,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC;QAC/D,IAAI,EAAE,CAAC,QAAgB,EAAE,KAAqB,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC;KAChF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,KAAc,EACd,IAAyB;IAEzB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;IAC/E,OAAO,YAAY,CAAC,KAAK,EAAE;QACzB,IAAI;QACJ,IAAI,EAAE,aAAa;QACnB,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE;QACxD,IAAI,EAAE,IAA2B;QACjC,GAAG,EAAE,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC;KACzD,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,KAAc,EACd,IAA2B;IAE3B,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;IAC/E,OAAO,YAAY,CAAC,KAAK,EAAE;QACzB,IAAI;QACJ,IAAI,EAAE,eAAe;QACrB,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE;QACxD,IAAI,EAAE,IAA2B;QACjC,GAAG,EAAE,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC;KACzD,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** Prompt caching (§2.6): providers like Anthropic cache a prompt prefix only
|
|
2
|
+
* when it carries explicit cache breakpoints; OpenAI-family models cache
|
|
3
|
+
* automatically for prompts ≥1024 tokens and ignore these markers.
|
|
4
|
+
*
|
|
5
|
+
* `markPromptCaching` stamps ephemeral cache breakpoints on the stable
|
|
6
|
+
* prefix of a prompt — the system message and the tail message of the
|
|
7
|
+
* conversation-so-far — so the next run with the same prefix is served from
|
|
8
|
+
* the provider cache (tracked as cachedInputTokens, §4 usage attribution).
|
|
9
|
+
*
|
|
10
|
+
* The stamp uses the AI SDK's provider-metadata channel; unknown providers
|
|
11
|
+
* ignore it harmlessly. */
|
|
12
|
+
export interface PromptCachingOptions {
|
|
13
|
+
/** Provider namespace for the metadata stamp. Default: 'anthropic'. */
|
|
14
|
+
provider?: string;
|
|
15
|
+
}
|
|
16
|
+
interface CacheableMessage {
|
|
17
|
+
role: string;
|
|
18
|
+
content: unknown;
|
|
19
|
+
[key: string]: unknown;
|
|
20
|
+
}
|
|
21
|
+
/** A system prompt, in the one shape that can carry a cache breakpoint.
|
|
22
|
+
*
|
|
23
|
+
* The SDK's `system:` STRING parameter becomes `{ role, content }` with no
|
|
24
|
+
* metadata channel at all, so a system prompt passed that way can never be
|
|
25
|
+
* cached — and it is usually the largest, most stable part of the prompt, the
|
|
26
|
+
* very thing caching exists for. Carried as a message it can be stamped. */
|
|
27
|
+
export declare function systemCacheMessage(system: string, provider?: string): {
|
|
28
|
+
role: 'system';
|
|
29
|
+
content: string;
|
|
30
|
+
} & Record<string, unknown>;
|
|
31
|
+
/** Mark the stable prefix of a prompt for provider-side caching:
|
|
32
|
+
* the system message (if any) plus the last message of the history. */
|
|
33
|
+
export declare function markPromptCaching<T extends CacheableMessage>(messages: T[], opts?: {
|
|
34
|
+
provider?: string;
|
|
35
|
+
}): T[];
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;4BAU4B;AAC5B,MAAM,WAAW,oBAAoB;IACnC,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAQD,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AA0CD;;;;;6EAK6E;AAC7E,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,MAAM,EACd,QAAQ,SAAc,GACrB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAO/D;AAED;wEACwE;AACxE,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,gBAAgB,EAC1D,QAAQ,EAAE,CAAC,EAAE,EACb,IAAI,GAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAC/B,CAAC,EAAE,CAaL"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const cacheStamp = (provider) => ({
|
|
2
|
+
[provider]: { cacheControl: { type: 'ephemeral' } },
|
|
3
|
+
});
|
|
4
|
+
function toParts(content) {
|
|
5
|
+
if (typeof content === 'string')
|
|
6
|
+
return [{ type: 'text', text: content }];
|
|
7
|
+
if (Array.isArray(content))
|
|
8
|
+
return content;
|
|
9
|
+
return [];
|
|
10
|
+
}
|
|
11
|
+
/** Stamp the marker where the SDK will actually read it.
|
|
12
|
+
*
|
|
13
|
+
* Two rules, and breaking either one is silent:
|
|
14
|
+
* - The SDK reads `providerOptions ?? experimental_providerMetadata`. A bare
|
|
15
|
+
* `providerMetadata` is read by nothing, so stamping that alone leaves the
|
|
16
|
+
* breakpoint inert — set, and never seen by a provider.
|
|
17
|
+
* - A SYSTEM message's content must stay a string; it carries its metadata on
|
|
18
|
+
* the message itself. Splitting it into parts the way a user message allows
|
|
19
|
+
* makes the whole prompt fail validation, and every run throws. */
|
|
20
|
+
function stampCacheBreakpoint(message, provider) {
|
|
21
|
+
if (message.role === 'system') {
|
|
22
|
+
return {
|
|
23
|
+
...message,
|
|
24
|
+
providerOptions: cacheStamp(provider),
|
|
25
|
+
experimental_providerMetadata: cacheStamp(provider),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const parts = toParts(message.content);
|
|
29
|
+
if (parts.length === 0)
|
|
30
|
+
return message;
|
|
31
|
+
const stamped = [...parts];
|
|
32
|
+
const last = stamped[stamped.length - 1];
|
|
33
|
+
stamped[stamped.length - 1] = {
|
|
34
|
+
...last,
|
|
35
|
+
providerOptions: cacheStamp(provider),
|
|
36
|
+
experimental_providerMetadata: cacheStamp(provider),
|
|
37
|
+
};
|
|
38
|
+
return { ...message, content: stamped };
|
|
39
|
+
}
|
|
40
|
+
/** A system prompt, in the one shape that can carry a cache breakpoint.
|
|
41
|
+
*
|
|
42
|
+
* The SDK's `system:` STRING parameter becomes `{ role, content }` with no
|
|
43
|
+
* metadata channel at all, so a system prompt passed that way can never be
|
|
44
|
+
* cached — and it is usually the largest, most stable part of the prompt, the
|
|
45
|
+
* very thing caching exists for. Carried as a message it can be stamped. */
|
|
46
|
+
export function systemCacheMessage(system, provider = 'anthropic') {
|
|
47
|
+
return {
|
|
48
|
+
role: 'system',
|
|
49
|
+
content: system,
|
|
50
|
+
providerOptions: cacheStamp(provider),
|
|
51
|
+
experimental_providerMetadata: cacheStamp(provider),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Mark the stable prefix of a prompt for provider-side caching:
|
|
55
|
+
* the system message (if any) plus the last message of the history. */
|
|
56
|
+
export function markPromptCaching(messages, opts = {}) {
|
|
57
|
+
const provider = opts.provider ?? 'anthropic';
|
|
58
|
+
const out = messages.map((m) => ({ ...m }));
|
|
59
|
+
const systemIndex = out.findIndex((m) => m.role === 'system');
|
|
60
|
+
if (systemIndex >= 0)
|
|
61
|
+
out[systemIndex] = stampCacheBreakpoint(out[systemIndex], provider);
|
|
62
|
+
if (out.length > 0) {
|
|
63
|
+
const last = out.length - 1;
|
|
64
|
+
out[last] = stampCacheBreakpoint(out[last], provider);
|
|
65
|
+
}
|
|
66
|
+
return out;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AA4BA,MAAM,UAAU,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC;IACxC,CAAC,QAAQ,CAAC,EAAE,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE;CACpD,CAAC,CAAC;AAEH,SAAS,OAAO,CAAC,OAAgB;IAC/B,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAC1E,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,OAA0B,CAAC;IAC9D,OAAO,EAAE,CAAC;AACZ,CAAC;AAED;;;;;;;;uEAQuE;AACvE,SAAS,oBAAoB,CAA6B,OAAU,EAAE,QAAgB;IACpF,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO;YACL,GAAG,OAAO;YACV,eAAe,EAAE,UAAU,CAAC,QAAQ,CAAC;YACrC,6BAA6B,EAAE,UAAU,CAAC,QAAQ,CAAC;SACpD,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,OAAO,CAAC;IACvC,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IAC1C,OAAO,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG;QAC5B,GAAG,IAAI;QACP,eAAe,EAAE,UAAU,CAAC,QAAQ,CAAC;QACrC,6BAA6B,EAAE,UAAU,CAAC,QAAQ,CAAC;KACpD,CAAC;IACF,OAAO,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;AAC1C,CAAC;AAED;;;;;6EAK6E;AAC7E,MAAM,UAAU,kBAAkB,CAChC,MAAc,EACd,QAAQ,GAAG,WAAW;IAEtB,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,OAAO,EAAE,MAAM;QACf,eAAe,EAAE,UAAU,CAAC,QAAQ,CAAC;QACrC,6BAA6B,EAAE,UAAU,CAAC,QAAQ,CAAC;KACpD,CAAC;AACJ,CAAC;AAED;wEACwE;AACxE,MAAM,UAAU,iBAAiB,CAC/B,QAAa,EACb,OAA8B,EAAE;IAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,WAAW,CAAC;IAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAE5C,MAAM,WAAW,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IAC9D,IAAI,WAAW,IAAI,CAAC;QAAE,GAAG,CAAC,WAAW,CAAC,GAAG,oBAAoB,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,CAAC;IAE1F,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;QAC5B,GAAG,CAAC,IAAI,CAAC,GAAG,oBAAoB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RuntimePorts } from '../ports/runtime.js';
|
|
2
|
+
import type { ContextUsage, MessageDTO } from './types.js';
|
|
3
|
+
/** Universal context ceiling across all models (§2.6) */
|
|
4
|
+
export declare const CONTEXT_TOKEN_CEILING = 265000;
|
|
5
|
+
/** Effective budget = min(native window, ceiling). The model's declared
|
|
6
|
+
* `contextWindow` (via `resolveModel`, §3.3) wins over the fallback tables;
|
|
7
|
+
* models below the ceiling keep their native window. */
|
|
8
|
+
export declare function contextBudget(deps: RuntimePorts, model: string): number;
|
|
9
|
+
/** Read-only view of the §2.6 budget math — what compactContext would see on
|
|
10
|
+
* the next run, without summarizing anything. */
|
|
11
|
+
export declare function contextUsage(deps: RuntimePorts, threadId: string, model: string): Promise<ContextUsage>;
|
|
12
|
+
export declare function compactContext(deps: RuntimePorts, threadId: string, model: string): Promise<MessageDTO[]>;
|
|
13
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI3D,yDAAyD;AACzD,eAAO,MAAM,qBAAqB,SAAU,CAAC;AAS7C;;yDAEyD;AACzD,wBAAgB,aAAa,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAavE;AAID;kDACkD;AAClD,wBAAsB,YAAY,CAChC,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,YAAY,CAAC,CAUvB;AAKD,wBAAsB,cAAc,CAClC,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,UAAU,EAAE,CAAC,CA+CvB"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { generateText } from 'ai';
|
|
2
|
+
import { publish } from './publish.js';
|
|
3
|
+
import { attributeTokens } from './usage.js';
|
|
4
|
+
/** Universal context ceiling across all models (§2.6) */
|
|
5
|
+
export const CONTEXT_TOKEN_CEILING = 265_000;
|
|
6
|
+
const DEFAULT_NATIVE_WINDOWS = {
|
|
7
|
+
'gpt-4o': 128_000,
|
|
8
|
+
'gpt-4o-mini': 128_000,
|
|
9
|
+
'claude-3-5-sonnet': 200_000,
|
|
10
|
+
'gemini-1.5-pro': 1_000_000,
|
|
11
|
+
};
|
|
12
|
+
/** Effective budget = min(native window, ceiling). The model's declared
|
|
13
|
+
* `contextWindow` (via `resolveModel`, §3.3) wins over the fallback tables;
|
|
14
|
+
* models below the ceiling keep their native window. */
|
|
15
|
+
export function contextBudget(deps, model) {
|
|
16
|
+
let declared;
|
|
17
|
+
try {
|
|
18
|
+
declared = deps.resolveModel(model).contextWindow;
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// unknown registry key — fall through to the tables below
|
|
22
|
+
}
|
|
23
|
+
const native = declared ??
|
|
24
|
+
deps.config.nativeWindows?.[model] ??
|
|
25
|
+
DEFAULT_NATIVE_WINDOWS[model] ??
|
|
26
|
+
deps.config.contextCeilingTokens;
|
|
27
|
+
return Math.min(native, deps.config.contextCeilingTokens);
|
|
28
|
+
}
|
|
29
|
+
const estimateTokens = (content) => Math.ceil(JSON.stringify(content).length / 4);
|
|
30
|
+
/** Read-only view of the §2.6 budget math — what compactContext would see on
|
|
31
|
+
* the next run, without summarizing anything. */
|
|
32
|
+
export async function contextUsage(deps, threadId, model) {
|
|
33
|
+
const budgetTokens = contextBudget(deps, model) - deps.config.contextOutputReserveTokens;
|
|
34
|
+
// The main agent's stream only — a nested run's turns are its own (§2.7)
|
|
35
|
+
const history = await deps.storage.messages.list(threadId, { agentId: null });
|
|
36
|
+
return {
|
|
37
|
+
usedTokens: history.reduce((sum, m) => sum + estimateTokens(m.content), 0),
|
|
38
|
+
budgetTokens,
|
|
39
|
+
compactAtTokens: Math.floor(budgetTokens * deps.config.compactionTrigger),
|
|
40
|
+
messages: history.length,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// Returns a history array guaranteed to fit the model's budget. Compaction is
|
|
44
|
+
// durable: the summary is persisted as a Message, so every client and every
|
|
45
|
+
// reconnect replay (§2.2) reconstructs the exact same context.
|
|
46
|
+
export async function compactContext(deps, threadId, model) {
|
|
47
|
+
const budget = contextBudget(deps, model) - deps.config.contextOutputReserveTokens;
|
|
48
|
+
// Scoped to the main agent: unscoped, delegated turns would be compacted
|
|
49
|
+
// into — and then fed back through — the parent's prompt (§2.7)
|
|
50
|
+
const history = await deps.storage.messages.list(threadId, { agentId: null });
|
|
51
|
+
const total = history.reduce((sum, m) => sum + estimateTokens(m.content), 0);
|
|
52
|
+
if (total <= budget * deps.config.compactionTrigger)
|
|
53
|
+
return history;
|
|
54
|
+
// Keep the most recent tail verbatim ...
|
|
55
|
+
const tail = [];
|
|
56
|
+
let tailTokens = 0;
|
|
57
|
+
for (const m of [...history].reverse()) {
|
|
58
|
+
if (tailTokens + estimateTokens(m.content) > budget * deps.config.contextTailShare)
|
|
59
|
+
break;
|
|
60
|
+
tail.unshift(m);
|
|
61
|
+
tailTokens += estimateTokens(m.content);
|
|
62
|
+
}
|
|
63
|
+
const older = history.slice(0, history.length - tail.length);
|
|
64
|
+
if (older.length === 0)
|
|
65
|
+
return history; // single oversized turn — blocked by the input guards above
|
|
66
|
+
// ... and summarize everything before it with a cheap model
|
|
67
|
+
const { text, usage, ...rest } = await generateText({
|
|
68
|
+
model: deps.resolveModel('gpt-4o-mini').instance(),
|
|
69
|
+
prompt: 'Summarize the following conversation history into a dense context brief ' +
|
|
70
|
+
'(decisions, open threads, key facts) for an AI agent:\n\n' +
|
|
71
|
+
older.map((m) => `${m.role}: ${JSON.stringify(m.content)}`).join('\n'),
|
|
72
|
+
});
|
|
73
|
+
const summary = await deps.storage.messages.append(threadId, {
|
|
74
|
+
role: 'system',
|
|
75
|
+
content: { type: 'CONTEXT_SUMMARY', text },
|
|
76
|
+
});
|
|
77
|
+
// Token attribution (§4): input + cached + output. The cache hit is reported
|
|
78
|
+
// in provider metadata, never in `usage` — attributing without it books every
|
|
79
|
+
// cached prompt at the full input price.
|
|
80
|
+
await deps.storage.usage.record(threadId, {
|
|
81
|
+
agentId: null,
|
|
82
|
+
...attributeTokens(usage, rest.providerMetadata ?? rest.experimental_providerMetadata),
|
|
83
|
+
});
|
|
84
|
+
await publish(deps, threadId, 'CONTEXT_COMPACTED', { summarizedMessages: older.length });
|
|
85
|
+
return [summary, ...tail];
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/core/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { RuntimePorts } from '../ports/runtime.js';
|
|
2
|
+
import type { DeleteThreadResult } from '../ports/runtime.js';
|
|
3
|
+
/** The §3.2 deletion behavior: one call removes the thread and everything
|
|
4
|
+
* that follows it — messages, events, usage rows, subagent runs — plus the
|
|
5
|
+
* thread's hot kv keys (state cache, run lock, event seq, retry counter).
|
|
6
|
+
*
|
|
7
|
+
* Guards:
|
|
8
|
+
* - RUNNING is refused: a live worker is mid-segment and would keep writing
|
|
9
|
+
* behind the delete. `stop()` first, then delete.
|
|
10
|
+
* - WAITING_FOR_INPUT deletes cleanly: a park holds NO process (§2.5) — the
|
|
11
|
+
* run segment already ended, and a late resume dispatch is a no-op against
|
|
12
|
+
* the missing thread (the engine's terminal-state guard, §2.8). */
|
|
13
|
+
export declare function deleteThread(deps: RuntimePorts, threadId: string): Promise<DeleteThreadResult>;
|
|
14
|
+
//# sourceMappingURL=deleteThread.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deleteThread.d.ts","sourceRoot":"","sources":["../../src/core/deleteThread.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAI9D;;;;;;;;;sEASsE;AACtE,wBAAsB,YAAY,CAChC,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,kBAAkB,CAAC,CAuB7B"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { publishNotice } from './publish.js';
|
|
2
|
+
import { redriveKey, runIdKey } from './keys.js';
|
|
3
|
+
/** The §3.2 deletion behavior: one call removes the thread and everything
|
|
4
|
+
* that follows it — messages, events, usage rows, subagent runs — plus the
|
|
5
|
+
* thread's hot kv keys (state cache, run lock, event seq, retry counter).
|
|
6
|
+
*
|
|
7
|
+
* Guards:
|
|
8
|
+
* - RUNNING is refused: a live worker is mid-segment and would keep writing
|
|
9
|
+
* behind the delete. `stop()` first, then delete.
|
|
10
|
+
* - WAITING_FOR_INPUT deletes cleanly: a park holds NO process (§2.5) — the
|
|
11
|
+
* run segment already ended, and a late resume dispatch is a no-op against
|
|
12
|
+
* the missing thread (the engine's terminal-state guard, §2.8). */
|
|
13
|
+
export async function deleteThread(deps, threadId) {
|
|
14
|
+
const thread = await deps.storage.threads.get(threadId);
|
|
15
|
+
if (!thread)
|
|
16
|
+
return { accepted: false, error: 'Thread not found' };
|
|
17
|
+
if (thread.state === 'RUNNING') {
|
|
18
|
+
return { accepted: false, error: 'Thread has an active run — stop it before deleting' };
|
|
19
|
+
}
|
|
20
|
+
// Cascade: messages, events, usage, runs follow the thread (§3.2)
|
|
21
|
+
await deps.storage.threads.delete(threadId);
|
|
22
|
+
// Live UIs subscribed to the thread channel learn it ceased to exist —
|
|
23
|
+
// bus-only notice (seq 0, never persisted: the event log is gone with it)
|
|
24
|
+
await publishNotice(deps, threadId, 'THREAD_DELETED', { threadId });
|
|
25
|
+
// Hot cache cleanup — a deleted thread must not resurrect from kv
|
|
26
|
+
await deps.kv.del(`agent:state:${threadId}`);
|
|
27
|
+
await deps.kv.del(`agent:lock:${threadId}`);
|
|
28
|
+
await deps.kv.del(`agent:seq:${threadId}`);
|
|
29
|
+
await deps.kv.del(`agent:attempts:${threadId}`);
|
|
30
|
+
await deps.kv.del(runIdKey(threadId));
|
|
31
|
+
await deps.kv.del(redriveKey(threadId));
|
|
32
|
+
return { accepted: true };
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=deleteThread.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deleteThread.js","sourceRoot":"","sources":["../../src/core/deleteThread.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAEjD;;;;;;;;;sEASsE;AACtE,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAkB,EAClB,QAAgB;IAEhB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxD,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,kBAAkB,EAAE,CAAC;IACnE,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,oDAAoD,EAAE,CAAC;IAC1F,CAAC;IAED,kEAAkE;IAClE,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAE5C,uEAAuE;IACvE,0EAA0E;IAC1E,MAAM,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,gBAAgB,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAEpE,kEAAkE;IAClE,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,eAAe,QAAQ,EAAE,CAAC,CAAC;IAC7C,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,cAAc,QAAQ,EAAE,CAAC,CAAC;IAC5C,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,aAAa,QAAQ,EAAE,CAAC,CAAC;IAC3C,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,kBAAkB,QAAQ,EAAE,CAAC,CAAC;IAChD,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACtC,MAAM,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;IAExC,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { RuntimePorts } from '../ports/runtime.js';
|
|
2
|
+
import type { ExecutionState, ProviderOptions } from './types.js';
|
|
3
|
+
import type { TokenAttribution } from './usage.js';
|
|
4
|
+
import type { RegisteredAgent } from './agent.js';
|
|
5
|
+
import { type AgentRunState } from './state.js';
|
|
6
|
+
export { countTokens } from './usage.js';
|
|
7
|
+
export { executeStep, isParked, runLoop, type LoopInput, type LoopOutcome, type RunLedger, type StepResult } from './loop.js';
|
|
8
|
+
/** The safety cap (§2.1) must be either absent (unbounded apart from
|
|
9
|
+
* maxSteps) or a positive number — `0`/negative/NaN would silently disable
|
|
10
|
+
* the cap and let a run spend without bound. */
|
|
11
|
+
export declare function validateTokenBudget(value: number | undefined, label: string): void;
|
|
12
|
+
/** Tools the engine treats as destructive: parked behind parkForApproval
|
|
13
|
+
* (§2.5) instead of executing directly. Purely a marker — see withHitl. */
|
|
14
|
+
export declare function markRequiresConfirmation<T extends object>(t: T): T;
|
|
15
|
+
/** The engine (§2.1, §5.6). Worker-side only — runs are dispatched via the
|
|
16
|
+
* queue (§2.8) and may outlive any HTTP response.
|
|
17
|
+
*
|
|
18
|
+
* Execution is a platform-owned loop of single-round-trip steps
|
|
19
|
+
* (`executeStep`, maxSteps: 1): after EVERY step the produced messages are
|
|
20
|
+
* persisted, so a worker that dies mid-run resumes from the last step, and
|
|
21
|
+
* every continuation decision — tool results ready, budget spent, step
|
|
22
|
+
* ceiling, HITL park, user stop — is made here between steps, never inside
|
|
23
|
+
* the SDK.
|
|
24
|
+
*
|
|
25
|
+
* Concurrency: acquires the per-thread run lock (`agent:lock:{threadId}`,
|
|
26
|
+
* SET NX + lease) before any work — two workers can never run one thread,
|
|
27
|
+
* and a crashed worker's lock expires instead of blocking forever (§3.4).
|
|
28
|
+
* Returns 'lock-conflict' when the lock is held, so callers can tell a
|
|
29
|
+
* genuine no-op apart from a completed run. */
|
|
30
|
+
export interface ExecuteInput {
|
|
31
|
+
threadId: string;
|
|
32
|
+
model: string;
|
|
33
|
+
/** This dispatch's run id (§2.1). A job without one keeps the old
|
|
34
|
+
* behavior: no staleness check, and no redrive on a lock conflict. */
|
|
35
|
+
runId?: string;
|
|
36
|
+
/** Epoch ms at enqueue, for the queue-wait measurement (§2.9). */
|
|
37
|
+
enqueuedAt?: number;
|
|
38
|
+
/** The run's state (§2.10) — carried so a redrive keeps it. */
|
|
39
|
+
state?: AgentRunState;
|
|
40
|
+
tokenBudget?: number;
|
|
41
|
+
providerOptions?: ProviderOptions;
|
|
42
|
+
}
|
|
43
|
+
/** 'executed' — this worker ran the segment (or it was a legitimate no-op).
|
|
44
|
+
* 'lock-conflict' — someone else holds the thread's run lock; nothing ran.
|
|
45
|
+
* 'stale' — a NEWER run owns the thread; this job must do nothing. */
|
|
46
|
+
export type ExecuteOutcome = 'executed' | 'lock-conflict' | 'stale';
|
|
47
|
+
export declare function execute(deps: RuntimePorts, agent: RegisteredAgent, input: ExecuteInput): Promise<ExecuteOutcome>;
|
|
48
|
+
export interface FinalizeInput {
|
|
49
|
+
state: ExecutionState;
|
|
50
|
+
stopReason: 'completed' | 'token_budget' | 'max_steps' | 'cancelled';
|
|
51
|
+
tokensUsed: number;
|
|
52
|
+
attribution: TokenAttribution;
|
|
53
|
+
/** generate-text flavor only: publish the final text as one TEXT_RESULT. */
|
|
54
|
+
oneShotText?: string;
|
|
55
|
+
/** The run this finalize speaks for (§2.1). State is written only while
|
|
56
|
+
* that run is still the thread's current one. */
|
|
57
|
+
runId?: string;
|
|
58
|
+
/** Loop iterations this segment completed (§2.9). */
|
|
59
|
+
steps?: number;
|
|
60
|
+
/** Why it failed, when it did (§2.9). */
|
|
61
|
+
error?: string;
|
|
62
|
+
}
|
|
63
|
+
/** Finalize a finished run (§5.6): attribute the segment's total tokens
|
|
64
|
+
* (input + cached + output, §4), then flip state on both homes and publish.
|
|
65
|
+
* Message persistence already happened per step inside the loop — finalize
|
|
66
|
+
* never touches messages.
|
|
67
|
+
*
|
|
68
|
+
* A budget break is NOT a user stop: the run completes with stopReason
|
|
69
|
+
* 'token_budget' and the usage it actually spent. */
|
|
70
|
+
export declare function finalize(deps: RuntimePorts, agent: RegisteredAgent, threadId: string, f: FinalizeInput): Promise<void>;
|
|
71
|
+
/** §2.8 failure policy: transient errors redrive through the queue; exhausted
|
|
72
|
+
* attempts finalize FAILED (hot cache + durable). A user stop is never
|
|
73
|
+
* retried, and a successful run resets the attempt counter.
|
|
74
|
+
*
|
|
75
|
+
* `exec` is an injection seam for tests (default: the real execute). */
|
|
76
|
+
export declare function executeWithPolicy(deps: RuntimePorts, agent: RegisteredAgent, input: ExecuteInput, policy?: {
|
|
77
|
+
maxAttempts?: number;
|
|
78
|
+
}, exec?: typeof execute): Promise<void>;
|
|
79
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/core/engine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAc,MAAM,YAAY,CAAC;AAE9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAGnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAUlD,OAAO,EAAgB,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAG9D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,KAAK,SAAS,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAI9H;;iDAEiD;AACjD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAIlF;AAED;4EAC4E;AAC5E,wBAAgB,wBAAwB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAElE;AAiND;;;;;;;;;;;;;;gDAcgD;AAChD,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd;2EACuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,eAAe,CAAC;CACnC;AAED;;+EAE+E;AAC/E,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,eAAe,GAAG,OAAO,CAAC;AAEpE,wBAAsB,OAAO,CAC3B,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,cAAc,CAAC,CAwNzB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,cAAc,CAAC;IACtB,UAAU,EAAE,WAAW,GAAG,cAAc,GAAG,WAAW,GAAG,WAAW,CAAC;IACrE,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,gBAAgB,CAAC;IAC9B,4EAA4E;IAC5E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;sDACkD;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qDAAqD;IACrD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;sDAMsD;AACtD,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE,MAAM,EAChB,CAAC,EAAE,aAAa,GACf,OAAO,CAAC,IAAI,CAAC,CA8Bf;AAyCD;;;;yEAIyE;AACzE,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE,YAAY,EACnB,MAAM,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,EACjC,IAAI,GAAE,OAAO,OAAiB,GAC7B,OAAO,CAAC,IAAI,CAAC,CA+Cf"}
|