agentenkit 0.2.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -14
- package/dist/adapters/inline.d.ts +19 -5
- package/dist/adapters/inline.d.ts.map +1 -1
- package/dist/adapters/inline.js +87 -14
- package/dist/adapters/inline.js.map +1 -1
- package/dist/adapters/memory.d.ts +65 -3
- package/dist/adapters/memory.d.ts.map +1 -1
- package/dist/adapters/memory.js +267 -3
- package/dist/adapters/memory.js.map +1 -1
- package/dist/adapters/prisma.d.ts +125 -18
- package/dist/adapters/prisma.d.ts.map +1 -1
- package/dist/adapters/prisma.js +308 -67
- package/dist/adapters/prisma.js.map +1 -1
- package/dist/adapters/qstash.d.ts +15 -2
- package/dist/adapters/qstash.d.ts.map +1 -1
- package/dist/adapters/qstash.js +31 -14
- package/dist/adapters/qstash.js.map +1 -1
- package/dist/adapters/redis.d.ts +40 -4
- package/dist/adapters/redis.d.ts.map +1 -1
- package/dist/adapters/redis.js +265 -20
- package/dist/adapters/redis.js.map +1 -1
- package/dist/adapters/sqlite.d.ts +52 -2
- package/dist/adapters/sqlite.d.ts.map +1 -1
- package/dist/adapters/sqlite.js +342 -35
- package/dist/adapters/sqlite.js.map +1 -1
- package/dist/adapters/stream-scripts.d.ts +49 -0
- package/dist/adapters/stream-scripts.d.ts.map +1 -0
- package/dist/adapters/stream-scripts.js +150 -0
- package/dist/adapters/stream-scripts.js.map +1 -0
- package/dist/adapters/upstash.d.ts +20 -0
- package/dist/adapters/upstash.d.ts.map +1 -1
- package/dist/adapters/upstash.js +29 -0
- package/dist/adapters/upstash.js.map +1 -1
- package/dist/admin/memory.d.ts +11 -1
- package/dist/admin/memory.d.ts.map +1 -1
- package/dist/admin/memory.js +83 -14
- package/dist/admin/memory.js.map +1 -1
- package/dist/admin/migrations/postgres/0002-run-settled-at.d.ts +5 -0
- package/dist/admin/migrations/postgres/0002-run-settled-at.d.ts.map +1 -0
- package/dist/admin/migrations/postgres/0002-run-settled-at.js +11 -0
- package/dist/admin/migrations/postgres/0002-run-settled-at.js.map +1 -0
- package/dist/admin/migrations/postgres/0003-run-enqueued-at.d.ts +5 -0
- package/dist/admin/migrations/postgres/0003-run-enqueued-at.d.ts.map +1 -0
- package/dist/admin/migrations/postgres/0003-run-enqueued-at.js +15 -0
- package/dist/admin/migrations/postgres/0003-run-enqueued-at.js.map +1 -0
- package/dist/admin/migrations/postgres/0004-run-settle-claim.d.ts +5 -0
- package/dist/admin/migrations/postgres/0004-run-settle-claim.d.ts.map +1 -0
- package/dist/admin/migrations/postgres/0004-run-settle-claim.js +15 -0
- package/dist/admin/migrations/postgres/0004-run-settle-claim.js.map +1 -0
- package/dist/admin/migrations/postgres/0005-bigint-counters.d.ts +5 -0
- package/dist/admin/migrations/postgres/0005-bigint-counters.d.ts.map +1 -0
- package/dist/admin/migrations/postgres/0005-bigint-counters.js +12 -0
- package/dist/admin/migrations/postgres/0005-bigint-counters.js.map +1 -0
- package/dist/admin/migrations/postgres/index.d.ts.map +1 -1
- package/dist/admin/migrations/postgres/index.js +16 -1
- package/dist/admin/migrations/postgres/index.js.map +1 -1
- package/dist/admin/migrations/runner.d.ts +21 -1
- package/dist/admin/migrations/runner.d.ts.map +1 -1
- package/dist/admin/migrations/runner.js +41 -4
- package/dist/admin/migrations/runner.js.map +1 -1
- package/dist/admin/migrations/sqlite/0002-run-settled-at.d.ts +5 -0
- package/dist/admin/migrations/sqlite/0002-run-settled-at.d.ts.map +1 -0
- package/dist/admin/migrations/sqlite/0002-run-settled-at.js +11 -0
- package/dist/admin/migrations/sqlite/0002-run-settled-at.js.map +1 -0
- package/dist/admin/migrations/sqlite/0003-run-enqueued-at.d.ts +5 -0
- package/dist/admin/migrations/sqlite/0003-run-enqueued-at.d.ts.map +1 -0
- package/dist/admin/migrations/sqlite/0003-run-enqueued-at.js +15 -0
- package/dist/admin/migrations/sqlite/0003-run-enqueued-at.js.map +1 -0
- package/dist/admin/migrations/sqlite/0004-run-settle-claim.d.ts +5 -0
- package/dist/admin/migrations/sqlite/0004-run-settle-claim.d.ts.map +1 -0
- package/dist/admin/migrations/sqlite/0004-run-settle-claim.js +15 -0
- package/dist/admin/migrations/sqlite/0004-run-settle-claim.js.map +1 -0
- package/dist/admin/migrations/sqlite/index.d.ts +2 -2
- package/dist/admin/migrations/sqlite/index.d.ts.map +1 -1
- package/dist/admin/migrations/sqlite/index.js +17 -3
- package/dist/admin/migrations/sqlite/index.js.map +1 -1
- package/dist/admin/postgres.d.ts +14 -4
- package/dist/admin/postgres.d.ts.map +1 -1
- package/dist/admin/postgres.js +131 -36
- package/dist/admin/postgres.js.map +1 -1
- package/dist/admin/shared.d.ts +19 -0
- package/dist/admin/shared.d.ts.map +1 -0
- package/dist/admin/shared.js +28 -0
- package/dist/admin/shared.js.map +1 -0
- package/dist/admin/sqlite.d.ts +9 -1
- package/dist/admin/sqlite.d.ts.map +1 -1
- package/dist/admin/sqlite.js +112 -29
- package/dist/admin/sqlite.js.map +1 -1
- package/dist/core/admin.d.ts +28 -6
- package/dist/core/admin.d.ts.map +1 -1
- package/dist/core/admin.js +92 -23
- package/dist/core/admin.js.map +1 -1
- package/dist/core/agent.d.ts +7 -4
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/agent.js +15 -11
- package/dist/core/agent.js.map +1 -1
- package/dist/core/agui.d.ts +17 -0
- package/dist/core/agui.d.ts.map +1 -0
- package/dist/core/agui.js +69 -0
- package/dist/core/agui.js.map +1 -0
- package/dist/core/context.d.ts +13 -1
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/context.js +70 -19
- package/dist/core/context.js.map +1 -1
- package/dist/core/deleteThread.d.ts.map +1 -1
- package/dist/core/deleteThread.js +33 -4
- package/dist/core/deleteThread.js.map +1 -1
- package/dist/core/engine.d.ts +41 -11
- package/dist/core/engine.d.ts.map +1 -1
- package/dist/core/engine.js +855 -352
- package/dist/core/engine.js.map +1 -1
- package/dist/core/follow.d.ts +63 -1
- package/dist/core/follow.d.ts.map +1 -1
- package/dist/core/follow.js +293 -16
- package/dist/core/follow.js.map +1 -1
- package/dist/core/hitl.d.ts +43 -0
- package/dist/core/hitl.d.ts.map +1 -1
- package/dist/core/hitl.js +163 -35
- package/dist/core/hitl.js.map +1 -1
- package/dist/core/keys.d.ts +22 -4
- package/dist/core/keys.d.ts.map +1 -1
- package/dist/core/keys.js +23 -5
- package/dist/core/keys.js.map +1 -1
- package/dist/core/lease.d.ts +46 -0
- package/dist/core/lease.d.ts.map +1 -0
- package/dist/core/lease.js +142 -0
- package/dist/core/lease.js.map +1 -0
- package/dist/core/loop.d.ts +27 -7
- package/dist/core/loop.d.ts.map +1 -1
- package/dist/core/loop.js +140 -55
- package/dist/core/loop.js.map +1 -1
- package/dist/core/messages.d.ts +21 -2
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +61 -2
- package/dist/core/messages.js.map +1 -1
- package/dist/core/prune.d.ts +24 -0
- package/dist/core/prune.d.ts.map +1 -0
- package/dist/core/prune.js +43 -0
- package/dist/core/prune.js.map +1 -0
- package/dist/core/publish.d.ts +38 -10
- package/dist/core/publish.d.ts.map +1 -1
- package/dist/core/publish.js +126 -12
- package/dist/core/publish.js.map +1 -1
- package/dist/core/reclaim.d.ts +8 -1
- package/dist/core/reclaim.d.ts.map +1 -1
- package/dist/core/reclaim.js +149 -18
- package/dist/core/reclaim.js.map +1 -1
- package/dist/core/run.d.ts +7 -3
- package/dist/core/run.d.ts.map +1 -1
- package/dist/core/run.js +95 -35
- package/dist/core/run.js.map +1 -1
- package/dist/core/segment.d.ts +62 -0
- package/dist/core/segment.d.ts.map +1 -0
- package/dist/core/segment.js +318 -0
- package/dist/core/segment.js.map +1 -0
- package/dist/core/settle.d.ts +57 -0
- package/dist/core/settle.d.ts.map +1 -0
- package/dist/core/settle.js +181 -0
- package/dist/core/settle.js.map +1 -0
- package/dist/core/snapshot.d.ts +36 -0
- package/dist/core/snapshot.d.ts.map +1 -0
- package/dist/core/snapshot.js +87 -0
- package/dist/core/snapshot.js.map +1 -0
- package/dist/core/stop.d.ts +16 -1
- package/dist/core/stop.d.ts.map +1 -1
- package/dist/core/stop.js +69 -15
- package/dist/core/stop.js.map +1 -1
- package/dist/core/stream-events.d.ts +184 -0
- package/dist/core/stream-events.d.ts.map +1 -0
- package/dist/core/stream-events.js +26 -0
- package/dist/core/stream-events.js.map +1 -0
- package/dist/core/stream.d.ts +29 -0
- package/dist/core/stream.d.ts.map +1 -1
- package/dist/core/stream.js +79 -0
- package/dist/core/stream.js.map +1 -1
- package/dist/core/subagent.d.ts +36 -5
- package/dist/core/subagent.d.ts.map +1 -1
- package/dist/core/subagent.js +117 -22
- package/dist/core/subagent.js.map +1 -1
- package/dist/core/types.d.ts +197 -11
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +26 -1
- package/dist/core/types.js.map +1 -1
- package/dist/core/usage.d.ts +53 -5
- package/dist/core/usage.d.ts.map +1 -1
- package/dist/core/usage.js +170 -47
- package/dist/core/usage.js.map +1 -1
- package/dist/index.d.ts +16 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -7
- package/dist/index.js.map +1 -1
- package/dist/ports/admin.d.ts +59 -0
- package/dist/ports/admin.d.ts.map +1 -1
- package/dist/ports/kv.d.ts +17 -0
- package/dist/ports/kv.d.ts.map +1 -1
- package/dist/ports/queue.d.ts +87 -7
- package/dist/ports/queue.d.ts.map +1 -1
- package/dist/ports/queue.js +36 -1
- package/dist/ports/queue.js.map +1 -1
- package/dist/ports/runtime.d.ts +171 -20
- package/dist/ports/runtime.d.ts.map +1 -1
- package/dist/ports/storage.d.ts +26 -5
- package/dist/ports/storage.d.ts.map +1 -1
- package/dist/ports/streams.d.ts +60 -0
- package/dist/ports/streams.d.ts.map +1 -0
- package/dist/ports/streams.js +20 -0
- package/dist/ports/streams.js.map +1 -0
- package/dist/pricing.d.ts +5 -0
- package/dist/pricing.d.ts.map +1 -1
- package/dist/pricing.js +35 -10
- package/dist/pricing.js.map +1 -1
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +144 -46
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
import { THREAD_KEY_TTL_SECONDS } from './keys.js';
|
|
2
|
+
import { publish } from './publish.js';
|
|
3
|
+
import { streamIdOf } from './stream-events.js';
|
|
4
|
+
/** The worker's side of a run stream: one per segment, open from pickup to
|
|
5
|
+
* the segment's end. Everything published on the thread while it is open
|
|
6
|
+
* is turned into typed stream events here (see forward), so the engine
|
|
7
|
+
* keeps calling `publish` and only opens and closes the segment.
|
|
8
|
+
*
|
|
9
|
+
* Events are appended together: they wait up to `streamFlushMs`, or until
|
|
10
|
+
* `streamFlushEvents` are waiting. A step end, a tool result, a park and a
|
|
11
|
+
* close go out at once. A failed append is logged, never thrown: the stream
|
|
12
|
+
* is delivery, and the run's messages are saved either way. */
|
|
13
|
+
/** The segment counter: each pickup of a run takes the next number, so a
|
|
14
|
+
* retry or a resume gets a stream of its own. */
|
|
15
|
+
export const segmentKey = (runId) => `agent:segment:${runId}`;
|
|
16
|
+
/** Open segments by thread, per RunStreams, so two runtimes in one process
|
|
17
|
+
* never see each other's. */
|
|
18
|
+
const open = new WeakMap();
|
|
19
|
+
/** The segment this process has open on a thread, if any. */
|
|
20
|
+
export function activeSegment(deps, threadId) {
|
|
21
|
+
return deps.streams ? open.get(deps.streams)?.get(threadId) : undefined;
|
|
22
|
+
}
|
|
23
|
+
/** Events that go out at once rather than wait for the window. */
|
|
24
|
+
const IMMEDIATE = new Set([
|
|
25
|
+
'RUN_STARTED', 'TOOL_CALL_RESULT', 'STEP_FINISHED', 'INPUT_REQUIRED', 'SUBAGENT_FINISHED',
|
|
26
|
+
]);
|
|
27
|
+
const immediate = (e) => IMMEDIATE.has(e.type) || (e.type === 'SUBAGENT_EVENT' && immediate(e.event));
|
|
28
|
+
/** Opens the segment's stream and says RUN_STARTED on it. Null when the
|
|
29
|
+
* runtime has no streams, or the open failed (logged): the run goes on
|
|
30
|
+
* without a stream. */
|
|
31
|
+
export async function openSegment(deps, threadId, runId) {
|
|
32
|
+
if (!deps.streams || !runId)
|
|
33
|
+
return null;
|
|
34
|
+
try {
|
|
35
|
+
const segment = await deps.kv.incrWithExpiry(segmentKey(runId), THREAD_KEY_TTL_SECONDS);
|
|
36
|
+
const streamId = streamIdOf(runId, segment);
|
|
37
|
+
await deps.streams.open(streamId, { threadId, runId }, deps.config.streamTtlMs);
|
|
38
|
+
const seg = new SegmentStream(deps, deps.streams, threadId, runId, segment, streamId);
|
|
39
|
+
let byThread = open.get(deps.streams);
|
|
40
|
+
if (!byThread) {
|
|
41
|
+
byThread = new Map();
|
|
42
|
+
open.set(deps.streams, byThread);
|
|
43
|
+
}
|
|
44
|
+
byThread.set(threadId, seg);
|
|
45
|
+
await seg.push([{ type: 'RUN_STARTED', threadId, runId, streamId, segment }]);
|
|
46
|
+
// The thread record says which stream is open, so a tab that opens the
|
|
47
|
+
// thread finds it.
|
|
48
|
+
await publish(deps, threadId, 'RUN_STARTED', { runId, streamId, segment }, runId);
|
|
49
|
+
return seg;
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
(deps.log ?? console).error('run stream not opened', { threadId, runId, err });
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/** Closes a segment's stream that its worker could not: the sweep's end for
|
|
57
|
+
* a run whose worker died. A stream that is already closed or gone is left
|
|
58
|
+
* as it is. */
|
|
59
|
+
export async function closeLostSegment(deps, threadId, runId, error) {
|
|
60
|
+
if (!deps.streams)
|
|
61
|
+
return;
|
|
62
|
+
const segment = Number(await deps.kv.get(segmentKey(runId)));
|
|
63
|
+
if (!segment)
|
|
64
|
+
return;
|
|
65
|
+
const streamId = streamIdOf(runId, segment);
|
|
66
|
+
const snap = await deps.streams.snapshot(streamId).catch(() => null);
|
|
67
|
+
if (!snap || snap.end)
|
|
68
|
+
return; // gone, or its worker closed it after all
|
|
69
|
+
await deps.streams
|
|
70
|
+
.close(streamId, { type: 'RUN_ERROR', status: 'lost', error }, deps.config.streamGraceMs)
|
|
71
|
+
.catch(() => undefined);
|
|
72
|
+
await publish(deps, threadId, 'RUN_ENDED', { runId, streamId, segment, status: 'lost', error }, runId);
|
|
73
|
+
}
|
|
74
|
+
export class SegmentStream {
|
|
75
|
+
deps;
|
|
76
|
+
streams;
|
|
77
|
+
threadId;
|
|
78
|
+
runId;
|
|
79
|
+
segment;
|
|
80
|
+
streamId;
|
|
81
|
+
buf = [];
|
|
82
|
+
timer;
|
|
83
|
+
chain = Promise.resolve();
|
|
84
|
+
ended = false;
|
|
85
|
+
agents = new Map();
|
|
86
|
+
ids = 0;
|
|
87
|
+
/** A one-shot agent's final text, carried on RUN_FINISHED. */
|
|
88
|
+
oneShotText;
|
|
89
|
+
constructor(deps, streams, threadId, runId, segment, streamId) {
|
|
90
|
+
this.deps = deps;
|
|
91
|
+
this.streams = streams;
|
|
92
|
+
this.threadId = threadId;
|
|
93
|
+
this.runId = runId;
|
|
94
|
+
this.segment = segment;
|
|
95
|
+
this.streamId = streamId;
|
|
96
|
+
}
|
|
97
|
+
get closed() {
|
|
98
|
+
return this.ended;
|
|
99
|
+
}
|
|
100
|
+
/** Queue events; resolves once they are appended when any must go at once. */
|
|
101
|
+
push(events) {
|
|
102
|
+
if (this.ended || events.length === 0)
|
|
103
|
+
return Promise.resolve();
|
|
104
|
+
this.buf.push(...events);
|
|
105
|
+
const { streamFlushMs, streamFlushEvents } = this.deps.config;
|
|
106
|
+
if (streamFlushMs === 0 || this.buf.length >= streamFlushEvents || events.some(immediate)) {
|
|
107
|
+
return this.flush();
|
|
108
|
+
}
|
|
109
|
+
if (!this.timer) {
|
|
110
|
+
this.timer = setTimeout(() => void this.flush(), streamFlushMs);
|
|
111
|
+
this.timer.unref?.();
|
|
112
|
+
}
|
|
113
|
+
return Promise.resolve();
|
|
114
|
+
}
|
|
115
|
+
/** Append what waits; resolves once everything pushed so far is out. */
|
|
116
|
+
flush() {
|
|
117
|
+
if (this.timer)
|
|
118
|
+
clearTimeout(this.timer);
|
|
119
|
+
this.timer = undefined;
|
|
120
|
+
const batch = this.buf.splice(0);
|
|
121
|
+
if (batch.length > 0) {
|
|
122
|
+
this.chain = this.chain
|
|
123
|
+
.then(() => this.streams.append(this.streamId, batch))
|
|
124
|
+
.then(() => undefined)
|
|
125
|
+
.catch((err) => {
|
|
126
|
+
(this.deps.log ?? console).error('run stream events not appended', { streamId: this.streamId, err });
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return this.chain;
|
|
130
|
+
}
|
|
131
|
+
/** End the stream: what is open is ended, what waits is appended, and the
|
|
132
|
+
* end item goes last. A second close is a no-op. */
|
|
133
|
+
async close(end) {
|
|
134
|
+
if (this.ended)
|
|
135
|
+
return;
|
|
136
|
+
const closing = [];
|
|
137
|
+
for (const key of this.agents.keys())
|
|
138
|
+
closing.push(...this.endBlocks(key));
|
|
139
|
+
await this.push(closing);
|
|
140
|
+
await this.flush();
|
|
141
|
+
this.ended = true;
|
|
142
|
+
const byThread = open.get(this.streams);
|
|
143
|
+
if (byThread?.get(this.threadId) === this)
|
|
144
|
+
byThread.delete(this.threadId);
|
|
145
|
+
await this.streams.close(this.streamId, end, this.deps.config.streamGraceMs).catch((err) => {
|
|
146
|
+
(this.deps.log ?? console).error('run stream not closed', { streamId: this.streamId, err });
|
|
147
|
+
});
|
|
148
|
+
// The thread record says how the segment ended.
|
|
149
|
+
await publish(this.deps, this.threadId, 'RUN_ENDED', {
|
|
150
|
+
runId: this.runId, streamId: this.streamId, segment: this.segment, status: end.status,
|
|
151
|
+
...(end.type === 'RUN_ERROR' ? { error: end.error } : {}),
|
|
152
|
+
}, this.runId).catch((err) => {
|
|
153
|
+
(this.deps.log ?? console).error('run end not recorded', { streamId: this.streamId, err });
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/** Turn a published event into stream events. `reserved` is whether the
|
|
157
|
+
* type is one of the platform's; any other is an app's own, and goes out
|
|
158
|
+
* as CUSTOM. */
|
|
159
|
+
forward(type, payload, reserved) {
|
|
160
|
+
const p = (payload ?? {});
|
|
161
|
+
switch (type) {
|
|
162
|
+
case 'CHUNK':
|
|
163
|
+
return this.push(this.mapChunk('', p));
|
|
164
|
+
case 'SUBAGENT_CHUNK': {
|
|
165
|
+
const agentId = String(p.agentId);
|
|
166
|
+
return this.push(this.wrap(agentId, this.mapChunk(agentId, p.chunk ?? {})));
|
|
167
|
+
}
|
|
168
|
+
// The step is saved: the stream's STEP_FINISHED says so, right here,
|
|
169
|
+
// ahead of any park the step raised.
|
|
170
|
+
case 'STEP_COMMITTED': {
|
|
171
|
+
const agentId = p.agentId ?? null;
|
|
172
|
+
const ending = agentId === null ? this.endBlocks('') : this.wrap(agentId, this.endBlocks(agentId));
|
|
173
|
+
return this.push([
|
|
174
|
+
...ending,
|
|
175
|
+
{
|
|
176
|
+
type: 'STEP_FINISHED',
|
|
177
|
+
step: Number(p.step ?? 0),
|
|
178
|
+
agentId,
|
|
179
|
+
finishReason: String(p.finishReason ?? ''),
|
|
180
|
+
usage: {
|
|
181
|
+
inputTokens: Number(p.inputTokens ?? 0),
|
|
182
|
+
cachedInputTokens: Number(p.cachedInputTokens ?? 0),
|
|
183
|
+
outputTokens: Number(p.outputTokens ?? 0),
|
|
184
|
+
totalTokens: Number(p.totalTokens ?? 0),
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
]);
|
|
188
|
+
}
|
|
189
|
+
case 'INPUT_REQUIRED':
|
|
190
|
+
// Through JSON, so a Date goes out as the string every store holds.
|
|
191
|
+
return this.push([{ ...JSON.parse(JSON.stringify(p)), type: 'INPUT_REQUIRED' }]);
|
|
192
|
+
case 'SUBAGENT_STARTED':
|
|
193
|
+
return this.push([
|
|
194
|
+
{ type: 'SUBAGENT_STARTED', subagentId: String(p.agentId), name: String(p.name ?? ''), depth: Number(p.depth ?? 0) },
|
|
195
|
+
]);
|
|
196
|
+
case 'SUBAGENT_COMPLETED':
|
|
197
|
+
case 'SUBAGENT_FAILED': {
|
|
198
|
+
const agentId = String(p.agentId);
|
|
199
|
+
const failed = type === 'SUBAGENT_FAILED';
|
|
200
|
+
const status = !failed ? 'completed' : p.state === 'CANCELLED' ? 'cancelled' : 'failed';
|
|
201
|
+
return this.push([
|
|
202
|
+
...this.wrap(agentId, this.endBlocks(agentId)),
|
|
203
|
+
{
|
|
204
|
+
type: 'SUBAGENT_FINISHED',
|
|
205
|
+
subagentId: agentId,
|
|
206
|
+
status,
|
|
207
|
+
...(failed && p.error !== undefined ? { error: String(p.error) } : {}),
|
|
208
|
+
},
|
|
209
|
+
]);
|
|
210
|
+
}
|
|
211
|
+
case 'TEXT_RESULT':
|
|
212
|
+
this.oneShotText = typeof p.text === 'string' ? p.text : undefined;
|
|
213
|
+
return Promise.resolve();
|
|
214
|
+
default:
|
|
215
|
+
if (reserved)
|
|
216
|
+
return Promise.resolve(); // the thread record's, or a notice
|
|
217
|
+
return this.push([{ type: 'CUSTOM', name: type, value: payload ?? null }]);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
blocks(key) {
|
|
221
|
+
let b = this.agents.get(key);
|
|
222
|
+
if (!b) {
|
|
223
|
+
b = { tools: new Set() };
|
|
224
|
+
this.agents.set(key, b);
|
|
225
|
+
}
|
|
226
|
+
return b;
|
|
227
|
+
}
|
|
228
|
+
newId() {
|
|
229
|
+
return `${this.streamId}:m${++this.ids}`;
|
|
230
|
+
}
|
|
231
|
+
wrap(agentId, events) {
|
|
232
|
+
return events.map((event) => ({ type: 'SUBAGENT_EVENT', subagentId: agentId, event }));
|
|
233
|
+
}
|
|
234
|
+
/** End an agent's open text and reasoning. */
|
|
235
|
+
endBlocks(key) {
|
|
236
|
+
const b = this.agents.get(key);
|
|
237
|
+
if (!b)
|
|
238
|
+
return [];
|
|
239
|
+
const out = [];
|
|
240
|
+
if (b.reasoning)
|
|
241
|
+
out.push({ type: 'REASONING_END', messageId: b.reasoning });
|
|
242
|
+
if (b.text)
|
|
243
|
+
out.push({ type: 'TEXT_MESSAGE_END', messageId: b.text });
|
|
244
|
+
b.reasoning = undefined;
|
|
245
|
+
b.text = undefined;
|
|
246
|
+
return out;
|
|
247
|
+
}
|
|
248
|
+
/** One SDK stream part as stream events, for one agent ('' the main one). */
|
|
249
|
+
mapChunk(key, c) {
|
|
250
|
+
const b = this.blocks(key);
|
|
251
|
+
const out = [];
|
|
252
|
+
const startTool = (toolCallId, toolName) => {
|
|
253
|
+
if (b.tools.has(toolCallId))
|
|
254
|
+
return;
|
|
255
|
+
b.tools.add(toolCallId);
|
|
256
|
+
out.push({ type: 'TOOL_CALL_START', toolCallId, toolName });
|
|
257
|
+
};
|
|
258
|
+
switch (c.type) {
|
|
259
|
+
case 'text-delta': {
|
|
260
|
+
if (b.reasoning) {
|
|
261
|
+
out.push({ type: 'REASONING_END', messageId: b.reasoning });
|
|
262
|
+
b.reasoning = undefined;
|
|
263
|
+
}
|
|
264
|
+
if (!b.text) {
|
|
265
|
+
b.text = this.newId();
|
|
266
|
+
out.push({ type: 'TEXT_MESSAGE_START', messageId: b.text, role: 'assistant' });
|
|
267
|
+
}
|
|
268
|
+
out.push({ type: 'TEXT_MESSAGE_CONTENT', messageId: b.text, delta: String(c.textDelta ?? '') });
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
case 'reasoning': {
|
|
272
|
+
if (b.text) {
|
|
273
|
+
out.push({ type: 'TEXT_MESSAGE_END', messageId: b.text });
|
|
274
|
+
b.text = undefined;
|
|
275
|
+
}
|
|
276
|
+
if (!b.reasoning) {
|
|
277
|
+
b.reasoning = this.newId();
|
|
278
|
+
out.push({ type: 'REASONING_START', messageId: b.reasoning });
|
|
279
|
+
}
|
|
280
|
+
out.push({ type: 'REASONING_CONTENT', messageId: b.reasoning, delta: String(c.textDelta ?? '') });
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
case 'tool-call-streaming-start':
|
|
284
|
+
out.push(...this.endBlocks(key));
|
|
285
|
+
startTool(String(c.toolCallId), String(c.toolName));
|
|
286
|
+
break;
|
|
287
|
+
case 'tool-call-delta':
|
|
288
|
+
startTool(String(c.toolCallId), String(c.toolName));
|
|
289
|
+
out.push({ type: 'TOOL_CALL_ARGS', toolCallId: String(c.toolCallId), delta: String(c.argsTextDelta ?? '') });
|
|
290
|
+
break;
|
|
291
|
+
case 'tool-call': {
|
|
292
|
+
out.push(...this.endBlocks(key));
|
|
293
|
+
const toolCallId = String(c.toolCallId);
|
|
294
|
+
startTool(toolCallId, String(c.toolName));
|
|
295
|
+
b.tools.delete(toolCallId);
|
|
296
|
+
let args = c.args;
|
|
297
|
+
if (typeof args === 'string') {
|
|
298
|
+
try {
|
|
299
|
+
args = JSON.parse(args);
|
|
300
|
+
}
|
|
301
|
+
catch { /* left as the string it came as */ }
|
|
302
|
+
}
|
|
303
|
+
out.push({ type: 'TOOL_CALL_END', toolCallId, toolName: String(c.toolName), args: args ?? null });
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
case 'tool-result':
|
|
307
|
+
out.push({
|
|
308
|
+
type: 'TOOL_CALL_RESULT', toolCallId: String(c.toolCallId), toolName: String(c.toolName), result: c.result ?? null,
|
|
309
|
+
});
|
|
310
|
+
break;
|
|
311
|
+
case 'source':
|
|
312
|
+
out.push({ type: 'SOURCE', source: c.source ?? null });
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
return out;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
//# sourceMappingURL=segment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"segment.js","sourceRoot":"","sources":["../../src/core/segment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { RunFinishInfo, RuntimePorts } from '../ports/runtime.js';
|
|
2
|
+
import type { ExecutionState, UsageTotals } from './types.js';
|
|
3
|
+
import type { RegisteredAgent } from './agent.js';
|
|
4
|
+
/** How long a settle claim holds (§5.6). A claim older than this belongs to a
|
|
5
|
+
* settler that died, and the next settle takes the run over. */
|
|
6
|
+
export declare const SETTLE_CLAIM_TTL_MS: number;
|
|
7
|
+
/** Whether a state is one a run cannot leave. */
|
|
8
|
+
export declare const isTerminal: (state?: ExecutionState | null) => boolean;
|
|
9
|
+
/** Sum every model call a run made, nested runs included (§4). A storage
|
|
10
|
+
* hiccup must not turn a finished run into a failed one, so the read never
|
|
11
|
+
* throws; but a hook that bills from these totals must be able to tell
|
|
12
|
+
* "spent nothing" from "could not read", so the error comes back beside the
|
|
13
|
+
* zero totals rather than swallowed. */
|
|
14
|
+
export declare function runBill(deps: RuntimePorts, threadId: string, runId?: string): Promise<{
|
|
15
|
+
usage: UsageTotals;
|
|
16
|
+
error?: unknown;
|
|
17
|
+
}>;
|
|
18
|
+
/** Run the spec's `onSettle` for a run, once (§5.6). Every path that ends a
|
|
19
|
+
* run goes through here: the worker that finished or aborted it, the worker
|
|
20
|
+
* that failed it, a stop that ended it while no worker held it, and the
|
|
21
|
+
* late-settle sweep.
|
|
22
|
+
*
|
|
23
|
+
* Once is kept by a claim on the run record, made in one conditional write
|
|
24
|
+
* before the hook runs: only the settler that wins it calls the hook, so two
|
|
25
|
+
* that arrive together cannot both bill. The hook's success marks the run
|
|
26
|
+
* settled; its failure drops the claim, so a later stop, delivery or sweep
|
|
27
|
+
* runs it again. A claim that is never ended (the settler died mid-hook) is
|
|
28
|
+
* taken over after SETTLE_CLAIM_TTL_MS. That is also why the hook must be
|
|
29
|
+
* idempotent by runId: a hook slower than the claim, or a mark that could
|
|
30
|
+
* not be written, can see the same run twice.
|
|
31
|
+
*
|
|
32
|
+
* `reached` is whether this call ran the settle at all; `error` is the
|
|
33
|
+
* hook's. A run with no record (a foreign dispatch) settles unclaimed, as it
|
|
34
|
+
* always did. A store that cannot take the claim leaves the run unsettled
|
|
35
|
+
* for the sweep rather than risk a second bill. */
|
|
36
|
+
export declare function settleRun(deps: RuntimePorts, agent: RegisteredAgent | null, info: RunFinishInfo): Promise<{
|
|
37
|
+
reached: boolean;
|
|
38
|
+
error?: unknown;
|
|
39
|
+
}>;
|
|
40
|
+
/** Fire a spec's `onFinish`. The run has already ended: a callback that throws
|
|
41
|
+
* is the caller's bug to see in the log, not a reason to change the end. */
|
|
42
|
+
export declare function callOnFinish(deps: RuntimePorts, agent: RegisteredAgent | null, info: RunFinishInfo): Promise<void>;
|
|
43
|
+
/** Settle a run whose record has ended but whose settle never ran (§2.1,
|
|
44
|
+
* §5.6): a stop that ended it while it was queued or parked, a worker that
|
|
45
|
+
* died between finishing and settling, or a settle hook that failed. The
|
|
46
|
+
* steps it did make were priced as they happened, so its bill is real and
|
|
47
|
+
* has to reach the hook. Nothing happens when the run already settled, or
|
|
48
|
+
* when its record is still open.
|
|
49
|
+
*
|
|
50
|
+
* The caller holds the run lock: a stop takes it for exactly this, and so do
|
|
51
|
+
* a worker that finds the thread already ended and the sweep. */
|
|
52
|
+
export declare function settleEndedRun(deps: RuntimePorts, agent: RegisteredAgent | null, threadId: string, runId?: string): Promise<boolean>;
|
|
53
|
+
/** Settle an ended run whose settle never ran (§5.6), under the run lock.
|
|
54
|
+
* False when it was settled meanwhile, or a worker holds the run (that
|
|
55
|
+
* worker settles it). */
|
|
56
|
+
export declare function settleLate(deps: RuntimePorts, agent: RegisteredAgent | null, threadId: string, runId?: string): Promise<boolean>;
|
|
57
|
+
//# sourceMappingURL=settle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settle.d.ts","sourceRoot":"","sources":["../../src/core/settle.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAIlD;iEACiE;AACjE,eAAO,MAAM,mBAAmB,QAAiB,CAAC;AAIlD,iDAAiD;AACjD,eAAO,MAAM,UAAU,GAAI,QAAQ,cAAc,GAAG,IAAI,KAAG,OACW,CAAC;AAEvE;;;;yCAIyC;AACzC,wBAAsB,OAAO,CAC3B,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CAQlD;AAED;;;;;;;;;;;;;;;;;oDAiBoD;AACpD,wBAAsB,SAAS,CAC7B,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,eAAe,GAAG,IAAI,EAC7B,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,CA6DhD;AAED;6EAC6E;AAC7E,wBAAsB,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,EAAE,IAAI,EAAE,aAAa,iBAQxG;AAED;;;;;;;;kEAQkE;AAClE,wBAAsB,cAAc,CAClC,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,eAAe,GAAG,IAAI,EAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAuBlB;AAED;;0BAE0B;AAC1B,wBAAsB,UAAU,CAC9B,IAAI,EAAE,YAAY,EAClB,KAAK,EAAE,eAAe,GAAG,IAAI,EAC7B,QAAQ,EAAE,MAAM,EAChB,KAAK,CAAC,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAYlB"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { emptyTotals } from './usage.js';
|
|
3
|
+
import { Lease } from './lease.js';
|
|
4
|
+
/** How long a settle claim holds (§5.6). A claim older than this belongs to a
|
|
5
|
+
* settler that died, and the next settle takes the run over. */
|
|
6
|
+
export const SETTLE_CLAIM_TTL_MS = 10 * 60 * 1000;
|
|
7
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
8
|
+
/** Whether a state is one a run cannot leave. */
|
|
9
|
+
export const isTerminal = (state) => state === 'CANCELLED' || state === 'COMPLETED' || state === 'FAILED';
|
|
10
|
+
/** Sum every model call a run made, nested runs included (§4). A storage
|
|
11
|
+
* hiccup must not turn a finished run into a failed one, so the read never
|
|
12
|
+
* throws; but a hook that bills from these totals must be able to tell
|
|
13
|
+
* "spent nothing" from "could not read", so the error comes back beside the
|
|
14
|
+
* zero totals rather than swallowed. */
|
|
15
|
+
export async function runBill(deps, threadId, runId) {
|
|
16
|
+
if (!runId)
|
|
17
|
+
return { usage: emptyTotals() };
|
|
18
|
+
try {
|
|
19
|
+
return { usage: await deps.storage.usage.total(threadId, { runId }) };
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
(deps.log ?? console).error('run bill not read', { run: runId, err: error });
|
|
23
|
+
return { usage: emptyTotals(), error };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/** Run the spec's `onSettle` for a run, once (§5.6). Every path that ends a
|
|
27
|
+
* run goes through here: the worker that finished or aborted it, the worker
|
|
28
|
+
* that failed it, a stop that ended it while no worker held it, and the
|
|
29
|
+
* late-settle sweep.
|
|
30
|
+
*
|
|
31
|
+
* Once is kept by a claim on the run record, made in one conditional write
|
|
32
|
+
* before the hook runs: only the settler that wins it calls the hook, so two
|
|
33
|
+
* that arrive together cannot both bill. The hook's success marks the run
|
|
34
|
+
* settled; its failure drops the claim, so a later stop, delivery or sweep
|
|
35
|
+
* runs it again. A claim that is never ended (the settler died mid-hook) is
|
|
36
|
+
* taken over after SETTLE_CLAIM_TTL_MS. That is also why the hook must be
|
|
37
|
+
* idempotent by runId: a hook slower than the claim, or a mark that could
|
|
38
|
+
* not be written, can see the same run twice.
|
|
39
|
+
*
|
|
40
|
+
* `reached` is whether this call ran the settle at all; `error` is the
|
|
41
|
+
* hook's. A run with no record (a foreign dispatch) settles unclaimed, as it
|
|
42
|
+
* always did. A store that cannot take the claim leaves the run unsettled
|
|
43
|
+
* for the sweep rather than risk a second bill. */
|
|
44
|
+
export async function settleRun(deps, agent, info) {
|
|
45
|
+
const log = deps.log ?? console;
|
|
46
|
+
const hook = async () => {
|
|
47
|
+
const onSettle = agent?.args.onSettle;
|
|
48
|
+
if (typeof onSettle !== 'function')
|
|
49
|
+
return undefined;
|
|
50
|
+
try {
|
|
51
|
+
await onSettle(info);
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
catch (err) {
|
|
55
|
+
return err ?? new Error('onSettle threw');
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
const runId = info.runId;
|
|
59
|
+
if (!runId)
|
|
60
|
+
return { reached: true, error: await hook() };
|
|
61
|
+
const token = randomUUID();
|
|
62
|
+
let claimed = false;
|
|
63
|
+
let failure;
|
|
64
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
65
|
+
if (attempt > 0)
|
|
66
|
+
await sleep(attempt * 200);
|
|
67
|
+
try {
|
|
68
|
+
claimed = await deps.admin.runs.claimSettle(runId, token, new Date(Date.now() - SETTLE_CLAIM_TTL_MS));
|
|
69
|
+
failure = undefined;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
failure = err;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (failure !== undefined) {
|
|
77
|
+
log.error('settle not claimed; the run stays unsettled for the late-settle sweep', { run: runId, err: failure });
|
|
78
|
+
return { reached: false };
|
|
79
|
+
}
|
|
80
|
+
if (!claimed) {
|
|
81
|
+
const rec = await deps.admin.runs.get(runId).catch(() => undefined);
|
|
82
|
+
// No record to claim: settled unclaimed.
|
|
83
|
+
if (rec === null)
|
|
84
|
+
return { reached: true, error: await hook() };
|
|
85
|
+
return { reached: false }; // settled already, or being settled by someone else
|
|
86
|
+
}
|
|
87
|
+
const error = await hook();
|
|
88
|
+
let markError;
|
|
89
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
90
|
+
if (attempt > 0)
|
|
91
|
+
await sleep(attempt * 200);
|
|
92
|
+
try {
|
|
93
|
+
await deps.admin.runs.endSettle(runId, token, error === undefined);
|
|
94
|
+
markError = undefined;
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
markError = err;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (error !== undefined) {
|
|
102
|
+
// The claim is dropped, so a later stop, delivery or sweep can run the
|
|
103
|
+
// hook again.
|
|
104
|
+
log.error('settle hook failed; the run stays unsettled for a retry', { run: runId, err: error });
|
|
105
|
+
}
|
|
106
|
+
else if (markError !== undefined) {
|
|
107
|
+
log.error('settle mark not written; the claim lapses and the late-settle sweep may settle this run again', {
|
|
108
|
+
run: runId, err: markError,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return { reached: true, error };
|
|
112
|
+
}
|
|
113
|
+
/** Fire a spec's `onFinish`. The run has already ended: a callback that throws
|
|
114
|
+
* is the caller's bug to see in the log, not a reason to change the end. */
|
|
115
|
+
export async function callOnFinish(deps, agent, info) {
|
|
116
|
+
const onFinish = agent?.args.onFinish;
|
|
117
|
+
if (typeof onFinish !== 'function')
|
|
118
|
+
return;
|
|
119
|
+
try {
|
|
120
|
+
await onFinish(info);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
(deps.log ?? console).error('onFinish threw', { runId: info.runId, err: String(err) });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** Settle a run whose record has ended but whose settle never ran (§2.1,
|
|
127
|
+
* §5.6): a stop that ended it while it was queued or parked, a worker that
|
|
128
|
+
* died between finishing and settling, or a settle hook that failed. The
|
|
129
|
+
* steps it did make were priced as they happened, so its bill is real and
|
|
130
|
+
* has to reach the hook. Nothing happens when the run already settled, or
|
|
131
|
+
* when its record is still open.
|
|
132
|
+
*
|
|
133
|
+
* The caller holds the run lock: a stop takes it for exactly this, and so do
|
|
134
|
+
* a worker that finds the thread already ended and the sweep. */
|
|
135
|
+
export async function settleEndedRun(deps, agent, threadId, runId) {
|
|
136
|
+
if (!agent || !runId)
|
|
137
|
+
return false;
|
|
138
|
+
const rec = await deps.admin.runs.get(runId).catch(() => null);
|
|
139
|
+
if (!rec || rec.settledAt || !isTerminal(rec.state))
|
|
140
|
+
return false;
|
|
141
|
+
const bill = await runBill(deps, threadId, runId);
|
|
142
|
+
const info = {
|
|
143
|
+
threadId, runId, state: rec.state, stopReason: rec.stopReason || 'cancelled',
|
|
144
|
+
cancelled: rec.state === 'CANCELLED',
|
|
145
|
+
...(rec.error ? { error: rec.error } : {}),
|
|
146
|
+
tokensUsed: rec.totalTokens,
|
|
147
|
+
attribution: {
|
|
148
|
+
inputTokens: rec.inputTokens, cachedInputTokens: rec.cachedInputTokens,
|
|
149
|
+
outputTokens: rec.outputTokens, totalTokens: rec.totalTokens,
|
|
150
|
+
},
|
|
151
|
+
steps: rec.steps,
|
|
152
|
+
usage: bill.usage,
|
|
153
|
+
...(bill.error !== undefined ? { usageError: bill.error } : {}),
|
|
154
|
+
};
|
|
155
|
+
// The hook's error is not acted on: the run has already ended either way,
|
|
156
|
+
// and the claim is dropped for a retry.
|
|
157
|
+
const { reached } = await settleRun(deps, agent, info);
|
|
158
|
+
if (reached)
|
|
159
|
+
await callOnFinish(deps, agent, info);
|
|
160
|
+
return reached;
|
|
161
|
+
}
|
|
162
|
+
/** Settle an ended run whose settle never ran (§5.6), under the run lock.
|
|
163
|
+
* False when it was settled meanwhile, or a worker holds the run (that
|
|
164
|
+
* worker settles it). */
|
|
165
|
+
export async function settleLate(deps, agent, threadId, runId) {
|
|
166
|
+
if (!runId)
|
|
167
|
+
return false;
|
|
168
|
+
const lease = await Lease.acquire(deps, threadId, runId, undefined);
|
|
169
|
+
if (!lease)
|
|
170
|
+
return false;
|
|
171
|
+
// Renewed while the hook runs: a slow settle must not let a queued job take
|
|
172
|
+
// the lock and settle the same run beside it.
|
|
173
|
+
lease.keep();
|
|
174
|
+
try {
|
|
175
|
+
return await settleEndedRun(deps, agent, threadId, runId);
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
await lease.release();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=settle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settle.js","sourceRoot":"","sources":["../../src/core/settle.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { RuntimePorts, ThreadSnapshot } from '../ports/runtime.js';
|
|
2
|
+
import type { StreamEnd, StreamItem } from './stream-events.js';
|
|
3
|
+
/** The run stream a snapshot carries: the segment in flight, or one that
|
|
4
|
+
* ended a moment ago, so a tab that loads just as a run ends still sees
|
|
5
|
+
* its end. */
|
|
6
|
+
export interface SnapshotStream {
|
|
7
|
+
streamId: string;
|
|
8
|
+
runId: string;
|
|
9
|
+
/** What the messages do not have yet: each agent's events after its last
|
|
10
|
+
* finished step. A finished step is in the messages already, and showing
|
|
11
|
+
* its deltas too would put its text on screen twice. */
|
|
12
|
+
items: StreamItem[];
|
|
13
|
+
/** The stream's end, when it has one. */
|
|
14
|
+
end: StreamEnd | null;
|
|
15
|
+
/** Where a live read picks up: the last offset the stream held, cut items
|
|
16
|
+
* included. Null for a stream with nothing in it. */
|
|
17
|
+
offset: string | null;
|
|
18
|
+
}
|
|
19
|
+
/** How long after its end a stream still rides on the snapshot. */
|
|
20
|
+
export declare const RECENT_END_MS = 60000;
|
|
21
|
+
/** Drop each agent's content up to its last finished step (see
|
|
22
|
+
* SnapshotStream.items). */
|
|
23
|
+
export declare function cutCommitted(items: StreamItem[]): StreamItem[];
|
|
24
|
+
/** The thread's current run stream, from the thread record: the latest
|
|
25
|
+
* segment that started, while it is open or only just ended. Null when
|
|
26
|
+
* there is none, or it is gone. */
|
|
27
|
+
export declare function snapshotStream(deps: RuntimePorts, threadId: string): Promise<SnapshotStream | null>;
|
|
28
|
+
/** One read for a UI: the thread, its messages, its runs, the unfinished
|
|
29
|
+
* run's record entries and its run stream. Null when the thread is gone.
|
|
30
|
+
* `afterMessageId` keeps only the messages after that one: what a tab that
|
|
31
|
+
* already has it is missing (a SNAPSHOT frame). An id the thread does not
|
|
32
|
+
* have keeps them all. */
|
|
33
|
+
export declare function threadSnapshot(deps: RuntimePorts, threadId: string, opts?: {
|
|
34
|
+
afterMessageId?: string;
|
|
35
|
+
}): Promise<ThreadSnapshot | null>;
|
|
36
|
+
//# sourceMappingURL=snapshot.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snapshot.d.ts","sourceRoot":"","sources":["../../src/core/snapshot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAGxE,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGhE;;eAEe;AACf,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd;;6DAEyD;IACzD,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,yCAAyC;IACzC,GAAG,EAAE,SAAS,GAAG,IAAI,CAAC;IACtB;0DACsD;IACtD,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,mEAAmE;AACnE,eAAO,MAAM,aAAa,QAAS,CAAC;AAgBpC;6BAC6B;AAC7B,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAS9D;AAED;;oCAEoC;AACpC,wBAAsB,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAsBzG;AAED;;;;2BAI2B;AAC3B,wBAAsB,cAAc,CAClC,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAO,GACrC,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CAsBhC"}
|