@theokit/agents 14.5.0 → 15.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/README.md +44 -15
  3. package/dist/{agent-compiler-D7-Xd6Zh.d.ts → agent-compiler-DEMJlZNS.d.ts} +225 -6
  4. package/dist/auth.js +1 -1
  5. package/dist/{bridge-entry-kh9JllQT.d.ts → bridge-entry-qz6EGrLd.d.ts} +87 -6
  6. package/dist/bridge.d.ts +4 -5
  7. package/dist/bridge.js +5 -3
  8. package/dist/{chunk-5WS66AW7.js → chunk-3DAWVAHP.js} +7 -1
  9. package/dist/chunk-3DAWVAHP.js.map +1 -0
  10. package/dist/{chunk-D2EFYZBV.js → chunk-4ULFP7GK.js} +2 -3
  11. package/dist/chunk-4ULFP7GK.js.map +1 -0
  12. package/dist/{chunk-DLBGAMHP.js → chunk-A2FQ2C35.js} +33 -6
  13. package/dist/chunk-A2FQ2C35.js.map +1 -0
  14. package/dist/{chunk-44IHBFL6.js → chunk-FLTPPA4Y.js} +98 -33
  15. package/dist/chunk-FLTPPA4Y.js.map +1 -0
  16. package/dist/config.d.ts +57 -7
  17. package/dist/config.js +53 -7
  18. package/dist/config.js.map +1 -1
  19. package/dist/{delegation-scoring-CH9Mr9NF.d.ts → delegation-scoring-Bbr4zCpR.d.ts} +2 -2
  20. package/dist/hooks.js +1 -1
  21. package/dist/index.d.ts +21 -10
  22. package/dist/index.js +13 -6
  23. package/dist/index.js.map +1 -1
  24. package/dist/mcp-health.d.ts +1 -1
  25. package/dist/session.js +1 -1
  26. package/dist/testing.d.ts +3 -4
  27. package/dist/testing.js +1 -1
  28. package/dist/tools.d.ts +13 -7
  29. package/dist/tools.js +2 -2
  30. package/dist/tools.js.map +1 -1
  31. package/dist/{types-C16Wuh9E.d.ts → types-CxI2x6mU.d.ts} +38 -10
  32. package/package.json +2 -2
  33. package/dist/chunk-44IHBFL6.js.map +0 -1
  34. package/dist/chunk-5WS66AW7.js.map +0 -1
  35. package/dist/chunk-D2EFYZBV.js.map +0 -1
  36. package/dist/chunk-DLBGAMHP.js.map +0 -1
  37. package/dist/define-agent-y3fsG91f.d.ts +0 -188
package/CHANGELOG.md CHANGED
@@ -1,5 +1,149 @@
1
1
  # @theokit/agents
2
2
 
