@theokit/agents 9.3.0 → 9.4.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.
@@ -0,0 +1,236 @@
1
+ import { TrustPosture, SettingSource, CustomTool, MemorySettings } from '@theokit/sdk';
2
+ import { z } from 'zod';
3
+ import { R as ReasoningEffort, G as Guardrail, H as HumanInTheLoopOptions, S as SkillsSelection, M as McpServersMap, C as CompiledAgentOptions } from './agent-compiler-CIPQkehU.js';
4
+ import { H as HookHandlers } from './hook-handlers-Cw2FsnE5.js';
5
+ import { TheokitAgentError } from '@theokit/sdk/errors';
6
+
7
+ /**
8
+ * M68 — the trust gate for `settingSources`.
9
+ *
10
+ * ## The defect this module closes
11
+ *
12
+ * `settingSources` enables on-disk config discovery. `'user'` reads `~/.theokit/` — the operator's
13
+ * own machine, which no third party controls. `'project'` reads `<cwd>/.theokit/`, **including
14
+ * `hooks.json`, which executes shell**.
15
+ *
16
+ * The previous API took `readonly SettingSource[]`, and its JSDoc justified the risk this way:
17
+ * *"it is opt-in because `.theokit/` is the app's own repo (informed consent)"*. That premise holds
18
+ * for a web app whose `cwd` is its own deploy. It does **not** hold for the class of product this
19
+ * framework addresses — an agent whose `cwd` is a repository the user just cloned. There `.theokit/`
20
+ * is attacker-controlled content, and enabling `'project'` is remote code execution on the first
21
+ * `build()`.
22
+ *
23
+ * Documenting it did not prevent it. The measured consumer (TheoCode) did not trust the API: it
24
+ * gated from the outside, with a `posture.allows` of its own (`chat.ts:386`, comment B-008). It
25
+ * already **had** the right decision and could not pass it through, because the API only accepted
26
+ * strings. The gate existed on its side and evaporated at the boundary.
27
+ *
28
+ * ## The evidence is the SDK's, not one invented here
29
+ *
30
+ * `TrustPosture` is `@theokit/sdk`'s own trust primitive, and `recordWiring`'s doc says *"a posture
31
+ * is the only thing in this package that retains a capability"*. A bespoke type would make two trust
32
+ * grammars coexist and drift apart (ADR 0063).
33
+ */
34
+ /**
35
+ * The framework's capability vocabulary — deliberately a single name (ADR 0065).
36
+ *
37
+ * `allows` is all-or-nothing in the SDK: every declared `K` gets the same boolean. A finer
38
+ * vocabulary (`hooks`, `skills`, `subagents`, `mcp`) would promise the consumer it can gate one
39
+ * without gating the other, and the primitive does not deliver that. An API that suggests a
40
+ * distinction the runtime does not make teaches the wrong thing, and the error only surfaces when
41
+ * somebody depends on the distinction.
42
+ */
43
+ type SettingSourceCapability = 'projectSettings';
44
+ /** Authorization to read config from the working directory. Requires the posture, never a claim. */
45
+ interface ProjectSettingsGrant {
46
+ /**
47
+ * Typically the output of `resolveTrustPosture` — which is what gives it `source` (`'env' |
48
+ * 'store' | 'default'`) and therefore a refusal that says WHERE the decision came from instead of
49
+ * merely denying.
50
+ */
51
+ readonly trustedBy: TrustPosture<SettingSourceCapability>;
52
+ }
53
+ /**
54
+ * Which on-disk config roots the agent may read.
55
+ *
56
+ * The asymmetry is the design: `user` is a boolean because `~/.theokit/` belongs to the operator;
57
+ * `project` requires evidence because `<cwd>/.theokit/` may not. Omitting a root is not enabling it
58
+ * — never "enabling without a gate". The asymmetry is inherited from the SDK itself, whose
59
+ * `TrustPostureInput.envOverride` documents that `false` and `undefined` both mean "the operator did
60
+ * not turn it on", not "turned it off".
61
+ */
62
+ interface SettingSourcesSelection {
63
+ /** `~/.theokit/` — the operator's machine. No gate: no third party controls it. */
64
+ readonly user?: boolean;
65
+ /** `<cwd>/.theokit/` — controlled by whoever wrote the open repository. Requires evidence. */
66
+ readonly project?: ProjectSettingsGrant;
67
+ }
68
+ /**
69
+ * Refusal to read the working directory for lack of trust.
70
+ *
71
+ * Descends from `TheokitAgentError` because typed errors are an unbreakable rule here — and because
72
+ * `isTransientError` only sees this hierarchy. A class extending plain `Error` would be invisible to
73
+ * the predicate that separates recoverable from unrecoverable (the defect M67 fixed in five
74
+ * classes).
75
+ */
76
+ declare class UntrustedSettingSourceError extends TheokitAgentError {
77
+ /** Where the trust decision came from: `'env' | 'store' | 'default'`. */
78
+ readonly trustSource: string;
79
+ /** The refused capability. */
80
+ readonly capability: SettingSourceCapability;
81
+ readonly name = "UntrustedSettingSourceError";
82
+ constructor(message: string,
83
+ /** Where the trust decision came from: `'env' | 'store' | 'default'`. */
84
+ trustSource: string,
85
+ /** The refused capability. */
86
+ capability: SettingSourceCapability);
87
+ }
88
+ /**
89
+ * Translate the declared selection into the `SettingSource`s the SDK accepts, refusing what the
90
+ * posture does not authorize.
91
+ *
92
+ * Refuses rather than ignores (ADR 0064). Ignoring would leave the product running in the belief
93
+ * that the repository's hooks are active — a silent failure mode, on the wrong side. The SDK already
94
+ * picked that side for the same problem: `recordWiring` throws `UngatedCapabilityError` when
95
+ * somebody registers a capability the posture does not gate.
96
+ *
97
+ * @throws {UntrustedSettingSourceError} when `project` is requested and the posture does not grant it.
98
+ */
99
+ declare function resolveSettingSources(selection: SettingSourcesSelection | undefined): readonly SettingSource[];
100
+
101
+ /**
102
+ * M2 (theokit-ai-first) — `defineAgent`, the zero-config imperative agent surface.
103
+ *
104
+ * ADR-B1: `defineAgent({...})` (default-exported from a top-level `agents/<name>.ts`) is
105
+ * the canonical zero-config surface; the `@Agent` class decorator stays the advanced/DI
106
+ * surface. Both compile to {@link CompiledAgentOptions} and run through the same SDK
107
+ * runtime (`createSdkAgentStream`) — one runtime, two syntaxes.
108
+ *
109
+ * This module is PURE metadata (sdk-runtime.md / G2): `defineAgent` describes an agent, it
110
+ * NEVER calls an LLM. It imports only `zod` (types) + the compiler shape — no `theokit`
111
+ * core, preserving the agents → (nothing) dependency direction (G1).
112
+ */
113
+
114
+ /**
115
+ * Brand tag for a `defineAgent` value. `Symbol.for` (global registry, not `Symbol()`) so
116
+ * the brand survives duplicate module instances (dual-package / bundling) — the scanner's
117
+ * brand-check then works regardless of which copy created the definition.
118
+ */
119
+ declare const AGENT_BRAND: unique symbol;
120
+ /** Config accepted by {@link defineAgent}. */
121
+ interface DefineAgentConfig<TInput extends z.ZodType = z.ZodType> {
122
+ /** Zod schema for the request body — lifted into the typed client (M2, {@link InferAgentInput}). */
123
+ input?: TInput;
124
+ /** Model id (e.g. `claude-sonnet-4-6`). Falls back to the SDK default when omitted. */
125
+ model?: string;
126
+ /** Static system prompt. */
127
+ system?: string;
128
+ /** Extended-thinking effort. */
129
+ reasoningEffort?: ReasoningEffort;
130
+ /**
131
+ * Pre-built tools. Accepts the `@theokit/sdk` `CustomTool` that `defineAgentTool`
132
+ * (theokit/server) and every `@theokit/sdk-tools` factory return (issue #81) — they are
133
+ * normalized to the internal {@link CompiledTool} shape at compile time.
134
+ */
135
+ tools?: readonly CustomTool[];
136
+ /**
137
+ * M7 — run-context: an opaque, per-agent object forwarded to every tool handler's
138
+ * `ctx.context` at run time (injected by the theokit adapter's tool wrapper). Set shared config
139
+ * (e.g. `{ projectRoot }`) ONCE at the agent level instead of baking it into each tool
140
+ * factory. Mirrors ai-sdk `experimental_context`, mastra `RuntimeContext`, and
141
+ * openai-agents-js `RunContext`. Distinct from `@Agent`'s context-window `context`.
142
+ */
143
+ context?: Record<string, unknown>;
144
+ /**
145
+ * M9 — guardrails: input/output guards applied at the framework boundary (ADR-0040 § D2).
146
+ * Input guards run on the user message before the SDK runtime; a `block` fails the run fast.
147
+ * Built-ins live in `@theokit/agents` (`promptInjectionDetector`, `piiDetector`, `costGuard`,
148
+ * `unicodeNormalizer`, `outputModeration`).
149
+ */
150
+ guardrails?: readonly Guardrail[];
151
+ /**
152
+ * M14 — HITL approvals keyed by tool name. Each gated tool pauses the run and emits an
153
+ * `approval_required` event until approved (reuses the same `compiled.hitl` wiring the `@Agent`
154
+ * + `@HumanInTheLoop` path produces). A key that does not match a declared tool fails fast at
155
+ * compile time.
156
+ */
157
+ approvals?: Record<string, HumanInTheLoopOptions>;
158
+ /**
159
+ * M13 — skills selection: a static list (compiled straight to the SDK `skills.enabled`) OR a
160
+ * per-request resolver `(ctx) => string[]` (carried on `compiled.skillsResolver`, resolved by the
161
+ * request path against the run-context). Absent ⇒ the SDK enables every discovered skill.
162
+ */
163
+ skills?: SkillsSelection;
164
+ /**
165
+ * theokit-file-based-config — opt into `.theokit/` file-based config (skills, subagents, hooks,
166
+ * MCP, context, cron). The SDK discovers config from these roots under the app's `cwd`:
167
+ * `project` = `<cwd>/.theokit/`, `user` = `~/.theokit/`. Absent ⇒ inline (code) config only.
168
+ *
169
+ * SECURITY (M68): `project` reads `.theokit/hooks.json`, which **executes shell**, so it requires
170
+ * a `TrustPosture` rather than a string. This field used to take `readonly SettingSource[]`, and
171
+ * its own JSDoc justified the risk as *"opt-in because `.theokit/` is the app's own repo (informed
172
+ * consent)"*. That premise holds for a web app whose `cwd` is its own deploy; it does not hold for
173
+ * an agent whose `cwd` is a repository the user just cloned, where `.theokit/` is
174
+ * attacker-controlled content.
175
+ *
176
+ * `user` stays a plain boolean — `~/.theokit/` is the operator's own machine. Omitting a root is
177
+ * not enabling it. The SDK owns discovery + execution (G2 / ADR-0040); theokit resolves the
178
+ * selection through `resolveSettingSources` and wires the result into
179
+ * `Agent.create({ local.settingSources })`.
180
+ */
181
+ settingSources?: SettingSourcesSelection;
182
+ /**
183
+ * M49 — durable memory (the SDK's `.theokit/memory/` subsystem: `Remember:` capture, MEMORY.md
184
+ * store, auto-injected `<memory>` block, `memory_search`/`memory_get` tools). The shape is the
185
+ * SDK's own `MemorySettings` — the canonical runtime contract. Projected into
186
+ * `Agent.create({ memory })` by `assembleM8CreateOptions`.
187
+ */
188
+ memory?: MemorySettings;
189
+ /**
190
+ * Code `Plugin` objects forwarded to `Agent.create({ plugins })` — EXTENSION units (tools,
191
+ * commands, model providers, memory adapters). For lifecycle interception use {@link hooks}.
192
+ */
193
+ plugins?: readonly unknown[];
194
+ /**
195
+ * Lifecycle hooks keyed by `HookName` (`pre_tool_call` may veto via `{ block, message }`). Set by
196
+ * the builder's `hooks()`; converted into a code plugin at `build()` and never reaching the SDK
197
+ * under this name — the plugin is the TRANSPORT, this is the contract callers write against.
198
+ */
199
+ hooks?: HookHandlers | Readonly<Record<string, unknown>>;
200
+ /**
201
+ * MCP servers available to the agent — the builder-chain equivalent of the `@MCP` class
202
+ * decorator. Each key is a server name; the value is the server configuration. Forwarded
203
+ * unchanged to `Agent.create({ mcpServers })` (the SDK owns MCP execution). Absent ⇒ no MCP.
204
+ */
205
+ mcpServers?: McpServersMap;
206
+ }
207
+ /**
208
+ * A branded agent definition — the value {@link defineAgent} returns.
209
+ *
210
+ * `TTools` (M8) is a phantom type parameter carrying the tool-name union: the `AgentBuilder.create()` builder
211
+ * threads its accumulated literal tool names here (`.build()` returns `AgentDefinition<TInput,
212
+ * 'a' | 'b'>`), so the generated client (`.theokit/agents.d.ts`) can expose them via
213
+ * {@link InferAgentToolNames}. `defineAgent` leaves it `string` (its tools array carries no literal
214
+ * names). Never present at runtime.
215
+ */
216
+ type AgentDefinition<TInput extends z.ZodType = z.ZodType, TTools extends string = string> = DefineAgentConfig<TInput> & {
217
+ readonly [AGENT_BRAND]: true;
218
+ readonly __toolNames?: TTools;
219
+ };
220
+ /** Infer the request type of an agent definition from its `input` Zod schema. */
221
+ type InferAgentInput<T> = T extends AgentDefinition<infer S> ? (S extends z.ZodType ? z.infer<S> : never) : never;
222
+ /**
223
+ * Infer the tool-name union of an agent definition (M8). Yields the literal union for agents built
224
+ * with the `AgentBuilder.create()` builder (`'read_file' | 'count_lines'`), or `string` for `defineAgent` agents
225
+ * whose tools array carries no literal names.
226
+ */
227
+ type InferAgentToolNames<T> = T extends AgentDefinition<z.ZodType, infer N> ? N : never;
228
+ /** Brand-check: is `value` a {@link defineAgent} result? */
229
+ declare function isAgentDefinition(value: unknown): value is AgentDefinition;
230
+ /**
231
+ * Lower a definition to the SDK-ready {@link CompiledAgentOptions} — the same shape
232
+ * `compileAgent` (decorator path) produces, so both surfaces converge on one runtime.
233
+ */
234
+ declare function compileAgentDefinition(def: AgentDefinition): CompiledAgentOptions;
235
+
236
+ export { type AgentDefinition as A, type DefineAgentConfig as D, type InferAgentInput as I, type ProjectSettingsGrant as P, type SettingSourcesSelection as S, UntrustedSettingSourceError as U, AGENT_BRAND as a, type InferAgentToolNames as b, type SettingSourceCapability as c, compileAgentDefinition as d, isAgentDefinition as i, resolveSettingSources as r };