@theokit/agents 9.4.0 → 10.1.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,79 @@
1
1
  # @theokit/agents
2
2
 
3
+ ## 10.1.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c227a8d: `LivenessVerdict` now carries the `cwd` it is about, so a caller can act on the verdict instead of parsing a sentence.
8
+
9
+ `classifyProjects` PROBES a path to decide `alive` — it has it in hand at the moment it returns — and kept only a prose `reason`. That made the verdict unable to replace the function it was absorbed from: the consumer's GC uses the resolved cwd to consult the agent registry and the resumable pointer for that project (`all-sessions.ts:161,175`). Recovering it by string-matching `reason` would be exactly the fragile coupling this module exists to remove.
10
+
11
+ `alive` reports the member of the collision class that was found to EXIST, not the first one read — the class can hold a gone path and a live one, and sending a registry lookup to the gone sibling defeats the point. `dead` reports the recorded cwd that was checked and found missing. `undetermined` established no path, so the field is absent rather than an empty string a caller might mistake for one.
12
+
13
+ Additive and optional: no existing call site changes.
14
+
15
+ ## 10.0.0
16
+
17
+ ### Major Changes
18
+
19
+ - 4cd49ef: BREAKING: `deleteSession` and `runTranscriptGC` are now `async`.
20
+
21
+ Their return type goes from `T` to `Promise<T>`. A caller that does not `await` reads `undefined`
22
+ instead of the result and throws on the first field access — which is what happened to this repo's
23
+ own `theokit agent sessions gc` command, unnoticed for a day because the workspace typecheck was
24
+ measured against a stale `.d.ts`.
25
+
26
+ The change is required rather than cosmetic: the only agent registry in the ecosystem is
27
+ `Agent.delete(id): Promise<void>`, and the registry half of session deletion is unreachable without
28
+ awaiting it. Migration is `await`.
29
+
30
+ BREAKING: `SessionRegistryRemoverError` changes constructor arity and meaning. It was
31
+ `constructor(sessionId)` for "you passed a thenable to a synchronous seam"; it is now
32
+ `constructor(sessionId, timeoutMs)` for "the registry did not answer in time". The old condition no
33
+ longer exists, so a `catch` that depended on it will never fire again. The class moved module and is
34
+ re-exported from its old home, so import paths are unaffected.
35
+
36
+ Also: the registry timeout now has a bounded DEFAULT (`DEFAULT_REGISTRY_TIMEOUT_MS`, 30s) where it
37
+ previously waited forever. Unbounded remains available by passing a non-finite value.
38
+
39
+ ### Minor Changes
40
+
41
+ - 7519927: Security: `auto-edit` no longer auto-approves from a framework-chosen default. A product declares its own set.
42
+
43
+ `shouldAutoApprove`'s `auto-edit` branch defaulted to `WRITE_SCOPED_TOOLS` — `apply_patch`, `edit_file`, `write_file`. The only real consumer auto-approves one of those and registers two, so adopting the framework symbol would have made `edit_file` stop requiring a human: a live, model-callable write tool, silently un-gated as a side effect of deleting duplicated code.
44
+
45
+ Two questions had been conflated. "Does this tool bound its own writes to a write root?" is a fact about the SDK's tool factories, and the framework can answer it. "May this tool run without asking a human?" is the product's policy, and the framework cannot answer it — it does not know which tools the product registered or what it renamed them to.
46
+
47
+ `auto-edit` with no `writeScopedTools` now approves nothing, which is the same shape the module already applies to sandbox posture (an absent posture counts as unconfined). `WRITE_SCOPED_TOOLS` is still exported as the catalog; passing it is a decision rather than an inheritance.
48
+
49
+ `WRITE_SCOPED_TOOLS` is now genuinely immutable — its mutators throw. `ReadonlySet` is erased at runtime, and one cast on an approval gate reachable from every consumer would widen what auto-approves everywhere. `Object.freeze` alone is not enough for a `Set`: entries live in internal slots, not own properties, so freezing leaves `add` working.
50
+
51
+ Not a breaking change for published consumers: `npm pack @theokit/agents@9.4.0` exports neither `shouldAutoApprove` nor `WRITE_SCOPED_TOOLS`. Anyone already calling it on a pre-release build must pass `{ writeScopedTools }` to keep `auto-edit` approving anything.
52
+
53
+ - 0513d03: `deleteSession` re-checks protection immediately before unlinking, instead of trusting a snapshot taken before an await.
54
+
55
+ The protection check ran at the top of the function; control then left for as long as the caller's registry remover took — 30s by default, unbounded with `registryTimeoutMs: Infinity` — and only then was the transcript removed. Anything concluded before that await is a snapshot, and a user resuming the session during the window makes it false. The file was deleted anyway and `SessionInUseError` never fired, which is the outcome that error exists to prevent.
56
+
57
+ The batch path already treats this as non-negotiable: `transcript-gc.ts` invariant 4 is "the apply phase re-checks — a plan is a snapshot, and between snapshot and delete a user can resume a session". The single-session path skipped it, and it is the one with no later sweep to catch the mistake.
58
+
59
+ `SessionInUseError` gains `registryRemoved`. Refusing after the registry half has run leaves an orphan file — the recoverable direction the function already chose in its ordering — but the caller has to be told, or it retries a removal that is already done and reads the resulting `false` ("no entry to remove") as a failure. The constructor parameter is optional and defaults to `false`, so existing construction sites are unaffected.
60
+
61
+ - 01735c7: `classifyProjects` (`@theokit/agents/session`) — answers "does the project behind `projects/<encoded>/` still exist?" without the caller writing the search itself.
62
+
63
+ `minor`, not `major`, and the distinction was measured rather than assumed: `npm pack @theokit/agents@9.4.0` ships the `./session` subpath but contains neither `classifyProjects` nor `FsSeam`. This is a new export on an existing subpath, so the option and seam changes made while stabilising it break no published consumer — there is none. The only migration note that would be honest is the one for the consumer this was absorbed from, and it is written as adoption guidance below rather than as a break.
64
+
65
+ The question is hard because `encodeProjectDir(cwd)` is `cwd.replace(/[^a-zA-Z0-9]/g, '-')` — one-way and many-to-one, so a directory name cannot be turned back into a path, only CHECKED against candidates. Every product that retains or garbage-collects transcripts has to answer it; the consumer's own version is 188 lines whose docstring measured 13,269 project directories, ~3,200 falling through to filesystem search and ~64M syscalls without a shared budget.
66
+
67
+ Three properties carry the safety of this module, and each exists because dropping it produced a measured deletion of live data:
68
+
69
+ - **The verdict is three-valued and `undetermined` is not a soft `dead`.** Callers DELETE on `dead`. Budget spent, unreadable directory, enumeration threw — all resolve to `undetermined`, because deleting on "could not tell" is data loss and the two errors are not symmetric.
70
+ - **`FsSeam.exists` returns `boolean | undefined`.** The third state is in the return type rather than in prose because that is the only place an adapter author reliably reads it. A signature of `=> boolean` invites `try { return existsSync(p) } catch { return false }` — which is exactly the consumer's scar B-020, where a cwd that exists but cannot be stat-ed (EACCES on a non-traversable parent, ENOTDIR mid-path, EMFILE under a wide sweep) was classified DEAD.
71
+ - **Every member of the collision class is probed, not the first match.** Because the encoding is many-to-one, `encodeProjectDir(cwd) === name` narrows to a CLASS, never to a path — `/home/op/my-app` and `/home/op/my/app` share one project directory. First-match-wins lets one record condemn the rest, and transcripts are user-writable, so that record can be PLANTED. Any live member now yields `alive`; `dead` requires every member to be definitively gone.
72
+
73
+ **The budget is shared across the whole sweep, not per project.** A bound that resets each iteration is not a bound — that is what produced the 64M figure.
74
+
75
+ Adoption (for a product that already wrote this search): supply `candidatePaths` returning REAL ABSOLUTE PATHS — not encoded directory names, which is the distinction that made 6 of 6 live projects classify `dead` while the two sides were being wired together — pass `projectsRoot` via the exported `projectsRoot()` rather than joining the segment by hand, and give `fs` an `exists` that returns `undefined` for every errno except ENOENT.
76
+
3
77
  ## 9.4.0