3
+ ## 15.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - d4c00bb: **Breaking:** `CheckpointOptions` is narrowed to `{ resumeSignal?: boolean }`. `storage`, `strategy`,
8
+ `maxCheckpoints` and `ttl` are removed, along with the `CheckpointStorage` and `CheckpointStrategy`
9
+ types.
10
+
11
+ The option read as a durable-checkpoint configuration and was a signalling flag: four fields
12
+ declared, exactly one ever read, as an `=== 'filesystem'` equality deciding whether a
13
+ `checkpoint_saved` event is emitted. `'drizzle'` and `'redis'` were indistinguishable from
14
+ `'memory'` in every code path.
15
+
16
+ The warning that pushed authors toward `'filesystem'` is gone. It said that value "selects the SDK's
17
+ durable conversation store"; the SDK persists every session to its transcript regardless, so it
18
+ selected nothing — and on a pod with no volume it named the one storage that is unreachable.
19
+
20
+ **Migration:** delete the removed fields; they configured nothing. `storage: 'filesystem'` becomes
21
+ `resumeSignal: true` if you want the `checkpoint_saved` event. Resume itself is a property of the
22
+ SDK's session transcript and needs no option.
23
+
24
+ ### Minor Changes
25
+
26
+ - c3d677d: An SDK that cannot read a foreign configuration root is now refused with a typed
27
+ `CompatRootUnsupportedError`, instead of warned about.
28
+
29
+ `compatSources` landed in `@theokit/sdk@5.0.0`. Below it the option is accepted and ignored, so every
30
+ `.claude/` surface is unavailable while the package resolves, compiles and runs. A `console.warn`
31
+ stood there, and its own text named the condition that kept it a warning: "Until this package's floor
32
+ can name a stable 5.x". The floor is `^5.3.0`, so the only way to reach that branch is an override —
33
+ and an override that silently disables every foreign surface is what a refusal is for.
34
+
35
+ Separate from `CompatImportUnsupportedError`, which is about narrowing a root the SDK can already
36
+ read (5.4.0). Reusing it would name the wrong version and send the reader to the wrong upgrade.
37
+
38
+ - fb80f7d: `createPermissionsPlugin` now requires a gate for the `ask` verdict, and `AgentBuilder` gained
39
+ `.subagents()`.
40
+
41
+ The gate is mandatory rather than optional because its absence had a silent, catastrophic default:
42
+ `PermissionEngine` answers `ask` for a tool no rule matches, and the SDK turns that into a hard block
43
+ when nothing answers it. Wiring the engine without a gate made every tool an operator had not
44
+ enumerated stop working, the moment they wrote any `permissions` block at all.
45
+
46
+ `.subagents()` supplies subagent definitions by name, reaching `AgentOptions.agents`. It is distinct
47
+ from `settingSources`, which discovers them: the framework reads `.claude/agents/<name>.md` and takes
48
+ the prompt from the file, so a caller that enriched a definition — `applySubagentMemory` folding in a
49
+ `MEMORY.md` is the measured case — had nowhere to put the result and it was silently discarded.
50
+
51
+ - b81957c: `FOREIGN_KEY_DECISIONS` records what this package does with each `.claude/settings.json` key its
52
+ diagnostics name, and why — `honoured` or `refused`, each with a reason about this product rather
53
+ than about the reference.
54
+
55
+ `model` and `cleanupPeriodDays` join the settings schema as honoured keys. Reporting a key as "not
56
+ implemented here" says the code does not act on it; it never says whether that is a refusal or an
57
+ omission, and an author reading it cannot tell whether to stop writing the key or to wait for it.
58
+
59
+ ### Patch Changes
60
+
61
+ - 4aa6602: Documents that a subagent's `memory:` declaration needs `@theokit/sdk@5.9.0`, and pins it
62
+ with a test.
63
+
64
+ `applySubagentMemory` shipped in 14.5.0 reading a declaration the SDK parses off subagent
65
+ frontmatter. Before 5.9.0 that parse REFUSES the key — measured against the published
66
+ tarballs, with a control that declares no `memory:` and loads on both:
67
+
68
+ 5.3.0 ConfigurationError: Subagent note-taker.md: unknown frontmatter field "memory"
69
+ (accepted: name, description, model, tools, reasoning_effort, mcp, sandbox)
70
+ 5.9.0 loads both; `memory: "project"` survives
71
+
72
+ The failure was never silent. What misleads is where it points: naming the field reads as a
73
+ typo, so the line an author meant to write gets deleted instead of the SDK upgraded.
74
+
75
+ **The range is unchanged at `^5.3.0`, and there is no runtime guard.** Both were tried and
76
+ both were refused by gates that were right. Raising the floor is refused by
77
+ `the-declared-sdk-range-delivers-what-the-code-assumes.test.ts`, which holds that a gap
78
+ announcing itself is guarded rather than closed by the range — closing it strands every
79
+ consumer, including those who never write `memory:`. A guard is refused by the bundle
80
+ budget: wiring one into `listSubagentNames` cost **161 bytes** of a root barrel with 72 of
81
+ headroom, and the cost is the COUPLING rather than the code — four different bodies produced
82
+ byte-identical bundles, and a dedicated module was worse at 40 403 because it duplicated
83
+ `createRequire`.
84
+
85
+ So the requirement is documented where someone hits it, and a test fails if it stops being
86
+ true. `applySubagentMemory` itself needs no particular SDK: it reads `node:fs`, takes an
87
+ object, and works on any version — the requirement belongs to the parser.
88
+
89
+ - f6a5526: Two rows of the foreign-surfaces table were false, and a test now checks the class they
90
+ belong to.
91
+
92
+ `agent-memory/` read _"Measured 2026-09-15: no consumer does yet"_ while `apps/theocode`
93
+ imported `applySubagentMemory` and applied it in `delegation/role-discovery.ts:84-85`. The
94
+ measurement was true when taken — the consumer could not call it, because the function was
95
+ not in the version it pinned, and its own source says so: _"the one line that wires it does
96
+ not compile here yet"_. The integration was written, tested, and left disconnected, waiting
97
+ on a publish. Nothing about either side changed; the consumer moved into this repository and
98
+ the import resolved.
99
+
100
+ `themes/*.json` read _"nobody reads it, in any of the three packages"_ and never said which
101
+ three. Naming them took one edit and the sentence failed immediately: `apps/theocode`
102
+ resolves `~/.claude/themes/` in `tui/src/theme/custom-theme.ts`, with three reads in that one
103
+ file. It is the same shape as `keybindings.json` — out of scope HERE, read by the consumer —
104
+ which this section had explicitly denied.
105
+
106
+ **A claim nobody can check is not a weaker claim; it is a claim that has never been tested.**
107
+
108
+ `an-absence-is-a-decision-or-it-is-a-gap.test.ts` now confronts any row asserting an absence
109
+ of consumption with the consumer's own source, and fails naming both. It reads TABLE ROWS
110
+ rather than the file — the first version matched the prose explaining the old claim, which is
111
+ the mistake that file already records one block below. Positive controls on both rows: each
112
+ restored claim fails the test with the reason.
113
+
114
+ - 3d73fd2: Every text-bearing channel a client receives now reflects the declared output guards.
115
+
116
+ `DoneEvent.result` was not moderated: with a redactor declared, one turn delivered `text_delta ->
117
+ "here: [R]"` and `done.result -> "here: sk-abc123"`, so a client rendering the terminal frame got the
118
+ secret the guard existed to remove. It is now rebuilt from the round's own moderated deltas — which is
119
+ exact rather than approximate, because the frame carries the visible text of its own round.
120
+
121
+ `task_progress.text` — the fourth channel — takes an ordinary third `moderateOutputStream` pass on
122
+ both the runner and the served path. It is not a mirror of anything: it carries text the model writes
123
+ through `task-tools`, and a milestone naming a secret is the same disclosure as a delta naming it.
124
+
125
+ - Updated dependencies [54d87cf]
126
+ - @theokit/presenter@0.10.0
127
+
128
+ ## 14.5.1
129
+
130
+ ### Patch Changes
131
+
132
+ - b5d26e9: `applySubagentMemory` now resolves the `user` scope, which it could never resolve before.
133
+
134
+ It built its input as `{ ...(home === undefined ? {} : { home }) }` while `resolveAgentMemory`
135
+ reads `input.homeDir`. Every `user`-scope call threw `memory scope "user" needs a home directory
136
+ and none was given` — with a home directory that had been given. `project` and `local` were
137
+ unaffected: they read `cwd`, which was never renamed.
138
+
139
+ TypeScript could not see it. The field arrives through a SPREAD, where excess-property checking
140
+ does not apply, and `homeDir` is optional, so its absence is legal. An optional field plus a
141
+ spread is a silent rename.
142
+
143
+ Six tests covered this function and all six declared `project`, so the one root that needs `home`
144
+ went through it zero times. Found by wiring the function into a consumer for the first time — the
145
+ call that had never existed is what ran the branch that had never run.
146
+
3
147
  ## 14.5.0
