@coderifts/agent-guard 4.2.0 → 5.0.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.
Files changed (56) hide show
  1. package/README.md +180 -35
  2. package/dist/cjs/adapters/anthropic.d.ts +90 -0
  3. package/dist/cjs/adapters/anthropic.d.ts.map +1 -0
  4. package/dist/cjs/adapters/anthropic.js +97 -0
  5. package/dist/cjs/adapters/anthropic.js.map +1 -0
  6. package/dist/cjs/adapters/gemini.d.ts +114 -0
  7. package/dist/cjs/adapters/gemini.d.ts.map +1 -0
  8. package/dist/cjs/adapters/gemini.js +110 -0
  9. package/dist/cjs/adapters/gemini.js.map +1 -0
  10. package/dist/cjs/adapters/langgraph.d.ts +117 -0
  11. package/dist/cjs/adapters/langgraph.d.ts.map +1 -0
  12. package/dist/cjs/adapters/langgraph.js +113 -0
  13. package/dist/cjs/adapters/langgraph.js.map +1 -0
  14. package/dist/cjs/adapters/openai.d.ts +93 -0
  15. package/dist/cjs/adapters/openai.d.ts.map +1 -0
  16. package/dist/cjs/adapters/openai.js +97 -0
  17. package/dist/cjs/adapters/openai.js.map +1 -0
  18. package/dist/cjs/final-answer-proof.d.ts +80 -0
  19. package/dist/cjs/final-answer-proof.d.ts.map +1 -0
  20. package/dist/cjs/final-answer-proof.js +222 -0
  21. package/dist/cjs/final-answer-proof.js.map +1 -0
  22. package/dist/cjs/guard.d.ts.map +1 -1
  23. package/dist/cjs/guard.js +5 -1
  24. package/dist/cjs/guard.js.map +1 -1
  25. package/dist/cjs/index.d.ts +10 -0
  26. package/dist/cjs/index.d.ts.map +1 -1
  27. package/dist/cjs/index.js +33 -2
  28. package/dist/cjs/index.js.map +1 -1
  29. package/dist/esm/adapters/anthropic.d.ts +90 -0
  30. package/dist/esm/adapters/anthropic.d.ts.map +1 -0
  31. package/dist/esm/adapters/anthropic.js +91 -0
  32. package/dist/esm/adapters/anthropic.js.map +1 -0
  33. package/dist/esm/adapters/gemini.d.ts +114 -0
  34. package/dist/esm/adapters/gemini.d.ts.map +1 -0
  35. package/dist/esm/adapters/gemini.js +104 -0
  36. package/dist/esm/adapters/gemini.js.map +1 -0
  37. package/dist/esm/adapters/langgraph.d.ts +117 -0
  38. package/dist/esm/adapters/langgraph.d.ts.map +1 -0
  39. package/dist/esm/adapters/langgraph.js +107 -0
  40. package/dist/esm/adapters/langgraph.js.map +1 -0
  41. package/dist/esm/adapters/openai.d.ts +93 -0
  42. package/dist/esm/adapters/openai.d.ts.map +1 -0
  43. package/dist/esm/adapters/openai.js +91 -0
  44. package/dist/esm/adapters/openai.js.map +1 -0
  45. package/dist/esm/final-answer-proof.d.ts +80 -0
  46. package/dist/esm/final-answer-proof.d.ts.map +1 -0
  47. package/dist/esm/final-answer-proof.js +217 -0
  48. package/dist/esm/final-answer-proof.js.map +1 -0
  49. package/dist/esm/guard.d.ts.map +1 -1
  50. package/dist/esm/guard.js +5 -1
  51. package/dist/esm/guard.js.map +1 -1
  52. package/dist/esm/index.d.ts +10 -0
  53. package/dist/esm/index.d.ts.map +1 -1
  54. package/dist/esm/index.js +12 -0
  55. package/dist/esm/index.js.map +1 -1
  56. package/package.json +2 -2
