@adjudicate/adapter-core 0.1.0 → 0.1.1
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/dist/bridge.d.ts +80 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +78 -0
- package/dist/bridge.js.map +1 -0
- package/dist/decisions.d.ts +79 -0
- package/dist/decisions.d.ts.map +1 -0
- package/dist/decisions.js +211 -0
- package/dist/decisions.js.map +1 -0
- package/dist/errors.d.ts +23 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +27 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/loop.d.ts +23 -0
- package/dist/loop.d.ts.map +1 -0
- package/dist/loop.js +422 -0
- package/dist/loop.js.map +1 -0
- package/dist/persistence-redis.d.ts +84 -0
- package/dist/persistence-redis.d.ts.map +1 -0
- package/dist/persistence-redis.js +97 -0
- package/dist/persistence-redis.js.map +1 -0
- package/dist/persistence.d.ts +72 -0
- package/dist/persistence.d.ts.map +1 -0
- package/dist/persistence.js +92 -0
- package/dist/persistence.js.map +1 -0
- package/dist/trace.d.ts +76 -0
- package/dist/trace.d.ts.map +1 -0
- package/dist/trace.js +65 -0
- package/dist/trace.js.map +1 -0
- package/dist/types.d.ts +219 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +14 -0
- package/dist/types.js.map +1 -0
- package/package.json +5 -5
package/dist/loop.js
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `createAdjudicatedAgent` — the provider-neutral message-loop orchestrator.
|
|
3
|
+
*
|
|
4
|
+
* Wires the planner, renderer, provider bridge, kernel, and Decision
|
|
5
|
+
* translator into a single send/resume/confirm surface.
|
|
6
|
+
*
|
|
7
|
+
* Invariants the loop preserves:
|
|
8
|
+
* - `pack.planner.plan(state, context)` is called every iteration. State
|
|
9
|
+
* may change mid-turn (a refund executes, freeing a previously-locked
|
|
10
|
+
* tool); the visible-tool surface MUST update accordingly.
|
|
11
|
+
* - The Pack passed in MUST already be `safePlan` + `withBasisAudit`
|
|
12
|
+
* wrapped (Pack-author convention). The loop does NOT double-wrap.
|
|
13
|
+
* - Every intent envelope crosses `adjudicateAndAudit()` from
|
|
14
|
+
* `@adjudicate/core/kernel`. The loop never bypasses the kernel,
|
|
15
|
+
* never raises taint, and never short-circuits the guard ordering.
|
|
16
|
+
* - First non-continue Decision wins: subsequent tool_use blocks in the
|
|
17
|
+
* same assistant turn are surfaced as `not_processed_due_to_pause`.
|
|
18
|
+
* - History `H` is opaque. The bridge is the only thing that knows the
|
|
19
|
+
* conversation-history shape; the loop threads it.
|
|
20
|
+
*/
|
|
21
|
+
import { noopAuditSink, sha256Canonical, } from "@adjudicate/core";
|
|
22
|
+
import { adjudicateAndAudit } from "@adjudicate/core/kernel";
|
|
23
|
+
import { resumeDeferredIntent } from "@adjudicate/runtime";
|
|
24
|
+
import { buildEnvelopeFromToolUse, classifyIncomingToolUse, } from "./bridge.js";
|
|
25
|
+
import { makeOutOfPlanToolResult, translateDecision, } from "./decisions.js";
|
|
26
|
+
import { AdapterError, AdapterErrorCode } from "./errors.js";
|
|
27
|
+
import { noopTraceSink } from "./trace.js";
|
|
28
|
+
const DEFAULT_MAX_ITERATIONS = 8;
|
|
29
|
+
export function createAdjudicatedAgent(options) {
|
|
30
|
+
const maxIterations = options.maxIterations ?? DEFAULT_MAX_ITERATIONS;
|
|
31
|
+
const rk = options.rk ?? ((raw) => raw);
|
|
32
|
+
const deriveNonce = options.deriveNonce ?? ((args) => args.toolUseId);
|
|
33
|
+
const bridge = options.bridge;
|
|
34
|
+
const traceSink = options.traceSink ?? noopTraceSink;
|
|
35
|
+
function pauseActionToReason(kind) {
|
|
36
|
+
switch (kind) {
|
|
37
|
+
case "pause_for_defer":
|
|
38
|
+
return "deferred";
|
|
39
|
+
case "pause_for_user_confirmation":
|
|
40
|
+
return "awaiting_confirmation";
|
|
41
|
+
case "complete_for_escalation":
|
|
42
|
+
return "escalated";
|
|
43
|
+
default:
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function runLoop(sessionId, initialHistory, state, context, seedEvents,
|
|
48
|
+
/**
|
|
49
|
+
* Optional pre-seeded Decision injected before the first provider
|
|
50
|
+
* call — used by `confirm()` and `resume()` to splice an authoritative
|
|
51
|
+
* Decision (from the user's confirmation or the resumed envelope) back
|
|
52
|
+
* into the conversation without consulting the LLM again first.
|
|
53
|
+
*/
|
|
54
|
+
seedDecision) {
|
|
55
|
+
const events = [...seedEvents];
|
|
56
|
+
let history = initialHistory;
|
|
57
|
+
let lastDecision = null;
|
|
58
|
+
if (seedDecision !== null) {
|
|
59
|
+
const single = await processSingleDecision({
|
|
60
|
+
decision: seedDecision.decision,
|
|
61
|
+
envelope: seedDecision.envelope,
|
|
62
|
+
toolUseId: seedDecision.toolUseId,
|
|
63
|
+
sessionId,
|
|
64
|
+
state,
|
|
65
|
+
historySnapshot: history,
|
|
66
|
+
});
|
|
67
|
+
lastDecision = seedDecision.decision;
|
|
68
|
+
events.push(...single.events);
|
|
69
|
+
if (single.toolResult !== null) {
|
|
70
|
+
history = bridge.appendToolResults(history, [single.toolResult]);
|
|
71
|
+
}
|
|
72
|
+
if (single.loopAction.kind !== "continue") {
|
|
73
|
+
return {
|
|
74
|
+
events,
|
|
75
|
+
history,
|
|
76
|
+
outcome: pauseToOutcome(single.loopAction, lastDecision),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
for (let iter = 0; iter < maxIterations; iter++) {
|
|
81
|
+
traceSink.onTrace({
|
|
82
|
+
phase: "iteration_start",
|
|
83
|
+
sessionId,
|
|
84
|
+
iteration: iter + 1,
|
|
85
|
+
});
|
|
86
|
+
const plan = options.pack.planner.plan(state, context);
|
|
87
|
+
const rendered = options.renderer.render(state, context, plan);
|
|
88
|
+
const sent = await bridge.send(history, {
|
|
89
|
+
systemPrompt: rendered.systemPrompt,
|
|
90
|
+
maxTokens: rendered.maxTokens,
|
|
91
|
+
toolSchemas: rendered.toolSchemas,
|
|
92
|
+
});
|
|
93
|
+
history = sent.history;
|
|
94
|
+
for (const text of sent.turn.textBlocks) {
|
|
95
|
+
events.push({ kind: "assistant_text", text });
|
|
96
|
+
}
|
|
97
|
+
if (sent.turn.toolUses.length === 0) {
|
|
98
|
+
traceSink.onTrace({
|
|
99
|
+
phase: "completed",
|
|
100
|
+
sessionId,
|
|
101
|
+
iteration: iter + 1,
|
|
102
|
+
});
|
|
103
|
+
return {
|
|
104
|
+
events,
|
|
105
|
+
history,
|
|
106
|
+
outcome: {
|
|
107
|
+
kind: "completed",
|
|
108
|
+
assistantText: sent.turn.textBlocks.join(""),
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const toolResults = [];
|
|
113
|
+
let pauseAction = null;
|
|
114
|
+
for (const tu of sent.turn.toolUses) {
|
|
115
|
+
events.push({
|
|
116
|
+
kind: "tool_use",
|
|
117
|
+
toolUseId: tu.id,
|
|
118
|
+
toolName: tu.name,
|
|
119
|
+
input: tu.input,
|
|
120
|
+
});
|
|
121
|
+
if (pauseAction !== null) {
|
|
122
|
+
// First non-continue Decision wins: surface remaining tool_uses
|
|
123
|
+
// as not-processed so the LLM (on resume) understands they were
|
|
124
|
+
// skipped this turn.
|
|
125
|
+
toolResults.push({
|
|
126
|
+
toolUseId: tu.id,
|
|
127
|
+
content: "Not processed: prior tool_use paused this turn.",
|
|
128
|
+
isError: true,
|
|
129
|
+
});
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
const cls = classifyIncomingToolUse({ name: tu.name, input: tu.input }, plan);
|
|
133
|
+
if (cls.kind === "out_of_plan") {
|
|
134
|
+
const result = makeOutOfPlanToolResult(tu.id, tu.name);
|
|
135
|
+
toolResults.push(result);
|
|
136
|
+
events.push({ kind: "tool_result", toolUseId: tu.id, payload: result });
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (cls.kind === "read") {
|
|
140
|
+
let readResult;
|
|
141
|
+
try {
|
|
142
|
+
readResult = await options.executor.invokeRead(cls.name, cls.input, state);
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
const message = err instanceof Error ? err.message : "executor read failed";
|
|
146
|
+
const errResult = {
|
|
147
|
+
toolUseId: tu.id,
|
|
148
|
+
content: `Tool failed: ${message}`,
|
|
149
|
+
isError: true,
|
|
150
|
+
};
|
|
151
|
+
toolResults.push(errResult);
|
|
152
|
+
events.push({
|
|
153
|
+
kind: "tool_result",
|
|
154
|
+
toolUseId: tu.id,
|
|
155
|
+
payload: errResult,
|
|
156
|
+
});
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const result = {
|
|
160
|
+
toolUseId: tu.id,
|
|
161
|
+
content: JSON.stringify({ ok: true, result: readResult }),
|
|
162
|
+
};
|
|
163
|
+
toolResults.push(result);
|
|
164
|
+
events.push({
|
|
165
|
+
kind: "handler_result",
|
|
166
|
+
toolUseId: tu.id,
|
|
167
|
+
result: readResult,
|
|
168
|
+
});
|
|
169
|
+
events.push({ kind: "tool_result", toolUseId: tu.id, payload: result });
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
// cls.kind === "intent"
|
|
173
|
+
const envelope = buildEnvelopeFromToolUse({
|
|
174
|
+
intentKind: cls.intentKind,
|
|
175
|
+
payload: cls.payload,
|
|
176
|
+
sessionId,
|
|
177
|
+
taint: "UNTRUSTED",
|
|
178
|
+
nonce: deriveNonce({
|
|
179
|
+
sessionId,
|
|
180
|
+
toolUseId: tu.id,
|
|
181
|
+
payload: cls.payload,
|
|
182
|
+
}),
|
|
183
|
+
});
|
|
184
|
+
events.push({ kind: "intent_proposed", envelope });
|
|
185
|
+
const { decision } = await adjudicateAndAudit(envelope, state, options.pack.policy, {
|
|
186
|
+
sink: options.auditSink ?? noopAuditSink(),
|
|
187
|
+
ledger: options.ledger,
|
|
188
|
+
context: options.runtimeContext,
|
|
189
|
+
plan: () => ({
|
|
190
|
+
visibleReadTools: plan.visibleReadTools,
|
|
191
|
+
allowedIntents: plan.allowedIntents,
|
|
192
|
+
}),
|
|
193
|
+
});
|
|
194
|
+
lastDecision = decision;
|
|
195
|
+
events.push({ kind: "decision", decision, envelope });
|
|
196
|
+
traceSink.onTrace({
|
|
197
|
+
phase: "decision_emitted",
|
|
198
|
+
sessionId,
|
|
199
|
+
iteration: iter + 1,
|
|
200
|
+
decisionKind: decision.kind,
|
|
201
|
+
});
|
|
202
|
+
const single = await processSingleDecision({
|
|
203
|
+
decision,
|
|
204
|
+
envelope: envelope,
|
|
205
|
+
toolUseId: tu.id,
|
|
206
|
+
sessionId,
|
|
207
|
+
state,
|
|
208
|
+
historySnapshot: history,
|
|
209
|
+
});
|
|
210
|
+
events.push(...single.events);
|
|
211
|
+
if (single.toolResult)
|
|
212
|
+
toolResults.push(single.toolResult);
|
|
213
|
+
if (single.loopAction.kind !== "continue") {
|
|
214
|
+
pauseAction = single.loopAction;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
if (toolResults.length > 0) {
|
|
218
|
+
history = bridge.appendToolResults(history, toolResults);
|
|
219
|
+
}
|
|
220
|
+
if (pauseAction !== null) {
|
|
221
|
+
const reason = pauseActionToReason(pauseAction.kind);
|
|
222
|
+
traceSink.onTrace({
|
|
223
|
+
phase: "paused",
|
|
224
|
+
sessionId,
|
|
225
|
+
iteration: iter + 1,
|
|
226
|
+
...(reason !== undefined ? { pauseReason: reason } : {}),
|
|
227
|
+
...(lastDecision !== null
|
|
228
|
+
? { decisionKind: lastDecision.kind }
|
|
229
|
+
: {}),
|
|
230
|
+
});
|
|
231
|
+
return {
|
|
232
|
+
events,
|
|
233
|
+
history,
|
|
234
|
+
outcome: pauseToOutcome(pauseAction, lastDecision),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
traceSink.onTrace({
|
|
239
|
+
phase: "max_iterations_exceeded",
|
|
240
|
+
sessionId,
|
|
241
|
+
iteration: maxIterations,
|
|
242
|
+
...(lastDecision !== null ? { decisionKind: lastDecision.kind } : {}),
|
|
243
|
+
});
|
|
244
|
+
return {
|
|
245
|
+
events,
|
|
246
|
+
history,
|
|
247
|
+
outcome: { kind: "max_iterations_exceeded", lastDecision },
|
|
248
|
+
};
|
|
249
|
+
async function processSingleDecision(args) {
|
|
250
|
+
const t = await translateDecision({
|
|
251
|
+
decision: args.decision,
|
|
252
|
+
envelope: args.envelope,
|
|
253
|
+
toolUseId: args.toolUseId,
|
|
254
|
+
sessionId: args.sessionId,
|
|
255
|
+
state: args.state,
|
|
256
|
+
executor: options.executor,
|
|
257
|
+
deferStore: options.deferStore,
|
|
258
|
+
confirmationStore: options.confirmationStore,
|
|
259
|
+
historySnapshot: args.historySnapshot,
|
|
260
|
+
rk,
|
|
261
|
+
log: options.log,
|
|
262
|
+
generateToken: () => globalThis.crypto?.randomUUID?.() ??
|
|
263
|
+
`ct-${Math.random().toString(36).slice(2)}-${Date.now()}`,
|
|
264
|
+
});
|
|
265
|
+
return {
|
|
266
|
+
events: [...t.extraEvents],
|
|
267
|
+
toolResult: t.toolResult,
|
|
268
|
+
loopAction: t.loopAction,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
async send(input) {
|
|
274
|
+
const baseHistory = input.history ?? bridge.emptyHistory();
|
|
275
|
+
const initialHistory = bridge.appendUserMessage(baseHistory, input.userMessage);
|
|
276
|
+
const seedEvents = [
|
|
277
|
+
{ kind: "user_message", text: input.userMessage },
|
|
278
|
+
];
|
|
279
|
+
return runLoop(input.sessionId, initialHistory, input.state, input.context, seedEvents, null);
|
|
280
|
+
},
|
|
281
|
+
async resume(args) {
|
|
282
|
+
const result = await resumeDeferredIntent({
|
|
283
|
+
sessionId: args.sessionId,
|
|
284
|
+
signal: args.signal,
|
|
285
|
+
redis: options.deferStore,
|
|
286
|
+
rk,
|
|
287
|
+
log: options.log,
|
|
288
|
+
verifyHash: options.verifyParkedHash ?? "warn",
|
|
289
|
+
});
|
|
290
|
+
if (!result.resumed || !result.parked) {
|
|
291
|
+
throw new AdapterError(AdapterErrorCode.RESUME_NO_PARKED, `No parked envelope for session "${args.sessionId}" and signal "${args.signal}" (reason: ${result.reason ?? "unknown"})`, { sessionId: args.sessionId, signal: args.signal, reason: result.reason });
|
|
292
|
+
}
|
|
293
|
+
const envelope = {
|
|
294
|
+
version: 2,
|
|
295
|
+
kind: result.parked.envelope.kind,
|
|
296
|
+
payload: result.parked.envelope.payload,
|
|
297
|
+
createdAt: new Date().toISOString(),
|
|
298
|
+
nonce: result.parked.envelope.intentHash,
|
|
299
|
+
actor: {
|
|
300
|
+
principal: "system",
|
|
301
|
+
sessionId: result.parked.envelope.actor.sessionId,
|
|
302
|
+
},
|
|
303
|
+
taint: "TRUSTED",
|
|
304
|
+
intentHash: result.parked.envelope.intentHash,
|
|
305
|
+
};
|
|
306
|
+
const resumePlan = options.pack.planner.plan(args.state, args.context);
|
|
307
|
+
const { decision } = await adjudicateAndAudit(envelope, args.state, options.pack.policy, {
|
|
308
|
+
sink: options.auditSink ?? noopAuditSink(),
|
|
309
|
+
ledger: options.ledger,
|
|
310
|
+
context: options.runtimeContext,
|
|
311
|
+
plan: () => ({
|
|
312
|
+
visibleReadTools: resumePlan.visibleReadTools,
|
|
313
|
+
allowedIntents: resumePlan.allowedIntents,
|
|
314
|
+
}),
|
|
315
|
+
});
|
|
316
|
+
const seedEvents = [
|
|
317
|
+
{ kind: "intent_proposed", envelope },
|
|
318
|
+
{ kind: "decision", decision, envelope },
|
|
319
|
+
];
|
|
320
|
+
const fauxToolUseId = `resume-${result.parked.envelope.intentHash.slice(0, 8)}`;
|
|
321
|
+
const seedDecision = {
|
|
322
|
+
decision,
|
|
323
|
+
envelope,
|
|
324
|
+
toolUseId: fauxToolUseId,
|
|
325
|
+
};
|
|
326
|
+
return runLoop(args.sessionId, args.history ?? bridge.emptyHistory(), args.state, args.context, seedEvents, seedDecision);
|
|
327
|
+
},
|
|
328
|
+
async confirm(args) {
|
|
329
|
+
const pending = await options.confirmationStore.take(args.confirmationToken);
|
|
330
|
+
if (pending === null) {
|
|
331
|
+
throw new AdapterError(AdapterErrorCode.CONFIRMATION_TOKEN_INVALID, `Confirmation token "${args.confirmationToken}" is unknown or expired.`, { confirmationToken: args.confirmationToken });
|
|
332
|
+
}
|
|
333
|
+
const verifyMode = options.verifyParkedHash ?? "warn";
|
|
334
|
+
if (verifyMode !== "off") {
|
|
335
|
+
const derived = sha256Canonical({
|
|
336
|
+
version: pending.envelope.version,
|
|
337
|
+
kind: pending.envelope.kind,
|
|
338
|
+
payload: pending.envelope.payload,
|
|
339
|
+
nonce: pending.envelope.nonce,
|
|
340
|
+
actor: pending.envelope.actor,
|
|
341
|
+
taint: pending.envelope.taint,
|
|
342
|
+
});
|
|
343
|
+
if (derived !== pending.envelope.intentHash) {
|
|
344
|
+
options.log?.warn?.({
|
|
345
|
+
sessionId: pending.sessionId,
|
|
346
|
+
stored: pending.envelope.intentHash,
|
|
347
|
+
derived,
|
|
348
|
+
confirmationToken: args.confirmationToken,
|
|
349
|
+
}, "[adjudicated-agent] confirmation blob tampered — refusing to resume");
|
|
350
|
+
throw new AdapterError(AdapterErrorCode.CONFIRMATION_TOKEN_INVALID, `Confirmation token "${args.confirmationToken}" failed hash verification (envelope was modified after persistence).`, {
|
|
351
|
+
confirmationToken: args.confirmationToken,
|
|
352
|
+
reason: "confirmation_blob_tampered",
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (!args.accepted) {
|
|
357
|
+
const declineEvent = {
|
|
358
|
+
kind: "assistant_text",
|
|
359
|
+
text: "User declined the confirmation. Action skipped.",
|
|
360
|
+
};
|
|
361
|
+
return {
|
|
362
|
+
events: [declineEvent],
|
|
363
|
+
history: pending.assistantHistorySnapshot,
|
|
364
|
+
outcome: {
|
|
365
|
+
kind: "completed",
|
|
366
|
+
assistantText: "User declined the confirmation. Action skipped.",
|
|
367
|
+
},
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
const envelope = pending.envelope;
|
|
371
|
+
const confirmPlan = options.pack.planner.plan(args.state, args.context);
|
|
372
|
+
const { decision } = await adjudicateAndAudit(envelope, args.state, options.pack.policy, {
|
|
373
|
+
sink: options.auditSink ?? noopAuditSink(),
|
|
374
|
+
ledger: options.ledger,
|
|
375
|
+
context: options.runtimeContext,
|
|
376
|
+
plan: () => ({
|
|
377
|
+
visibleReadTools: confirmPlan.visibleReadTools,
|
|
378
|
+
allowedIntents: confirmPlan.allowedIntents,
|
|
379
|
+
}),
|
|
380
|
+
confirmationReceipt: {
|
|
381
|
+
intentHash: envelope.intentHash,
|
|
382
|
+
at: new Date().toISOString(),
|
|
383
|
+
},
|
|
384
|
+
});
|
|
385
|
+
const seedEvents = [
|
|
386
|
+
{ kind: "intent_proposed", envelope },
|
|
387
|
+
{ kind: "decision", decision, envelope },
|
|
388
|
+
];
|
|
389
|
+
const seedDecision = {
|
|
390
|
+
decision,
|
|
391
|
+
envelope,
|
|
392
|
+
toolUseId: pending.toolUseId,
|
|
393
|
+
};
|
|
394
|
+
return runLoop(pending.sessionId, pending.assistantHistorySnapshot, args.state, args.context, seedEvents, seedDecision);
|
|
395
|
+
},
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
function pauseToOutcome(action, lastDecision) {
|
|
399
|
+
switch (action.kind) {
|
|
400
|
+
case "continue":
|
|
401
|
+
return { kind: "max_iterations_exceeded", lastDecision };
|
|
402
|
+
case "pause_for_user_confirmation":
|
|
403
|
+
return {
|
|
404
|
+
kind: "awaiting_confirmation",
|
|
405
|
+
prompt: action.prompt,
|
|
406
|
+
confirmationToken: action.token,
|
|
407
|
+
};
|
|
408
|
+
case "pause_for_defer":
|
|
409
|
+
return {
|
|
410
|
+
kind: "deferred",
|
|
411
|
+
signal: action.signal,
|
|
412
|
+
intentHash: action.intentHash,
|
|
413
|
+
};
|
|
414
|
+
case "complete_for_escalation":
|
|
415
|
+
return {
|
|
416
|
+
kind: "escalated",
|
|
417
|
+
to: action.to,
|
|
418
|
+
reason: action.reason,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
//# sourceMappingURL=loop.js.map
|
package/dist/loop.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redis-backed `ConfirmationStore` — restart-durable pending confirmations.
|
|
3
|
+
*
|
|
4
|
+
* The in-memory `createInMemoryConfirmationStore` (see `./persistence.ts`)
|
|
5
|
+
* is suitable for tests and the quickstart, but a process restart loses
|
|
6
|
+
* every pending confirmation. Adopters running the adapter loop in a
|
|
7
|
+
* production process need restart durability so user-held tokens
|
|
8
|
+
* (REQUEST_CONFIRMATION flows that block for hours) survive deploys.
|
|
9
|
+
*
|
|
10
|
+
* This module ships a Redis-backed implementation that uses the same
|
|
11
|
+
* minimal `RedisLedgerClient` surface (`get`/`set`) as the rest of the
|
|
12
|
+
* audit + ledger stack. The store is generic over `H` (the conversation-
|
|
13
|
+
* history shape) — the caller supplies a serializer for their provider's
|
|
14
|
+
* history type.
|
|
15
|
+
*
|
|
16
|
+
* # Wire format
|
|
17
|
+
*
|
|
18
|
+
* Each pending confirmation is JSON-encoded under the key
|
|
19
|
+
* `${prefix}:confirm:${token}`. The TTL on the key matches the
|
|
20
|
+
* adopter-supplied `ttlSeconds` from `put()`.
|
|
21
|
+
*
|
|
22
|
+
* # Get-and-delete (take semantics)
|
|
23
|
+
*
|
|
24
|
+
* `take()` is single-use: a successful take deletes the key. Two
|
|
25
|
+
* concurrent `take(token)` calls race — Redis `GET` + `DEL` is not atomic
|
|
26
|
+
* without scripting, so at most one caller receives the pending
|
|
27
|
+
* confirmation. Production adopters needing strict at-most-once semantics
|
|
28
|
+
* across replicas should wire a Lua script; the JS implementation here
|
|
29
|
+
* accepts a tiny race window where two `take` calls might both return
|
|
30
|
+
* the same pending (the LATER one's adjudication then fails on
|
|
31
|
+
* `REPLAY_SUPPRESSED` via the kernel's ledger — fail-closed by design).
|
|
32
|
+
*
|
|
33
|
+
* # Replay safety
|
|
34
|
+
*
|
|
35
|
+
* Confirmation tokens are NOT inputs to the kernel's adjudication —
|
|
36
|
+
* they're externally-held opaque references. The kernel's
|
|
37
|
+
* `confirmationReceipt` (which IS adjudicated against) is reconstructed
|
|
38
|
+
* from the persisted envelope, not from the token. So storing them in
|
|
39
|
+
* Redis does not change replay determinism.
|
|
40
|
+
*/
|
|
41
|
+
import type { ConfirmationStore } from "./persistence.js";
|
|
42
|
+
/**
|
|
43
|
+
* Minimal Redis surface required by the Redis confirmation store. Same
|
|
44
|
+
* shape as `@adjudicate/audit`'s `RedisLedgerClient` so adopters can
|
|
45
|
+
* reuse the same connection.
|
|
46
|
+
*/
|
|
47
|
+
export interface ConfirmationRedisClient {
|
|
48
|
+
set(key: string, value: string, options?: {
|
|
49
|
+
NX?: boolean;
|
|
50
|
+
EX?: number;
|
|
51
|
+
}): Promise<string | null>;
|
|
52
|
+
get(key: string): Promise<string | null>;
|
|
53
|
+
del(key: string): Promise<unknown>;
|
|
54
|
+
}
|
|
55
|
+
export interface CreateRedisConfirmationStoreOptions<H> {
|
|
56
|
+
readonly client: ConfirmationRedisClient;
|
|
57
|
+
/**
|
|
58
|
+
* Adopter-supplied key namespacer. Adjudicate convention: wrap the
|
|
59
|
+
* raw suffix into a tenant/env-namespaced key (e.g.,
|
|
60
|
+
* `${APP_ENV}:adjudicate:${suffix}`). Defaults to identity.
|
|
61
|
+
*/
|
|
62
|
+
readonly keyFor?: (suffix: string) => string;
|
|
63
|
+
/**
|
|
64
|
+
* Serializer for the assistant history snapshot. Required because `H`
|
|
65
|
+
* is the provider's opaque history shape — Anthropic's MessageParam[]
|
|
66
|
+
* and OpenAI's ChatCompletionMessageParam[] are both JSON-serializable
|
|
67
|
+
* by default. Adopters who use richer types (Date, BigInt) should plug
|
|
68
|
+
* in a custom serializer.
|
|
69
|
+
*
|
|
70
|
+
* Default: `JSON.stringify` / `JSON.parse`.
|
|
71
|
+
*/
|
|
72
|
+
readonly serializeHistory?: (h: H) => string;
|
|
73
|
+
readonly deserializeHistory?: (s: string) => H;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Redis-backed `ConfirmationStore<H>`. Wraps the minimal `set/get/del`
|
|
77
|
+
* surface. `put` writes with EX (TTL); `take` does GET then DEL.
|
|
78
|
+
*
|
|
79
|
+
* Adopters share the underlying Redis client across the ledger, the
|
|
80
|
+
* kill switch, and the confirmation store — one connection per role
|
|
81
|
+
* (read/write vs subscribe) is the typical production wiring.
|
|
82
|
+
*/
|
|
83
|
+
export declare function createRedisConfirmationStore<H = unknown>(opts: CreateRedisConfirmationStoreOptions<H>): ConfirmationStore<H>;
|
|
84
|
+
//# sourceMappingURL=persistence-redis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence-redis.d.ts","sourceRoot":"","sources":["../src/persistence-redis.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAGH,OAAO,KAAK,EACV,iBAAiB,EAElB,MAAM,kBAAkB,CAAC;AAE1B;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACtC,GAAG,CACD,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,OAAO,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,OAAO,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GACtC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,mCAAmC,CAAC,CAAC;IACpD,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7C;;;;;;;;OAQG;IACH,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAC;IAC7C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,CAAC,CAAC;CAChD;AAUD;;;;;;;GAOG;AACH,wBAAgB,4BAA4B,CAAC,CAAC,GAAG,OAAO,EACtD,IAAI,EAAE,mCAAmC,CAAC,CAAC,CAAC,GAC3C,iBAAiB,CAAC,CAAC,CAAC,CAwDtB"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Redis-backed `ConfirmationStore` — restart-durable pending confirmations.
|
|
3
|
+
*
|
|
4
|
+
* The in-memory `createInMemoryConfirmationStore` (see `./persistence.ts`)
|
|
5
|
+
* is suitable for tests and the quickstart, but a process restart loses
|
|
6
|
+
* every pending confirmation. Adopters running the adapter loop in a
|
|
7
|
+
* production process need restart durability so user-held tokens
|
|
8
|
+
* (REQUEST_CONFIRMATION flows that block for hours) survive deploys.
|
|
9
|
+
*
|
|
10
|
+
* This module ships a Redis-backed implementation that uses the same
|
|
11
|
+
* minimal `RedisLedgerClient` surface (`get`/`set`) as the rest of the
|
|
12
|
+
* audit + ledger stack. The store is generic over `H` (the conversation-
|
|
13
|
+
* history shape) — the caller supplies a serializer for their provider's
|
|
14
|
+
* history type.
|
|
15
|
+
*
|
|
16
|
+
* # Wire format
|
|
17
|
+
*
|
|
18
|
+
* Each pending confirmation is JSON-encoded under the key
|
|
19
|
+
* `${prefix}:confirm:${token}`. The TTL on the key matches the
|
|
20
|
+
* adopter-supplied `ttlSeconds` from `put()`.
|
|
21
|
+
*
|
|
22
|
+
* # Get-and-delete (take semantics)
|
|
23
|
+
*
|
|
24
|
+
* `take()` is single-use: a successful take deletes the key. Two
|
|
25
|
+
* concurrent `take(token)` calls race — Redis `GET` + `DEL` is not atomic
|
|
26
|
+
* without scripting, so at most one caller receives the pending
|
|
27
|
+
* confirmation. Production adopters needing strict at-most-once semantics
|
|
28
|
+
* across replicas should wire a Lua script; the JS implementation here
|
|
29
|
+
* accepts a tiny race window where two `take` calls might both return
|
|
30
|
+
* the same pending (the LATER one's adjudication then fails on
|
|
31
|
+
* `REPLAY_SUPPRESSED` via the kernel's ledger — fail-closed by design).
|
|
32
|
+
*
|
|
33
|
+
* # Replay safety
|
|
34
|
+
*
|
|
35
|
+
* Confirmation tokens are NOT inputs to the kernel's adjudication —
|
|
36
|
+
* they're externally-held opaque references. The kernel's
|
|
37
|
+
* `confirmationReceipt` (which IS adjudicated against) is reconstructed
|
|
38
|
+
* from the persisted envelope, not from the token. So storing them in
|
|
39
|
+
* Redis does not change replay determinism.
|
|
40
|
+
*/
|
|
41
|
+
/**
|
|
42
|
+
* Redis-backed `ConfirmationStore<H>`. Wraps the minimal `set/get/del`
|
|
43
|
+
* surface. `put` writes with EX (TTL); `take` does GET then DEL.
|
|
44
|
+
*
|
|
45
|
+
* Adopters share the underlying Redis client across the ledger, the
|
|
46
|
+
* kill switch, and the confirmation store — one connection per role
|
|
47
|
+
* (read/write vs subscribe) is the typical production wiring.
|
|
48
|
+
*/
|
|
49
|
+
export function createRedisConfirmationStore(opts) {
|
|
50
|
+
const keyFor = opts.keyFor ?? ((s) => s);
|
|
51
|
+
const serialize = opts.serializeHistory ?? ((h) => JSON.stringify(h));
|
|
52
|
+
const deserialize = opts.deserializeHistory ?? ((s) => JSON.parse(s));
|
|
53
|
+
return {
|
|
54
|
+
async put(token, pending, ttlSeconds) {
|
|
55
|
+
const wire = {
|
|
56
|
+
envelope: pending.envelope,
|
|
57
|
+
sessionId: pending.sessionId,
|
|
58
|
+
historyJson: serialize(pending.assistantHistorySnapshot),
|
|
59
|
+
toolUseId: pending.toolUseId,
|
|
60
|
+
prompt: pending.prompt,
|
|
61
|
+
};
|
|
62
|
+
await opts.client.set(keyFor(`confirm:${token}`), JSON.stringify(wire), { EX: ttlSeconds });
|
|
63
|
+
},
|
|
64
|
+
async take(token) {
|
|
65
|
+
const key = keyFor(`confirm:${token}`);
|
|
66
|
+
const raw = await opts.client.get(key);
|
|
67
|
+
if (raw === null)
|
|
68
|
+
return null;
|
|
69
|
+
// Get-and-delete: a single use. Concurrent takes may race; the
|
|
70
|
+
// kernel's ledger backstops with REPLAY_SUPPRESSED on the second
|
|
71
|
+
// adjudication.
|
|
72
|
+
await opts.client.del(key);
|
|
73
|
+
let wire;
|
|
74
|
+
try {
|
|
75
|
+
wire = JSON.parse(raw);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
let history;
|
|
81
|
+
try {
|
|
82
|
+
history = deserialize(wire.historyJson);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
envelope: wire.envelope,
|
|
89
|
+
sessionId: wire.sessionId,
|
|
90
|
+
assistantHistorySnapshot: history,
|
|
91
|
+
toolUseId: wire.toolUseId,
|
|
92
|
+
prompt: wire.prompt,
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=persistence-redis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence-redis.js","sourceRoot":"","sources":["../src/persistence-redis.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AAoDH;;;;;;;GAOG;AACH,MAAM,UAAU,4BAA4B,CAC1C,IAA4C;IAE5C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,SAAS,GACb,IAAI,CAAC,gBAAgB,IAAI,CAAC,CAAC,CAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,MAAM,WAAW,GACf,IAAI,CAAC,kBAAkB,IAAI,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAM,CAAC,CAAC;IAEjE,OAAO;QACL,KAAK,CAAC,GAAG,CACP,KAAa,EACb,OAA+B,EAC/B,UAAkB;YAElB,MAAM,IAAI,GAAe;gBACvB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,WAAW,EAAE,SAAS,CAAC,OAAO,CAAC,wBAAwB,CAAC;gBACxD,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC;YACF,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CACnB,MAAM,CAAC,WAAW,KAAK,EAAE,CAAC,EAC1B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EACpB,EAAE,EAAE,EAAE,UAAU,EAAE,CACnB,CAAC;QACJ,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,KAAa;YACtB,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;YACvC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACvC,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO,IAAI,CAAC;YAC9B,+DAA+D;YAC/D,iEAAiE;YACjE,gBAAgB;YAChB,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC3B,IAAI,IAAgB,CAAC;YACrB,IAAI,CAAC;gBACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;YACvC,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,OAAU,CAAC;YACf,IAAI,CAAC;gBACH,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;YACD,OAAO;gBACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,wBAAwB,EAAE,OAAO;gBACjC,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,MAAM,EAAE,IAAI,CAAC,MAAM;aACpB,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC"}
|