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,489 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { compactContext } from './context.js';
|
|
3
|
+
import { markPromptCaching } from './cache.js';
|
|
4
|
+
import { mergeProviderOptions } from './types.js';
|
|
5
|
+
import { hitlKey, loadOpenHitls, withHitl, } from './hitl.js';
|
|
6
|
+
import { publish, setThreadState } from './publish.js';
|
|
7
|
+
import { runNestedAgent, spawnSubagentTool } from './subagent.js';
|
|
8
|
+
import { redriveKey, runIdKey } from './keys.js';
|
|
9
|
+
import { withRunState } from './state.js';
|
|
10
|
+
import { runLoop } from './loop.js';
|
|
11
|
+
export { countTokens } from './usage.js';
|
|
12
|
+
// executeStep and the loop live in ./loop.js so a nested run can share them
|
|
13
|
+
// without engine ↔ subagent becoming a cycle (§2.7).
|
|
14
|
+
export { executeStep, isParked, runLoop } from './loop.js';
|
|
15
|
+
const runLockKey = (threadId) => `agent:lock:${threadId}`;
|
|
16
|
+
/** The safety cap (§2.1) must be either absent (unbounded apart from
|
|
17
|
+
* maxSteps) or a positive number — `0`/negative/NaN would silently disable
|
|
18
|
+
* the cap and let a run spend without bound. */
|
|
19
|
+
export function validateTokenBudget(value, label) {
|
|
20
|
+
if (value !== undefined && (!Number.isFinite(value) || value <= 0)) {
|
|
21
|
+
throw new Error(`${label} must be a positive finite number`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Tools the engine treats as destructive: parked behind parkForApproval
|
|
25
|
+
* (§2.5) instead of executing directly. Purely a marker — see withHitl. */
|
|
26
|
+
export function markRequiresConfirmation(t) {
|
|
27
|
+
return Object.assign(t, { requiresConfirmation: true });
|
|
28
|
+
}
|
|
29
|
+
/** Is this approval settled yet (§2.7)? Read-only on purpose: with several
|
|
30
|
+
* open at once, nothing may be executed until EVERY one is ready, or a
|
|
31
|
+
* redelivery would run half of them and then leave the thread parked with
|
|
32
|
+
* those verdicts already consumed. */
|
|
33
|
+
async function verdictReady(deps, pending) {
|
|
34
|
+
if (await deps.kv.get(hitlKey(pending.toolCallId)))
|
|
35
|
+
return 'answered';
|
|
36
|
+
return Date.now() - pending.requestedAt >= deps.config.hitlTtlMs ? 'expired' : 'open';
|
|
37
|
+
}
|
|
38
|
+
/** Turn a settled approval into the tool result the conversation will carry
|
|
39
|
+
* (§2.5): run the approved tool, record the denial, or convert an expired
|
|
40
|
+
* request into the timeout denial ("user had no response").
|
|
41
|
+
*
|
|
42
|
+
* The tool failure is surfaced TO THE MODEL as the tool result — the verdict
|
|
43
|
+
* arrives from a different process than the one that ran the model, so the
|
|
44
|
+
* conversation always stays executable. */
|
|
45
|
+
async function settleVerdict(deps, threadId, pending, target, signal) {
|
|
46
|
+
const raw = await deps.kv.get(hitlKey(pending.toolCallId));
|
|
47
|
+
await deps.kv.del(hitlKey(pending.toolCallId));
|
|
48
|
+
if (!raw) {
|
|
49
|
+
await publish(deps, threadId, 'INPUT_EXPIRED', { toolCallId: pending.toolCallId });
|
|
50
|
+
return { responded: false, cancelled: true, reason: 'timeout' };
|
|
51
|
+
}
|
|
52
|
+
const answer = JSON.parse(raw);
|
|
53
|
+
if (!answer.approved)
|
|
54
|
+
return { denied: true };
|
|
55
|
+
try {
|
|
56
|
+
return target?.execute
|
|
57
|
+
? await target.execute(pending.arguments, {
|
|
58
|
+
toolCallId: pending.toolCallId,
|
|
59
|
+
abortSignal: signal,
|
|
60
|
+
})
|
|
61
|
+
: { error: `Unknown tool: ${pending.toolName}` };
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** Land a settled verdict and unwind whatever was waiting on it (§2.7).
|
|
68
|
+
*
|
|
69
|
+
* The verdict belongs to the stream that asked — the main agent's, or a
|
|
70
|
+
* nested run's. When a nested run asked, its own loop is re-entered from its
|
|
71
|
+
* persisted turns and its result is handed to the call waiting one level up,
|
|
72
|
+
* repeating until the main agent's `spawnSubagent` call is answered.
|
|
73
|
+
*
|
|
74
|
+
* Returns false when the unwind parked again: the thread stays
|
|
75
|
+
* WAITING_FOR_INPUT and a later dispatch picks up from the new request. */
|
|
76
|
+
async function unwindVerdict(deps, threadId, pending, result, subCtx, signal) {
|
|
77
|
+
await deps.storage.messages.append(threadId, {
|
|
78
|
+
role: 'tool',
|
|
79
|
+
agentId: pending.agentId,
|
|
80
|
+
content: [
|
|
81
|
+
{ type: 'tool-result', toolCallId: pending.toolCallId, toolName: pending.toolName, result },
|
|
82
|
+
],
|
|
83
|
+
});
|
|
84
|
+
// `producer` is whoever must now run to produce the next result. Undefined
|
|
85
|
+
// means the main agent, whose loop the caller re-enters itself.
|
|
86
|
+
let producer = pending.nested;
|
|
87
|
+
for (let i = 0; i < pending.frames.length; i += 1) {
|
|
88
|
+
const frame = pending.frames[i];
|
|
89
|
+
if (!producer || !subCtx)
|
|
90
|
+
break;
|
|
91
|
+
const outcome = await runNestedAgent(subCtx, producer, null, signal, pending.frames.slice(i));
|
|
92
|
+
if (outcome.parked)
|
|
93
|
+
return false; // parked again, one level down
|
|
94
|
+
if (outcome.aborted)
|
|
95
|
+
return false; // user stop mid-unwind (§2.1)
|
|
96
|
+
await deps.admin.runs.patch(producer.agentId, {
|
|
97
|
+
state: 'COMPLETED',
|
|
98
|
+
result: { text: outcome.text },
|
|
99
|
+
endedAt: new Date(),
|
|
100
|
+
});
|
|
101
|
+
await publish(deps, threadId, 'SUBAGENT_COMPLETED', { agentId: producer.agentId });
|
|
102
|
+
// Hand the capped result to the call one level up (§2.6)
|
|
103
|
+
await deps.storage.messages.append(threadId, {
|
|
104
|
+
role: 'tool',
|
|
105
|
+
agentId: frame.agentId,
|
|
106
|
+
content: [
|
|
107
|
+
{
|
|
108
|
+
type: 'tool-result',
|
|
109
|
+
toolCallId: frame.toolCallId,
|
|
110
|
+
toolName: 'spawnSubagent',
|
|
111
|
+
result: {
|
|
112
|
+
agentId: producer.agentId,
|
|
113
|
+
result: outcome.text.slice(0, deps.config.subagentResultCapChars),
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
});
|
|
118
|
+
producer = frame.nested;
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
/** Sum this segment onto the run's record and stamp how it ended (§2.9). */
|
|
123
|
+
async function closeRunRecord(deps, runId, f) {
|
|
124
|
+
try {
|
|
125
|
+
const prior = await deps.admin.runs.get(runId);
|
|
126
|
+
if (!prior)
|
|
127
|
+
return; // a run started before §2.9, or a foreign dispatch
|
|
128
|
+
const endedAt = new Date();
|
|
129
|
+
await deps.admin.runs.patch(runId, {
|
|
130
|
+
state: f.state,
|
|
131
|
+
stopReason: f.stopReason,
|
|
132
|
+
...(f.error ? { error: f.error } : {}),
|
|
133
|
+
endedAt,
|
|
134
|
+
durationMs: endedAt.getTime() - new Date(prior.startedAt).getTime(),
|
|
135
|
+
steps: prior.steps + (f.steps ?? 0),
|
|
136
|
+
inputTokens: prior.inputTokens + f.attribution.inputTokens,
|
|
137
|
+
cachedInputTokens: prior.cachedInputTokens + f.attribution.cachedInputTokens,
|
|
138
|
+
outputTokens: prior.outputTokens + f.attribution.outputTokens,
|
|
139
|
+
totalTokens: prior.totalTokens + f.attribution.totalTokens,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
// Observability must never be able to fail a run that otherwise succeeded.
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/** Finalise a run as FAILED on both homes AND keep why (§2.9). The reason used
|
|
147
|
+
* to be dropped entirely, so an operator could see that something failed but
|
|
148
|
+
* never what. */
|
|
149
|
+
async function failRun(deps, threadId, runId, error) {
|
|
150
|
+
await deps.kv.set(`agent:state:${threadId}`, 'FAILED');
|
|
151
|
+
await setThreadState(deps, threadId, 'FAILED');
|
|
152
|
+
if (runId) {
|
|
153
|
+
await closeRunRecord(deps, runId, {
|
|
154
|
+
state: 'FAILED',
|
|
155
|
+
stopReason: 'completed',
|
|
156
|
+
tokensUsed: 0,
|
|
157
|
+
attribution: { inputTokens: 0, cachedInputTokens: 0, outputTokens: 0, totalTokens: 0 },
|
|
158
|
+
error,
|
|
159
|
+
runId,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
await publish(deps, threadId, 'STATE_CHANGE', { state: 'FAILED', error });
|
|
163
|
+
}
|
|
164
|
+
/** Resolve every parked request at segment start (§2.5, §2.7) and flip the
|
|
165
|
+
* thread back to RUNNING. Returns false when at least one approval is still
|
|
166
|
+
* open within its TTL: the dispatch is an at-least-once redelivery and the
|
|
167
|
+
* thread stays parked. `rawTools` must be the UNWRAPPED main toolset. */
|
|
168
|
+
async function resumePendingHitl(deps, threadId, open, rawTools, subCtx, signal) {
|
|
169
|
+
// Readiness first, side effects second: the thread resumes only when EVERY
|
|
170
|
+
// open approval has been answered or has expired (§2.7).
|
|
171
|
+
const states = await Promise.all(open.map((p) => verdictReady(deps, p)));
|
|
172
|
+
if (states.includes('open'))
|
|
173
|
+
return false; // redelivery no-op (§2.8)
|
|
174
|
+
let expiredAny = false;
|
|
175
|
+
for (const pending of open) {
|
|
176
|
+
// A nested run's tools come from the delegation config, not the main
|
|
177
|
+
// agent's set — the approved tool has to be resolved where it lives.
|
|
178
|
+
const target = pending.agentId === null
|
|
179
|
+
? rawTools[pending.toolName]
|
|
180
|
+
: subCtx?.sub.tools?.[pending.toolName];
|
|
181
|
+
const result = await settleVerdict(deps, threadId, pending, target, signal);
|
|
182
|
+
if (result?.reason === 'timeout')
|
|
183
|
+
expiredAny = true;
|
|
184
|
+
if (!(await unwindVerdict(deps, threadId, pending, result, subCtx, signal)))
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
await deps.kv.set(`agent:state:${threadId}`, 'RUNNING');
|
|
188
|
+
await setThreadState(deps, threadId, 'RUNNING');
|
|
189
|
+
await publish(deps, threadId, 'STATE_CHANGE', { state: 'RUNNING' });
|
|
190
|
+
void expiredAny;
|
|
191
|
+
return true;
|
|
192
|
+
}
|
|
193
|
+
export async function execute(deps, agent, input) {
|
|
194
|
+
const { threadId, runId } = input;
|
|
195
|
+
const abort = new AbortController();
|
|
196
|
+
validateTokenBudget(input.tokenBudget, 'tokenBudget');
|
|
197
|
+
/** True once the thread has started a NEWER run than this one (§2.1). */
|
|
198
|
+
const stale = async () => runId !== undefined && (await deps.kv.get(runIdKey(threadId))) !== runId;
|
|
199
|
+
// The lock carries the run id, so a later conflict can tell a duplicate
|
|
200
|
+
// delivery of THIS run apart from an older run that is still finishing.
|
|
201
|
+
const locked = await deps.kv.set(runLockKey(threadId), runId ?? randomUUID(), {
|
|
202
|
+
onlyIfNotExists: true,
|
|
203
|
+
exSeconds: deps.config.runLockLeaseSeconds,
|
|
204
|
+
});
|
|
205
|
+
if (!locked)
|
|
206
|
+
return 'lock-conflict'; // another worker owns this thread (§2.8)
|
|
207
|
+
// Token budget (§2.1 safety cap) — precedence: execute input → spec →
|
|
208
|
+
// config. Checked BETWEEN steps: the finished step is always kept in full,
|
|
209
|
+
// nothing is aborted mid-generation. This is NOT a user stop.
|
|
210
|
+
const tokenBudget = input.tokenBudget ?? agent.spec.tokenBudget ?? deps.config.tokenBudget;
|
|
211
|
+
// Provider-specific options (§3.1): spec default <- execute input,
|
|
212
|
+
// shallow per-provider namespace; the execute input wins.
|
|
213
|
+
// Three levels, widest first: runtime config → agent spec → this run.
|
|
214
|
+
// Each wins over the one before it, per provider namespace (§3.1).
|
|
215
|
+
const providerOptions = mergeProviderOptions(mergeProviderOptions(deps.config.providerOptions, agent.spec.providerOptions), input.providerOptions);
|
|
216
|
+
// Two ways a run ends early, one behavior — everything tears down at once:
|
|
217
|
+
// 1. the state key reads CANCELLED: the user pressed stop (§2.1);
|
|
218
|
+
// 2. the run id has moved on: the user pressed stop and then sent another
|
|
219
|
+
// message, which put RUNNING back over CANCELLED before this poll could
|
|
220
|
+
// read it. The state key lies in that window; the run id never does.
|
|
221
|
+
const controlPoll = setInterval(async () => {
|
|
222
|
+
try {
|
|
223
|
+
if ((await deps.kv.get(`agent:state:${threadId}`)) === 'CANCELLED' || (await stale())) {
|
|
224
|
+
abort.abort();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
// transient kv errors must never kill the poller
|
|
229
|
+
}
|
|
230
|
+
}, deps.config.stopPollMs);
|
|
231
|
+
try {
|
|
232
|
+
// At-least-once idempotency (§2.8): a job whose run already ended — or
|
|
233
|
+
// was stopped — must be a no-op on redelivery. A MISSING thread is the
|
|
234
|
+
// same no-op: it was deleted (§3.2) and must never be resurrected.
|
|
235
|
+
// A newer run already owns this thread: this job has nothing to do, and
|
|
236
|
+
// must not touch state on the live run's behalf (§2.1).
|
|
237
|
+
if (await stale())
|
|
238
|
+
return 'stale';
|
|
239
|
+
const durable = await deps.storage.threads.get(threadId);
|
|
240
|
+
if (!durable ||
|
|
241
|
+
durable.state === 'CANCELLED' ||
|
|
242
|
+
durable.state === 'COMPLETED' ||
|
|
243
|
+
durable.state === 'FAILED') {
|
|
244
|
+
return 'executed';
|
|
245
|
+
}
|
|
246
|
+
const resume = {
|
|
247
|
+
agent: agent.name,
|
|
248
|
+
model: input.model,
|
|
249
|
+
...(runId ? { runId } : {}),
|
|
250
|
+
...(input.tokenBudget !== undefined ? { tokenBudget: input.tokenBudget } : {}),
|
|
251
|
+
...(providerOptions ? { providerOptions } : {}),
|
|
252
|
+
// Carried so the resumed segment scopes its storage the same way this
|
|
253
|
+
// one does (§2.10).
|
|
254
|
+
...(input.state ? { state: input.state } : {}),
|
|
255
|
+
};
|
|
256
|
+
// One ledger for the whole run: a nested run's spend counts against the
|
|
257
|
+
// same safety cap the main agent is checked against (§2.7).
|
|
258
|
+
const ledger = { tokensUsed: 0 };
|
|
259
|
+
// How long the dispatch sat in the queue before a worker took it (§2.9).
|
|
260
|
+
if (runId && input.enqueuedAt) {
|
|
261
|
+
await deps.admin.runs
|
|
262
|
+
.patch(runId, { queuedMs: Date.now() - input.enqueuedAt })
|
|
263
|
+
.catch(() => undefined);
|
|
264
|
+
}
|
|
265
|
+
// Platform-owned toolset: HITL (§2.5) over the user's set; spawnSubagent
|
|
266
|
+
// added ONLY when the spec opts in (§2.7). rawTools keeps the real
|
|
267
|
+
// implementations — the resolved park executes the approved tool.
|
|
268
|
+
const sub = agent.spec.subagents
|
|
269
|
+
? agent.spec.subagents === true
|
|
270
|
+
? {}
|
|
271
|
+
: agent.spec.subagents
|
|
272
|
+
: null;
|
|
273
|
+
const subCtx = sub
|
|
274
|
+
? {
|
|
275
|
+
threadId,
|
|
276
|
+
depth: 0,
|
|
277
|
+
sem: agent.sem,
|
|
278
|
+
ports: deps,
|
|
279
|
+
sub,
|
|
280
|
+
agent,
|
|
281
|
+
ledger,
|
|
282
|
+
resume,
|
|
283
|
+
agentId: null, // spawned by the main agent
|
|
284
|
+
frames: [],
|
|
285
|
+
tokenBudget,
|
|
286
|
+
providerOptions,
|
|
287
|
+
abortSignal: abort.signal,
|
|
288
|
+
state: input.state,
|
|
289
|
+
}
|
|
290
|
+
: null;
|
|
291
|
+
const rawTools = {
|
|
292
|
+
...(agent.args.tools ?? {}),
|
|
293
|
+
...(subCtx ? { spawnSubagent: spawnSubagentTool(subCtx) } : {}),
|
|
294
|
+
};
|
|
295
|
+
// The main agent's own toolset: nothing is waiting on its parks (§2.7).
|
|
296
|
+
// Every tool also sees the run's state (§2.10).
|
|
297
|
+
const tools = withRunState(withHitl(deps, threadId, rawTools, { resume, agentId: null, frames: [] }), input.state ?? {});
|
|
298
|
+
// §2.5 resume: a WAITING thread at segment start is either the /respond
|
|
299
|
+
// continuation or a redelivery of the original job while still parked.
|
|
300
|
+
if (durable?.state === 'WAITING_FOR_INPUT') {
|
|
301
|
+
// Every approval still open, not just the latest: one parent step can
|
|
302
|
+
// park several nested runs at once (§2.7).
|
|
303
|
+
const open = await loadOpenHitls(deps, threadId);
|
|
304
|
+
if (open.length === 0) {
|
|
305
|
+
// WAITING without a pending request cannot be continued — fail into
|
|
306
|
+
// the §2.8 policy rather than corrupting the conversation.
|
|
307
|
+
throw new Error(`Thread ${threadId} is WAITING_FOR_INPUT without a pending INPUT_REQUIRED`);
|
|
308
|
+
}
|
|
309
|
+
const resumed = await resumePendingHitl(deps, threadId, open, rawTools, subCtx, abort.signal);
|
|
310
|
+
if (!resumed)
|
|
311
|
+
return 'executed'; // still parked — nothing to do yet
|
|
312
|
+
}
|
|
313
|
+
// Durable compaction pass — history always fits the model budget (§2.6);
|
|
314
|
+
// the budget uses the resolved model's contextWindow (§3.3)
|
|
315
|
+
const history = await compactContext(deps, threadId, input.model);
|
|
316
|
+
const model = deps.resolveModel(input.model);
|
|
317
|
+
// Prompt caching (§2.6): stamp the stable prefix once — appended step
|
|
318
|
+
// messages extend the prompt without invalidating the breakpoints.
|
|
319
|
+
let messages = history.map((m) => ({ role: m.role, content: m.content }));
|
|
320
|
+
if (deps.config.promptCaching) {
|
|
321
|
+
messages = markPromptCaching(messages);
|
|
322
|
+
}
|
|
323
|
+
const userArgs = agent.args;
|
|
324
|
+
const loop = await runLoop(deps, agent, threadId, {
|
|
325
|
+
agentId: null, // the main agent's stream (§2.7)
|
|
326
|
+
runId,
|
|
327
|
+
kind: agent.kind,
|
|
328
|
+
model: model.instance(),
|
|
329
|
+
messages,
|
|
330
|
+
tools,
|
|
331
|
+
maxSteps: deps.config.maxSteps,
|
|
332
|
+
abortSignal: abort.signal,
|
|
333
|
+
providerOptions,
|
|
334
|
+
tokenBudget,
|
|
335
|
+
cacheSystemPrompt: deps.config.promptCaching,
|
|
336
|
+
onChunk: async (chunk) => {
|
|
337
|
+
// One canonical path for every client: durable log + live Pub/Sub (§2.1, §2.2)
|
|
338
|
+
await publish(deps, threadId, 'CHUNK', chunk);
|
|
339
|
+
userArgs.onChunk?.({ chunk }); // user callback still fires
|
|
340
|
+
},
|
|
341
|
+
}, ledger);
|
|
342
|
+
const { attribution, parked } = loop;
|
|
343
|
+
const tokensUsed = ledger.tokensUsed;
|
|
344
|
+
const lastText = loop.text;
|
|
345
|
+
const lastFinishReason = loop.finishReason;
|
|
346
|
+
if (parked) {
|
|
347
|
+
// The segment ends holding the park: bill the steps up to the park
|
|
348
|
+
// (§4) — the resumed segment records its own usage. NO state flip:
|
|
349
|
+
// WAITING_FOR_INPUT (or CANCELLED if the user stopped meanwhile) stands.
|
|
350
|
+
await deps.storage.usage.record(threadId, { agentId: agent.name, ...attribution });
|
|
351
|
+
return 'executed';
|
|
352
|
+
}
|
|
353
|
+
const stopReason = abort.signal.aborted
|
|
354
|
+
? 'cancelled'
|
|
355
|
+
: tokenBudget && tokensUsed >= tokenBudget
|
|
356
|
+
? 'token_budget'
|
|
357
|
+
: lastFinishReason === 'tool-calls'
|
|
358
|
+
? 'max_steps' // step ceiling hit (§2.1)
|
|
359
|
+
: 'completed';
|
|
360
|
+
await finalize(deps, agent, threadId, {
|
|
361
|
+
state: abort.signal.aborted ? 'CANCELLED' : 'COMPLETED',
|
|
362
|
+
stopReason,
|
|
363
|
+
tokensUsed,
|
|
364
|
+
attribution,
|
|
365
|
+
oneShotText: agent.kind === 'generate-text' ? lastText : undefined,
|
|
366
|
+
runId,
|
|
367
|
+
steps: loop.steps,
|
|
368
|
+
});
|
|
369
|
+
return 'executed';
|
|
370
|
+
}
|
|
371
|
+
finally {
|
|
372
|
+
clearInterval(controlPoll);
|
|
373
|
+
await deps.kv.del(runLockKey(threadId)); // release — success, failure, or stop
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
/** Finalize a finished run (§5.6): attribute the segment's total tokens
|
|
377
|
+
* (input + cached + output, §4), then flip state on both homes and publish.
|
|
378
|
+
* Message persistence already happened per step inside the loop — finalize
|
|
379
|
+
* never touches messages.
|
|
380
|
+
*
|
|
381
|
+
* A budget break is NOT a user stop: the run completes with stopReason
|
|
382
|
+
* 'token_budget' and the usage it actually spent. */
|
|
383
|
+
export async function finalize(deps, agent, threadId, f) {
|
|
384
|
+
// Tokens this segment actually spent are always ours to record (§4), even
|
|
385
|
+
// when the run was replaced part-way through.
|
|
386
|
+
await deps.storage.usage.record(threadId, { agentId: agent.name, ...f.attribution });
|
|
387
|
+
// Close the run's durable record (§2.9). Additive: a run that parked and
|
|
388
|
+
// resumed finalises once, but its steps and tokens accrued over several
|
|
389
|
+
// segments, so they are summed onto what is already there. The run lock
|
|
390
|
+
// (§3.4) makes this read-modify-write single-writer.
|
|
391
|
+
if (f.runId)
|
|
392
|
+
await closeRunRecord(deps, f.runId, f);
|
|
393
|
+
// Past that, a replaced run stays silent. Its CANCELLED would otherwise land
|
|
394
|
+
// on top of the next run's RUNNING and wedge the thread: the new worker
|
|
395
|
+
// would read a terminal state and no-op, and nobody would ever answer the
|
|
396
|
+
// message the user just sent (§2.1).
|
|
397
|
+
if (f.runId !== undefined && (await deps.kv.get(runIdKey(threadId))) !== f.runId)
|
|
398
|
+
return;
|
|
399
|
+
if (f.oneShotText !== undefined) {
|
|
400
|
+
// One-shot flavor: no CHUNK stream — publish the final text as one event
|
|
401
|
+
await publish(deps, threadId, 'TEXT_RESULT', { text: f.oneShotText });
|
|
402
|
+
}
|
|
403
|
+
await deps.kv.set(`agent:state:${threadId}`, f.state);
|
|
404
|
+
await setThreadState(deps, threadId, f.state);
|
|
405
|
+
await publish(deps, threadId, 'STATE_CHANGE', {
|
|
406
|
+
state: f.state,
|
|
407
|
+
stopReason: f.stopReason,
|
|
408
|
+
tokensUsed: f.tokensUsed,
|
|
409
|
+
usage: f.attribution,
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
/** A lock conflict has two very different causes (§2.8), and only one of them
|
|
413
|
+
* is a no-op:
|
|
414
|
+
*
|
|
415
|
+
* - the lock carries THIS run's id → an at-least-once duplicate of a job that
|
|
416
|
+
* is already executing. Drop it.
|
|
417
|
+
* - the lock belongs to an OLDER run that has not finished tearing down →
|
|
418
|
+
* this job never ran. Dropping it strands the message the user just sent,
|
|
419
|
+
* so come back once the lock clears. Bounded by maxAttempts, then FAILED,
|
|
420
|
+
* so a wedged lock reports itself instead of spinning forever. */
|
|
421
|
+
async function redriveOnLockConflict(deps, agent, input, maxAttempts) {
|
|
422
|
+
if (!input.runId)
|
|
423
|
+
return; // legacy dispatch, no identity — old drop behavior
|
|
424
|
+
if ((await deps.kv.get(runLockKey(input.threadId))) === input.runId)
|
|
425
|
+
return; // own duplicate
|
|
426
|
+
if ((await deps.kv.get(runIdKey(input.threadId))) !== input.runId)
|
|
427
|
+
return; // already replaced
|
|
428
|
+
const tries = await deps.kv.incr(redriveKey(input.threadId));
|
|
429
|
+
if (tries <= maxAttempts) {
|
|
430
|
+
return deps.queue.enqueue({
|
|
431
|
+
threadId: input.threadId,
|
|
432
|
+
runId: input.runId,
|
|
433
|
+
enqueuedAt: Date.now(),
|
|
434
|
+
model: input.model,
|
|
435
|
+
agent: agent.name,
|
|
436
|
+
tokenBudget: input.tokenBudget,
|
|
437
|
+
providerOptions: input.providerOptions,
|
|
438
|
+
}, { delaySeconds: deps.config.runRedriveDelaySeconds });
|
|
439
|
+
}
|
|
440
|
+
await deps.kv.del(redriveKey(input.threadId));
|
|
441
|
+
await failRun(deps, input.threadId, input.runId, 'the run lock never cleared');
|
|
442
|
+
}
|
|
443
|
+
/** §2.8 failure policy: transient errors redrive through the queue; exhausted
|
|
444
|
+
* attempts finalize FAILED (hot cache + durable). A user stop is never
|
|
445
|
+
* retried, and a successful run resets the attempt counter.
|
|
446
|
+
*
|
|
447
|
+
* `exec` is an injection seam for tests (default: the real execute). */
|
|
448
|
+
export async function executeWithPolicy(deps, agent, input, policy, exec = execute) {
|
|
449
|
+
const maxAttempts = policy?.maxAttempts ?? deps.config.runMaxAttempts;
|
|
450
|
+
try {
|
|
451
|
+
const outcome = await exec(deps, agent, input);
|
|
452
|
+
// Only a run THIS worker executed may reset the retry budget — a
|
|
453
|
+
// lock-conflict no-op must never clear it while the owning worker runs (§2.8)
|
|
454
|
+
if (outcome === 'executed') {
|
|
455
|
+
await deps.kv.del(`agent:attempts:${input.threadId}`);
|
|
456
|
+
await deps.kv.del(redriveKey(input.threadId));
|
|
457
|
+
return;
|
|
458
|
+
}
|
|
459
|
+
// A newer run owns the thread: this job is a genuine no-op.
|
|
460
|
+
if (outcome === 'stale')
|
|
461
|
+
return;
|
|
462
|
+
await redriveOnLockConflict(deps, agent, input, maxAttempts);
|
|
463
|
+
}
|
|
464
|
+
catch (err) {
|
|
465
|
+
// A user stop already finalized the thread — never retry a stop
|
|
466
|
+
if ((await deps.kv.get(`agent:state:${input.threadId}`)) === 'CANCELLED')
|
|
467
|
+
return;
|
|
468
|
+
const attempts = await deps.kv.incr(`agent:attempts:${input.threadId}`);
|
|
469
|
+
if (attempts < maxAttempts) {
|
|
470
|
+
return deps.queue.enqueue({
|
|
471
|
+
threadId: input.threadId,
|
|
472
|
+
// A retry is the SAME run trying again (§2.1). Dropping the id here
|
|
473
|
+
// left the retried job unable to notice it had been replaced, and
|
|
474
|
+
// unable to redrive if it found the lock held.
|
|
475
|
+
runId: input.runId,
|
|
476
|
+
enqueuedAt: Date.now(),
|
|
477
|
+
model: input.model,
|
|
478
|
+
agent: agent.name,
|
|
479
|
+
tokenBudget: input.tokenBudget,
|
|
480
|
+
providerOptions: input.providerOptions,
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
// Attempts exhausted: finalize FAILED on BOTH the hot cache and durable
|
|
484
|
+
// truth, or subsequent runs would still treat the thread as active (§2.1)
|
|
485
|
+
await failRun(deps, input.threadId, input.runId, err instanceof Error ? err.message : String(err));
|
|
486
|
+
await deps.kv.del(`agent:attempts:${input.threadId}`);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
//# sourceMappingURL=engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/core/engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { RuntimePorts } from '../ports/runtime.js';
|
|
2
|
+
import type { AgentEvent } from './types.js';
|
|
3
|
+
export interface FollowOptions {
|
|
4
|
+
/** Resume after this seq. `-1` (the default) replays the thread from the
|
|
5
|
+
* start. Comes from the client's cursor — `Last-Event-ID` for SSE. */
|
|
6
|
+
since?: number;
|
|
7
|
+
/** Stops the stream and unsubscribes. Wire your request's abort signal to
|
|
8
|
+
* it, or the subscription outlives the client. */
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
11
|
+
/** Every event on a thread, replay first and then live, as one sequence.
|
|
12
|
+
*
|
|
13
|
+
* The ordering here is the whole point, and it is easy to get wrong in a route
|
|
14
|
+
* handler:
|
|
15
|
+
*
|
|
16
|
+
* 1. **Subscribe before replaying.** An event published between the replay
|
|
17
|
+
* finishing and the tail starting is otherwise lost for ever.
|
|
18
|
+
* 2. **Never emit at or below the cursor.** The client would render it twice.
|
|
19
|
+
* 3. **`seq === 0` is a bus-only notice** (heartbeats, death notices).
|
|
20
|
+
* Always forward it, never let it move the cursor.
|
|
21
|
+
*
|
|
22
|
+
* Framework-neutral on purpose: an async iterable is something Express, Hono,
|
|
23
|
+
* Nest, Next and a plain worker can each consume in their own way. */
|
|
24
|
+
export declare function followEvents(deps: RuntimePorts, threadId: string, options?: FollowOptions): AsyncGenerator<AgentEvent>;
|
|
25
|
+
/** Headers an SSE response needs. `X-Accel-Buffering` is for nginx, which
|
|
26
|
+
* otherwise buffers the stream and makes it look like nothing is happening. */
|
|
27
|
+
export declare const SSE_HEADERS: Record<string, string>;
|
|
28
|
+
/** One event as an SSE frame.
|
|
29
|
+
*
|
|
30
|
+
* A bus-only notice (`seq === 0`) is sent WITHOUT an `id:` line. EventSource
|
|
31
|
+
* stores any id it sees and sends it back as `Last-Event-ID` on reconnect —
|
|
32
|
+
* so stamping `id: 0` on a heartbeat would rewind the client's cursor to the
|
|
33
|
+
* beginning of the thread and replay everything. */
|
|
34
|
+
export declare function sseFrame(event: AgentEvent): string;
|
|
35
|
+
export interface SseOptions extends FollowOptions {
|
|
36
|
+
/** Emitted once, up front: how long a browser waits before reconnecting. */
|
|
37
|
+
retryMs?: number;
|
|
38
|
+
}
|
|
39
|
+
export interface SseStream {
|
|
40
|
+
/** SSE-encoded bytes. Serve it directly where a web `Response` is native, or
|
|
41
|
+
* pipe it where it is not — see the docs for Express and Nest. */
|
|
42
|
+
stream: ReadableStream<Uint8Array>;
|
|
43
|
+
headers: Record<string, string>;
|
|
44
|
+
}
|
|
45
|
+
/** The event sequence, encoded as Server-Sent Events.
|
|
46
|
+
*
|
|
47
|
+
* Returns the stream and the headers rather than a `Response`, because half
|
|
48
|
+
* the ecosystem does not have one. */
|
|
49
|
+
export declare function toSseStream(events: AsyncGenerator<AgentEvent>, options?: SseOptions): SseStream;
|
|
50
|
+
//# sourceMappingURL=follow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"follow.d.ts","sourceRoot":"","sources":["../../src/core/follow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,aAAa;IAC5B;2EACuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;uDACmD;IACnD,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;;;;;;;;;uEAYuE;AACvE,wBAAuB,YAAY,CACjC,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,aAAkB,GAC1B,cAAc,CAAC,UAAU,CAAC,CA8E5B;AAED;gFACgF;AAChF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAK9C,CAAC;AAEF;;;;;qDAKqD;AACrD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAGlD;AAED,MAAM,WAAW,UAAW,SAAQ,aAAa;IAC/C,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB;uEACmE;IACnE,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC;AAED;;;uCAGuC;AACvC,wBAAgB,WAAW,CACzB,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAClC,OAAO,GAAE,UAAe,GACvB,SAAS,CAqCX"}
|