@intutic/gate 1.10.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.
Files changed (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +261 -0
  3. package/dist/actions.d.ts +86 -0
  4. package/dist/actions.d.ts.map +1 -0
  5. package/dist/actions.js +239 -0
  6. package/dist/actions.js.map +1 -0
  7. package/dist/client.d.ts +94 -0
  8. package/dist/client.d.ts.map +1 -0
  9. package/dist/client.js +207 -0
  10. package/dist/client.js.map +1 -0
  11. package/dist/dsh.d.ts +162 -0
  12. package/dist/dsh.d.ts.map +1 -0
  13. package/dist/dsh.js +189 -0
  14. package/dist/dsh.js.map +1 -0
  15. package/dist/errors.d.ts +41 -0
  16. package/dist/errors.d.ts.map +1 -0
  17. package/dist/errors.js +53 -0
  18. package/dist/errors.js.map +1 -0
  19. package/dist/eve.d.ts +425 -0
  20. package/dist/eve.d.ts.map +1 -0
  21. package/dist/eve.js +378 -0
  22. package/dist/eve.js.map +1 -0
  23. package/dist/gate.d.ts +113 -0
  24. package/dist/gate.d.ts.map +1 -0
  25. package/dist/gate.js +274 -0
  26. package/dist/gate.js.map +1 -0
  27. package/dist/harness.d.ts +482 -0
  28. package/dist/harness.d.ts.map +1 -0
  29. package/dist/harness.js +504 -0
  30. package/dist/harness.js.map +1 -0
  31. package/dist/headers.d.ts +26 -0
  32. package/dist/headers.d.ts.map +1 -0
  33. package/dist/headers.js +30 -0
  34. package/dist/headers.js.map +1 -0
  35. package/dist/imagecheck.d.ts +93 -0
  36. package/dist/imagecheck.d.ts.map +1 -0
  37. package/dist/imagecheck.js +286 -0
  38. package/dist/imagecheck.js.map +1 -0
  39. package/dist/index.d.ts +26 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +19 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/managedAgents.d.ts +375 -0
  44. package/dist/managedAgents.d.ts.map +1 -0
  45. package/dist/managedAgents.js +446 -0
  46. package/dist/managedAgents.js.map +1 -0
  47. package/dist/mastra.d.ts +175 -0
  48. package/dist/mastra.d.ts.map +1 -0
  49. package/dist/mastra.js +161 -0
  50. package/dist/mastra.js.map +1 -0
  51. package/dist/openai.d.ts +392 -0
  52. package/dist/openai.d.ts.map +1 -0
  53. package/dist/openai.js +658 -0
  54. package/dist/openai.js.map +1 -0
  55. package/dist/shlex.d.ts +16 -0
  56. package/dist/shlex.d.ts.map +1 -0
  57. package/dist/shlex.js +78 -0
  58. package/dist/shlex.js.map +1 -0
  59. package/dist/snapshot.d.ts +111 -0
  60. package/dist/snapshot.d.ts.map +1 -0
  61. package/dist/snapshot.js +243 -0
  62. package/dist/snapshot.js.map +1 -0
  63. package/dist/soprules.d.ts +88 -0
  64. package/dist/soprules.d.ts.map +1 -0
  65. package/dist/soprules.js +176 -0
  66. package/dist/soprules.js.map +1 -0
  67. package/dist/trueforge.d.ts +191 -0
  68. package/dist/trueforge.d.ts.map +1 -0
  69. package/dist/trueforge.js +184 -0
  70. package/dist/trueforge.js.map +1 -0
  71. package/dist/vercel.d.ts +174 -0
  72. package/dist/vercel.d.ts.map +1 -0
  73. package/dist/vercel.js +157 -0
  74. package/dist/vercel.js.map +1 -0
  75. package/dist/workflow.d.ts +209 -0
  76. package/dist/workflow.d.ts.map +1 -0
  77. package/dist/workflow.js +254 -0
  78. package/dist/workflow.js.map +1 -0
  79. package/dist/wrapTools.d.ts +68 -0
  80. package/dist/wrapTools.d.ts.map +1 -0
  81. package/dist/wrapTools.js +95 -0
  82. package/dist/wrapTools.js.map +1 -0
  83. package/package.json +123 -0
@@ -0,0 +1,482 @@
1
+ /**
2
+ * `@ai-sdk/harness` adapter: `intuticApprovalResponder()`, `intuticSubmitApprovals()`,
3
+ * `intuticStaticApprovals()`, `recommendedHarnessSettings()`, and
4
+ * `intuticSandboxBootstrap()`.
5
+ *
6
+ * `@intutic/gate/harness` — the same idea `vercel.ts` implements for the base
7
+ * `ai` package (wrap the framework's own veto point around this package's
8
+ * `Gate.guard()`), reshaped for Vercel's sandboxed coding-agent runtime,
9
+ * whose veto surface is materially different from `generateText`'s.
10
+ *
11
+ * ## Confirmed against a real install
12
+ *
13
+ * `@ai-sdk/harness@1.0.75` (plus `@ai-sdk/harness-claude-code@1.0.78` and
14
+ * `@ai-sdk/harness-grok-build@1.0.12`) were installed and their shipped
15
+ * `.d.ts`/compiled source read directly (not inferred from docs alone):
16
+ *
17
+ * 1. **The `toolApproval` setting is STATIC.** `HarnessAgentSettings.toolApproval`
18
+ * is `HarnessAgentToolApprovalConfiguration = Readonly<Record<string,
19
+ * ToolApprovalStatus>>` (`dist/agent/index.d.ts`), whose own doc comment says
20
+ * it mirrors "AI SDK `toolApproval` object configuration for host-executed
21
+ * tools, **without callback support**". `vercel.ts`'s callback-shaped
22
+ * `intuticToolApproval()` therefore does NOT apply here — there is no place
23
+ * to hang a function. Per-call gating instead goes through the approval
24
+ * FLOW: mark tools `'user-approval'` (see {@link intuticStaticApprovals}),
25
+ * let the turn pause, and answer each pending approval with the gate
26
+ * (see {@link intuticApprovalResponder}).
27
+ * 2. **The portable answer path is continuation-based.**
28
+ * `HarnessAgentToolApprovalContinuation` carries `{ approvalResponse,
29
+ * toolCall }`; `continueTurn`/`continueGenerate`/`continueStream` accept
30
+ * `toolApprovalContinuations` (dist/agent/index.d.ts). The adapter-session
31
+ * method `session.submitToolApproval?({approvalId, approved, reason})` is
32
+ * OPTIONAL (`dist/index.d.ts` — `HarnessV1PromptControl`), and support
33
+ * genuinely varies per adapter: `@ai-sdk/harness-claude-code@1.0.78`
34
+ * implements it; `@ai-sdk/harness-grok-build@1.0.12` does not (zero
35
+ * occurrences in its shipped dist). This module therefore builds the
36
+ * responder on the continuation path and treats `submitToolApproval` as an
37
+ * optimization when present ({@link intuticSubmitApprovals}).
38
+ * 3. **Built-in sandbox tools are NOT governed by `toolApproval` at all.**
39
+ * They are governed only by `permissionMode: 'allow-reads' | 'allow-edits'
40
+ * | 'allow-all'`, which **defaults to `'allow-all'`** — the shipped doc
41
+ * comment says so verbatim: "Defaults to `'allow-all'`, preserving the
42
+ * existing bypass-permissions behavior unless users opt in." A HarnessAgent
43
+ * with default settings runs read/write/edit/bash/glob/grep in the sandbox
44
+ * with no approval step this gate could hook.
45
+ * {@link recommendedHarnessSettings} exists to steer callers off that
46
+ * default.
47
+ * 4. **Execution is server-side, in a sandbox.** The agent's tools run inside
48
+ * a microVM (`@ai-sdk/sandbox-vercel` and friends), NOT on the machine
49
+ * where the Intutic proxy runs — the laptop proxy cannot see sandbox
50
+ * egress. The only egress control available at this layer is the sandbox's
51
+ * own `HarnessV1NetworkPolicy` (`{mode:'allow-all'|'deny-all'} | {mode:
52
+ * 'custom', allowedHosts/allowedCIDRs/deniedCIDRs}`), applied via the
53
+ * sandbox session's optional `setNetworkPolicy?.()`. That is coarse
54
+ * host-level filtering, not Intutic DLP — stated plainly in
55
+ * `apps/docs/integrations/ai-sdk-harness.md` rather than oversold.
56
+ *
57
+ * ## What this module does NOT import
58
+ *
59
+ * Deliberately no runtime dependency on `@ai-sdk/harness` — the structural
60
+ * types below capture only the shapes this adapter touches, matching the
61
+ * convention `vercel.ts`/`mastra.ts`/`dsh.ts` established. The real package
62
+ * is a devDependency used by `__tests__/harness.test.ts` to (a) structurally
63
+ * check these types against the shipped ones and (b) run this responder's
64
+ * output through the REAL `collectHarnessAgentToolApprovalContinuations`
65
+ * machinery.
66
+ *
67
+ * @module
68
+ */
69
+ import { type Gate, type ToolInput } from './gate.js';
70
+ /** Structural copy of `ai`'s `ToolApprovalResponse` prompt part (re-exported
71
+ * from `@ai-sdk/provider-utils@5.0.27` — confirmed field-for-field). This is
72
+ * the part a `role: 'tool'` message carries to answer an approval request. */
73
+ export interface HarnessToolApprovalResponse {
74
+ type: 'tool-approval-response';
75
+ approvalId: string;
76
+ approved: boolean;
77
+ reason?: string;
78
+ providerExecuted?: boolean;
79
+ }
80
+ /** Structural copy of the `toolCall` member of `@ai-sdk/harness`'s
81
+ * `HarnessAgentToolApprovalContinuation` (dist/agent/index.d.ts). */
82
+ export interface HarnessToolCallPart {
83
+ readonly type: 'tool-call';
84
+ readonly toolCallId: string;
85
+ readonly toolName: string;
86
+ readonly input: unknown;
87
+ readonly providerExecuted?: boolean;
88
+ }
89
+ /** Structural copy of `@ai-sdk/harness`'s `HarnessAgentToolApprovalContinuation`
90
+ * — the element type of the `toolApprovalContinuations` array
91
+ * `continueGenerate`/`continueStream` accept. */
92
+ export interface HarnessToolApprovalContinuation {
93
+ readonly approvalResponse: HarnessToolApprovalResponse;
94
+ readonly toolCall: HarnessToolCallPart;
95
+ }
96
+ /**
97
+ * One pending tool-approval request, in the shape this responder consumes.
98
+ *
99
+ * Covers BOTH places a HarnessAgent surfaces one:
100
+ *
101
+ * - the `tool-approval-request` stream/message parts of a running turn
102
+ * (paired with their `tool-call` parts — `input` is the parsed value), and
103
+ * - `HarnessAgentPendingToolApproval` rows from a suspended session, where
104
+ * `input` is a JSON **string** (confirmed: `HarnessV1PendingToolApproval.
105
+ * input: string` in `@ai-sdk/harness@1.0.75`'s dist/index.d.ts). String
106
+ * inputs are JSON-parsed before the gate evaluates them — see
107
+ * {@link renderHarnessToolInput}.
108
+ */
109
+ export interface HarnessApprovalRequest {
110
+ readonly approvalId: string;
111
+ readonly toolCallId: string;
112
+ readonly toolName: string;
113
+ /** Parsed input object, or the JSON string a pending-approval row carries. */
114
+ readonly input: unknown;
115
+ readonly providerExecuted?: boolean;
116
+ }
117
+ /** Structural copy of `@ai-sdk/harness`'s `HarnessV1PermissionMode`. */
118
+ export type HarnessPermissionMode = 'allow-reads' | 'allow-edits' | 'allow-all';
119
+ /** Structural copy of `@ai-sdk/harness`'s `HarnessV1NetworkPolicy`. The two
120
+ * `custom` branches of the real union each require at least one allow field;
121
+ * this single structural branch keeps both optional and relies on the test
122
+ * suite's assignability check against the real (stricter) type for the
123
+ * values this module itself constructs. */
124
+ export type HarnessNetworkPolicy = {
125
+ mode: 'allow-all';
126
+ } | {
127
+ mode: 'deny-all';
128
+ } | {
129
+ mode: 'custom';
130
+ allowedHosts?: readonly string[];
131
+ allowedCIDRs?: readonly string[];
132
+ deniedCIDRs?: readonly string[];
133
+ };
134
+ /** The slice of `@ai-sdk/harness`'s adapter-session control surface this
135
+ * module touches — `submitToolApproval` is OPTIONAL in the real
136
+ * `HarnessV1PromptControl` too, and per-adapter support varies (see module
137
+ * doc point 2). */
138
+ export interface HarnessSessionLike {
139
+ submitToolApproval?(input: {
140
+ approvalId: string;
141
+ approved: boolean;
142
+ reason?: string;
143
+ }): PromiseLike<void>;
144
+ }
145
+ export interface IntuticApprovalResponderOptions {
146
+ /** Overrides the process-wide installed gate (`install(new Gate(...))`). */
147
+ gate?: Gate;
148
+ }
149
+ /**
150
+ * Render a pending approval's `input` as the `tool_input` object
151
+ * {@link Gate.guard} evaluates.
152
+ *
153
+ * Mirrors `dsh.ts`'s `renderDshToolInput`, plus one harness-specific case: a
154
+ * `HarnessAgentPendingToolApproval` carries its input as a JSON **string**,
155
+ * so strings are parsed first. A string that does not parse (or parses to a
156
+ * non-object) falls back to `{ args: [...] }` so the gate still has
157
+ * something to evaluate rather than throwing on a shape it does not
158
+ * recognise.
159
+ */
160
+ export declare function renderHarnessToolInput(input: unknown): ToolInput;
161
+ /**
162
+ * Build an approval responder: a function that evaluates each pending
163
+ * tool-approval request via `Gate.guard()` and produces the
164
+ * `toolApprovalContinuations` array for the continue-turn call —
165
+ * `agent.continueGenerate({ session, toolApprovalContinuations })` /
166
+ * `continueStream(...)`:
167
+ *
168
+ * ```ts
169
+ * import { HarnessAgent } from '@ai-sdk/harness/agent'
170
+ * import { Gate, install } from '@intutic/gate'
171
+ * import {
172
+ * intuticApprovalResponder,
173
+ * intuticStaticApprovals,
174
+ * recommendedHarnessSettings,
175
+ * } from '@intutic/gate/harness'
176
+ *
177
+ * install(new Gate({ workspaceId: process.env.INTUTIC_WORKSPACE_ID }))
178
+ *
179
+ * const agent = new HarnessAgent({
180
+ * harness,
181
+ * sandbox,
182
+ * tools,
183
+ * ...recommendedHarnessSettings(), // permissionMode: 'allow-edits'
184
+ * toolApproval: intuticStaticApprovals(tools), // every custom tool -> 'user-approval'
185
+ * })
186
+ *
187
+ * const respond = intuticApprovalResponder()
188
+ * // ...run a turn; when it pauses awaiting approval, collect the pending
189
+ * // tool-approval requests (stream parts or suspended-session rows), then:
190
+ * const toolApprovalContinuations = await respond(pendingApprovals)
191
+ * await agent.continueGenerate({ session, toolApprovalContinuations })
192
+ * ```
193
+ *
194
+ * Decision mapping, per request:
195
+ *
196
+ * - gate allows -> `approved: true`
197
+ * - `IntuticGateRefusal` -> `approved: false`, `reason` = the
198
+ * `[Intutic Governance] BLOCKED: ...` message (the runtime submits an
199
+ * `execution-denied` result to the model in place of a tool result)
200
+ * - any OTHER throw -> `approved: false` with a "gate crashed"
201
+ * reason — **fail closed**, same posture as `dsh.ts`'s listener: this
202
+ * responder's output is a decision list consumed by a paused turn, and a
203
+ * deny is deliverable and auditable where an escaped throw could leave
204
+ * the turn suspended with no answer at all.
205
+ *
206
+ * Requires a `Gate` — either passed via `{ gate }`, or installed process-wide
207
+ * with `install(new Gate(...))`. A call with neither rejects before
208
+ * evaluating anything, refusing to answer approvals unguarded.
209
+ */
210
+ export declare function intuticApprovalResponder(opts?: IntuticApprovalResponderOptions): (requests: readonly HarnessApprovalRequest[]) => Promise<HarnessToolApprovalContinuation[]>;
211
+ export interface IntuticSubmitApprovalsResult {
212
+ /** The evaluated decisions, always produced — pass these to
213
+ * `continueGenerate`/`continueStream` when `submitted` is false. */
214
+ continuations: HarnessToolApprovalContinuation[];
215
+ /** True when the session supported `submitToolApproval` and every decision
216
+ * was delivered through it; false when the caller must use the
217
+ * continuation path instead. */
218
+ submitted: boolean;
219
+ }
220
+ /**
221
+ * Evaluate pending approvals and deliver the decisions through
222
+ * `session.submitToolApproval` when the adapter supports it.
223
+ *
224
+ * `submitToolApproval` is an OPTIONAL adapter-session method and per-adapter
225
+ * support varies (`harness-claude-code` implements it, `harness-grok-build`
226
+ * does not — see module doc point 2). This helper treats it as an
227
+ * optimization: when present, every decision is submitted directly (the turn
228
+ * resumes in place); when absent, nothing is submitted and the caller passes
229
+ * the returned `continuations` to `continueGenerate`/`continueStream` — the
230
+ * portable path — instead. Either way the SAME evaluated decisions are
231
+ * returned, so the caller never re-runs the gate for one delivery mechanism
232
+ * vs. the other.
233
+ */
234
+ export declare function intuticSubmitApprovals(session: HarnessSessionLike, requests: readonly HarnessApprovalRequest[], opts?: IntuticApprovalResponderOptions): Promise<IntuticSubmitApprovalsResult>;
235
+ export interface IntuticStaticApprovalsOptions {
236
+ /** Tool names to mark `'denied'` unconditionally instead of
237
+ * `'user-approval'` — for tools that should never run under this agent
238
+ * regardless of what the gate would say about a specific call. */
239
+ deny?: readonly string[];
240
+ }
241
+ /**
242
+ * Build the static `toolApproval` record for `HarnessAgentSettings`.
243
+ *
244
+ * The record shape is `Readonly<Record<string, ToolApprovalStatus>>` — STATIC
245
+ * per-tool statuses "without callback support" (the shipped doc comment's own
246
+ * words), so a per-call gate function cannot be expressed here at all. What a
247
+ * static record CAN express is deny-by-default **routing**: every listed tool
248
+ * is marked `'user-approval'`, which pauses the turn on every call to it, and
249
+ * {@link intuticApprovalResponder} then answers each pause with a real
250
+ * per-call `Gate.guard()` verdict. `'denied'` is deliberately NOT the default
251
+ * here — it would refuse every call to the tool unconditionally, without the
252
+ * gate ever seeing the arguments; use `{ deny: [...] }` for tools where that
253
+ * is actually what you want.
254
+ *
255
+ * Two scope limits, stated plainly:
256
+ *
257
+ * - This covers CUSTOM host-executed tools only. Built-in sandbox tools
258
+ * (read/write/edit/bash/...) never consult `toolApproval` — they are
259
+ * governed solely by `permissionMode`, which defaults to `'allow-all'`.
260
+ * See {@link recommendedHarnessSettings}.
261
+ * - A tool absent from this record has status `undefined` =
262
+ * "not-applicable" and runs WITHOUT any approval pause. Pass the same
263
+ * `tools` record you give the agent (or every tool name), not a subset.
264
+ */
265
+ export declare function intuticStaticApprovals(tools: readonly string[] | Record<string, unknown>, opts?: IntuticStaticApprovalsOptions): Readonly<Record<string, 'user-approval' | 'denied'>>;
266
+ export interface RecommendedHarnessSettingsOptions {
267
+ /** `'allow-reads'` is stricter (built-ins can read but not write); the
268
+ * default recommendation is `'allow-edits'` (read + write inside the
269
+ * sandbox, but not the unrestricted `'allow-all'` the framework itself
270
+ * defaults to). `'allow-all'` is deliberately not accepted here — asking
271
+ * this function for the framework's own bypass default would make the
272
+ * helper's name a lie. */
273
+ permissionMode?: 'allow-reads' | 'allow-edits';
274
+ /** Hosts sandbox egress should be limited to. When omitted, the
275
+ * recommended policy is `{ mode: 'deny-all' }` — deny-by-default until
276
+ * the caller decides what the sandbox legitimately needs to reach. */
277
+ allowedHosts?: readonly string[];
278
+ /**
279
+ * Whether to also recommend excluding the sandbox's native `bash` builtin
280
+ * from the tool set entirely, via `HarnessAgentSettings.inactiveTools`.
281
+ * Defaults to `true` — see {@link RecommendedHarnessSettings.inactiveTools}
282
+ * for what this does and does not guarantee (TD-415).
283
+ */
284
+ filterBash?: boolean;
285
+ }
286
+ /** The exact policy shapes {@link recommendedHarnessSettings} constructs —
287
+ * narrower than {@link HarnessNetworkPolicy} so the value is assignable to
288
+ * the REAL `HarnessV1NetworkPolicy` union (whose `custom` branches each
289
+ * require an allow field) without a cast; the test suite pins that
290
+ * assignability against the shipped type. */
291
+ export type RecommendedNetworkPolicy = {
292
+ mode: 'deny-all';
293
+ } | {
294
+ mode: 'custom';
295
+ allowedHosts: readonly string[];
296
+ deniedCIDRs: readonly string[];
297
+ };
298
+ export interface RecommendedHarnessSettings {
299
+ /** Spread into `HarnessAgentSettings`. */
300
+ permissionMode: 'allow-reads' | 'allow-edits';
301
+ /**
302
+ * NOT a `HarnessAgentSettings` field — apply it to the sandbox session via
303
+ * its optional `setNetworkPolicy?.()` (e.g. from `sandboxConfig.onSession`),
304
+ * or configure the equivalent on the sandbox provider. Optional-call it:
305
+ * providers without a local enforcement primitive omit the method, and a
306
+ * missing implementation means NO egress policy is applied at all — check
307
+ * for `undefined` and treat that as an uncovered surface, not a silent ok.
308
+ */
309
+ networkPolicy: RecommendedNetworkPolicy;
310
+ /**
311
+ * Spread into `HarnessAgentSettings.inactiveTools` — `undefined` when
312
+ * `filterBash: false` was passed. TD-415, resolved with a corrected
313
+ * understanding: `HarnessV1BuiltinToolFiltering` (the same package's own
314
+ * type, `dist/index.d.ts`/`dist/agent/index.d.ts`) genuinely CAN drop
315
+ * `bash` at config time, confirmed against real shipped `dist/index.js`
316
+ * for both harnesses TD-417 discusses (not just their `.d.ts` — the
317
+ * behaviour lives in compiled logic no type file states):
318
+ *
319
+ * - `@ai-sdk/harness-claude-code@1.0.78` sets BOTH
320
+ * `supportsBuiltinToolApprovals: true` AND
321
+ * `supportsBuiltinToolFiltering: true` on its adapter object, and its
322
+ * `doStart`/`doContinueTurn` forward `builtinToolFiltering` verbatim
323
+ * onto the bridge `start`/`continue` message — true native exclusion,
324
+ * enforced by the wrapped Claude Agent SDK inside the sandbox itself,
325
+ * not merely a framework-side veto. `bash` never becomes callable.
326
+ * - `@ai-sdk/harness-grok-build@1.0.12` sets neither flag directly, but
327
+ * is built on `@ai-sdk/harness-acp@1.0.13` (its exact pinned
328
+ * dependency, confirmed via `npm pack`), which sets
329
+ * `supportsBuiltinToolApprovals: true` (and
330
+ * `supportsBuiltinToolFiltering: false`) — so Grok Build gets the
331
+ * FRAMEWORK's own fallback instead: `@ai-sdk/harness/agent`'s compiled
332
+ * `resolveHarnessAgentToolFiltering` (`dist/agent/index.js`) routes
333
+ * every inactive-builtin call through the approval path and
334
+ * auto-denies it before execution. Different mechanism, same practical
335
+ * outcome — `bash` is still never executed.
336
+ * - Confirmed further: if an adapter supported NEITHER flag, the
337
+ * framework does not silently ignore `inactiveTools` for a builtin —
338
+ * `HarnessAgent`'s constructor throws `HarnessCapabilityUnsupportedError`
339
+ * (`dist/agent/index.js`) rather than accepting a setting it cannot
340
+ * honour. So this recommendation is never a silent no-op for any
341
+ * adapter that accepts it at all.
342
+ *
343
+ * What this does NOT close: TD-415's original per-call gap. This is a
344
+ * coarse, all-or-nothing exclusion decided once at session-construction
345
+ * time — never a `Gate.guard()`-evaluated verdict per call, and a
346
+ * workspace that genuinely needs `bash` available cannot use this
347
+ * filtering and is back to the original `permissionMode` gap for it.
348
+ */
349
+ inactiveTools?: readonly ['bash'];
350
+ }
351
+ /**
352
+ * The settings posture this integration recommends, as a value callers can
353
+ * spread/apply rather than prose they have to transcribe:
354
+ *
355
+ * - `permissionMode: 'allow-edits'` (or `'allow-reads'`) — because the
356
+ * framework's own default is `'allow-all'`, under which built-in sandbox
357
+ * tools (including `bash`) run with no approval surface this gate can
358
+ * reach. There is no per-call gate for built-ins at ANY permissionMode;
359
+ * the mode itself is the entire control, which is why steering it off
360
+ * `'allow-all'` matters.
361
+ * - a `networkPolicy` for the sandbox — `{ mode: 'deny-all' }` by default,
362
+ * or a `custom` allow-list (with the cloud-metadata CIDR denied) when
363
+ * `allowedHosts` is given. This is the honest egress-governance story for
364
+ * server-side sandbox execution: the Intutic proxy on the developer's
365
+ * machine never sees sandbox traffic, and host-level filtering is what
366
+ * the sandbox layer actually offers. It is coarse — no DLP, no
367
+ * per-request policy — and the integration docs say so.
368
+ */
369
+ export declare function recommendedHarnessSettings(opts?: RecommendedHarnessSettingsOptions): RecommendedHarnessSettings;
370
+ /** Structural copy of `@ai-sdk/provider-utils`'s `SandboxSession`, narrowed
371
+ * to the one method {@link intuticSandboxBootstrap}'s `onBootstrap` calls.
372
+ * Confirmed field-for-field against `@ai-sdk/provider-utils@5.0.27`'s
373
+ * shipped `dist/index.d.ts` (`WriteFileOptions<string>` plus its own
374
+ * `encoding` addition on `writeTextFile`). */
375
+ export interface SandboxWriteSession {
376
+ writeTextFile(options: {
377
+ path: string;
378
+ content: string;
379
+ encoding?: string;
380
+ }): PromiseLike<void>;
381
+ }
382
+ /** Structural copy of `@ai-sdk/harness/agent`'s
383
+ * `HarnessAgentSandboxConfig['onBootstrap']` parameter shape
384
+ * (`dist/agent/index.d.ts`), narrowed to the fields this module reads. */
385
+ export interface SandboxBootstrapCallbackOptions {
386
+ readonly session: SandboxWriteSession;
387
+ readonly workDir: string;
388
+ readonly abortSignal?: AbortSignal;
389
+ }
390
+ export interface IntuticSandboxBootstrap {
391
+ /** Pass through unchanged to `HarnessAgentSettings.sandboxConfig.bootstrapHash`
392
+ * — required alongside `onBootstrap` by the real type. Deterministic: the
393
+ * same options always produce the same hash, and a snapshot-capable
394
+ * sandbox provider uses it to decide whether `onBootstrap` needs to run
395
+ * again. Computed the same way `snapshot.ts` computes the policy-snapshot
396
+ * digest — `createHash('sha256')` over the recipe content, this module's
397
+ * own existing hashing convention, not a new one. */
398
+ readonly bootstrapHash: string;
399
+ /** Pass through unchanged to `HarnessAgentSettings.sandboxConfig.onBootstrap`. */
400
+ readonly onBootstrap: (opts: SandboxBootstrapCallbackOptions) => Promise<void>;
401
+ }
402
+ export interface IntuticSandboxBootstrapOptions {
403
+ /**
404
+ * Compiled `.rules` text — the SAME artifact format `snapshot.ts` reads
405
+ * (`~/.intutic/hooks/policy-snapshot.rules` on a laptop). Copy the file
406
+ * content in, e.g. by reading it from the host running the orchestrator
407
+ * code before constructing this bootstrap. Omit to ship a hook script that
408
+ * loads zero rules (still present as a channel, evaluating nothing) —
409
+ * never silently skipped, so a missing snapshot shows up as an empty file
410
+ * inside the sandbox rather than a missing one.
411
+ */
412
+ policySnapshotRules?: string;
413
+ /** Embedded in the recipe hash only (so a workspace switch invalidates a
414
+ * cached snapshot) — this module does not otherwise use it, matching
415
+ * `snapshot.ts`'s reader, which also treats workspace id as an integrity
416
+ * check rather than a lookup key. */
417
+ workspaceId?: string;
418
+ /** Directory inside the sandbox (relative to `workDir`) the hook script
419
+ * and its rules file are written under. Defaults to `.intutic/hooks`,
420
+ * the same relative location the laptop writer uses. */
421
+ bootstrapDir?: string;
422
+ }
423
+ declare function sandboxJoin(workDir: string, relative: string): string;
424
+ /**
425
+ * Self-contained (zero-`require`) hand-port of `snapshot.ts`'s
426
+ * `normalise`/`evaluate` — Tier A1 only. See the module-level comment above
427
+ * for what this deliberately does and does not cover, and
428
+ * `__tests__/harness.test.ts` for the behavioural-parity check against the
429
+ * real `snapshot.evaluate()` this port is pinned to.
430
+ *
431
+ * Contract matches the laptop's `claude-code-check.js`
432
+ * (`services/sync-daemon/src/harness/claudeCodeHooks.ts`) deliberately:
433
+ * Claude Code's PreToolUse hook stdin carries `{tool_name, tool_input,
434
+ * session_id}` (this reads both the snake_case and camelCase field names,
435
+ * same as the laptop script); exit `2` blocks the call, exit `0` allows it;
436
+ * any parse/read error fails CLOSED (exit `2`), the same posture
437
+ * `emitJsFailClosedPrelude` documents for the laptop's version.
438
+ */
439
+ declare function renderSandboxGateScript(rulesFileName: string): string;
440
+ /**
441
+ * Compiles the `.claude/settings.json` content that registers the generated
442
+ * hook script — same matcher set and hook shape as the laptop writer's
443
+ * `hookEntry()` (`services/sync-daemon/src/harness/claudeCodeHooks.ts`):
444
+ * `Bash`, `Edit`, `Write`, `MultiEdit`, and `mcp__.*`.
445
+ */
446
+ declare function renderSandboxClaudeSettings(hookScriptSandboxPath: string): string;
447
+ /**
448
+ * Builds `{ bootstrapHash, onBootstrap }` for
449
+ * `HarnessAgentSettings.sandboxConfig` — the channel TD-417 identified as
450
+ * existing but unused:
451
+ *
452
+ * ```ts
453
+ * import { HarnessAgent } from '@ai-sdk/harness/agent'
454
+ * import { intuticSandboxBootstrap, recommendedHarnessSettings } from '@intutic/gate/harness'
455
+ *
456
+ * const agent = new HarnessAgent({
457
+ * harness,
458
+ * sandbox,
459
+ * ...recommendedHarnessSettings(),
460
+ * sandboxConfig: intuticSandboxBootstrap({
461
+ * policySnapshotRules: fs.readFileSync(snapshotPath(), 'utf-8'),
462
+ * workspaceId: process.env.INTUTIC_WORKSPACE_ID,
463
+ * }),
464
+ * })
465
+ * ```
466
+ *
467
+ * Writes two files under `<workDir>/<bootstrapDir>` (default
468
+ * `.intutic/hooks`) — the rules text verbatim, and a self-contained hook
469
+ * script implementing Tier A1 against it (see
470
+ * {@link renderSandboxGateScript}) — plus `.claude/settings.json` at
471
+ * `<workDir>/.claude/settings.json` registering that script as a
472
+ * `PreToolUse` hook. See the module-level comment above this section for
473
+ * what this does and does not cover, and why.
474
+ */
475
+ export declare function intuticSandboxBootstrap(opts?: IntuticSandboxBootstrapOptions): IntuticSandboxBootstrap;
476
+ export declare const _internal: {
477
+ renderSandboxGateScript: typeof renderSandboxGateScript;
478
+ renderSandboxClaudeSettings: typeof renderSandboxClaudeSettings;
479
+ sandboxJoin: typeof sandboxJoin;
480
+ };
481
+ export {};
482
+ //# sourceMappingURL=harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../src/harness.ts"],"names":[],"mappings":"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"}