4
148
 
5
149
  ### Minor Changes
package/README.md CHANGED
@@ -98,10 +98,10 @@ configuration that had no effect.
98
98
  | `skills/`, `agents/`, `commands/`, `plugins/` | read when the dialect is declared |
99
99
  | `.mcp.json` | read; a field this runtime does not carry is reported |
100
100
  | `output-styles/*.md` | read, selected by `settings.json` |
101
- | `agent-memory/` | **resolvable** — the SDK carries the declaration, `applySubagentMemory` applies it, and the host decides whether to call it. Measured 2026-09-15: no consumer does yet |
101
+ | `agent-memory/` | **read** — `applySubagentMemory` applies a subagent's `memory:` declaration, and `apps/theocode` calls it (`apps/theocode/packages/agent/src/delegation/role-discovery.ts`). The host still decides: nothing here calls it for you |
102
102
  | `workflows/*.js` | **refused**, and reported. Every other surface is data; a workflow is code, and executing JavaScript found under a caller-supplied directory is a decision that belongs to you |
103
103
  | `keybindings.json` | **out of scope HERE** — read by the consumer, see below |
104
- | `themes/*.json` | **out of scope** — nobody reads it, in any of the three packages |
104
+ | `themes/*.json` | **out of scope HERE** — read by the consumer, like `keybindings.json`. `apps/theocode` resolves `~/.claude/themes/` in `apps/theocode/packages/tui/src/theme/custom-theme.ts`; this package and `@theokit/tui` read neither |
105
105
  | `~/.claude.json` — OAuth state, UI toggles | **out of scope** — a CLI's own state |
106
106
  | `~/.claude.json` — personal-scope MCP servers | **read** — `loadPersonalMcpServers` |
107
107
 
@@ -124,8 +124,10 @@ in `terminal-io/keybindings.ts`, against a format it measured against the publis
124
124
  Naming the toolkit as the owner sent a reader to the package that does the least with it — and the
125
125
  row said `out of scope` without saying out of scope FOR WHOM, which is the half that misleads.
126
126
 
127
- `themes/*.json` is read by nobody, in any of the three packages. That is a genuine gap rather than a
128
- delegation, and it is stated here rather than implied by an ownership that does not exist.
127
+ `themes/*.json` is read by the CONSUMER, exactly as `keybindings.json` is: `apps/theocode` resolves
128
+ `~/.claude/themes/` in `apps/theocode/packages/tui/src/theme/custom-theme.ts` and selects one through `/theme custom:<slug>`.
129
+ This package reads it in 0 files and so does `@theokit/tui` — measured 2026-09-17 against the
130
+ installed 0.80.0.
129
131
 
130
132
  **`~/.claude.json` is two things under one name, and the split is the point.** Its OAuth state and UI
131
133
  toggles are a CLI's own state — that file is written by a specific program about its own session, and
