@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.
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Bridge module — the boundary between provider tool-use blocks and
3
+ * adjudicate's `IntentEnvelope`s.
4
+ *
5
+ * Convention: intent-kind tool name (e.g. `pix.charge.create`) is
6
+ * translated to a wire-friendly form by replacing `.` with `_` (most
7
+ * provider APIs forbid dots in tool names). The renderer applies the
8
+ * translation outbound; `classifyIncomingToolUse` accepts either the
9
+ * translated form (live API path) or the raw dotted form (mocked-test
10
+ * path) so test harnesses that bypass the renderer continue to work.
11
+ *
12
+ * Taint is ALWAYS `"UNTRUSTED"` for envelopes derived from LLM tool_use
13
+ * blocks. There is no path from this module that raises taint upward;
14
+ * TRUSTED intents (e.g. webhook confirmations) come from elsewhere.
15
+ */
16
+ import { type IntentEnvelope, type Taint } from "@adjudicate/core";
17
+ import type { Plan } from "@adjudicate/core/llm";
18
+ /**
19
+ * Translate an intent-kind / READ-tool name to its wire-API form.
20
+ * Replaces `.` with `_` so names like `pix.charge.create` become
21
+ * `pix_charge_create`, matching the lowest-common-denominator tool-name
22
+ * pattern (`^[a-zA-Z0-9_-]+$`) that both Anthropic and OpenAI accept.
23
+ * No-op for names that already contain only API-allowed characters.
24
+ *
25
+ * Reversibility caveat: an intent kind `a.b` and a READ tool `a_b` both
26
+ * translate to `a_b` and become indistinguishable on the wire. Adopters
27
+ * who hit this collision should rename one of them; the Pack-conformance
28
+ * check (P2) surfaces the collision at install time.
29
+ */
30
+ export declare function intentKindToApiName(name: string): string;
31
+ export type ToolUseClassification = {
32
+ readonly kind: "read";
33
+ readonly name: string;
34
+ readonly input: unknown;
35
+ } | {
36
+ readonly kind: "intent";
37
+ readonly intentKind: string;
38
+ readonly payload: unknown;
39
+ } | {
40
+ readonly kind: "out_of_plan";
41
+ readonly name: string;
42
+ };
43
+ /**
44
+ * Decide whether an incoming `tool_use` is a READ tool execution, an
45
+ * intent proposal, or a hallucinated tool the planner did not advertise.
46
+ *
47
+ * Out-of-plan tool_uses translate to `isError: true` tool-results so the
48
+ * loop never silently fails — the model gets a recoverable signal.
49
+ *
50
+ * The match is forgiving: the planner exposes the raw (dotted) intent
51
+ * kind, the renderer ships the translated (underscored) form to the
52
+ * provider API, and the model echoes back the translated form on
53
+ * `tool_use`. We compare both raw and translated against each candidate
54
+ * so mocked-test paths (which skip the renderer translation) and
55
+ * live-API paths (which round-trip through translation) both work.
56
+ */
57
+ export declare function classifyIncomingToolUse(toolUse: {
58
+ readonly name: string;
59
+ readonly input: unknown;
60
+ }, plan: Plan): ToolUseClassification;
61
+ export interface BuildEnvelopeFromToolUseArgs {
62
+ readonly intentKind: string;
63
+ readonly payload: unknown;
64
+ readonly sessionId: string;
65
+ /**
66
+ * Taint of the proposing context. The loop pins this to `"UNTRUSTED"`
67
+ * for LLM-derived envelopes; this argument exists for symmetry with
68
+ * `buildEnvelope` and to keep the boundary explicit.
69
+ */
70
+ readonly taint: Taint;
71
+ readonly nonce: string;
72
+ }
73
+ /**
74
+ * Construct an IntentEnvelope from a provider-neutral tool_use. Wraps
75
+ * `buildEnvelope` from @adjudicate/core with adapter-specific defaults:
76
+ * principal = `"llm"`, taint as supplied (always `"UNTRUSTED"` from the
77
+ * loop).
78
+ */
79
+ export declare function buildEnvelopeFromToolUse(args: BuildEnvelopeFromToolUseArgs): IntentEnvelope<string, unknown>;
80
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAiB,KAAK,cAAc,EAAE,KAAK,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAClF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAC;AAEjD;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,MAAM,MAAM,qBAAqB,GAC7B;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACzE;IACE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;CAC3B,GACD;IAAE,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,EAC3D,IAAI,EAAE,IAAI,GACT,qBAAqB,CAkBvB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,4BAA4B,GACjC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAQjC"}
package/dist/bridge.js ADDED
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Bridge module — the boundary between provider tool-use blocks and
3
+ * adjudicate's `IntentEnvelope`s.
4
+ *
5
+ * Convention: intent-kind tool name (e.g. `pix.charge.create`) is
6
+ * translated to a wire-friendly form by replacing `.` with `_` (most
7
+ * provider APIs forbid dots in tool names). The renderer applies the
8
+ * translation outbound; `classifyIncomingToolUse` accepts either the
9
+ * translated form (live API path) or the raw dotted form (mocked-test
10
+ * path) so test harnesses that bypass the renderer continue to work.
11
+ *
12
+ * Taint is ALWAYS `"UNTRUSTED"` for envelopes derived from LLM tool_use
13
+ * blocks. There is no path from this module that raises taint upward;
14
+ * TRUSTED intents (e.g. webhook confirmations) come from elsewhere.
15
+ */
16
+ import { buildEnvelope } from "@adjudicate/core";
17
+ /**
18
+ * Translate an intent-kind / READ-tool name to its wire-API form.
19
+ * Replaces `.` with `_` so names like `pix.charge.create` become
20
+ * `pix_charge_create`, matching the lowest-common-denominator tool-name
21
+ * pattern (`^[a-zA-Z0-9_-]+$`) that both Anthropic and OpenAI accept.
22
+ * No-op for names that already contain only API-allowed characters.
23
+ *
24
+ * Reversibility caveat: an intent kind `a.b` and a READ tool `a_b` both
25
+ * translate to `a_b` and become indistinguishable on the wire. Adopters
26
+ * who hit this collision should rename one of them; the Pack-conformance
27
+ * check (P2) surfaces the collision at install time.
28
+ */
29
+ export function intentKindToApiName(name) {
30
+ return name.replaceAll(".", "_");
31
+ }
32
+ /**
33
+ * Decide whether an incoming `tool_use` is a READ tool execution, an
34
+ * intent proposal, or a hallucinated tool the planner did not advertise.
35
+ *
36
+ * Out-of-plan tool_uses translate to `isError: true` tool-results so the
37
+ * loop never silently fails — the model gets a recoverable signal.
38
+ *
39
+ * The match is forgiving: the planner exposes the raw (dotted) intent
40
+ * kind, the renderer ships the translated (underscored) form to the
41
+ * provider API, and the model echoes back the translated form on
42
+ * `tool_use`. We compare both raw and translated against each candidate
43
+ * so mocked-test paths (which skip the renderer translation) and
44
+ * live-API paths (which round-trip through translation) both work.
45
+ */
46
+ export function classifyIncomingToolUse(toolUse, plan) {
47
+ const matchesName = (candidate) => candidate === toolUse.name ||
48
+ intentKindToApiName(candidate) === toolUse.name;
49
+ const readMatch = plan.visibleReadTools.find(matchesName);
50
+ if (readMatch !== undefined) {
51
+ return { kind: "read", name: readMatch, input: toolUse.input };
52
+ }
53
+ const intentMatch = plan.allowedIntents.find(matchesName);
54
+ if (intentMatch !== undefined) {
55
+ return {
56
+ kind: "intent",
57
+ intentKind: intentMatch,
58
+ payload: toolUse.input,
59
+ };
60
+ }
61
+ return { kind: "out_of_plan", name: toolUse.name };
62
+ }
63
+ /**
64
+ * Construct an IntentEnvelope from a provider-neutral tool_use. Wraps
65
+ * `buildEnvelope` from @adjudicate/core with adapter-specific defaults:
66
+ * principal = `"llm"`, taint as supplied (always `"UNTRUSTED"` from the
67
+ * loop).
68
+ */
69
+ export function buildEnvelopeFromToolUse(args) {
70
+ return buildEnvelope({
71
+ kind: args.intentKind,
72
+ payload: args.payload,
73
+ actor: { principal: "llm", sessionId: args.sessionId },
74
+ taint: args.taint,
75
+ nonce: args.nonce,
76
+ });
77
+ }
78
+ //# sourceMappingURL=bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,aAAa,EAAmC,MAAM,kBAAkB,CAAC;AAGlF;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACnC,CAAC;AAWD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CACrC,OAA2D,EAC3D,IAAU;IAEV,MAAM,WAAW,GAAG,CAAC,SAAiB,EAAW,EAAE,CACjD,SAAS,KAAK,OAAO,CAAC,IAAI;QAC1B,mBAAmB,CAAC,SAAS,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC;IAElD,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1D,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;IACjE,CAAC;IACD,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1D,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO;YACL,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,WAAW;YACvB,OAAO,EAAE,OAAO,CAAC,KAAK;SACvB,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;AACrD,CAAC;AAeD;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CACtC,IAAkC;IAElC,OAAO,aAAa,CAAC;QACnB,IAAI,EAAE,IAAI,CAAC,UAAU;QACrB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE;QACtD,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Decision → provider-neutral tool-result + loop-action translator.
3
+ *
4
+ * One branch per `Decision.kind`. Returns:
5
+ * - `toolResult` — the provider-neutral `ToolResultBlock` that goes back
6
+ * to the model in the next user-role message (or `null` if no tool-
7
+ * result is sent).
8
+ * - `loopAction` — what the loop should do next: `continue` (next
9
+ * iteration), `pause_for_user_confirmation` / `pause_for_defer`
10
+ * (return outcome to adopter), or `complete_for_escalation`
11
+ * (terminate the turn).
12
+ * - `events` — `AgentEvent`s to push for audit / transcript display.
13
+ *
14
+ * **REWRITE** runs the executor against the *rewritten* envelope (NOT
15
+ * the original) and surfaces a human-readable note in the tool-result
16
+ * by default.
17
+ *
18
+ * **First non-continue Decision wins**: if multiple tool_use blocks fire
19
+ * in the same assistant turn, the loop processes them in order but
20
+ * stops translating the moment a non-continue Decision arrives. The
21
+ * remaining blocks are surfaced as `not_processed_due_to_pause`.
22
+ */
23
+ import type { Decision, IntentEnvelope } from "@adjudicate/core";
24
+ import { AdapterError, AdapterErrorCode } from "./errors.js";
25
+ import type { ConfirmationStore, DeferRedis, ParkRedis } from "./persistence.js";
26
+ import type { AdopterExecutor, AgentEvent, AgentLogger, ToolResultBlock } from "./types.js";
27
+ export interface DecisionTranslationContext<K extends string, P, S, H> {
28
+ readonly decision: Decision;
29
+ readonly envelope: IntentEnvelope<K, P>;
30
+ readonly toolUseId: string;
31
+ readonly sessionId: string;
32
+ readonly state: S;
33
+ readonly executor: AdopterExecutor<K, P, S>;
34
+ readonly deferStore: DeferRedis & ParkRedis;
35
+ readonly confirmationStore: ConfirmationStore<H>;
36
+ readonly historySnapshot: H;
37
+ readonly rk: (raw: string) => string;
38
+ readonly log?: AgentLogger;
39
+ /**
40
+ * Per-turn token generator. Adapter passes `crypto.randomUUID()` by
41
+ * default; tests can inject a deterministic generator.
42
+ */
43
+ readonly generateToken: () => string;
44
+ }
45
+ export type LoopAction = {
46
+ readonly kind: "continue";
47
+ } | {
48
+ readonly kind: "pause_for_user_confirmation";
49
+ readonly prompt: string;
50
+ readonly token: string;
51
+ } | {
52
+ readonly kind: "pause_for_defer";
53
+ readonly signal: string;
54
+ readonly intentHash: string;
55
+ } | {
56
+ readonly kind: "complete_for_escalation";
57
+ readonly to: "human" | "supervisor";
58
+ readonly reason: string;
59
+ };
60
+ export interface DecisionTranslation {
61
+ readonly toolResult: ToolResultBlock | null;
62
+ readonly loopAction: LoopAction;
63
+ readonly extraEvents: ReadonlyArray<AgentEvent>;
64
+ }
65
+ /**
66
+ * Translate a `Decision` into a provider-neutral `ToolResultBlock` plus
67
+ * the next loop action. The caller (the send loop) appends the tool-
68
+ * result to the next user-role message and either continues or pauses
69
+ * based on `loopAction.kind`.
70
+ */
71
+ export declare function translateDecision<K extends string, P, S, H>(ctx: DecisionTranslationContext<K, P, S, H>): Promise<DecisionTranslation>;
72
+ /**
73
+ * Build the provider-neutral `ToolResultBlock` for an out-of-plan tool
74
+ * call. Re-exported so tests + adopters can construct one from outside
75
+ * the loop.
76
+ */
77
+ export declare function makeOutOfPlanToolResult(toolUseId: string, toolName: string): ToolResultBlock;
78
+ export { AdapterError, AdapterErrorCode };
79
+ //# sourceMappingURL=decisions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decisions.d.ts","sourceRoot":"","sources":["../src/decisions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEjE,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,SAAS,EACV,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EACV,eAAe,EACf,UAAU,EACV,WAAW,EACX,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,0BAA0B,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;IACnE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;IAClB,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,SAAS,CAAC;IAC5C,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAC;IACjD,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAC;IAC5B,QAAQ,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC;IACrC,QAAQ,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC;IAC3B;;;OAGG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,MAAM,CAAC;CACtC;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAA;CAAE,GAC7B;IACE,QAAQ,CAAC,IAAI,EAAE,6BAA6B,CAAC;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,iBAAiB,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;IACzC,QAAQ,CAAC,EAAE,EAAE,OAAO,GAAG,YAAY,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB,CAAC;AAEN,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,EAAE,eAAe,GAAG,IAAI,CAAC;IAC5C,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC;IAChC,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;CACjD;AAED;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAC/D,GAAG,EAAE,0BAA0B,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC1C,OAAO,CAAC,mBAAmB,CAAC,CA4H9B;AAgED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,eAAe,CAMjB;AAED,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Decision → provider-neutral tool-result + loop-action translator.
3
+ *
4
+ * One branch per `Decision.kind`. Returns:
5
+ * - `toolResult` — the provider-neutral `ToolResultBlock` that goes back
6
+ * to the model in the next user-role message (or `null` if no tool-
7
+ * result is sent).
8
+ * - `loopAction` — what the loop should do next: `continue` (next
9
+ * iteration), `pause_for_user_confirmation` / `pause_for_defer`
10
+ * (return outcome to adopter), or `complete_for_escalation`
11
+ * (terminate the turn).
12
+ * - `events` — `AgentEvent`s to push for audit / transcript display.
13
+ *
14
+ * **REWRITE** runs the executor against the *rewritten* envelope (NOT
15
+ * the original) and surfaces a human-readable note in the tool-result
16
+ * by default.
17
+ *
18
+ * **First non-continue Decision wins**: if multiple tool_use blocks fire
19
+ * in the same assistant turn, the loop processes them in order but
20
+ * stops translating the moment a non-continue Decision arrives. The
21
+ * remaining blocks are surfaced as `not_processed_due_to_pause`.
22
+ */
23
+ import { parkDeferredIntent } from "@adjudicate/runtime";
24
+ import { AdapterError, AdapterErrorCode } from "./errors.js";
25
+ /**
26
+ * Translate a `Decision` into a provider-neutral `ToolResultBlock` plus
27
+ * the next loop action. The caller (the send loop) appends the tool-
28
+ * result to the next user-role message and either continues or pauses
29
+ * based on `loopAction.kind`.
30
+ */
31
+ export async function translateDecision(ctx) {
32
+ switch (ctx.decision.kind) {
33
+ case "EXECUTE":
34
+ return runExecute(ctx, ctx.envelope, null);
35
+ case "REWRITE":
36
+ return runExecute(ctx, ctx.decision.rewritten, ctx.decision.reason);
37
+ case "REFUSE": {
38
+ const text = ctx.decision.refusal.userFacing;
39
+ const result = {
40
+ toolUseId: ctx.toolUseId,
41
+ content: text,
42
+ isError: true,
43
+ };
44
+ return {
45
+ toolResult: result,
46
+ loopAction: { kind: "continue" },
47
+ extraEvents: [
48
+ { kind: "tool_result", toolUseId: ctx.toolUseId, payload: result },
49
+ ],
50
+ };
51
+ }
52
+ case "REQUEST_CONFIRMATION": {
53
+ const token = ctx.generateToken();
54
+ await ctx.confirmationStore.put(token, {
55
+ envelope: ctx.envelope,
56
+ sessionId: ctx.sessionId,
57
+ assistantHistorySnapshot: ctx.historySnapshot,
58
+ toolUseId: ctx.toolUseId,
59
+ prompt: ctx.decision.prompt,
60
+ }, 24 * 60 * 60);
61
+ const result = {
62
+ toolUseId: ctx.toolUseId,
63
+ content: `Confirmation required: ${ctx.decision.prompt}`,
64
+ };
65
+ return {
66
+ toolResult: result,
67
+ loopAction: {
68
+ kind: "pause_for_user_confirmation",
69
+ prompt: ctx.decision.prompt,
70
+ token,
71
+ },
72
+ extraEvents: [
73
+ { kind: "tool_result", toolUseId: ctx.toolUseId, payload: result },
74
+ ],
75
+ };
76
+ }
77
+ case "ESCALATE": {
78
+ const result = {
79
+ toolUseId: ctx.toolUseId,
80
+ content: `Escalated to ${ctx.decision.to}: ${ctx.decision.reason}`,
81
+ };
82
+ return {
83
+ toolResult: result,
84
+ loopAction: {
85
+ kind: "complete_for_escalation",
86
+ to: ctx.decision.to,
87
+ reason: ctx.decision.reason,
88
+ },
89
+ extraEvents: [
90
+ { kind: "tool_result", toolUseId: ctx.toolUseId, payload: result },
91
+ ],
92
+ };
93
+ }
94
+ case "DEFER": {
95
+ const ttlSeconds = Math.max(ctx.decision.timeoutMs, 1000) / 1000 + 60;
96
+ const parkResult = await parkDeferredIntent({
97
+ envelope: {
98
+ intentHash: ctx.envelope.intentHash,
99
+ kind: ctx.envelope.kind,
100
+ actor: { sessionId: ctx.envelope.actor.sessionId },
101
+ payload: ctx.envelope.payload,
102
+ // Hash-verification fields. The resume path re-derives intentHash
103
+ // via sha256Canonical and asserts byte-equality with the stored
104
+ // value — detects blob tampering between park and resume.
105
+ version: ctx.envelope.version,
106
+ nonce: ctx.envelope.nonce,
107
+ taint: ctx.envelope.taint,
108
+ actorPrincipal: ctx.envelope.actor.principal,
109
+ },
110
+ signal: ctx.decision.signal,
111
+ ttlSeconds,
112
+ redis: ctx.deferStore,
113
+ rk: ctx.rk,
114
+ log: ctx.log,
115
+ });
116
+ if (!parkResult.parked) {
117
+ const result = {
118
+ toolUseId: ctx.toolUseId,
119
+ content: `This action could not be queued (per-session quota exceeded; ${parkResult.observed}/${parkResult.limit}).`,
120
+ isError: true,
121
+ };
122
+ return {
123
+ toolResult: result,
124
+ loopAction: { kind: "continue" },
125
+ extraEvents: [
126
+ { kind: "tool_result", toolUseId: ctx.toolUseId, payload: result },
127
+ ],
128
+ };
129
+ }
130
+ const result = {
131
+ toolUseId: ctx.toolUseId,
132
+ content: `Action queued. Waiting for signal "${ctx.decision.signal}" (timeout ${ctx.decision.timeoutMs}ms).`,
133
+ };
134
+ return {
135
+ toolResult: result,
136
+ loopAction: {
137
+ kind: "pause_for_defer",
138
+ signal: ctx.decision.signal,
139
+ intentHash: ctx.envelope.intentHash,
140
+ },
141
+ extraEvents: [
142
+ { kind: "tool_result", toolUseId: ctx.toolUseId, payload: result },
143
+ ],
144
+ };
145
+ }
146
+ }
147
+ }
148
+ /**
149
+ * Shared EXECUTE / REWRITE path. Runs the adopter's executor against the
150
+ * envelope passed in (the original for EXECUTE, the rewritten one for
151
+ * REWRITE), serializes the result, and returns a continue-loop translation.
152
+ */
153
+ async function runExecute(ctx, effectiveEnvelope, rewriteReason) {
154
+ let executorResult;
155
+ try {
156
+ executorResult = await ctx.executor.invokeIntent(effectiveEnvelope, ctx.state);
157
+ }
158
+ catch (err) {
159
+ const message = err instanceof Error ? err.message : "executor threw a non-Error value";
160
+ const errResult = {
161
+ toolUseId: ctx.toolUseId,
162
+ content: `Executor failed: ${message}`,
163
+ isError: true,
164
+ };
165
+ return {
166
+ toolResult: errResult,
167
+ loopAction: { kind: "continue" },
168
+ extraEvents: [
169
+ { kind: "tool_result", toolUseId: ctx.toolUseId, payload: errResult },
170
+ ],
171
+ };
172
+ }
173
+ const handlerEvent = {
174
+ kind: "handler_result",
175
+ toolUseId: ctx.toolUseId,
176
+ result: executorResult,
177
+ };
178
+ const body = rewriteReason === null
179
+ ? { ok: true, result: executorResult }
180
+ : {
181
+ ok: true,
182
+ result: executorResult,
183
+ note: `Note: kernel rewrote your proposal — ${rewriteReason}`,
184
+ };
185
+ const result = {
186
+ toolUseId: ctx.toolUseId,
187
+ content: JSON.stringify(body),
188
+ };
189
+ return {
190
+ toolResult: result,
191
+ loopAction: { kind: "continue" },
192
+ extraEvents: [
193
+ handlerEvent,
194
+ { kind: "tool_result", toolUseId: ctx.toolUseId, payload: result },
195
+ ],
196
+ };
197
+ }
198
+ /**
199
+ * Build the provider-neutral `ToolResultBlock` for an out-of-plan tool
200
+ * call. Re-exported so tests + adopters can construct one from outside
201
+ * the loop.
202
+ */
203
+ export function makeOutOfPlanToolResult(toolUseId, toolName) {
204
+ return {
205
+ toolUseId,
206
+ content: `Tool "${toolName}" is not available in the current plan.`,
207
+ isError: true,
208
+ };
209
+ }
210
+ export { AdapterError, AdapterErrorCode };
211
+ //# sourceMappingURL=decisions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decisions.js","sourceRoot":"","sources":["../src/decisions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Error taxonomy for the provider-neutral adapter loop.
3
+ *
4
+ * Most failures inside the loop become `isError: true` tool-results
5
+ * surfaced back to the model (so it can recover gracefully). Errors
6
+ * thrown out of the adapter are reserved for adopter-visible
7
+ * misconfiguration or contract violations.
8
+ */
9
+ export declare const AdapterErrorCode: {
10
+ readonly OUT_OF_PLAN_TOOL_USE: "OUT_OF_PLAN_TOOL_USE";
11
+ readonly EXECUTOR_FAILED: "EXECUTOR_FAILED";
12
+ readonly INVALID_PAYLOAD: "INVALID_PAYLOAD";
13
+ readonly MAX_ITERATIONS_EXCEEDED: "MAX_ITERATIONS_EXCEEDED";
14
+ readonly CONFIRMATION_TOKEN_INVALID: "CONFIRMATION_TOKEN_INVALID";
15
+ readonly RESUME_NO_PARKED: "RESUME_NO_PARKED";
16
+ };
17
+ export type AdapterErrorCode = (typeof AdapterErrorCode)[keyof typeof AdapterErrorCode];
18
+ export declare class AdapterError extends Error {
19
+ readonly code: AdapterErrorCode;
20
+ readonly details?: Record<string, unknown>;
21
+ constructor(code: AdapterErrorCode, message: string, details?: Record<string, unknown>);
22
+ }
23
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,eAAO,MAAM,gBAAgB;;;;;;;CAOnB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAC1B,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC;AAE3D,qBAAa,YAAa,SAAQ,KAAK;IACrC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAGzC,IAAI,EAAE,gBAAgB,EACtB,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;CAOpC"}
package/dist/errors.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Error taxonomy for the provider-neutral adapter loop.
3
+ *
4
+ * Most failures inside the loop become `isError: true` tool-results
5
+ * surfaced back to the model (so it can recover gracefully). Errors
6
+ * thrown out of the adapter are reserved for adopter-visible
7
+ * misconfiguration or contract violations.
8
+ */
9
+ export const AdapterErrorCode = {
10
+ OUT_OF_PLAN_TOOL_USE: "OUT_OF_PLAN_TOOL_USE",
11
+ EXECUTOR_FAILED: "EXECUTOR_FAILED",
12
+ INVALID_PAYLOAD: "INVALID_PAYLOAD",
13
+ MAX_ITERATIONS_EXCEEDED: "MAX_ITERATIONS_EXCEEDED",
14
+ CONFIRMATION_TOKEN_INVALID: "CONFIRMATION_TOKEN_INVALID",
15
+ RESUME_NO_PARKED: "RESUME_NO_PARKED",
16
+ };
17
+ export class AdapterError extends Error {
18
+ code;
19
+ details;
20
+ constructor(code, message, details) {
21
+ super(message);
22
+ this.name = "AdapterError";
23
+ this.code = code;
24
+ this.details = details;
25
+ }
26
+ }
27
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,oBAAoB,EAAE,sBAAsB;IAC5C,eAAe,EAAE,iBAAiB;IAClC,eAAe,EAAE,iBAAiB;IAClC,uBAAuB,EAAE,yBAAyB;IAClD,0BAA0B,EAAE,4BAA4B;IACxD,gBAAgB,EAAE,kBAAkB;CAC5B,CAAC;AAKX,MAAM,OAAO,YAAa,SAAQ,KAAK;IAC5B,IAAI,CAAmB;IACvB,OAAO,CAA2B;IAE3C,YACE,IAAsB,EACtB,OAAe,EACf,OAAiC;QAEjC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * `@adjudicate/adapter-core` — provider-neutral orchestration for
3
+ * adjudicate-backed LLM agents.
4
+ *
5
+ * The loop, bridge, decision translator, persistence shims, and error
6
+ * taxonomy live here. Provider adapters (`@adjudicate/anthropic`,
7
+ * `@adjudicate/openai`, …) implement a `ProviderBridge<H>` against
8
+ * their SDK and re-export a thin `createAdjudicatedAgent` that wires
9
+ * it into this loop.
10
+ *
11
+ * Invariants the loop preserves:
12
+ * - Every intent envelope crosses `adjudicateAndAudit()`. No bypass,
13
+ * no taint elevation, no guard-ordering short-circuit.
14
+ * - First non-continue Decision wins per assistant turn.
15
+ * - History `H` is opaque to the loop; the bridge owns its shape.
16
+ * - REWRITE executes the rewritten envelope, never the original.
17
+ * - DEFER persists full envelope fields so resume can re-derive the
18
+ * intentHash and detect tampering.
19
+ *
20
+ * Provider adapters MUST NOT bypass this loop. The kernel-side audit
21
+ * + ledger guarantees only hold when every adjudication flows here.
22
+ */
23
+ export { createAdjudicatedAgent } from "./loop.js";
24
+ export type { AdjudicatedAgent, AdjudicatedAgentOptions, AdopterExecutor, AgentEvent, AgentLogger, AgentOutcome, AgentTurnResult, AssistantTurn, ConfirmArgs, ProviderBridge, ProviderRequest, ResumeArgs, SendInput, ToolResultBlock, ToolUseRequest, } from "./types.js";
25
+ export { buildEnvelopeFromToolUse, classifyIncomingToolUse, intentKindToApiName, } from "./bridge.js";
26
+ export type { BuildEnvelopeFromToolUseArgs, ToolUseClassification, } from "./bridge.js";
27
+ export { makeOutOfPlanToolResult, translateDecision, } from "./decisions.js";
28
+ export type { DecisionTranslation, DecisionTranslationContext, LoopAction, } from "./decisions.js";
29
+ export { createInMemoryConfirmationStore, createInMemoryDeferStore, } from "./persistence.js";
30
+ export type { ConfirmationStore, DeferRedis, ParkRedis, PendingConfirmation, } from "./persistence.js";
31
+ export { createRedisConfirmationStore, type ConfirmationRedisClient, type CreateRedisConfirmationStoreOptions, } from "./persistence-redis.js";
32
+ export { noopTraceSink, createInMemoryTraceSink, type AdapterPauseReason, type AdapterTraceEvent, type AdapterTracePhase, type TraceSink, } from "./trace.js";
33
+ export { AdapterError, AdapterErrorCode } from "./errors.js";
34
+ /**
35
+ * In-memory Execution Ledger — re-export from `@adjudicate/audit` for
36
+ * zero-import-friction in tests, quickstarts, and local development.
37
+ *
38
+ * NOT for distributed or persistent production deployments. Production
39
+ * adopters wire `createRedisLedger` (or any backing store with SET-NX,
40
+ * EX, INCR, DECR) from `@adjudicate/audit`.
41
+ */
42
+ export { createMemoryLedger } from "@adjudicate/audit";
43
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AACnD,YAAY,EACV,gBAAgB,EAChB,uBAAuB,EACvB,eAAe,EACf,UAAU,EACV,WAAW,EACX,YAAY,EACZ,eAAe,EACf,aAAa,EACb,WAAW,EACX,cAAc,EACd,eAAe,EACf,UAAU,EACV,SAAS,EACT,eAAe,EACf,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,4BAA4B,EAC5B,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,mBAAmB,EACnB,0BAA0B,EAC1B,UAAU,GACX,MAAM,gBAAgB,CAAC;AAExB,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,iBAAiB,EACjB,UAAU,EACV,SAAS,EACT,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,4BAA4B,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,mCAAmC,GACzC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,SAAS,GACf,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE7D;;;;;;;GAOG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * `@adjudicate/adapter-core` — provider-neutral orchestration for
3
+ * adjudicate-backed LLM agents.
4
+ *
5
+ * The loop, bridge, decision translator, persistence shims, and error
6
+ * taxonomy live here. Provider adapters (`@adjudicate/anthropic`,
7
+ * `@adjudicate/openai`, …) implement a `ProviderBridge<H>` against
8
+ * their SDK and re-export a thin `createAdjudicatedAgent` that wires
9
+ * it into this loop.
10
+ *
11
+ * Invariants the loop preserves:
12
+ * - Every intent envelope crosses `adjudicateAndAudit()`. No bypass,
13
+ * no taint elevation, no guard-ordering short-circuit.
14
+ * - First non-continue Decision wins per assistant turn.
15
+ * - History `H` is opaque to the loop; the bridge owns its shape.
16
+ * - REWRITE executes the rewritten envelope, never the original.
17
+ * - DEFER persists full envelope fields so resume can re-derive the
18
+ * intentHash and detect tampering.
19
+ *
20
+ * Provider adapters MUST NOT bypass this loop. The kernel-side audit
21
+ * + ledger guarantees only hold when every adjudication flows here.
22
+ */
23
+ export { createAdjudicatedAgent } from "./loop.js";
24
+ export { buildEnvelopeFromToolUse, classifyIncomingToolUse, intentKindToApiName, } from "./bridge.js";
25
+ export { makeOutOfPlanToolResult, translateDecision, } from "./decisions.js";
26
+ export { createInMemoryConfirmationStore, createInMemoryDeferStore, } from "./persistence.js";
27
+ export { createRedisConfirmationStore, } from "./persistence-redis.js";
28
+ export { noopTraceSink, createInMemoryTraceSink, } from "./trace.js";
29
+ export { AdapterError, AdapterErrorCode } from "./errors.js";
30
+ /**
31
+ * In-memory Execution Ledger — re-export from `@adjudicate/audit` for
32
+ * zero-import-friction in tests, quickstarts, and local development.
33
+ *
34
+ * NOT for distributed or persistent production deployments. Production
35
+ * adopters wire `createRedisLedger` (or any backing store with SET-NX,
36
+ * EX, INCR, DECR) from `@adjudicate/audit`.
37
+ */
38
+ export { createMemoryLedger } from "@adjudicate/audit";
39
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAC;AAmBnD,OAAO,EACL,wBAAwB,EACxB,uBAAuB,EACvB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAMrB,OAAO,EACL,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAOxB,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,GACzB,MAAM,kBAAkB,CAAC;AAO1B,OAAO,EACL,4BAA4B,GAG7B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,aAAa,EACb,uBAAuB,GAKxB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE7D;;;;;;;GAOG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/loop.d.ts ADDED
@@ -0,0 +1,23 @@
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 type { AdjudicatedAgent, AdjudicatedAgentOptions } from "./types.js";
22
+ export declare function createAdjudicatedAgent<K extends string, P, S, C, H>(options: AdjudicatedAgentOptions<K, P, S, C, H>): AdjudicatedAgent<K, P, S, C, H>;
23
+ //# sourceMappingURL=loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAqBH,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EAQxB,MAAM,YAAY,CAAC;AAIpB,wBAAgB,sBAAsB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EACjE,OAAO,EAAE,uBAAuB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAC9C,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CA8djC"}