4
78
 
5
79
  ### Minor Changes
package/dist/ask.d.ts CHANGED
@@ -118,7 +118,7 @@ declare function createAskBridge(): AskBridge;
118
118
  * and tested without a mock.
119
119
  */
120
120
  /** A decision waiting for a human, as the surface knows it. */
121
- interface PendingItem {
121
+ interface PendingItem<TPayload = undefined> {
122
122
  /** The framework's id for the decision (an approval id, a question id). */
123
123
  readonly id: string;
124
124
  /**
@@ -128,15 +128,27 @@ interface PendingItem {
128
128
  * everything attached to messages that no longer exist.
129
129
  */
130
130
  readonly messageIndex: number;
131
+ /**
132
+ * The SURFACE's own state for this item — render timestamps, collapsed flags, whatever it needs.
133
+ *
134
+ * T2.7. The framework never reads it; it is carried, not interpreted. Without this slot a surface
135
+ * adopting the ledger has to keep a SECOND map keyed by the same id, which is strictly worse than
136
+ * the single map it already maintains — and that is the measured reason `createPendingLedger`
137
+ * shipped and went unused while a hand-written ledger stayed in the only real consumer.
138
+ *
139
+ * The default of `undefined` is what keeps this non-breaking: every existing caller writes
140
+ * `PendingItem` with no argument and passes items with no payload.
141
+ */
142
+ readonly payload?: TPayload;
131
143
  }
132
- interface PendingLedger {
144
+ interface PendingLedger<TPayload = undefined> {
133
145
  /**
134
146
  * Record what the framework reports as pending.
135
147
  *
136
148
  * Additive and idempotent: the same list arrives on every poll. An id already settled is NOT
137
149
  * re-added — that single rule is what stops the dismissed card from coming back.
138
150
  */
139
- ingest(items: readonly PendingItem[]): void;
151
+ ingest(items: readonly PendingItem<TPayload>[]): void;
140
152
  /**
141
153
  * Mark one as answered. `false` when it was unknown or already settled.
142
154
  *
@@ -145,7 +157,7 @@ interface PendingLedger {
145
157
  */
146
158
  settle(id: string): boolean;
147
159
  /** The oldest unsettled item, or `undefined`. A surface shows one at a time. */
148
- findNext(): PendingItem | undefined;
160
+ findNext(): PendingItem<TPayload> | undefined;
149
161
  /**
150
162
  * Forget everything attached to a message before `messageIndex`, settled or not. Returns how many
151
163
  * unsettled items were dropped.
@@ -154,7 +166,7 @@ interface PendingLedger {
154
166
  */
155
167
  pruneBefore(messageIndex: number): number;
156
168
  }
157
- declare function createPendingLedger(): PendingLedger;
169
+ declare function createPendingLedger<TPayload = undefined>(): PendingLedger<TPayload>;
158
170
 
159
171
  /**
160
172
  * M77 — adapt an {@link AskBridge} to the `askUser` shape the question tool expects.
package/dist/ask.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ask/ask-bridge.ts","../src/ask/pending-ledger.ts","../src/ask/ask-user-via.ts"],"mappings":";;;;;AAAA,SAASA,yBAAyB;AAmC3B,IAAMC,0BAAN,cAAsCC,kBAAAA;EAnC7C,OAmC6CA;;;EACzBC,OAAO;EACzB,YAAYC,UAAkB;AAC5B;MACE,WAAWA,QAAAA;;;;MAMX;QAAEC,MAAM;MAA2B;IAAA;EAEvC;AACF;AAGO,IAAMC,0BAAN,cAAsCJ,kBAAAA;EAnD7C,OAmD6CA;;;EACzBC,OAAO;EACzB,YAAYC,UAAkB;AAC5B,UACE,WAAWA,QAAAA,4LAGX;MAAEC,MAAM;IAA4B,CAAA;EAExC;AACF;AAMO,IAAME,yBAAN,cAAqCL,kBAAAA;EAnE5C,OAmE4CA;;;EACxBC,OAAO;EACzB,YAAYC,UAAkBI,KAAa;AACzC,UAAM,uBAAuBJ,QAAAA,oBAA4BI,GAAAA,IAAO;MAC9DH,MAAM;IACR,CAAA;EACF;AACF;AAgEO,SAASI,kBAAAA;AACd,QAAMC,kBAAkB,oBAAIC,IAAAA;AAC5B,QAAMC,cAAc,oBAAID,IAAAA;AACxB,QAAME,YAAY,oBAAIF,IAAAA;AAEtB,QAAMG,SAAS,wBAACV,UAAkBW,OAAAA;AAChCL,oBAAgBM,OAAOZ,QAAAA;AACvBQ,gBAAYI,OAAOD,EAAAA;EACrB,GAHe;AAKf,SAAO;IACLE,IAAIb,UAAUc,UAAQ;AACpB,UAAIR,gBAAgBS,IAAIf,QAAAA,GAAW;AACjC,eAAOgB,QAAQC,OAAO,IAAIpB,wBAAwBG,QAAAA,CAAAA;MACpD;AACA,YAAMkB,WAAWT,UAAUU,IAAInB,QAAAA;AAC/B,UAAIkB,aAAaE,QAAW;AAG1B,eAAOJ,QAAQC,OACb,IAAId,uBAAuBH,UAAU,wCAAA,CAAA;MAEzC;AAEA,YAAMW,KAAKU,OAAOC,WAAU;AAC5B,YAAMC,UAAU,IAAIP,QAAgB,CAACQ,SAASP,WAAAA;AAC5C,cAAMQ,QAAiB;UACrBd;UACAe,QAAQ,wBAACC,WAAAA;AACPjB,mBAAOV,UAAUW,EAAAA;AACjBa,oBAAQG,MAAAA;UACV,GAHQ;UAIRC,MAAM,wBAACC,UAAAA;AACLnB,mBAAOV,UAAUW,EAAAA;AACjBM,mBAAOY,KAAAA;UACT,GAHM;QAIR;AACAvB,wBAAgBwB,IAAI9B,UAAUyB,KAAAA;AAC9BjB,oBAAYsB,IAAInB,IAAI;UAAE,GAAGc;UAAOzB;QAAS,CAAA;MAC3C,CAAA;AAEAkB,eAASa,OAAO;QAAEpB;QAAIX;QAAUc;MAAS,CAAA;AACzC,aAAOS;IACT;IAEAI,OAAOhB,IAAIgB,QAAM;AACf,YAAMF,QAAQjB,YAAYW,IAAIR,EAAAA;AAG9B,UAAIc,UAAUL,OAAW,QAAO;AAChCK,YAAMC,OAAOC,MAAAA;AACb,aAAO;IACT;IAEAK,QAAQhC,UAAQ;AACd,YAAMyB,QAAQnB,gBAAgBa,IAAInB,QAAAA;AAElC,UAAIyB,UAAUL,OAAW,QAAO;AAChCK,YAAMG,KACJ,IAAIzB,uBAAuBH,UAAU,+CAAA,CAAA;AAEvCS,gBAAUU,IAAInB,QAAAA,GAAWiC,YAAYjC,QAAAA;AACrC,aAAO;IACT;IAEAkC,YAAYlC,UAAUkB,UAAUiB,SAAO;AACrC,UAAI1B,UAAUM,IAAIf,QAAAA,EAAW,OAAM,IAAIE,wBAAwBF,QAAAA;AAC/D,YAAMyB,QAAkB;QACtBM,QAAQb;QACR,GAAIiB,SAASF,cAAcb,UAAa;UAAEa,WAAWE,QAAQF;QAAU;MACzE;AACAxB,gBAAUqB,IAAI9B,UAAUyB,KAAAA;AACxB,aAAO,MAAA;AAGL,YAAIhB,UAAUU,IAAInB,QAAAA,MAAcyB,MAAOhB,WAAUG,OAAOZ,QAAAA;MAC1D;IACF;EACF;AACF;AA/EgBK;;;AC3ET,SAAS+B,sBAAAA;AACd,QAAMC,OAAO,oBAAIC,IAAAA;AAGjB,QAAMC,UAAU,oBAAID,IAAAA;AAEpB,SAAO;IACLE,OAAOC,OAAK;AACV,iBAAWC,QAAQD,OAAO;AACxB,YAAIF,QAAQI,IAAID,KAAKE,EAAE,KAAKP,KAAKM,IAAID,KAAKE,EAAE,EAAG;AAC/CP,aAAKQ,IAAIH,KAAKE,IAAIF,IAAAA;MACpB;IACF;IAEAI,OAAOF,IAAE;AACP,YAAMF,OAAOL,KAAKU,IAAIH,EAAAA;AACtB,UAAIF,SAASM,OAAW,QAAO;AAC/BX,WAAKY,OAAOL,EAAAA;AACZL,cAAQM,IAAID,IAAIF,KAAKQ,YAAY;AACjC,aAAO;IACT;IAEAC,WAAAA;AACE,UAAIC;AACJ,iBAAWV,QAAQL,KAAKgB,OAAM,GAAI;AAGhC,YAAID,WAAWJ,UAAaN,KAAKQ,eAAeE,OAAOF,aAAcE,UAASV;MAChF;AACA,aAAOU;IACT;IAEAE,YAAYJ,cAAY;AACtB,UAAIK,UAAU;AACd,iBAAW,CAACX,IAAIF,IAAAA,KAASL,MAAM;AAC7B,YAAIK,KAAKQ,eAAeA,cAAc;AACpCb,eAAKY,OAAOL,EAAAA;AACZW,qBAAW;QACb;MACF;AAKA,iBAAW,CAACX,IAAIY,EAAAA,KAAOjB,SAAS;AAC9B,YAAIiB,KAAKN,aAAcX,SAAQU,OAAOL,EAAAA;MACxC;AACA,aAAOW;IACT;EACF;AACF;AAlDgBnB;;;AC/BT,SAASqB,WACdC,QAAiB;AAEjB,SAAO,CAACC,UAAUC,aAAAA;AAChB,QAAIA,aAAaC,UAAaD,aAAa,IAAI;AAC7C,aAAOE,QAAQC,OACb,IAAIC,uBACF,UACA,0KACE,CAAA;IAGR;AACA,WAAON,OAAOO,IAAIL,UAAUD,QAAAA;EAC9B;AACF;AAfgBF;","names":["TheokitAgentError","ConcurrentQuestionError","TheokitAgentError","name","threadId","code","ConcurrentListenerError","QuestionAbandonedError","why","createAskBridge","pendingByThread","Map","pendingById","listeners","forget","id","delete","ask","question","has","Promise","reject","listener","get","undefined","crypto","randomUUID","promise","resolve","entry","settle","answer","fail","error","set","notify","abandon","onAbandon","setListener","options","createPendingLedger","open","Map","settled","ingest","items","item","has","id","set","settle","get","undefined","delete","messageIndex","findNext","oldest","values","pruneBefore","dropped","at","askUserVia","bridge","question","threadId","undefined","Promise","reject","QuestionAbandonedError","ask"]}
1
+ {"version":3,"sources":["../src/ask/ask-bridge.ts","../src/ask/pending-ledger.ts","../src/ask/ask-user-via.ts"],"mappings":"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","names":["TheokitAgentError","ConcurrentQuestionError","TheokitAgentError","name","threadId","code","ConcurrentListenerError","QuestionAbandonedError","why","createAskBridge","pendingByThread","Map","pendingById","listeners","forget","id","delete","ask","question","has","Promise","reject","listener","get","undefined","crypto","randomUUID","promise","resolve","entry","settle","answer","fail","error","set","notify","abandon","onAbandon","setListener","options","createPendingLedger","open","Map","settled","ingest","items","item","has","id","set","settle","get","undefined","delete","messageIndex","findNext","oldest","values","pruneBefore","dropped","at","askUserVia","bridge","question","threadId","undefined","Promise","reject","QuestionAbandonedError","ask"]}
@@ -409,6 +409,8 @@ interface HitlWiring {
409
409
  * an absent rule resolves to `ask`.
410
410
  */
411
411
 
412
+ /** The map of gated tools that `compileAgentDefinition` produces (`compiled.hitl`). */
413
+ type GatedTools = ReadonlyMap<string, HumanInTheLoopOptions>;
412
414
  /**
413
415
  * What this surface does when a gated tool asks for approval. Four variants, none of them
414
416
  * "omission" — each with a concrete consumer and a written reason.
@@ -461,6 +463,20 @@ type ApprovalPosture = {
461
463
  kind: 'owned-by-surface';
462
464
  reason: string;
463
465
  };
466
+ /**
467
+ * Writes the plugins the posture requires into `extra` — the object `toAgentFactory` spreads AFTER
468
+ * `m8` into the `Agent.create` options, and which therefore wins. Plugins already present (from the
469
+ * agent, via `m8`, and from an override, via `extra`) are preserved: running them over is the M14
470
+ * regression that `buildExtraCreateOptions` already carries a guard against.
471
+ *
472
+ * The legacy `plugins` shape (an `{ enabled }` object) cannot carry both, so a posture that needs to
473
+ * install a plugin alongside it is refused LOUD AND CLEAR, rather than resolved by dropping one of
474
+ * them: silently dropping the approval gate is exactly the class of defect this milestone closes
475
+ * (Rule 8, fail-closed).
476
+ */
477
+ declare function applyPosture(extra: Record<string, unknown>, m8: {
478
+ plugins?: unknown;
479
+ }, posturePolicy: ApprovalPosture, gated: GatedTools | undefined): void;
464
480
 
465
481
  /**
466
482
  * A definition, or a THUNK that produces one per session.
@@ -642,6 +658,85 @@ declare function toAgentFactory(def: DefinitionOrThunk, opts: {
642
658
  overrides?: RuntimeOverrides;
643
659
  }): (sessionId: string) => Promise<SdkAgentHandle>;
644
660
 
661
+ /**
662
+ * T2.1 — "may I auto-approve this tool right now?", as a symbol a surface can call.
663
+ *
664
+ * ## Why this exists next to `approval-posture.ts` rather than inside it
665
+ *
666
+ * {@link applyPosture} answers a different question: *"construct this agent with a gate?"*. It runs
667
+ * once, at factory time, mutating an options bag. A surface asks per EVENT, before it decides
668
+ * whether to render a prompt, and it has no options bag in hand.
669
+ *
670
+ * Until this function existed the only reachable half of the rule was the type. `approval-posture.ts`
671
+ * says in writing that the consumer implemented the refusal twice and calls that a G12 violation —
672
+ * and it was still true when this was written, because the enforcement stayed private. A rule that
673
+ * lives in an unexported function lives once for the framework and zero times for everyone else.
674
+ *
675
+ * ## The invariant, stated once
676
+ *
677
+ * **Nothing auto-approves without positive evidence of enforced confinement.** Two consumer defects
678
+ * reduce to it:
679
+ *
680
+ * - *B-006* — an absent posture counts as unconfined. Absence of evidence is not evidence of
681
+ * confinement, and defaulting the other way silently disables the guard anywhere the posture has
682
+ * not been threaded through.
683
+ * - *B-021* — the headless path made the posture a required argument precisely because omitting it
684
+ * returned "approved" for `full-auto`, skipping the refusal the function exists for.
685
+ *
686
+ * `posture` stays OPTIONAL in the type so a surface mid-migration still compiles; it just gets
687
+ * `false`. Making it required would be the stricter type and the worse outcome — a caller who cannot
688
+ * yet supply it writes its own predicate instead, which is how the duplication started.
689
+ *
690
+ * The peers resolve omission the same way: `codex`'s `GranularApprovalConfig` auto-REJECTS an absent
691
+ * field, and `opencode` resolves an absent rule to `ask`.
692
+ */
693
+
694
+ /**
695
+ * What a surface does about asking, as the three modes a coding agent actually offers.
696
+ *
697
+ * Not a framework invention: these are the values the only real consumer put in front of users, and
698
+ * naming them here is what lets its two copies of the rule become one call.
699
+ */
700
+ declare const APPROVAL_MODES: readonly ["suggest", "auto-edit", "full-auto"];
701
+ type ApprovalMode = (typeof APPROVAL_MODES)[number];
702
+ /**
703
+ * Tools whose writes are bounded by their own write root rather than by the kernel.
704
+ *
705
+ * A CATALOG, not a policy. The names are the SDK factories' defaults (`apply-patch.ts:51`,
706
+ * `edit-file.ts:155`, `write-file.ts:86`), so this answers "does this tool confine its own writes?"
707
+ * — a fact about the SDK. It does NOT answer "may this tool run without asking a human?", which is
708
+ * the product's to decide and is why {@link shouldAutoApprove} does not read this by default. See
709
+ * the `auto-edit` branch there for what conflating the two cost.
710
+ *
711
+ * Genuinely immutable, not merely typed that way. `ReadonlySet` is erased at runtime, and one
712
+ * `as Set<string>` on an approval gate reachable from every consumer of this package would widen
713
+ * what auto-approves everywhere, with no diff in the module that owns the rule. `Object.freeze`
714
+ * alone does not do it: a Set keeps its entries in internal slots rather than own properties, so
715
+ * freezing leaves `add` fully functional — the mutators have to be replaced.
716
+ */
717
+ declare const WRITE_SCOPED_TOOLS: ReadonlySet<string>;
718
+ interface ShouldAutoApproveOptions {
719
+ /**
720
+ * Which tools this PRODUCT lets run without asking, in `auto-edit`.
721
+ *
722
+ * Required in practice: absent, `auto-edit` approves nothing. {@link WRITE_SCOPED_TOOLS} is
723
+ * available for a product that wants every write-scoped tool, but passing it is a decision the
724
+ * product makes, not a default it inherits.
725
+ */
726
+ writeScopedTools?: ReadonlySet<string>;
727
+ }
728
+ /**
729
+ * Whether a gated tool may run without asking a human.
730
+ *
731
+ * Pure over its arguments and holds no state, so a surface can call it per event.
732
+ *
733
+ * @param mode - what the user chose.
734
+ * @param toolName - the name the model sees, which is also the approval key.
735
+ * @param posture - the sandbox's own answer to "am I kernel-enforced right now?". Absent or
736
+ * unenforced means NOT confined, and nothing auto-approves.
737
+ */
738
+ declare function shouldAutoApprove(mode: ApprovalMode, toolName: string, posture?: Pick<SandboxPosture, 'enforced'>, options?: ShouldAutoApproveOptions): boolean;
739
+
645
740
  /**
646
741
  * Model-selection mapping (M1 reasoning-visibility) — the single site that turns a
647
742
  * provider-agnostic `ReasoningEffort` into the SDK `ModelSelection`. Kept in its own small module
@@ -1499,4 +1594,4 @@ declare function agentsPlugin(opts: AgentsPluginOptions): {
1499
1594
  register(app: PluginApp): void;
1500
1595
  };
1501
1596
 
1502
- export { type ToolCallEvent as $, type AgentManifestEntry as A, type BeforeToolCallContext as B, type ContextWindowOptions as C, type DefinitionOrThunk as D, type EphemeralAgent as E, type ErrorEvent as F, type FileEditEvent as G, type HitlDecision as H, type IterationEvent as I, McpFileError as J, type McpRegistryConfig as K, type LLMCallContext as L, type McpApprovalSpec as M, type McpRequestContext as N, type McpSelection as O, type PartialToolCallEvent as P, type ProcessInputContext as Q, type RunStartedEvent as R, type SkillsOptions as S, type SdkAgentHandle as T, type SdkMessage as U, type SdkSendOptions as V, type SdkTurnHandle as W, type Segment as X, type StateUpdateEvent as Y, type TextDeltaEvent as Z, type ThinkingEvent as _, type ApprovalPosture as a, type ToolCallVeto as a0, type ToolHooks as a1, type ToolHooksPlugin as a2, type ToolResultEvent as a3, agentsPlugin as a4, buildModelSelection as a5, compileAgentModule as a6, compileContextWindow as a7, compileProjectContext as a8, compileSkills as a9, withClockCap as aA, withEphemeralAgent as aB, createAgentExecutionContext as aa, createApiErrorHandler as ab, createSdkAgentStream as ac, createThinkTagExtractor as ad, createToolHooksPlugin as ae, extractThinkTagStream as af, generateAgentManifest as ag, generateAgentRoutes as ah, isAgentContext as ai, isApprovalRequired as aj, isDone as ak, isError as al, isPartialToolCall as am, isTextDelta as an, isToolCall as ao, isToolResult as ap, loadMcpJson as aq, mcpRegistry as ar, mcpToolApprovals as as, presentUIMessageStream as at, projectContextMetadataOnlyKnobs as au, reasoningEffortOf as av, resolveMcpServers as aw, runWithApiErrorHandling as ax, toAgentFactory as ay, translateSdkEvent as az, type AfterToolCallContext as b, AgentBuilder as c, AgentDefinitionError as d, type AgentExecutionContext as e, type AgentManifest as f, type AgentManifestSource as g, type AgentManifestTool as h, type AgentRoute as i, type AgentRouteContext as j, type AgentRunInfo as k, type AgentStreamEvent as l, type AgentTurnMetadata as m, type AgentsPluginOptions as n, type ApiErrorContext as o, type ApiErrorDecision as p, type ApiErrorPolicy as q, type ApprovalRequiredEvent as r, streamAgentUIMessages as s, type ArtifactChunkEvent as t, type ArtifactStartEvent as u, type CheckpointSavedEvent as v, type CompiledContextWindow as w, ContextualTool as x, DelegationTimeoutError as y, type DoneEvent as z };
1597
+ export { type StateUpdateEvent as $, type AgentManifestEntry as A, type BeforeToolCallContext as B, type ContextWindowOptions as C, type DefinitionOrThunk as D, DelegationTimeoutError as E, type DoneEvent as F, type EphemeralAgent as G, type HitlDecision as H, type ErrorEvent as I, type FileEditEvent as J, type IterationEvent as K, type LLMCallContext as L, type McpApprovalSpec as M, McpFileError as N, type McpRegistryConfig as O, type McpRequestContext as P, type McpSelection as Q, type PartialToolCallEvent as R, type SkillsOptions as S, type ProcessInputContext as T, type RunStartedEvent as U, type SdkAgentHandle as V, type SdkMessage as W, type SdkSendOptions as X, type SdkTurnHandle as Y, type Segment as Z, type ShouldAutoApproveOptions as _, type ApprovalPosture as a, type TextDeltaEvent as a0, type ThinkingEvent as a1, type ToolCallEvent as a2, type ToolCallVeto as a3, type ToolHooks as a4, type ToolHooksPlugin as a5, type ToolResultEvent as a6, WRITE_SCOPED_TOOLS as a7, agentsPlugin as a8, applyPosture as a9, reasoningEffortOf as aA, resolveMcpServers as aB, runWithApiErrorHandling as aC, shouldAutoApprove as aD, toAgentFactory as aE, translateSdkEvent as aF, withClockCap as aG, withEphemeralAgent as aH, buildModelSelection as aa, compileAgentModule as ab, compileContextWindow as ac, compileProjectContext as ad, compileSkills as ae, createAgentExecutionContext as af, createApiErrorHandler as ag, createSdkAgentStream as ah, createThinkTagExtractor as ai, createToolHooksPlugin as aj, extractThinkTagStream as ak, generateAgentManifest as al, generateAgentRoutes as am, isAgentContext as an, isApprovalRequired as ao, isDone as ap, isError as aq, isPartialToolCall as ar, isTextDelta as as, isToolCall as at, isToolResult as au, loadMcpJson as av, mcpRegistry as aw, mcpToolApprovals as ax, presentUIMessageStream as ay, projectContextMetadataOnlyKnobs as az, APPROVAL_MODES as b, type AfterToolCallContext as c, AgentBuilder as d, AgentDefinitionError as e, type AgentExecutionContext as f, type AgentManifest as g, type AgentManifestSource as h, type AgentManifestTool as i, type AgentRoute as j, type AgentRouteContext as k, type AgentRunInfo as l, type AgentStreamEvent as m, type AgentTurnMetadata as n, type AgentsPluginOptions as o, type ApiErrorContext as p, type ApiErrorDecision as q, type ApiErrorPolicy as r, streamAgentUIMessages as s, type ApprovalMode as t, type ApprovalRequiredEvent as u, type ArtifactChunkEvent as v, type ArtifactStartEvent as w, type CheckpointSavedEvent as x, type CompiledContextWindow as y, ContextualTool as z };
package/dist/bridge.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { b as AfterToolCallContext, c as AgentBuilder, d as AgentDefinitionError, e as AgentExecutionContext, f as AgentManifest, A as AgentManifestEntry, g as AgentManifestSource, h as AgentManifestTool, i as AgentRoute, j as AgentRouteContext, k as AgentRunInfo, l as AgentStreamEvent, m as AgentTurnMetadata, n as AgentsPluginOptions, o as ApiErrorContext, p as ApiErrorDecision, q as ApiErrorPolicy, a as ApprovalPosture, r as ApprovalRequiredEvent, t as ArtifactChunkEvent, u as ArtifactStartEvent, B as BeforeToolCallContext, v as CheckpointSavedEvent, w as CompiledContextWindow, x as ContextualTool, D as DefinitionOrThunk, y as DelegationTimeoutError, z as DoneEvent, E as EphemeralAgent, F as ErrorEvent, G as FileEditEvent, I as IterationEvent, L as LLMCallContext, M as McpApprovalSpec, J as McpFileError, K as McpRegistryConfig, N as McpRequestContext, O as McpSelection, P as PartialToolCallEvent, Q as ProcessInputContext, R as RunStartedEvent, T as SdkAgentHandle, U as SdkMessage, V as SdkSendOptions, W as SdkTurnHandle, X as Segment, Y as StateUpdateEvent, Z as TextDeltaEvent, _ as ThinkingEvent, $ as ToolCallEvent, a0 as ToolCallVeto, a1 as ToolHooks, a2 as ToolHooksPlugin, a3 as ToolResultEvent, a4 as agentsPlugin, a5 as buildModelSelection, a6 as compileAgentModule, a7 as compileContextWindow, a8 as compileProjectContext, a9 as compileSkills, aa as createAgentExecutionContext, ab as createApiErrorHandler, ac as createSdkAgentStream, ad as createThinkTagExtractor, ae as createToolHooksPlugin, af as extractThinkTagStream, ag as generateAgentManifest, ah as generateAgentRoutes, ai as isAgentContext, aj as isApprovalRequired, ak as isDone, al as isError, am as isPartialToolCall, an as isTextDelta, ao as isToolCall, ap as isToolResult, aq as loadMcpJson, ar as mcpRegistry, as as mcpToolApprovals, at as presentUIMessageStream, au as projectContextMetadataOnlyKnobs, av as reasoningEffortOf, aw as resolveMcpServers, ax as runWithApiErrorHandling, s as streamAgentUIMessages, ay as toAgentFactory, az as translateSdkEvent, aA as withClockCap, aB as withEphemeralAgent } from './bridge-entry-CmYUgNit.js';
1
+ export { b as APPROVAL_MODES, c as AfterToolCallContext, d as AgentBuilder, e as AgentDefinitionError, f as AgentExecutionContext, g as AgentManifest, A as AgentManifestEntry, h as AgentManifestSource, i as AgentManifestTool, j as AgentRoute, k as AgentRouteContext, l as AgentRunInfo, m as AgentStreamEvent, n as AgentTurnMetadata, o as AgentsPluginOptions, p as ApiErrorContext, q as ApiErrorDecision, r as ApiErrorPolicy, t as ApprovalMode, a as ApprovalPosture, u as ApprovalRequiredEvent, v as ArtifactChunkEvent, w as ArtifactStartEvent, B as BeforeToolCallContext, x as CheckpointSavedEvent, y as CompiledContextWindow, z as ContextualTool, D as DefinitionOrThunk, E as DelegationTimeoutError, F as DoneEvent, G as EphemeralAgent, I as ErrorEvent, J as FileEditEvent, K as IterationEvent, L as LLMCallContext, M as McpApprovalSpec, N as McpFileError, O as McpRegistryConfig, P as McpRequestContext, Q as McpSelection, R as PartialToolCallEvent, T as ProcessInputContext, U as RunStartedEvent, V as SdkAgentHandle, W as SdkMessage, X as SdkSendOptions, Y as SdkTurnHandle, Z as Segment, _ as ShouldAutoApproveOptions, $ as StateUpdateEvent, a0 as TextDeltaEvent, a1 as ThinkingEvent, a2 as ToolCallEvent, a3 as ToolCallVeto, a4 as ToolHooks, a5 as ToolHooksPlugin, a6 as ToolResultEvent, a7 as WRITE_SCOPED_TOOLS, a8 as agentsPlugin, a9 as applyPosture, aa as buildModelSelection, ab as compileAgentModule, ac as compileContextWindow, ad as compileProjectContext, ae as compileSkills, af as createAgentExecutionContext, ag as createApiErrorHandler, ah as createSdkAgentStream, ai as createThinkTagExtractor, aj as createToolHooksPlugin, ak as extractThinkTagStream, al as generateAgentManifest, am as generateAgentRoutes, an as isAgentContext, ao as isApprovalRequired, ap as isDone, aq as isError, ar as isPartialToolCall, as as isTextDelta, at as isToolCall, au as isToolResult, av as loadMcpJson, aw as mcpRegistry, ax as mcpToolApprovals, ay as presentUIMessageStream, az as projectContextMetadataOnlyKnobs, aA as reasoningEffortOf, aB as resolveMcpServers, aC as runWithApiErrorHandling, aD as shouldAutoApprove, s as streamAgentUIMessages, aE as toAgentFactory, aF as translateSdkEvent, aG as withClockCap, aH as withEphemeralAgent } from './bridge-entry-emr2PSXC.js';
2
2
  export { C as CompiledAgentOptions, b as CompiledTool, l as ToolWalkResult, n as ToolboxWalkResult, o as compileTools } from './agent-compiler-CIPQkehU.js';
3
3
  export { B as BackgroundDelegation, d as BudgetExceededError, f as DelegateFn, a as DelegateOptions, g as DelegationBudgetExceededError, h as DelegationError, i as DelegationPort, c as DelegationResult, D as DelegationTarget, p as ScoreVerdict, q as ScoredDelegation, r as Scorer, S as StreamEvent, s as delegate, t as delegateBackground, u as delegateWithScoring, A as streamAgentResponse } from './delegation-scoring-CDvtrYKd.js';
4
4
  export { a as AGENT_BRAND, A as AgentDefinition, D as DefineAgentConfig, I as InferAgentInput, b as InferAgentToolNames, P as ProjectSettingsGrant, c as SettingSourceCapability, S as SettingSourcesSelection, U as UntrustedSettingSourceError, d as compileAgentDefinition, i as isAgentDefinition, r as resolveSettingSources } from './define-agent-BO5QSjV8.js';
package/dist/bridge.js CHANGED
@@ -28,12 +28,15 @@ import {
28
28
  runWithApiErrorHandling,
29
29
  streamAgentResponse,
30
30
  streamAgentUIMessages
31
- } from "./chunk-CAXGTLRU.js";
31
+ } from "./chunk-QJN2LLPF.js";
32
32
  import {
33
+ APPROVAL_MODES,
33
34
  BudgetExceededError,
34
35
  DelegationBudgetExceededError,
35
36
  DelegationError,
36
37
  DelegationTimeoutError,
38
+ WRITE_SCOPED_TOOLS,
39
+ applyPosture,
37
40
  buildModelSelection,
38
41
  compileProjectContext,
39
42
  createSdkAgentStream,
@@ -45,11 +48,12 @@ import {
45
48
  extractThinkTagStream,
46
49
  projectContextMetadataOnlyKnobs,
47
50
  reasoningEffortOf,
51
+ shouldAutoApprove,
48
52
  toAgentFactory,
49
53
  translateSdkEvent,
50
54
  withClockCap,
51
55
  withEphemeralAgent
52
- } from "./chunk-W6TABP2S.js";
56
+ } from "./chunk-CKRM5Q2K.js";
53
57
  import "./chunk-RKWCXVYG.js";
54
58
  import {
55
59
  AGENT_BRAND,
@@ -61,6 +65,7 @@ import {
61
65
  import "./chunk-Z4QWC7IK.js";
62
66
  export {
63
67
  AGENT_BRAND,
68
+ APPROVAL_MODES,
64
69
  AgentBuilder,
65
70
  AgentDefinitionError,
66
71
  BudgetExceededError,
@@ -70,7 +75,9 @@ export {
70
75
  DelegationTimeoutError,
71
76
  McpFileError,
72
77
  UntrustedSettingSourceError,
78
+ WRITE_SCOPED_TOOLS,
73
79
  agentsPlugin,
80
+ applyPosture,
74
81
  buildModelSelection,
75
82
  compileAgentDefinition,
76
83
  compileAgentModule,
@@ -107,6 +114,7 @@ export {
107
114
  resolveMcpServers,
108
115
  resolveSettingSources,
109
116
  runWithApiErrorHandling,
117
+ shouldAutoApprove,
110
118
  streamAgentResponse,
111
119
  streamAgentUIMessages,
112
120
  toAgentFactory,