@@ -148,9 +150,16 @@ The registry entry that prompted this counts four decisions across three files,
148
150
 
149
151
  ### `themes/*.json`
150
152
 
151
- Read by none of the three packages, measured 2026-09-15. After `keybindings.json` turned out to be
152
- read by the consumer rather than by the package it was attributed to, the obvious next move was to
153
- treat this as the same finding. It is not.
153
+ Read by the consumer, measured 2026-09-17. After `keybindings.json` turned out to be read by
154
+ `apps/theocode` rather than by the package it was attributed to, the obvious next move was to treat
155
+ this as the same finding — and it **is** the same finding, which this document denied until the
156
+ three packages were named.
157
+
158
+ The denial is worth keeping, because it shows what an unfalsifiable sentence costs. This section
159
+ read *"nobody reads it, in any of the three packages"* and never said which three. A reader could
160
+ not check a set they could not enumerate, so nobody did; naming them took one edit, and the sentence
161
+ was false the moment it became checkable — `apps/theocode` resolves `~/.claude/themes/` in
162
+ `apps/theocode/packages/tui/src/theme/custom-theme.ts`, with three reads in that one file.
154
163
 
155
164
  This package has no colour at all — a grep for `color`, `chalk` or `theme` across its source returns
156
165
  nothing, the one apparent hit being `ansi` inside `stateTransitionHistory`. It produces text and tool
@@ -207,15 +216,28 @@ and not applied, so nobody believes it took effect.
207
216
  **200 lines, capped at 25KB**, of its `MEMORY.md` — both caps apply, and truncation is reported
208
217
  rather than silent.
209
218
 
210
- **The host calls it. Nothing here calls it for you, and `memory:` in subagent frontmatter does not
211
- reach it.** Measured 2026-09-15: `resolveAgentMemory` has no caller in this repository outside its
212
- own tests, and `@theokit/sdk` — which is the package that loads `.claude/agents/*.md`, and does not
213
- depend on this one — lists `memory` among the fields it refuses, so a file declaring it is skipped
214
- with a diagnostic rather than granted a directory.
219
+ **The host calls it. Nothing here calls it for you** — and that sentence is the whole contract: this
220
+ package exposes the reader, an application wires it.
221
+
222
+ One does. `apps/theocode` imports `applySubagentMemory` from `@theokit/agents/config` and applies it
223
+ to both role sets in `apps/theocode/packages/agent/src/delegation/role-discovery.ts:84`; that reaches `resolveAgentMemory`
224
+ through `agent-memory.ts:231`. So the chain runs end to end, and this document says **read** rather
225
+ than **resolvable**.
226
+
227
+ It said the opposite until 2026-09-16, and the reason is worth keeping because it is the failure
228
+ mode this table exists to prevent. The measurement behind *"no consumer does yet"* was true when
229
+ taken: the consumer could not call it. Its own source says why — *"`applySubagentMemory` … is NOT in
230
+ the published 14.4.0 this project pins, so the one line that wires it does not compile here yet"*.
231
+ The integration was written, tested, and left disconnected, waiting on a publish.
232
+
233
+ What changed is not the code on either side. `apps/theocode` joined this repository, `@theokit/agents`
234
+ resolves through the workspace, and the line compiled. **A capability can be published, correct, and
235
+ unreachable** — and a document that reports the reachable state as the real one is reporting a
236
+ delivery problem as a design decision.
215
237
 
216
- Saying "read" in the table above, as this document did until that measurement, put this surface in
217
- the same column as `CLAUDE.md` and implied a wiring that does not exist. The reader is real and the
218
- three roots below are real; what an author supplies is the call.
238
+ `@theokit/sdk` before 5.9.0 refuses `memory:` in frontmatter entirely, naming the field rather than
239
+ the version — `agent-memory.ts` carries that measurement, and
240
+ `the-sdk-version-that-parses-memory.test.ts` pins it.
219
241
 
220
242
  | `memory:` | Root | Who can see it |
221
243
  |---|---|---|
@@ -270,6 +292,13 @@ which is a worse failure than never having documented it.
270
292
  Those are the SDK's, and a PR that adds one here is rejected on sight.
271
293
  - It does **not** depend on the `theokit` web framework. The dependency runs the other way.
272
294
  - Web Standards over Node APIs inside `src/` — `Request`/`Response`, `fetch`, `crypto.randomUUID`.
295
+ Two `node:crypto` imports remain and both are measured rather than overlooked: `createHash` in
296
+ `packages/agents/src/hooks/hook-fingerprint.ts`, because the Web equivalent is async and this
297
+ function is not, and `randomBytes` in `packages/agents/src/hooks/hook-spec.ts`, where
298
+ `getRandomValues` would buy conformance at the cost of a hand-written hex conversion. A third
299
+ was removed on 2026-09-17: `randomUUID` had no such defence — the global is the API this line
300
+ names, and three other files in the package were already using it.
301
+ File reads keep `node:fs`: there is no Web Standard to prefer.
273
302
  Node APIs live in adapters.
