@hesohq/sdk 0.1.2-dev.21

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 (45) hide show
  1. package/dist/adapters/ai-sdk.d.ts +43 -0
  2. package/dist/adapters/ai-sdk.d.ts.map +1 -0
  3. package/dist/adapters/ai-sdk.js +86 -0
  4. package/dist/adapters/ai-sdk.js.map +1 -0
  5. package/dist/adapters/mastra.d.ts +34 -0
  6. package/dist/adapters/mastra.d.ts.map +1 -0
  7. package/dist/adapters/mastra.js +84 -0
  8. package/dist/adapters/mastra.js.map +1 -0
  9. package/dist/capture.d.ts +230 -0
  10. package/dist/capture.d.ts.map +1 -0
  11. package/dist/capture.js +591 -0
  12. package/dist/capture.js.map +1 -0
  13. package/dist/cloud.d.ts +188 -0
  14. package/dist/cloud.d.ts.map +1 -0
  15. package/dist/cloud.js +196 -0
  16. package/dist/cloud.js.map +1 -0
  17. package/dist/config.d.ts +7 -0
  18. package/dist/config.d.ts.map +1 -0
  19. package/dist/config.js +16 -0
  20. package/dist/config.js.map +1 -0
  21. package/dist/delegation.d.ts +68 -0
  22. package/dist/delegation.d.ts.map +1 -0
  23. package/dist/delegation.js +139 -0
  24. package/dist/delegation.js.map +1 -0
  25. package/dist/gating.d.ts +33 -0
  26. package/dist/gating.d.ts.map +1 -0
  27. package/dist/gating.js +96 -0
  28. package/dist/gating.js.map +1 -0
  29. package/dist/index.d.ts +19 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +87 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/proxy.d.ts +30 -0
  34. package/dist/proxy.d.ts.map +1 -0
  35. package/dist/proxy.js +59 -0
  36. package/dist/proxy.js.map +1 -0
  37. package/dist/runtime.d.ts +30 -0
  38. package/dist/runtime.d.ts.map +1 -0
  39. package/dist/runtime.js +70 -0
  40. package/dist/runtime.js.map +1 -0
  41. package/dist/types.d.ts +259 -0
  42. package/dist/types.d.ts.map +1 -0
  43. package/dist/types.js +6 -0
  44. package/dist/types.js.map +1 -0
  45. package/package.json +38 -0