package/README.md CHANGED
@@ -89,6 +89,124 @@ const { tools, registry_report, composition_assurance } = withCodeRifts({
89
89
  // the guard — the composition can only protect the table it returns.
90
90
  ```
91
91
 
92
+ ### Final-answer proof block (ID645)
93
+
94
+ When a call produces a machine `GuardExecutionProof` (`outcome.proof`), you can embed a
95
+ **human-readable** block in the agent’s final answer. The renderer is faithful: `currently_authorized: null`
96
+ is **SKIPPED (not a pass)**; limits (e.g. host can still bypass; calls outside the guarded path are
97
+ invisible) always appear. It does not change the proof shape.
98
+
99
+ ```typescript
100
+ import { renderFinalAnswerProof, attachProofToAgentResponse } from '@coderifts/agent-guard';
101
+
102
+ // After guardToolCall / withCodeRifts …
103
+ const block = renderFinalAnswerProof(outcome.proof); // markdown string
104
+ const answer = attachProofToAgentResponse('I applied the authorized edit.', outcome.proof);
105
+ // string → appends block; object → adds final_answer_proof + final_answer_proof_text
106
+ ```
107
+
108
+ See `examples/final-answer-proof.mjs` for verified vs skipped side by side.
109
+
110
+ **OpenAI tool-calling (ID632 reference adapter).** Same input; OpenAI-shaped `tools` for
111
+ `chat.completions`, plus the same unflattened assurance objects. Shape conversion only — does
112
+ **not** claim product-level inescapability the core does not:
113
+
114
+ ```typescript
115
+ import { withCodeRiftsOpenAI } from '@coderifts/agent-guard';
116
+
117
+ const {
118
+ tools, // OpenAI: [{ type:'function', function:{ name, description?, parameters } }]
119
+ protected_tools, // guarded execute — dispatch tool_calls here, never re-register rawTools
120
+ registry_report,
121
+ composition_assurance, // still may be incomplete (inescapable_runtime:false) — do not drop
122
+ receipt_thread,
123
+ } = withCodeRiftsOpenAI({ tools: rawTools, client, operation: 'merge' });
124
+
125
+ // openai.chat.completions.create({ model, messages, tools })
126
+ // Host boundary: only `tools` / `protected_tools` enter the model loop — raw tools stay out.
127
+ ```
128
+
129
+ See also `examples/openai-adapter.mjs` (not published in the npm tarball).
130
+
131
+ **OpenAI-compatible models (no extra adapter).** DeepSeek, Kimi (Moonshot), and Qwen use the
132
+ same ChatCompletions tool-calling format as OpenAI (`{ type: 'function', function: { name,
133
+ description, parameters } }`). Use **`withCodeRiftsOpenAI`** and point your client `baseURL`
134
+ (and API key) at their endpoint — zero new adapters, same guarded tools + unflattened assurance.
135
+
136
+ **Grok (xAI).** Also OpenAI-compatible tool calling — use **`withCodeRiftsOpenAI`** with the xAI `baseURL`.
137
+
138
+ **Perplexity (Sonar).** OpenAI-compatible chat completions, but tool calling is model-dependent: `sonar-pro` supports it (with a stricter JSON-object parameter schema), while plain `sonar` rejects tool definitions. Use **`withCodeRiftsOpenAI`** with tool-capable Perplexity models only.
139
+
140
+ **Anthropic tool_use (ID632 slice 2).** Same thin pattern; Anthropic Messages `tools` shape
141
+ (`{ name, description?, input_schema }`) instead of OpenAI function tools. Assurance still
142
+ unflattened — composition may remain incomplete:
143
+
144
+ ```typescript
145
+ import { withCodeRiftsAnthropic } from '@coderifts/agent-guard';
146
+
147
+ const {
148
+ tools, // Anthropic: [{ name, description?, input_schema }]
149
+ protected_tools, // guarded execute — dispatch tool_use here, never re-register rawTools
150
+ registry_report,
151
+ composition_assurance, // still may be incomplete (inescapable_runtime:false) — do not drop
152
+ receipt_thread,
153
+ } = withCodeRiftsAnthropic({ tools: rawTools, client, operation: 'merge' });
154
+
155
+ // anthropic.messages.create({ model, messages, tools, max_tokens })
156
+ // Host boundary: only `tools` / `protected_tools` enter the model loop — raw tools stay out.
157
+ ```
158
+
159
+ See also `examples/anthropic-adapter.mjs` (not published in the npm tarball).
160
+
161
+ **LangChain / LangGraph (ID632 slice 3).** Same thin pattern; emits **dependency-free** plain
162
+ descriptors the host can hand to LangChain `tool()` / LangGraph `ToolNode` / `bind_tools`. This
163
+ package does **not** depend on langchain or langgraph — the host owns those imports. Assurance
164
+ still unflattened:
165
+
166
+ ```typescript
167
+ import { withCodeRiftsLangGraph } from '@coderifts/agent-guard';
168
+ // host-owned (not a dependency of this package):
169
+ // import { tool } from '@langchain/core/tools';
170
+ // import { ToolNode } from '@langchain/langgraph/prebuilt';
171
+
172
+ const {
173
+ tools, // [{ name, description?, schema, func, invoke }] — guarded execute bound
174
+ protected_tools,
175
+ registry_report,
176
+ composition_assurance, // still may be incomplete (inescapable_runtime:false) — do not drop
177
+ receipt_thread,
178
+ } = withCodeRiftsLangGraph({ tools: rawTools, client, operation: 'merge' });
179
+
180
+ // const lcTools = tools.map((d) =>
181
+ // tool(d.func, { name: d.name, description: d.description, schema: d.schema }),
182
+ // );
183
+ // const toolNode = new ToolNode(lcTools); // StateGraph … .addNode('tools', toolNode)
184
+ // Host boundary: only `tools` / `protected_tools` enter the graph — raw tools stay out.
185
+ ```
186
+
187
+ See also `examples/langgraph-adapter.mjs` (not published in the npm tarball).
188
+
189
+ **Google Gemini (ID632 slice 4).** Same thin pattern; Gemini nests **all** tools under one
190
+ `functionDeclarations` array (not one OpenAI-style `{ type: 'function' }` per tool). Assurance
191
+ still unflattened:
192
+
193
+ ```typescript
194
+ import { withCodeRiftsGemini } from '@coderifts/agent-guard';
195
+
196
+ const {
197
+ tools, // Gemini: [{ functionDeclarations: [{ name, description?, parameters }, …] }]
198
+ protected_tools, // guarded execute — dispatch functionCall here, never re-register rawTools
199
+ registry_report,
200
+ composition_assurance, // still may be incomplete (inescapable_runtime:false) — do not drop
201
+ receipt_thread,
202
+ } = withCodeRiftsGemini({ tools: rawTools, client, operation: 'merge' });
203
+
204
+ // model.generateContent({ contents, tools })
205
+ // Host boundary: only `tools` / `protected_tools` enter the model loop — raw tools stay out.
206
+ ```
207
+
208
+ See also `examples/gemini-adapter.mjs` (not published in the npm tarball).
209
+
92
210
  **Why `operation` is mandatory (no default).** Receipts bind to an operation and `merge` is not
93
211
  `deploy`, so a silent default would evaluate a deployment under merge semantics. `operation` is the
94
212
  session-level default for **generic** mutating tools only; a tool with a specialised mutation class
@@ -123,10 +241,13 @@ mutating tools):
123
241
  `withCodeRifts` passes it through **untouched**.
124
242
  - **`composition_assurance`** is the narrower, product-level statement — what `withCodeRifts` itself
125
243
  claims. Today it reports `PARTIAL` with `inescapable_runtime: false` and the residual
126
- `composition_call_policy_incomplete`, because composition-level completeness still needs more than
127
- tool wrapping: receipt carry-forward, and a freshness-safe prior for write-style calls (path + new
128
- content only). Call-time STOP on BLOCK/RA is already on the frozen path; both-sides edit binders
129
- (old_string/new_string, edits[]) are already shipped neither alone flips this residual off.
244
+ `composition_call_policy_incomplete`, because **composition-call-policy completeness**
245
+ (`COMPOSITION_CALL_POLICY_COMPLETE`) is still false not because tool wrapping or receipt
246
+ carry-forward are missing. Receipt carry-forward **ships** (per-composition cursor, `threadReceipts`
247
+ default on). Call-time STOP on BLOCK/RA and both-sides edit binders are already on the frozen path.
248
+ What still blocks the product-level claim includes a **freshness-safe prior for write-style calls**
249
+ (path + new content only) wired into enforce, among other policy gates — carry-forward alone does
250
+ not flip this residual off.
130
251
  - **This is deliberate, not a defect.** The composition will not claim runtime inescapability it cannot
131
252
  yet deliver.
132
253
 
@@ -136,17 +257,19 @@ does not weaken it. `composition_assurance` answers a *different* question: not
136
257
  wrapped" (true today) but "is the whole execution path through this composition inescapable yet" (not
137
258
  yet). The composition says so rather than borrowing the registry's answer.
138
259
 
139
- **What you get today:** one entry point, every mutator in the returned table wrapped fail-closed, and an
140
- honest composition statement. **What you do not get yet:** any product-level claim of runtime
141
- inescapability `composition_assurance.inescapable_runtime` stays `false` until receipt carry-forward
142
- and a freshness-safe prior for write-style calls (path + new content only) land. Both-sides edit
143
- binders already shipped; they do not complete that claim alone.
260
+ **What you get today:** one entry point, every mutator in the returned table wrapped fail-closed,
261
+ automatic receipt carry-forward on by default, and an honest composition statement. **What you do not
262
+ get yet:** any product-level claim of runtime inescapability —
263
+ `composition_assurance.inescapable_runtime` stays `false` while **composition-call-policy** remains
264
+ incomplete (`COMPOSITION_CALL_POLICY_COMPLETE` is false). That is **not** because carry-forward is
265
+ missing (it ships). A green construction is still **not** a product-level runtime-inescapability
266
+ guarantee.
144
267
 
145
268
  **`requireCoverage?` (optional).** Aborts construction when the **registry** coverage is weaker than
146
269
  required, by the ordering `COMPLETE > PARTIAL > BYPASSED > UNKNOWN`. It constrains the **registry surface
147
- only** — it **cannot** demand product-level inescapability (still blocked on receipt carry-forward and
148
- write-style prior content, not on registry wrapping), and a green construction under it is not a
149
- product-level enforcement guarantee.
270
+ only** — it **cannot** demand product-level inescapability (still gated on composition-call-policy
271
+ completeness, not on registry wrapping or on whether carry-forward is enabled), and a green
272
+ construction under it is not a product-level enforcement guarantee.
150
273
 
151
274
  **`unknownToolPolicy` defaults to `'mutating'`.** An unclassified tool (no `mutationClass`, no
152
275
  name-heuristic match) is treated as a mutator and wrapped — never silently downgraded to readonly, which
@@ -164,8 +287,11 @@ change it.
164
287
  artifacts when a contract path is present — it does **not** invent a `before` for write-style
165
288
  path+new-content-only calls (no IO; empty before is forbidden).
166
289
 
167
- **Not in this yet** (do not infer these from the one-call ergonomics): receipt carry-forward,
168
- freshness-safe prior content for write-style calls, and framework adapters.
290
+ **Not in this yet** (do not infer these from the one-call ergonomics): freshness-safe prior content
291
+ for write-style calls wired into enforce (path + new content only — pure core may exist; product
292
+ path is incomplete), platform-native bypass exclusion, a concurrent receipt manager (overlap
293
+ refuses to advance the package cursor — host owns serialisation if a linear chain is required), and
294
+ framework adapters. **Receipt carry-forward is shipped** (see below); do not list it as missing.
169
295
 
170
296
  #### `composition_assurance` is the runtime placement input
171
297
 
@@ -359,48 +485,67 @@ Neither replaces the other. Lifecycle crumbs ≠ full settle record; settle reco
359
485
  - A throwing `onSettledCall` does not break the call; a **returned rejected promise** is handled (not left unhandled).
360
486
  - If the tool/`guardToolCall` path **rejects**, the rejection **propagates** after the THREW observation fires — no fake GuardOutcome is invented on that arm.
361
487
 
362
- ### Receipt chaining (optional, host-threaded no package cursor)
488
+ ### Receipt chaining (package cursor default-on; host may override)
363
489
 
364
490
  The signed receipt body has always carried a **previous-receipt** field (`prev`): the issuer stores
365
491
  the literal `null` when no prior token was supplied, or `sha256:`+hex of the prior token when the
366
492
  preflight request included `previous_receipt`. That makes **hash-linked sequences** possible.
367
- Historically the guard sent `previous_receipt: undefined` on every call, so every receipt was a
368
- root. Chaining is now **possible**, not automatic.
369
493
 
370
- **How to thread a prior (host-owned):**
494
+ **Package-level composition cursor (shipped, default on):** `withCodeRifts` keeps a **per-composition-
495
+ instance** receipt cursor. With `threadReceipts` defaulting to **true** (`threadReceipts !== false`),
496
+ each enforced+receipt-verified guarded call can advance that cursor and supply it as
497
+ `previous_receipt` on the next preflight for the same composition. Opt out with
498
+ `threadReceipts: false` (every call is then a root unless the host threads manually). This is **not**
499
+ process/session global; it is one cursor per `withCodeRifts` result. The package does **not** verify
500
+ signatures or self-attest chain authenticity — re-run `verifyReceiptChainLinkage` (and signature
501
+ verify) on tokens you export if you need product truth.
502
+
503
+ **Host override (always wins):** `previousReceipt` on the composition (string or getter) overrides the
504
+ package cursor at resolve time when set — use it to inject a prior the composition does not hold.
371
505
 
372
506
  ```typescript
507
+ // Default: automatic carry-forward for this composition (threadReceipts defaults true).
508
+ const { tools, receipt_thread } = withCodeRifts({
509
+ tools: rawTools,
510
+ client,
511
+ operation: 'merge',
512
+ });
513
+ // receipt_thread.enabled === true; receipt_thread.lastToken() after settled guarded calls.
514
+
515
+ // Opt out of the package cursor:
516
+ const { tools: t2 } = withCodeRifts({
517
+ tools: rawTools,
518
+ client,
519
+ operation: 'merge',
520
+ threadReceipts: false,
521
+ });
522
+
523
+ // Host-owned prior (overrides the package cursor when both exist):
373
524
  let lastToken: string | undefined;
374
- const { tools } = withCodeRifts({
525
+ const { tools: t3 } = withCodeRifts({
375
526
  tools: rawTools,
376
527
  client,
377
528
  operation: 'merge',
378
- // Read on each preflight; the package does not store or advance this value.
379
529
  previousReceipt: () => lastToken,
380
530
  onSettledCall: (o) => {
381
- // Advance the chain only on a GUARDED return that carries a receipt token.
382
531
  if (o.kind !== 'settled_call' || o.route !== 'GUARDED' || o.terminal !== 'RETURNED') return;
383
532
  const v = o.outcome.verdict;
384
533
  if (v && 'envelope' in v && v.envelope?.receipt?.token) {
385
- lastToken = v.envelope.receipt.token; // host advances the cursor
534
+ lastToken = v.envelope.receipt.token;
386
535
  }
387
536
  },
388
537
  });
389
538
  ```
390
539
 
391
- The same field exists on `GuardConfig` for direct `guardToolCall` / `guardToolRegistry` use
392
- (`previousReceipt?: string | (() => string | undefined | null)`). A plain string works if the host
393
- mutates it between calls; a getter is preferred so the package never looks like it owns the value.
394
-
395
- **Concurrency (serial only for a linear chain):** The getter/`onSettledCall` pattern above is correct
396
- when guarded contract calls run **one after another**. Modern agents often issue **overlapping** tool
397
- calls. `onSettledCall` runs **after** a call settles, so two preflights in flight can both read the
398
- same `lastToken` before either advances it. The issuer then produces two children of one parent —
399
- a **forest**, not a single linear chain. The package holds nothing, so it cannot serialise that
400
- advance; **the host owns the ordering rule**. If you need a linear chain under concurrency, you
401
- must serialise your own advance (no package mutex or queue is provided). Symptom of treating a
402
- fork as a line: `verifyReceiptChainLinkage` reports `broken_link` on a sequence you believed was
403
- linear, with no other explanation in the tokens themselves.
540
+ The same `previousReceipt` field exists on `GuardConfig` for direct `guardToolCall` /
541
+ `guardToolRegistry` use (`previousReceipt?: string | (() => string | undefined | null)`).
542
+
543
+ **Concurrency (serial only for a linear chain):** Automatic advance is correct when guarded contract
544
+ calls run **one after another**. Overlapping tool calls can race; the package **refuses to advance**
545
+ the composition cursor under overlap rather than inventing a concurrent receipt manager. If you need
546
+ a linear chain under concurrency, **the host owns the ordering rule** (no package mutex or queue).
547
+ Symptom of treating a fork as a line: `verifyReceiptChainLinkage` reports `broken_link` on a
548
+ sequence you believed was linear, with no other explanation in the tokens themselves.
404
549
 
405
550
  **Offline linkage check (not signature verification):**
406
551
 
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Anthropic tool_use adapter over withCodeRifts (ID632 slice 2 — same thin pattern as OpenAI).
3
+ *
4
+ * Thin SHAPE converter only. Guard logic stays in withCodeRifts; this module:
5
+ * 1. calls withCodeRifts with the same input shape,
6
+ * 2. maps each ProtectedTool → Anthropic Messages API tool definition,
7
+ * 3. returns Anthropic-shaped tools PLUS the untouched assurance objects
8
+ * (registry_report, composition_assurance, receipt_thread).
9
+ *
10
+ * Honesty (do not "upgrade" assurance):
11
+ * - composition_assurance is passed through EXACTLY as the core reported it
12
+ * (COMPOSITION_CALL_POLICY_COMPLETE may still be false; inescapable_runtime may be false).
13
+ * - The adapter converts tool SHAPE for the model API; it does not claim product-level
14
+ * inescapability the core does not claim.
15
+ *
16
+ * Only-protected-tools (6/D at the adapter surface):
17
+ * - `tools` is derived ONLY from the frozen registry's ProtectedTool list.
18
+ * - Raw tools never appear in the returned Anthropic table. The host may still hold a raw
19
+ * reference outside this table; that boundary stays the host's responsibility.
20
+ *
21
+ * Ergonomics (5–10 lines): pass raw tools + client + operation → Anthropic-ready guarded tools.
22
+ * Mirrors src/adapters/openai.ts — only the target tool shape differs.
23
+ */
24
+ import type { WithCodeRiftsInput, WithCodeRiftsResult, CompositionAssurance, ReceiptThreadHandle } from '../with-coderifts.js';
25
+ import type { ProtectedTool, RegistryCoverageReport } from '../tool-registry.js';
26
+ /**
27
+ * Anthropic Messages API `tools[]` element (tool_use definition).
28
+ * @see https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview
29
+ */
30
+ export type AnthropicTool = {
31
+ name: string;
32
+ description?: string;
33
+ /** JSON Schema object for the tool input (Anthropic `input_schema`). */
34
+ input_schema: Record<string, unknown>;
35
+ };
36
+ /**
37
+ * Result of withCodeRiftsAnthropic — Anthropic tool definitions + core assurance, unflattened.
38
+ *
39
+ * `tools` is the ONLY list intended for the model/runtime tool table. `protected_tools` is the
40
+ * same guarded list (with execute) for host dispatch after tool_use blocks — never the raw tools.
41
+ */
42
+ export type WithCodeRiftsAnthropicResult = {
43
+ /** Anthropic-shaped tools for messages.create — only protected/guarded tools. */
44
+ tools: AnthropicTool[];
45
+ /**
46
+ * Guarded ProtectedTool list from withCodeRifts (same tools as `tools`, with execute).
47
+ * Host dispatches model tool_use through these only. Never raw tools.
48
+ */
49
+ protected_tools: ProtectedTool[];
50
+ /** Untouched registry report — registry's own truth. */
51
+ registry_report: RegistryCoverageReport;
52
+ /**
53
+ * Product-level assurance — deliberately narrower than the registry.
54
+ * Passed through untouched; may still show inescapable_runtime:false and
55
+ * residual composition_call_policy_incomplete.
56
+ */
57
+ composition_assurance: CompositionAssurance;
58
+ /** Per-composition receipt cursor — NOT product-truth chain evidence. */
59
+ receipt_thread: ReceiptThreadHandle;
60
+ repository?: string;
61
+ };
62
+ /**
63
+ * Map one ProtectedTool → Anthropic tool definition (shape only; no execute).
64
+ * Prefer tool.inputSchema when it is a plain object; otherwise empty object schema.
65
+ */
66
+ export declare function protectedToolToAnthropic(tool: ProtectedTool): AnthropicTool;
67
+ /**
68
+ * Convert a list of ProtectedTool into Anthropic tool definitions.
69
+ * Does NOT call the guard — pure shape map over an already-protected list.
70
+ */
71
+ export declare function toAnthropicTools(protectedTools: readonly ProtectedTool[]): AnthropicTool[];
72
+ /**
73
+ * Build Anthropic-ready guarded tools from raw tools + client + operation.
74
+ *
75
+ * Calls withCodeRifts internally (guard logic stays in the core). Returns:
76
+ * - `tools` — Anthropic messages API shape ({ name, description?, input_schema })
77
+ * - `protected_tools` — same guarded tools for host execute dispatch
78
+ * - assurance objects from the core, passed through untouched
79
+ *
80
+ * @param input Same shape as withCodeRifts (WithCodeRiftsInput).
81
+ */
82
+ export declare function withCodeRiftsAnthropic(input: WithCodeRiftsInput): WithCodeRiftsAnthropicResult;
83
+ /**
84
+ * Shape-only adapter over an existing WithCodeRiftsResult (composition style).
85
+ * Prefer withCodeRiftsAnthropic when starting from raw tools.
86
+ *
87
+ * Does not re-run the guard; does not invent assurance.
88
+ */
89
+ export declare function anthropicToolAdapter(result: WithCodeRiftsResult): WithCodeRiftsAnthropicResult;
90
+ //# sourceMappingURL=anthropic.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.d.ts","sourceRoot":"","sources":["../../../src/adapters/anthropic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAGH,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAEjF;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,4BAA4B,GAAG;IACzC,iFAAiF;IACjF,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB;;;OAGG;IACH,eAAe,EAAE,aAAa,EAAE,CAAC;IACjC,wDAAwD;IACxD,eAAe,EAAE,sBAAsB,CAAC;IACxC;;;;OAIG;IACH,qBAAqB,EAAE,oBAAoB,CAAC;IAC5C,yEAAyE;IACzE,cAAc,EAAE,mBAAmB,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAQF;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,aAAa,GAAG,aAAa,CAgB3E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,cAAc,EAAE,SAAS,aAAa,EAAE,GAAG,aAAa,EAAE,CAE1F;AAED;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,GAAG,4BAA4B,CAG9F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,mBAAmB,GAAG,4BAA4B,CAc9F"}
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+ /**
3
+ * Anthropic tool_use adapter over withCodeRifts (ID632 slice 2 — same thin pattern as OpenAI).
4
+ *
5
+ * Thin SHAPE converter only. Guard logic stays in withCodeRifts; this module:
6
+ * 1. calls withCodeRifts with the same input shape,
7
+ * 2. maps each ProtectedTool → Anthropic Messages API tool definition,
8
+ * 3. returns Anthropic-shaped tools PLUS the untouched assurance objects
9
+ * (registry_report, composition_assurance, receipt_thread).
10
+ *
11
+ * Honesty (do not "upgrade" assurance):
12
+ * - composition_assurance is passed through EXACTLY as the core reported it
13
+ * (COMPOSITION_CALL_POLICY_COMPLETE may still be false; inescapable_runtime may be false).
14
+ * - The adapter converts tool SHAPE for the model API; it does not claim product-level
15
+ * inescapability the core does not claim.
16
+ *
17
+ * Only-protected-tools (6/D at the adapter surface):
18
+ * - `tools` is derived ONLY from the frozen registry's ProtectedTool list.
19
+ * - Raw tools never appear in the returned Anthropic table. The host may still hold a raw
20
+ * reference outside this table; that boundary stays the host's responsibility.
21
+ *
22
+ * Ergonomics (5–10 lines): pass raw tools + client + operation → Anthropic-ready guarded tools.
23
+ * Mirrors src/adapters/openai.ts — only the target tool shape differs.
24
+ */
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.protectedToolToAnthropic = protectedToolToAnthropic;
27
+ exports.toAnthropicTools = toAnthropicTools;
28
+ exports.withCodeRiftsAnthropic = withCodeRiftsAnthropic;
29
+ exports.anthropicToolAdapter = anthropicToolAdapter;
30
+ const with_coderifts_js_1 = require("../with-coderifts.js");
31
+ /** Empty JSON Schema object — used when a ProtectedTool has no inputSchema. */
32
+ const EMPTY_INPUT_SCHEMA = Object.freeze({
33
+ type: 'object',
34
+ properties: {},
35
+ });
36
+ /**
37
+ * Map one ProtectedTool → Anthropic tool definition (shape only; no execute).
38
+ * Prefer tool.inputSchema when it is a plain object; otherwise empty object schema.
39
+ */
40
+ function protectedToolToAnthropic(tool) {
41
+ const input_schema = tool.inputSchema != null
42
+ && typeof tool.inputSchema === 'object'
43
+ && !Array.isArray(tool.inputSchema)
44
+ ? tool.inputSchema
45
+ : { ...EMPTY_INPUT_SCHEMA };
46
+ const out = {
47
+ name: tool.name,
48
+ input_schema,
49
+ };
50
+ if (tool.description != null && tool.description !== '') {
51
+ out.description = tool.description;
52
+ }
53
+ return out;
54
+ }
55
+ /**
56
+ * Convert a list of ProtectedTool into Anthropic tool definitions.
57
+ * Does NOT call the guard — pure shape map over an already-protected list.
58
+ */
59
+ function toAnthropicTools(protectedTools) {
60
+ return protectedTools.map(protectedToolToAnthropic);
61
+ }
62
+ /**
63
+ * Build Anthropic-ready guarded tools from raw tools + client + operation.
64
+ *
65
+ * Calls withCodeRifts internally (guard logic stays in the core). Returns:
66
+ * - `tools` — Anthropic messages API shape ({ name, description?, input_schema })
67
+ * - `protected_tools` — same guarded tools for host execute dispatch
68
+ * - assurance objects from the core, passed through untouched
69
+ *
70
+ * @param input Same shape as withCodeRifts (WithCodeRiftsInput).
71
+ */
72
+ function withCodeRiftsAnthropic(input) {
73
+ const core = (0, with_coderifts_js_1.withCodeRifts)(input);
74
+ return anthropicToolAdapter(core);
75
+ }
76
+ /**
77
+ * Shape-only adapter over an existing WithCodeRiftsResult (composition style).
78
+ * Prefer withCodeRiftsAnthropic when starting from raw tools.
79
+ *
80
+ * Does not re-run the guard; does not invent assurance.
81
+ */
82
+ function anthropicToolAdapter(result) {
83
+ const protected_tools = result.tools;
84
+ const tools = toAnthropicTools(protected_tools);
85
+ const out = {
86
+ tools,
87
+ protected_tools,
88
+ registry_report: result.registry_report,
89
+ composition_assurance: result.composition_assurance,
90
+ receipt_thread: result.receipt_thread,
91
+ };
92
+ if (result.repository !== undefined) {
93
+ out.repository = result.repository;
94
+ }
95
+ return out;
96
+ }
97
+ //# sourceMappingURL=anthropic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anthropic.js","sourceRoot":"","sources":["../../../src/adapters/anthropic.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;;AA2DH,4DAgBC;AAMD,4CAEC;AAYD,wDAGC;AAQD,oDAcC;AAtHD,4DAAqD;AA+CrD,+EAA+E;AAC/E,MAAM,kBAAkB,GAA4B,MAAM,CAAC,MAAM,CAAC;IAChE,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE,EAAE;CACf,CAAC,CAAC;AAEH;;;GAGG;AACH,SAAgB,wBAAwB,CAAC,IAAmB;IAC1D,MAAM,YAAY,GAChB,IAAI,CAAC,WAAW,IAAI,IAAI;WACrB,OAAO,IAAI,CAAC,WAAW,KAAK,QAAQ;WACpC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;QACjC,CAAC,CAAE,IAAI,CAAC,WAAuC;QAC/C,CAAC,CAAC,EAAE,GAAG,kBAAkB,EAAE,CAAC;IAEhC,MAAM,GAAG,GAAkB;QACzB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,YAAY;KACb,CAAC;IACF,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,IAAI,IAAI,CAAC,WAAW,KAAK,EAAE,EAAE,CAAC;QACxD,GAAG,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC;IACrC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;GAGG;AACH,SAAgB,gBAAgB,CAAC,cAAwC;IACvE,OAAO,cAAc,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;AACtD,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,sBAAsB,CAAC,KAAyB;IAC9D,MAAM,IAAI,GAAwB,IAAA,iCAAa,EAAC,KAAK,CAAC,CAAC;IACvD,OAAO,oBAAoB,CAAC,IAAI,CAAC,CAAC;AACpC,CAAC;AAED;;;;;GAKG;AACH,SAAgB,oBAAoB,CAAC,MAA2B;IAC9D,MAAM,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC;IACrC,MAAM,KAAK,GAAG,gBAAgB,CAAC,eAAe,CAAC,CAAC;IAChD,MAAM,GAAG,GAAiC;QACxC,KAAK;QACL,eAAe;QACf,eAAe,EAAE,MAAM,CAAC,eAAe;QACvC,qBAAqB,EAAE,MAAM,CAAC,qBAAqB;QACnD,cAAc,EAAE,MAAM,CAAC,cAAc;KACtC,CAAC;IACF,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACpC,GAAG,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IACrC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Google Gemini function-calling adapter over withCodeRifts (ID632 slice 4 —
3
+ * same thin pattern as OpenAI / Anthropic / LangGraph).
4
+ *
5
+ * Thin SHAPE converter only. Guard logic stays in withCodeRifts; this module:
6
+ * 1. calls withCodeRifts with the same input shape,
7
+ * 2. maps ProtectedTool[] → Gemini generateContent tools shape,
8
+ * 3. returns Gemini-shaped tools PLUS the untouched assurance objects
9
+ * (registry_report, composition_assurance, receipt_thread).
10
+ *
11
+ * Gemini nesting (differs from OpenAI):
12
+ * tools: [ { functionDeclarations: [ { name, description?, parameters }, … ] } ]
13
+ * One tools entry wraps ALL declarations in a single functionDeclarations array —
14
+ * not one { type: 'function' } object per tool.
15
+ *
16
+ * Honesty (do not "upgrade" assurance):
17
+ * - composition_assurance is passed through EXACTLY as the core reported it
18
+ * (COMPOSITION_CALL_POLICY_COMPLETE may still be false; inescapable_runtime may be false).
19
+ * - The adapter converts tool SHAPE for the model API; it does not claim product-level
20
+ * inescapability the core does not claim.
21
+ *
22
+ * Only-protected-tools (6/D at the adapter surface):
23
+ * - `tools` is derived ONLY from the frozen registry's ProtectedTool list.
24
+ * - Raw tools never appear in the returned Gemini table. The host may still hold a raw
25
+ * reference outside this table; that boundary stays the host's responsibility.
26
+ *
27
+ * Ergonomics (5–10 lines): pass raw tools + client + operation → Gemini-ready tools.
28
+ * Mirrors src/adapters/openai.ts — only the target tool shape differs.
29
+ */
30
+ import type { WithCodeRiftsInput, WithCodeRiftsResult, CompositionAssurance, ReceiptThreadHandle } from '../with-coderifts.js';
31
+ import type { ProtectedTool, RegistryCoverageReport } from '../tool-registry.js';
32
+ /**
33
+ * One Gemini function declaration (inside functionDeclarations[]).
34
+ * @see https://ai.google.dev/gemini-api/docs/function-calling
35
+ */
36
+ export type GeminiFunctionDeclaration = {
37
+ name: string;
38
+ description?: string;
39
+ /**
40
+ * OpenAPI-like JSON Schema for function parameters
41
+ * (Gemini `parameters` — from ProtectedTool.inputSchema).
42
+ */
43
+ parameters: Record<string, unknown>;
44
+ };
45
+ /**
46
+ * Gemini `tools[]` element: a single wrapper holding all functionDeclarations.
47
+ * Unlike OpenAI (one {type:'function'} per tool), Gemini nests every declaration
48
+ * under one functionDeclarations array.
49
+ */
50
+ export type GeminiTool = {
51
+ functionDeclarations: GeminiFunctionDeclaration[];
52
+ };
53
+ /**
54
+ * Result of withCodeRiftsGemini — Gemini tool definitions + core assurance, unflattened.
55
+ *
56
+ * `tools` is typically a one-element array:
57
+ * [ { functionDeclarations: [ …all protected tools… ] } ]
58
+ * `protected_tools` is the same guarded list (with execute) for host dispatch after functionCall.
59
+ */
60
+ export type WithCodeRiftsGeminiResult = {
61
+ /**
62
+ * Gemini generateContent `tools` array — only protected/guarded tools, nested under
63
+ * functionDeclarations (usually length 1 wrapper).
64
+ */
65
+ tools: GeminiTool[];
66
+ /**
67
+ * Guarded ProtectedTool list from withCodeRifts.
68
+ * Host dispatches model functionCall through these only. Never raw tools.
69
+ */
70
+ protected_tools: ProtectedTool[];
71
+ /** Untouched registry report — registry's own truth. */
72
+ registry_report: RegistryCoverageReport;
73
+ /**
74
+ * Product-level assurance — deliberately narrower than the registry.
75
+ * Passed through untouched; may still show inescapable_runtime:false and
76
+ * residual composition_call_policy_incomplete.
77
+ */
78
+ composition_assurance: CompositionAssurance;
79
+ /** Per-composition receipt cursor — NOT product-truth chain evidence. */
80
+ receipt_thread: ReceiptThreadHandle;
81
+ repository?: string;
82
+ };
83
+ /**
84
+ * Map one ProtectedTool → Gemini functionDeclaration (shape only; no execute).
85
+ * Prefer tool.inputSchema when it is a plain object; otherwise empty object schema.
86
+ */
87
+ export declare function protectedToolToFunctionDeclaration(tool: ProtectedTool): GeminiFunctionDeclaration;
88
+ /**
89
+ * Convert ProtectedTool[] into Gemini `tools` array:
90
+ * [ { functionDeclarations: [ … ] } ]
91
+ *
92
+ * Empty protected list → empty tools array (no empty wrapper).
93
+ * Does NOT call the guard — pure shape map over an already-protected list.
94
+ */
95
+ export declare function toGeminiTools(protectedTools: readonly ProtectedTool[]): GeminiTool[];
96
+ /**
97
+ * Build Gemini-ready guarded tools from raw tools + client + operation.
98
+ *
99
+ * Calls withCodeRifts internally (guard logic stays in the core). Returns:
100
+ * - `tools` — Gemini shape [ { functionDeclarations: […] } ]
101
+ * - `protected_tools` — same guarded tools for host execute dispatch
102
+ * - assurance objects from the core, passed through untouched
103
+ *
104
+ * @param input Same shape as withCodeRifts (WithCodeRiftsInput).
105
+ */
106
+ export declare function withCodeRiftsGemini(input: WithCodeRiftsInput): WithCodeRiftsGeminiResult;
107
+ /**
108
+ * Shape-only adapter over an existing WithCodeRiftsResult (composition style).
109
+ * Prefer withCodeRiftsGemini when starting from raw tools.
110
+ *
111
+ * Does not re-run the guard; does not invent assurance.
112
+ */
113
+ export declare function geminiToolAdapter(result: WithCodeRiftsResult): WithCodeRiftsGeminiResult;
114
+ //# sourceMappingURL=gemini.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../../src/adapters/gemini.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,KAAK,EACV,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAEjF;;;GAGG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,oBAAoB,EAAE,yBAAyB,EAAE,CAAC;CACnD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC;;;OAGG;IACH,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB;;;OAGG;IACH,eAAe,EAAE,aAAa,EAAE,CAAC;IACjC,wDAAwD;IACxD,eAAe,EAAE,sBAAsB,CAAC;IACxC;;;;OAIG;IACH,qBAAqB,EAAE,oBAAoB,CAAC;IAC5C,yEAAyE;IACzE,cAAc,EAAE,mBAAmB,CAAC;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAQF;;;GAGG;AACH,wBAAgB,kCAAkC,CAAC,IAAI,EAAE,aAAa,GAAG,yBAAyB,CAgBjG;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,cAAc,EAAE,SAAS,aAAa,EAAE,GAAG,UAAU,EAAE,CAKpF;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,kBAAkB,GAAG,yBAAyB,CAGxF;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,mBAAmB,GAAG,yBAAyB,CAcxF"}