274
303
 
275
304
  ## Who decides policy
@@ -1,8 +1,10 @@
1
- import { InlineSkill, SystemPromptResolver, SessionStore, PermissionGate, MemorySettings, SkillsSettings, ContextSettings, TelemetrySettings } from '@theokit/sdk';
2
- import { AgentDefinition } from '@theokit/sdk/subagents-loader';
1
+ import { InlineSkill, CustomTool, MemorySettings, TelemetrySettings, SystemPromptResolver, SessionStore, PermissionGate, SkillsSettings, ContextSettings } from '@theokit/sdk';
2
+ import { AgentDefinition as AgentDefinition$1 } from '@theokit/sdk/subagents-loader';
3
3
  import { TheokitAgentError } from '@theokit/sdk/errors';
4
- import { R as ReasoningEffort, a as MemoryOptions, P as ProjectContextOptions, M as McpServersMap, H as HumanInTheLoopOptions, C as CheckpointOptions, T as ToolOptions, A as ApprovalOptions, B as BudgetOptions } from './types-C16Wuh9E.js';
5
- import { G as GatedSettingSource, a as GatedCompatSource } from './setting-sources-gate-BJJiKq33.js';
4
+ import { R as ReasoningEffort, H as HumanInTheLoopOptions, M as McpServersMap, a as MemoryOptions, P as ProjectContextOptions, C as CheckpointOptions, T as ToolOptions, A as ApprovalOptions, B as BudgetOptions } from './types-CxI2x6mU.js';
5
+ import { z } from 'zod';
6
+ import { S as SettingSourcesSelection, G as GatedSettingSource, a as GatedCompatSource } from './setting-sources-gate-BJJiKq33.js';
7
+ import { H as HookHandlers } from './hook-handlers-Cw2FsnE5.js';
6
8
 