@@ -0,0 +1,43 @@
1
+ import { type GateOptions } from '../capture.js';
2
+ /**
3
+ * The structural slice of a Vercel AI SDK v5 tool this adapter needs: an optional
4
+ * `execute`. Declared here (not imported from 'ai') so the SDK is an optional dep.
5
+ * Provider/client tools omit `execute`; those are returned unchanged.
6
+ */
7
+ export interface ToolLike {
8
+ execute?: (...args: unknown[]) => unknown;
9
+ }
10
+ /**
11
+ * Wrap one AI SDK v5 tool so its `execute` is gated by heso. The tool's name is
12
+ * supplied by the caller (AI SDK tool objects don't carry their own name). A tool
13
+ * with no `execute` (a provider/client tool) is returned unchanged. The gate runs
14
+ * BEFORE the original `execute`, so a blocked action throws — which AI SDK v5 turns
15
+ * into a tool-error the model sees — before any side effect.
16
+ *
17
+ * @example
18
+ * import { streamText, tool } from 'ai'
19
+ * // Reached via the `./adapters/*` subpath declared in package.json `exports`.
20
+ * import { gateTool } from '@hesohq/sdk/adapters/ai-sdk'
21
+ *
22
+ * streamText({
23
+ * model,
24
+ * tools: {
25
+ * search: gateTool('search', tool({ inputSchema, execute })),
26
+ * },
27
+ * })
28
+ */
29
+ export declare function gateTool<T extends ToolLike>(name: string, tool: T, opts?: GateOptions): T;
30
+ /**
31
+ * Wrap a whole AI SDK v5 `tools` record, gating each tool by its record key (the
32
+ * name the model calls). Provider/client tools (no `execute`) pass through
33
+ * unchanged. The same {@link GateOptions} apply to every tool.
34
+ *
35
+ * @example
36
+ * import { streamText } from 'ai'
37
+ * // Reached via the `./adapters/*` subpath declared in package.json `exports`.
38
+ * import { gateTools } from '@hesohq/sdk/adapters/ai-sdk'
39
+ *
40
+ * streamText({ model, tools: gateTools({ search, sendEmail }) })
41
+ */
42
+ export declare function gateTools<R extends Record<string, ToolLike>>(tools: R, opts?: GateOptions): R;
43
+ //# sourceMappingURL=ai-sdk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-sdk.d.ts","sourceRoot":"","sources":["../../src/adapters/ai-sdk.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAA;AAEpE;;;;GAIG;AACH,MAAM,WAAW,QAAQ;IACvB,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAA;CAC1C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,CAAC,CAUzF;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,CAAC,CAM7F"}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ // Vercel AI SDK v5 drop-in for the shared capture core. The 'ai' package defines a
3
+ // tool as `tool({ inputSchema, execute })`, where `execute(input, options)` runs
4
+ // the tool body and returns its result (or a Promise of it). Crucially, AI SDK v5
5
+ // does NOT carry a tool's name on the tool object — the name is the record key the
6
+ // tool is registered under (`tools: { search: ... }`) — so the adapter takes the
7
+ // name from the caller.
8
+ //
9
+ // THE THROW->TOOL-ERROR CONTRACT: when an `execute` throws, AI SDK v5 catches it
10
+ // and converts it into a tool-error result the model sees; the tool body never
11
+ // fires and the model learns the call was refused. That makes THROWING the correct
12
+ // way to abort. So this adapter gates BEFORE awaiting the original `execute` (a
13
+ // blocked/suspended action throws BlockedError/SuspendedError from gate() in
14
+ // blocking mode, so the wrapped body never runs ungated) and deliberately does NOT
15
+ // catch the heso error — it must propagate out of `execute` into the SDK's own
16
+ // tool-error path. On allow, the original runs and recordResult() binds its output
17
+ // to a follow-up receipt (best-effort).
18
+ //
19
+ // OPTIONAL DEP: the 'ai' package is never imported here. We wrap a structural,
20
+ // tool-like shape ({ execute? }) so importing @hesohq/sdk does not require 'ai'.
21
+ //
22
+ // TWO-PHASE APPROVAL — the adapter handles PHASE ONE only:
23
+ // Phase 1 (here): gate() throws SuspendedError(actionHash) the instant an action
24
+ // is gated to a human. The adapter CANNOT block execute() waiting for the human
25
+ // — AI SDK turns the throw into a tool-error the model sees, and execute returns.
26
+ // The action_hash rides on the SuspendedError; capture it there.
27
+ // Phase 2 (out-of-band): once the approval resolves, the caller polls
28
+ // cloud.waitForApproval(actionHash) (or getL1Parts), then calls finalizeL1(
29
+ // suspendedContent, relayedParts) to assemble + mirror the L1 receipt. This is a
30
+ // SEPARATE call keyed on the action_hash — never inside execute(). A rejected
31
+ // decision makes finalizeL1 throw ApprovalRejectedError and never mints an L1.
32
+ Object.defineProperty(exports, "__esModule", { value: true });
33
+ exports.gateTool = gateTool;
34
+ exports.gateTools = gateTools;
35
+ const capture_js_1 = require("../capture.js");
36
+ /**
37
+ * Wrap one AI SDK v5 tool so its `execute` is gated by heso. The tool's name is
38
+ * supplied by the caller (AI SDK tool objects don't carry their own name). A tool
39
+ * with no `execute` (a provider/client tool) is returned unchanged. The gate runs
40
+ * BEFORE the original `execute`, so a blocked action throws — which AI SDK v5 turns
41
+ * into a tool-error the model sees — before any side effect.
42
+ *
43
+ * @example
44
+ * import { streamText, tool } from 'ai'
45
+ * // Reached via the `./adapters/*` subpath declared in package.json `exports`.
46
+ * import { gateTool } from '@hesohq/sdk/adapters/ai-sdk'
47
+ *
48
+ * streamText({
49
+ * model,
50
+ * tools: {
51
+ * search: gateTool('search', tool({ inputSchema, execute })),
52
+ * },
53
+ * })
54
+ */
55
+ function gateTool(name, tool, opts) {
56
+ const original = tool.execute;
57
+ if (typeof original !== 'function')
58
+ return tool;
59
+ const execute = async (input, ...rest) => {
60
+ const action = (0, capture_js_1.gate)(name, input, opts ?? {});
61
+ const result = await original(input, ...rest);
62
+ (0, capture_js_1.recordResult)(action, result);
63
+ return result;
64
+ };
65
+ return { ...tool, execute };
66
+ }
67
+ /**
68
+ * Wrap a whole AI SDK v5 `tools` record, gating each tool by its record key (the
69
+ * name the model calls). Provider/client tools (no `execute`) pass through
70
+ * unchanged. The same {@link GateOptions} apply to every tool.
71
+ *
72
+ * @example
73
+ * import { streamText } from 'ai'
74
+ * // Reached via the `./adapters/*` subpath declared in package.json `exports`.
75
+ * import { gateTools } from '@hesohq/sdk/adapters/ai-sdk'
76
+ *
77
+ * streamText({ model, tools: gateTools({ search, sendEmail }) })
78
+ */
79
+ function gateTools(tools, opts) {
80
+ const out = {};
81
+ for (const [name, tool] of Object.entries(tools)) {
82
+ out[name] = gateTool(name, tool, opts);
83
+ }
84
+ return out;
85
+ }
86
+ //# sourceMappingURL=ai-sdk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-sdk.js","sourceRoot":"","sources":["../../src/adapters/ai-sdk.ts"],"names":[],"mappings":";AAAA,mFAAmF;AACnF,iFAAiF;AACjF,kFAAkF;AAClF,mFAAmF;AACnF,iFAAiF;AACjF,wBAAwB;AACxB,EAAE;AACF,iFAAiF;AACjF,+EAA+E;AAC/E,mFAAmF;AACnF,gFAAgF;AAChF,6EAA6E;AAC7E,mFAAmF;AACnF,+EAA+E;AAC/E,mFAAmF;AACnF,wCAAwC;AACxC,EAAE;AACF,+EAA+E;AAC/E,iFAAiF;AACjF,EAAE;AACF,2DAA2D;AAC3D,mFAAmF;AACnF,oFAAoF;AACpF,sFAAsF;AACtF,qEAAqE;AACrE,wEAAwE;AACxE,gFAAgF;AAChF,qFAAqF;AACrF,kFAAkF;AAClF,mFAAmF;;AAgCnF,4BAUC;AAcD,8BAMC;AA5DD,8CAAoE;AAWpE;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAgB,QAAQ,CAAqB,IAAY,EAAE,IAAO,EAAE,IAAkB;IACpF,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAA;IAC7B,IAAI,OAAO,QAAQ,KAAK,UAAU;QAAE,OAAO,IAAI,CAAA;IAC/C,MAAM,OAAO,GAAG,KAAK,EAAE,KAAc,EAAE,GAAG,IAAe,EAAoB,EAAE;QAC7E,MAAM,MAAM,GAAG,IAAA,iBAAI,EAAC,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,CAAA;QAC5C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAA;QAC7C,IAAA,yBAAY,EAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC5B,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;IACD,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAO,CAAA;AAClC,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,SAAS,CAAqC,KAAQ,EAAE,IAAkB;IACxF,MAAM,GAAG,GAA6B,EAAE,CAAA;IACxC,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAA;IACxC,CAAC;IACD,OAAO,GAAQ,CAAA;AACjB,CAAC"}
@@ -0,0 +1,34 @@
1
+ import { type GateOptions } from '../capture.js';
2
+ /**
3
+ * The structural slice of a Mastra tool this adapter needs: an optional `id` (the
4
+ * tool name) and an optional `execute`. Declared here (not imported from
5
+ * '@mastra/core') so Mastra stays an optional dep. Tools without `execute`
6
+ * (provider/client tools) are returned unchanged.
7
+ */
8
+ export interface ToolLike {
9
+ id?: string;
10
+ execute?: (...args: unknown[]) => unknown;
11
+ }
12
+ /**
13
+ * Wrap one Mastra tool so its `execute` is gated by heso. The tool's name is taken
14
+ * from `tool.id` (falling back to `'mastra_tool'`), and the gated input is unwrapped
15
+ * from Mastra's `execute` argument (`.context` / `.inputData` / the argument itself).
16
+ * A tool with no `execute` (a provider/client tool) is returned unchanged. The gate
17
+ * runs BEFORE the original `execute`, so a blocked action throws — which Mastra turns
18
+ * into an aborted tool call — before any side effect.
19
+ *
20
+ * @example
21
+ * import { createTool } from '@mastra/core/tools'
22
+ * import { gateTool } from '@hesohq/sdk/adapters/mastra'
23
+ *
24
+ * const search = gateTool(
25
+ * createTool({
26
+ * id: 'search',
27
+ * description: 'Search the web',
28
+ * inputSchema,
29
+ * execute: async ({ context }) => runSearch(context),
30
+ * }),
31
+ * )
32
+ */
33
+ export declare function gateTool<T extends ToolLike>(tool: T, opts?: GateOptions): T;
34
+ //# sourceMappingURL=mastra.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mastra.d.ts","sourceRoot":"","sources":["../../src/adapters/mastra.ts"],"names":[],"mappings":"AAiCA,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,eAAe,CAAA;AAEpE;;;;;GAKG;AACH,MAAM,WAAW,QAAQ;IACvB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAA;CAC1C;AAgBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,QAAQ,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,WAAW,GAAG,CAAC,CAW3E"}
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ // Mastra drop-in for the shared capture core. A Mastra tool is built with
3
+ // `createTool({ id, description, inputSchema, outputSchema, execute })`, where
4
+ // `id` is the tool name the agent calls and `execute` is an async function that
5
+ // runs the tool body. Unlike the AI SDK, `execute` receives ONE argument that
6
+ // carries the tool input — and across Mastra versions that input lives under
7
+ // `.context` or `.inputData`, or the argument IS the input object itself. So the
8
+ // adapter takes the tool's name from `tool.id` and unwraps the input from
9
+ // whichever shape the running version uses.
10
+ //
11
+ // THE THROW->ABORT CONTRACT: when a Mastra `execute` throws, Mastra aborts the
12
+ // tool call — the body never produces a result and the failure surfaces to the
13
+ // agent. That makes THROWING the correct way to refuse. So this adapter gates
14
+ // BEFORE awaiting the original `execute` (a blocked/suspended action throws
15
+ // BlockedError/SuspendedError from gate() in blocking mode, so the wrapped body
16
+ // never runs ungated) and deliberately does NOT catch the heso error — it must
17
+ // propagate out of `execute` into Mastra's own abort path. On allow, the original
18
+ // runs and recordResult() binds its output to a follow-up receipt (best-effort).
19
+ //
20
+ // OPTIONAL DEP: the '@mastra/core' package is never imported here. We wrap a
21
+ // structural, tool-like shape ({ id?, execute? }) so importing @hesohq/sdk does not
22
+ // require Mastra to be installed.
23
+ //
24
+ // TWO-PHASE APPROVAL — the adapter handles PHASE ONE only:
25
+ // Phase 1 (here): gate() throws SuspendedError(actionHash) the instant an action
26
+ // is gated to a human. The adapter CANNOT block execute() waiting for the human
27
+ // — Mastra aborts the tool call on the throw and execute returns. The action_hash
28
+ // rides on the SuspendedError; capture it there.
29
+ // Phase 2 (out-of-band): once the approval resolves, the caller polls
30
+ // cloud.waitForApproval(actionHash) (or getL1Parts), then calls finalizeL1(
31
+ // suspendedContent, relayedParts) to assemble + mirror the L1 receipt. This is a
32
+ // SEPARATE call keyed on the action_hash — never inside execute(). A rejected
33
+ // decision makes finalizeL1 throw ApprovalRejectedError and never mints an L1.
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.gateTool = gateTool;
36
+ const capture_js_1 = require("../capture.js");
37
+ /**
38
+ * Unwrap the tool input from Mastra's `execute` argument. Mastra passes ONE
39
+ * argument that, depending on version, carries the input under `.context` or
40
+ * `.inputData`, or simply IS the input object. We prefer `context`, then
41
+ * `inputData`, then the argument itself; a non-object argument is returned as-is.
42
+ */
43
+ function extractInput(arg) {
44
+ if (arg !== null && typeof arg === 'object') {
45
+ const rec = arg;
46
+ return rec.context ?? rec.inputData ?? arg;
47
+ }
48
+ return arg;
49
+ }
50
+ /**
51
+ * Wrap one Mastra tool so its `execute` is gated by heso. The tool's name is taken
52
+ * from `tool.id` (falling back to `'mastra_tool'`), and the gated input is unwrapped
53
+ * from Mastra's `execute` argument (`.context` / `.inputData` / the argument itself).
54
+ * A tool with no `execute` (a provider/client tool) is returned unchanged. The gate
55
+ * runs BEFORE the original `execute`, so a blocked action throws — which Mastra turns
56
+ * into an aborted tool call — before any side effect.
57
+ *
58
+ * @example
59
+ * import { createTool } from '@mastra/core/tools'
60
+ * import { gateTool } from '@hesohq/sdk/adapters/mastra'
61
+ *
62
+ * const search = gateTool(
63
+ * createTool({
64
+ * id: 'search',
65
+ * description: 'Search the web',
66
+ * inputSchema,
67
+ * execute: async ({ context }) => runSearch(context),
68
+ * }),
69
+ * )
70
+ */
71
+ function gateTool(tool, opts) {
72
+ const name = typeof tool.id === 'string' && tool.id ? tool.id : 'mastra_tool';
73
+ const original = tool.execute;
74
+ if (typeof original !== 'function')
75
+ return tool;
76
+ const execute = async (arg, ...rest) => {
77
+ const action = (0, capture_js_1.gate)(name, extractInput(arg), opts ?? {});
78
+ const result = await original(arg, ...rest);
79
+ (0, capture_js_1.recordResult)(action, result);
80
+ return result;
81
+ };
82
+ return { ...tool, execute };
83
+ }
84
+ //# sourceMappingURL=mastra.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mastra.js","sourceRoot":"","sources":["../../src/adapters/mastra.ts"],"names":[],"mappings":";AAAA,0EAA0E;AAC1E,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,6EAA6E;AAC7E,iFAAiF;AACjF,0EAA0E;AAC1E,4CAA4C;AAC5C,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,8EAA8E;AAC9E,4EAA4E;AAC5E,gFAAgF;AAChF,+EAA+E;AAC/E,kFAAkF;AAClF,iFAAiF;AACjF,EAAE;AACF,6EAA6E;AAC7E,oFAAoF;AACpF,kCAAkC;AAClC,EAAE;AACF,2DAA2D;AAC3D,mFAAmF;AACnF,oFAAoF;AACpF,sFAAsF;AACtF,qDAAqD;AACrD,wEAAwE;AACxE,gFAAgF;AAChF,qFAAqF;AACrF,kFAAkF;AAClF,mFAAmF;;AAkDnF,4BAWC;AA3DD,8CAAoE;AAapE;;;;;GAKG;AACH,SAAS,YAAY,CAAC,GAAY;IAChC,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5C,MAAM,GAAG,GAAG,GAA8B,CAAA;QAC1C,OAAO,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAA;IAC5C,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,QAAQ,CAAqB,IAAO,EAAE,IAAkB;IACtE,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAA;IAC7E,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAA;IAC7B,IAAI,OAAO,QAAQ,KAAK,UAAU;QAAE,OAAO,IAAI,CAAA;IAC/C,MAAM,OAAO,GAAG,KAAK,EAAE,GAAY,EAAE,GAAG,IAAe,EAAoB,EAAE;QAC3E,MAAM,MAAM,GAAG,IAAA,iBAAI,EAAC,IAAI,EAAE,YAAY,CAAC,GAAG,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC,CAAA;QACxD,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;QAC3C,IAAA,yBAAY,EAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC5B,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;IACD,OAAO,EAAE,GAAG,IAAI,EAAE,OAAO,EAAO,CAAA;AAClC,CAAC"}
@@ -0,0 +1,230 @@
1
+ import type { ActionContent, ActionReceipt, RedactionMode, Verb } from './types.js';
2
+ import type { L1Parts, QuorumParts } from './cloud.js';
3
+ /** The native engine could not run or its output could not be parsed (fail closed). */
4
+ export declare class BridgeError extends Error {
5
+ constructor(message: string);
6
+ }
7
+ /** A captured action was refused by policy. Thrown so the wrapped call never fires. */
8
+ export declare class BlockedError extends Error {
9
+ readonly toolName: string;
10
+ readonly ruleId: string | null;
11
+ readonly reason: string | null;
12
+ constructor(toolName: string, ruleId: string | null, reason: string | null);
13
+ }
14
+ /** A captured action was gated to a human and awaits approval. Thrown so it never fires. */
15
+ export declare class SuspendedError extends Error {
16
+ readonly toolName: string;
17
+ readonly actionHash: string | null;
18
+ constructor(toolName: string, actionHash: string | null);
19
+ }
20
+ /**
21
+ * A human resolved an approval as anything other than ``approved``
22
+ * (``rejected``/``escalated``). Thrown by {@link finalizeL1} BEFORE any assemble —
23
+ * a non-approval NEVER mints an L1 (M3). Carries the resolved decision so a caller
24
+ * can branch (e.g. surface the rejection reason).
25
+ */
26
+ export declare class ApprovalRejectedError extends Error {
27
+ readonly actionHash: string;
28
+ readonly decision: string;
29
+ constructor(actionHash: string, decision: string);
30
+ }
31
+ /**
32
+ * The operator key loaded from the project keystore does NOT match the suspended
33
+ * body's ``agent_identity`` (MANDATORY-1). The action was suspended under a now-
34
+ * rotated key, so the in-core assemble fails closed rather than minting a receipt
35
+ * the verifier would reject. A DISTINCT typed signal so {@link finalizeL1} /
36
+ * {@link finalizeQuorum} can drive key-rotation auto-recovery (re-suspend under the new
37
+ * key) instead of surfacing an opaque {@link BridgeError}. Carries the
38
+ * ``agent_identity`` the suspended content expects so the caller can branch.
39
+ */
40
+ export declare class OperatorKeyMismatchError extends Error {
41
+ readonly actionHash: string;
42
+ readonly expectedAgentIdentity: string;
43
+ /** The loaded operator pubkey when known (proactive path); ``null`` when the
44
+ * mismatch was only discovered reactively inside the native assemble. */
45
+ readonly loadedPublicKey: string | null;
46
+ constructor(actionHash: string, expectedAgentIdentity: string,
47
+ /** The loaded operator pubkey when known (proactive path); ``null`` when the
48
+ * mismatch was only discovered reactively inside the native assemble. */
49
+ loadedPublicKey?: string | null);
50
+ }
51
+ /** Capture-point hints the engine recognizes (any other value supplies no surface fact). */
52
+ export type Surface = 'decorator' | 'mcp_proxy' | 'http_proxy' | 'sql_proxy' | 'sdk_wrap' | 'browser_hook' | 'process_monitor';
53
+ export type Fields = Record<string, unknown>;
54
+ export type OutcomeKind = 'allowed' | 'blocked' | 'suspended';
55
+ export interface GateOptions {
56
+ /** Escalate-only verb hint (default `tool_call`). The engine classifies structurally. */
57
+ verb?: Verb;
58
+ /** Capture-point hint (default `decorator` — the right value for a framework tool call). */
59
+ surface?: Surface;
60
+ /** Target host, when the capture observed one (lets the engine classify by host). */
61
+ targetHost?: string;
62
+ /** Extra observed signal hints (e.g. http method/path) merged under `signal`. */
63
+ signal?: Record<string, unknown>;
64
+ /** Field names whose values the engine redacts before hashing/signing (default none). */
65
+ redact?: string[];
66
+ /** How redacted fields are treated (default `destructive` — value dropped, not recoverable). */
67
+ redactStrategy?: RedactionMode;
68
+ }
69
+ /** The exact `ProcessInput` wire object (snake_case — mirrors the Rust wire type). */
70
+ interface ProcessInput {
71
+ verb: Verb;
72
+ tool_name: string;
73
+ workflow: string;
74
+ account: string;
75
+ fields: Fields;
76
+ redact_fields: string[];
77
+ redact_strategy: 'destructive' | 'commit_and_reveal';
78
+ signal: Record<string, unknown>;
79
+ target_host?: string;
80
+ result_hash?: string;
81
+ clock_override?: string;
82
+ /** RFC-3161 TSA endpoint to mint a trusted-time anchor from at sign time. */
83
+ tsa_url?: string;
84
+ /** How a missing/failed anchor is treated (default `off` ⇒ anchorless). */
85
+ anchor_policy?: 'off' | 'best_effort' | 'required';
86
+ /** Passphrase decrypting an HSK1-encrypted operator key (else HESO_KEY_PASSPHRASE). */
87
+ key_passphrase?: string;
88
+ }
89
+ /** A captured action: the public handle + the exact wire payload recordResult re-binds. */
90
+ export interface Action {
91
+ verb: Verb;
92
+ toolName: string;
93
+ fields: Fields;
94
+ /** @internal the wire payload, so recordResult can rebuild the same identity. */
95
+ readonly input: ProcessInput;
96
+ }
97
+ export interface Outcome {
98
+ kind: OutcomeKind;
99
+ allowed: boolean;
100
+ /** The signed receipt: the L0 authorization on ``allowed``; the signed,
101
+ * chain-free, anchorless operator-only suspended L0 receipt on ``suspended``
102
+ * (mirror-pushed so the byte-exact suspended content exists server-side for the
103
+ * later L1 relay); ``null`` on ``blocked``. */
104
+ receipt: ActionReceipt | null;
105
+ ruleId: string | null;
106
+ reason: string | null;
107
+ actionHash: string | null;
108
+ }
109
+ /**
110
+ * Build the action's `fields` from a framework's tool input: an object is used as
111
+ * the structured fields; a JSON-object string is parsed; anything else is recorded
112
+ * verbatim under `input`. Never throws — capture must not crash the agent.
113
+ */
114
+ export declare function normalizeFields(input: unknown): Fields;
115
+ /**
116
+ * Translate a captured call into an {@link Action}, stamping the active config's
117
+ * workflow/account/clock. The `verb` is an escalate-only hint — the engine
118
+ * classifies the `surface`/`signal` structurally and takes the stricter lane.
119
+ */
120
+ export declare function buildAction(toolName: string, fields: Fields, opts?: GateOptions): Action;
121
+ /**
122
+ * Capture + drive an action WITHOUT enforcing. Returns `{ outcome, action }` so an
123
+ * adapter can map the decision onto a framework verdict (allow/deny) instead of
124
+ * throwing. The returned `action` is what {@link recordResult} binds the result to.
125
+ */
126
+ export declare function evaluate(toolName: string, input: unknown, opts?: GateOptions): {
127
+ outcome: Outcome;
128
+ action: Action;
129
+ };
130
+ /**
131
+ * Capture + drive + ENFORCE an action before its side effect runs. Throws
132
+ * {@link BlockedError} / {@link SuspendedError} on a refusal in blocking mode (so
133
+ * the wrapped call never fires ungated); returns the gated {@link Action} on allow
134
+ * (or in observe-only mode), which {@link recordResult} later binds the result to.
135
+ */
136
+ export declare function gate(toolName: string, input: unknown, opts?: GateOptions): Action;
137
+ /**
138
+ * Bind a finished call's result to a follow-up receipt (evidence of WHAT happened,
139
+ * not only what was allowed). Best-effort: a recording failure is swallowed — the
140
+ * load-bearing decision was the gate on the way in, and recording must never crash
141
+ * the agent.
142
+ */
143
+ export declare function recordResult(action: Action, output: unknown): void;
144
+ /**
145
+ * True when the active config enforces refusals (blocking mode), false in
146
+ * observe-only mode. Decision-returning adapters consult this to mirror
147
+ * {@link gate}'s observe-only behavior: in observe-only the verdict is "allow".
148
+ */
149
+ export declare function isEnforcing(): boolean;
150
+ /**
151
+ * Finalize an approved gate into a signed L1 receipt — the out-of-band SECOND call
152
+ * of the two-phase pattern. Phase one is {@link gate}, which throws
153
+ * {@link SuspendedError} (carrying the ``action_hash``) and cannot block ``execute``
154
+ * waiting for a human. Once the cloud relays the approver parts (poll keyed on that
155
+ * ``action_hash``), this assembles and mirrors the L1.
156
+ *
157
+ * Order is load-bearing:
158
+ * 1. Assert the relayed record is ``approved`` BEFORE touching the keystore (M3) —
159
+ * a ``rejected``/``escalated`` decision throws {@link ApprovalRejectedError} and
160
+ * NEVER assembles an L1.
161
+ * 2. Assemble in-core: the native addon loads the OPERATOR key from the project
162
+ * keystore, runs the MANDATORY-1 operator-key identity check against the
163
+ * suspended content's ``agent_identity``, and verifies Valid(L1) internally —
164
+ * throwing on any bad part. The record is passed as the SAME bytes the cloud
165
+ * stored verbatim (M2): build the L1 over the operator-stamped ``suspendedContent``.
166
+ * 3. Re-verify the assembled receipt locally and REFUSE to push unless it is
167
+ * Valid(L1) — a defense-in-depth gate independent of the addon's internal check.
168
+ * 4. Mirror-push, superseding the suspended L0 entry the L1 was built from (M5).
169
+ *
170
+ * @returns the signed L1 {@link ActionReceipt} that was pushed.
171
+ */
172
+ export declare function finalizeL1(suspendedContent: ActionContent, relayedParts: L1Parts, keyPassphrase?: string): Promise<ActionReceipt>;
173
+ /** The outcome of a key-rotation re-suspend: the fresh suspended L0 the engine
174
+ * re-minted under the CURRENT operator key (new ``agent_identity`` + ``action_hash``),
175
+ * already mirror-pushed. The caller re-opens/re-routes the approval against the new
176
+ * hash; the stale approval on the OLD hash is non-replayable by construction. */
177
+ export interface ReSuspendResult {
178
+ /** The fresh suspended L0 receipt (new identity), mirror-pushed to the cloud. */
179
+ receipt: ActionReceipt;
180
+ /** The new suspended ``action_hash`` to re-open the approval against. */
181
+ actionHash: string;
182
+ /** The current operator ``agent_identity`` the fresh suspend was minted under. */
183
+ agentIdentity: string;
184
+ }
185
+ /**
186
+ * Finalize an approved k-of-n gate into a signed QUORUM receipt — the multi-approver
187
+ * sibling of {@link finalizeL1}. Every relayed leg must be ``approved``; the native
188
+ * addon assembles the quorum in-core off the operator-stamped suspended content and the
189
+ * verbatim per-approver records + co-signatures (canonicalization stays the Rust
190
+ * moat), verifying Valid(L1) WITH a ``multi_approval`` block before it returns. A
191
+ * quorum embeds ``trust_level: 'L1'`` WITH that block — it is NOT a higher level than
192
+ * single-approver L1.
193
+ *
194
+ * Order is load-bearing:
195
+ * 1. Assert EVERY leg's ``record.decision`` is ``approved`` BEFORE touching the
196
+ * keystore (M3) — any non-approval throws {@link ApprovalRejectedError} and NEVER
197
+ * assembles a quorum.
198
+ * 2. KEY-ROTATION (proactive): if ``loadedOperatorPubkeyB64`` is supplied and does
199
+ * NOT equal the suspended content's ``agent_identity``, skip the wasted assemble
200
+ * and drive recovery straight away.
201
+ * 3. Assemble in-core (the addon runs MANDATORY-1 + verifies Valid(L1) with a
202
+ * ``multi_approval`` block); a reactive ``[OperatorKeyMismatch]`` is caught and
203
+ * drives the SAME recovery.
204
+ * 4. Re-verify locally and REFUSE to push unless Valid(L1) WITH a ``multi_approval``
205
+ * block (defense in depth).
206
+ * 5. Mirror-push, superseding the suspended L0 entry the quorum was built from (M5:
207
+ * suspended/L0 -> L1; the server rejects an already-decided L1 target).
208
+ *
209
+ * On a key mismatch (proactive or reactive) and a supplied ``onKeyRotation``
210
+ * recovery, this re-suspends under the new key and throws an
211
+ * {@link OperatorKeyMismatchError} carrying the fresh hash via ``cause`` so the
212
+ * caller never mistakes recovery for a successful mint. With no recovery requested
213
+ * it throws the typed mismatch unhandled.
214
+ *
215
+ * @returns the signed QUORUM {@link ActionReceipt} that was pushed (L1 with a
216
+ * ``multi_approval`` block).
217
+ */
218
+ export declare function finalizeQuorum(suspendedContent: ActionContent, relayedParts: QuorumParts, options?: {
219
+ keyPassphrase?: string;
220
+ /** The loaded operator pubkey, base64 — enables the PROACTIVE key-rotation check
221
+ * (skip the wasted assemble when it disagrees with the suspended identity). When
222
+ * omitted, only the REACTIVE in-core mismatch is caught. */
223
+ loadedOperatorPubkeyB64?: string;
224
+ /** When the operator key rotated, re-suspend under the new key and return the
225
+ * fresh result instead of throwing the bare typed mismatch. The fresh suspended
226
+ * L0 is mirror-pushed; the returned hash is what the caller re-opens against. */
227
+ onKeyRotation?: (result: ReSuspendResult) => void;
228
+ }): Promise<ActionReceipt>;
229
+ export {};
230
+ //# sourceMappingURL=capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../src/capture.ts"],"names":[],"mappings":"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"}