7
9
  /**
8
10
  * M9 (theokit-ai-first) — guardrail contract + typed errors.
@@ -277,6 +279,214 @@ declare class CompatImportUnsupportedError extends TheokitAgentError {
277
279
  constructor(version: string | undefined);
278
280
  }
279
281
 
282
+ /**
283
+ * M2 (theokit-ai-first) — `defineAgent`, the zero-config imperative agent surface.
284
+ *
285
+ * ADR-B1: `defineAgent({...})` (default-exported from a top-level `agents/<name>.ts`) is
286
+ * the canonical zero-config surface; the `@Agent` class decorator stays the advanced/DI
287
+ * surface. Both compile to {@link CompiledAgentOptions} and run through the same SDK
288
+ * runtime (`createSdkAgentStream`) — one runtime, two syntaxes.
289
+ *
290
+ * This module is PURE metadata (sdk-runtime.md / G2): `defineAgent` describes an agent, it
291
+ * NEVER calls an LLM. It imports only `zod` (types) + the compiler shape — no `theokit`
292
+ * core, preserving the agents → (nothing) dependency direction (G1).
293
+ */
294
+
295
+ /**
296
+ * One subagent, as `AgentOptions.agents` in the SDK takes it.
297
+ *
298
+ * Declared here rather than imported so the framework states its own contract: the SDK's
299
+ * `AgentDefinition` carries fields this bridge does not thread, and re-exporting it would promise
300
+ * every one of them.
301
+ */
302
+ interface SubagentAgentDefinition {
303
+ /** What the model reads when choosing this subagent. */
304
+ readonly description: string;
305
+ /** The instructions it runs with — the field that carries an applied memory. */
306
+ readonly prompt: string;
307
+ /** Tool names it may call. Absent means the framework decides, as it does for a discovered one. */
308
+ readonly tools?: readonly string[];
309
+ }
310
+ /**
311
+ * Brand tag for a `defineAgent` value. `Symbol.for` (global registry, not `Symbol()`) so
312
+ * the brand survives duplicate module instances (dual-package / bundling) — the scanner's
313
+ * brand-check then works regardless of which copy created the definition.
314
+ */
315
+ declare const AGENT_BRAND: unique symbol;
316
+ /** Config accepted by {@link defineAgent}. */
317
+ interface DefineAgentConfig<TInput extends z.ZodType = z.ZodType> {
318
+ /** Zod schema for the request body — lifted into the typed client (M2, {@link InferAgentInput}). */
319
+ input?: TInput;
320
+ /** Model id (e.g. `claude-sonnet-4-6`). Falls back to the SDK default when omitted. */
321
+ model?: string;
322
+ /** Static system prompt. */
323
+ system?: string;
324
+ /** Extended-thinking effort. */
325
+ reasoningEffort?: ReasoningEffort;
326
+ /**
327
+ * theokit#363 — hard ceiling on the agent's tool-calling turns within ONE run. Reaching it ends
328
+ * the turn instead of letting the model keep calling tools; absent ⇒ the SDK's own ceiling (8).
329
+ *
330
+ * Named `maxIterations`, not `maxSteps`, because the concept already has exactly one name here —
331
+ * `@Agent({ maxIterations })`, `@MainLoop({ maxIterations })`, `AgentRunner.stream({ maxIterations })`,
332
+ * `delegate({ maxIterations })` — and one name in the SDK it lowers to (`SendOptions.maxIterations`).
333
+ * A second name would be the only place needing translation, and the translation is invisible where
334
+ * it costs most: the SDK rejects an invalid value with a message naming `SendOptions.maxIterations`,
335
+ * which an author who typed `.maxSteps()` has no way to connect to what they wrote. Familiarity
336
+ * argues for the ai-sdk spelling, but ai-sdk's own name is `stopWhen: stepCountIs(n)` — borrowing
337
+ * "steps" would buy recognition of a word, not of an API.
338
+ */
339
+ maxIterations?: number;
340
+ /**
341
+ * Pre-built tools. Accepts the `@theokit/sdk` `CustomTool` that `defineAgentTool`
342
+ * (theokit/server) and every `@theokit/sdk-tools` factory return (issue #81) — they are
343
+ * normalized to the internal {@link CompiledTool} shape at compile time.
344
+ */
345
+ tools?: readonly CustomTool[];
346
+ /**
347
+ * M7 — run-context: an opaque, per-agent object forwarded to every tool handler's
348
+ * `ctx.context` at run time (injected by the theokit adapter's tool wrapper). Set shared config
349
+ * (e.g. `{ projectRoot }`) ONCE at the agent level instead of baking it into each tool
350
+ * factory. Mirrors ai-sdk `experimental_context`, mastra `RuntimeContext`, and
351
+ * openai-agents-js `RunContext`. Distinct from `@Agent`'s context-window `context`.
352
+ */
353
+ context?: Record<string, unknown>;
354
+ /**
355
+ * M9 — guardrails: input/output guards applied at the framework boundary (ADR-0040 § D2).
356
+ * Input guards run on the user message before the SDK runtime; a `block` fails the run fast.
357
+ * Built-ins live in `@theokit/agents` (`promptInjectionDetector`, `piiDetector`, `costGuard`,
358
+ * `unicodeNormalizer`, `outputModeration`).
359
+ */
360
+ guardrails?: readonly Guardrail[];
361
+ /**
362
+ * M14 — HITL approvals keyed by tool name. Each gated tool pauses the run and emits an
363
+ * `approval_required` event until approved (reuses the same `compiled.hitl` wiring the `@Agent`
364
+ * + `@HumanInTheLoop` path produces). A key that does not match a declared tool fails fast at
365
+ * compile time.
366
+ */
367
+ approvals?: Record<string, HumanInTheLoopOptions>;
368
+ /**
369
+ * M13 — skills selection: a static list (compiled straight to the SDK `skills.enabled`) OR a
370
+ * per-request resolver `(ctx) => string[]` (carried on `compiled.skillsResolver`, resolved by the
371
+ * request path against the run-context). Absent ⇒ the SDK enables every discovered skill.
372
+ */
373
+ skills?: SkillsSelection;
374
+ /**
375
+ * Subagents this agent carries, registered by name — `AgentOptions.agents` in the SDK.
376
+ *
377
+ * #825 — distinct from what `settingSources` discovers, and that distinction is the whole reason it
378
+ * exists. The framework reads `.claude/agents/<name>.md` itself and takes the prompt from the FILE,
379
+ * so a caller that enriches a definition — `applySubagentMemory` folding in a `MEMORY.md` is the
380
+ * measured case — had nowhere to put the result. It computed the enriched copy and the framework
381
+ * used the file's, with nothing reporting a difference.
382
+ *
383
+ * A name declared here and also found on disk is the same subagent; the definition given here is
384
+ * the one that runs, because it is the one an author decided rather than the one a loader guessed.
385
+ */
386
+ subagents?: Record<string, SubagentAgentDefinition>;
387
+ /**
388
+ * theokit-file-based-config — opt into `.theokit/` file-based config (skills, subagents, hooks,
389
+ * MCP, context, cron). The SDK discovers config from these roots under the app's `cwd`:
390
+ * `project` = `<cwd>/.theokit/`, `user` = `~/.theokit/`. Absent ⇒ inline (code) config only.
391
+ *
392
+ * SECURITY (M68): `project` reads `.theokit/hooks.json`, which **executes shell**, so it requires
393
+ * a `TrustPosture` rather than a string. This field used to take `readonly SettingSource[]`, and
394
+ * its own JSDoc justified the risk as *"opt-in because `.theokit/` is the app's own repo (informed
395
+ * consent)"*. That premise holds for a web app whose `cwd` is its own deploy; it does not hold for
396
+ * an agent whose `cwd` is a repository the user just cloned, where `.theokit/` is
397
+ * attacker-controlled content.
398
+ *
399
+ * `user` stays a plain boolean — `~/.theokit/` is the operator's own machine. Omitting a root is
400
+ * not enabling it. The SDK owns discovery + execution (G2 / ADR-0040); theokit resolves the
401
+ * selection through `resolveSettingSources` and wires the result into
402
+ * `Agent.create({ local.settingSources })`.
403
+ */
404
+ settingSources?: SettingSourcesSelection;
405
+ /**
406
+ * #686 — decide whether a hook declared in a config root is spawned at all, BEFORE it runs.
407
+ *
408
+ * Covers any root, including a foreign dialect imported through `settingSources.claudeCode`.
409
+ * Requires `@theokit/sdk >= 5.4.0`: declaring it against an older SDK is REFUSED at assembly
410
+ * rather than forwarded, because a gate that silently does not gate is worse than none.
411
+ */
412
+ hookApproval?: HookApprovalGate;
413
+ /**
414
+ * B-054 — `MEMORY.md` here is NOT the Claude Code CLI's auto-memory file. This is the durable
415
+ * subsystem below: a SQLite+FTS5 store under `.theokit/memory/`, with `memory_search`/`memory_get`
416
+ * tools and no index cap. The CLI's lives under its own home (`CLAUDE_CONFIG_DIR` or `~/.claude`),
417
+ * is capped at 200 lines / 25 KB on read, and is swept on `cleanupPeriodDays` — none of which is
418
+ * implemented here. The SDK READS that directory for interop and does not write to it.
419
+ *
420
+ * Same filename, different directory, different semantics. Stated at both ends because a checklist
421
+ * that greps for `MEMORY.md` finds one and concludes the other exists.
422
+ *
423
+ * M49 — durable memory (the SDK's `.theokit/memory/` subsystem: `Remember:` capture, MEMORY.md
424
+ * store, auto-injected `<memory>` block, `memory_search`/`memory_get` tools). The shape is the
425
+ * SDK's own `MemorySettings` — the canonical runtime contract. Projected into
426
+ * `Agent.create({ memory })` by `assembleM8CreateOptions`.
427
+ */
428
+ memory?: MemorySettings;
429
+ /**
430
+ * B-072 — OpenTelemetry for this agent. Forwarded verbatim to `Agent.create({ telemetry })`,
431
+ * where the SDK emits spans for `agent.send`, `llm.call`, `tool.call` and `memory.search`.
432
+ *
433
+ * `{ enabled: true }` is the minimal opt-in. `@opentelemetry/api` is an OPTIONAL peer of the SDK:
434
+ * without it the whole thing is a silent no-op, which is the usual reason a run reports no spans.
435
+ */
436
+ telemetry?: TelemetrySettings;
437
+ /**
438
+ * Code `Plugin` objects forwarded to `Agent.create({ plugins })` — EXTENSION units (tools,
439
+ * commands, model providers, memory adapters). For lifecycle interception use {@link hooks}.
440
+ */
441
+ /**
442
+ * Code plugins — `{ name, register }`. NOT the Claude Code filesystem-bundle form, which is
443
+ * declared by living in a `plugins/` directory rather than by being passed here (B-055).
444
+ *
445
+ * `readonly unknown[]` is what let the wrong shape through silently.
446
+ */
447
+ plugins?: readonly CodePlugin[];
448
+ /**
449
+ * Lifecycle hooks keyed by `HookName` (`pre_tool_call` may veto via `{ block, message }`). Set by
450
+ * the builder's `hooks()`; converted into a code plugin at `build()` and never reaching the SDK
451
+ * under this name — the plugin is the TRANSPORT, this is the contract callers write against.
452
+ */
453
+ hooks?: HookHandlers | Readonly<Record<string, unknown>>;
454
+ /**
455
+ * MCP servers available to the agent — the builder-chain equivalent of the `@MCP` class
456
+ * decorator. Each key is a server name; the value is the server configuration. Forwarded
457
+ * unchanged to `Agent.create({ mcpServers })` (the SDK owns MCP execution). Absent ⇒ no MCP.
458
+ */
459
+ mcpServers?: McpServersMap;
460
+ }
461
+ /**
462
+ * A branded agent definition — the value {@link defineAgent} returns.
463
+ *
464
+ * `TTools` (M8) is a phantom type parameter carrying the tool-name union: the `AgentBuilder.create()` builder
465
+ * threads its accumulated literal tool names here (`.build()` returns `AgentDefinition<TInput,
466
+ * 'a' | 'b'>`), so the generated client (`.theokit/agents.d.ts`) can expose them via
467
+ * {@link InferAgentToolNames}. `defineAgent` leaves it `string` (its tools array carries no literal
468
+ * names). Never present at runtime.
469
+ */
470
+ type AgentDefinition<TInput extends z.ZodType = z.ZodType, TTools extends string = string> = DefineAgentConfig<TInput> & {
471
+ readonly [AGENT_BRAND]: true;
472
+ readonly __toolNames?: TTools;
473
+ };
474
+ /** Infer the request type of an agent definition from its `input` Zod schema. */
475
+ type InferAgentInput<T> = T extends AgentDefinition<infer S> ? (S extends z.ZodType ? z.infer<S> : never) : never;
476
+ /**
477
+ * Infer the tool-name union of an agent definition (M8). Yields the literal union for agents built
478
+ * with the `AgentBuilder.create()` builder (`'read_file' | 'count_lines'`), or `string` for `defineAgent` agents
479
+ * whose tools array carries no literal names.
480
+ */
481
+ type InferAgentToolNames<T> = T extends AgentDefinition<z.ZodType, infer N> ? N : never;
482
+ /** Brand-check: is `value` a {@link defineAgent} result? */
483
+ declare function isAgentDefinition(value: unknown): value is AgentDefinition;
484
+ /**
485
+ * Lower a definition to the SDK-ready {@link CompiledAgentOptions} — the same shape
486
+ * `compileAgent` (decorator path) produces, so both surfaces converge on one runtime.
487
+ */
488
+ declare function compileAgentDefinition(def: AgentDefinition): CompiledAgentOptions;
489
+
280
490
  /**
281
491
  * Agent compiler — transforms decorator metadata into SDK calls.
282
492
  *
@@ -352,7 +562,7 @@ declare function compileTools(toolboxes: ToolboxWalkResult[], toolboxInstances:
352
562
  * The local type was referenced in exactly two places, both of them its own declaration and the
353
563
  * field that held it, so adopting the SDK shape removed a mismatch rather than migrating users.
354
564
  */
355
- type CompiledSubAgent = AgentDefinition;
565
+ type CompiledSubAgent = AgentDefinition$1;
356
566
  /** Compiled agent options ready for SDK Agent.create(). */
357
567
  interface CompiledAgentOptions {
358
568
  model?: string;
@@ -372,6 +582,15 @@ interface CompiledAgentOptions {
372
582
  * (merged with `cwd`, decoupled from inline skills). Absent ⇒ inline (code) config only.
373
583
  */
374
584
  settingSources?: readonly GatedSettingSource[];
585
+ /**
586
+ * #825 — subagents the AUTHOR declared, carried through to `AgentOptions.agents`.
587
+ *
588
+ * Beside `settingSources` on purpose: that field says which roots the SDK may DISCOVER subagents
589
+ * in, and this one says which subagents exist with which instructions. A caller that applied a
590
+ * `MEMORY.md` to a definition has only this field to put the result in — through the other, the
591
+ * SDK re-reads the file and the enriched copy is lost.
592
+ */
593
+ subagents?: Readonly<Record<string, SubagentAgentDefinition>>;
375
594
  /**
376
595
  * Foreign configuration dialects, already authorised (usetheokit/theokit#634).
377
596
  *
@@ -477,4 +696,4 @@ interface CompiledAgentOptions {
477
696
  skillsResolver?: SkillsSelection;
478
697
  }
479
698
 
480
- export { type CodePlugin as C, type Guardrail as G, type HookApprovalGate as H, MalformedGuardrailResultError as M, type SkillsSelection as S, type ToolWalkResult as T, UnreadableTextPayloadError as U, type CompiledAgentOptions as a, type CompiledTool as b, CompatImportUnsupportedError as c, CostBudgetExceededError as d, type GuardrailAction as e, GuardrailError as f, type GuardrailPhase as g, type GuardrailResult as h, GuardrailViolationError as i, type HookApprovalRequest as j, HookGateUnsupportedError as k, type SkillsRequestContext as l, type ToolboxWalkResult as m, compileTools as n, resolveEnabledSkills as r };
699
+ export { type AgentDefinition as A, type CompiledAgentOptions as C, type DefineAgentConfig as D, type Guardrail as G, type HookApprovalGate as H, type InferAgentInput as I, MalformedGuardrailResultError as M, type SkillsRequestContext as S, type ToolWalkResult as T, UnreadableTextPayloadError as U, type CompiledTool as a, AGENT_BRAND as b, CompatImportUnsupportedError as c, CostBudgetExceededError as d, type GuardrailAction as e, GuardrailError as f, type GuardrailPhase as g, type GuardrailResult as h, GuardrailViolationError as i, type HookApprovalRequest as j, HookGateUnsupportedError as k, type InferAgentToolNames as l, type SkillsSelection as m, type ToolboxWalkResult as n, compileAgentDefinition as o, compileTools as p, isAgentDefinition as q, resolveEnabledSkills as r, type SubagentAgentDefinition as s, type CodePlugin as t };
package/dist/auth.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  readSecureJson,
3
3
  writeSecureJson
4
- } from "./chunk-D2EFYZBV.js";
4
+ } from "./chunk-4ULFP7GK.js";
5
5
  import {
6
6
  debugLog
7
7
  } from "./chunk-M5J3Q6YC.js";