@theokit/agents 7.5.0 → 8.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 (59) hide show
  1. package/dist/{agent-handle-BX4oFqfb.d.ts → agent-handle-Dgi4ZGbg.d.ts} +11 -1
  2. package/dist/ask.d.ts +190 -0
  3. package/dist/ask.js +167 -0
  4. package/dist/ask.js.map +1 -0
  5. package/dist/auth.d.ts +96 -2
  6. package/dist/auth.js +85 -1
  7. package/dist/auth.js.map +1 -1
  8. package/dist/{bridge-entry-Z8GjrwH4.d.ts → bridge-entry-BEniSXWE.d.ts} +228 -609
  9. package/dist/bridge.d.ts +6 -3
  10. package/dist/bridge.js +18 -6
  11. package/dist/chunk-4VHCH6IZ.js +181 -0
  12. package/dist/chunk-4VHCH6IZ.js.map +1 -0
  13. package/dist/{chunk-WKBZZQBO.js → chunk-C7UXZWVY.js} +168 -177
  14. package/dist/chunk-C7UXZWVY.js.map +1 -0
  15. package/dist/{chunk-2BAFKRXT.js → chunk-M6HMASZC.js} +9 -4
  16. package/dist/chunk-M6HMASZC.js.map +1 -0
  17. package/dist/client-react.d.ts +2 -1
  18. package/dist/client-react.js +1 -1
  19. package/dist/client.d.ts +3 -2
  20. package/dist/client.js +1 -1
  21. package/dist/commands.d.ts +120 -0
  22. package/dist/commands.js +145 -0
  23. package/dist/commands.js.map +1 -0
  24. package/dist/define-agent-3Kuf6iKM.d.ts +633 -0
  25. package/dist/doctor.d.ts +119 -0
  26. package/dist/doctor.js +84 -0
  27. package/dist/doctor.js.map +1 -0
  28. package/dist/hook-handlers-Cw2FsnE5.d.ts +56 -0
  29. package/dist/hooks.d.ts +225 -0
  30. package/dist/hooks.js +286 -0
  31. package/dist/hooks.js.map +1 -0
  32. package/dist/index.d.ts +170 -26
  33. package/dist/index.js +105 -20
  34. package/dist/index.js.map +1 -1
  35. package/dist/mcp-health.d.ts +69 -0
  36. package/dist/mcp-health.js +42 -0
  37. package/dist/mcp-health.js.map +1 -0
  38. package/dist/persistence.d.ts +1 -1
  39. package/dist/persistence.js +4 -0
  40. package/dist/persistence.js.map +1 -1
  41. package/dist/sandbox.d.ts +1 -1
  42. package/dist/sandbox.js +29 -2
  43. package/dist/sandbox.js.map +1 -1
  44. package/dist/session.d.ts +238 -0
  45. package/dist/session.js +338 -0
  46. package/dist/session.js.map +1 -0
  47. package/dist/testing.d.ts +90 -1
  48. package/dist/testing.js +76 -1
  49. package/dist/testing.js.map +1 -1
  50. package/dist/tool-scope.d.ts +133 -0
  51. package/dist/tool-scope.js +61 -0
  52. package/dist/tool-scope.js.map +1 -0
  53. package/dist/tools.js.map +1 -1
  54. package/dist/usage.d.ts +98 -0
  55. package/dist/usage.js +55 -0
  56. package/dist/usage.js.map +1 -0
  57. package/package.json +37 -12
  58. package/dist/chunk-2BAFKRXT.js.map +0 -1
  59. package/dist/chunk-WKBZZQBO.js.map +0 -1
package/dist/testing.d.ts CHANGED
@@ -1,3 +1,11 @@
1
+ import { AgentOutputEvent } from '@theokit/presenter';
2
+ import { WireChunk } from '@theokit/presenter/wire';
3
+ import { A as AgentDefinition } from './define-agent-3Kuf6iKM.js';
4
+ import '@theokit/sdk';
5
+ import 'zod';
6
+ import '@theokit/sdk/errors';
7
+ import './hook-handlers-Cw2FsnE5.js';
8
+
1
9
  /**
2
10
  * createMockAgentStream — test agents without an LLM API key.
3
11
  *
@@ -44,4 +52,85 @@ interface MockStreamEvent {
44
52
  }
45
53
  declare function createMockAgentStream(opts: MockAgentStreamOptions): (_message: string, _sessionId: string) => AsyncIterable<MockStreamEvent>;
46
54
 
47
- export { type MockAgentStreamOptions, type MockResponse, type MockStreamEvent, createMockAgentStream };
55
+ /**
56
+ * Typed builders for the chunks a test needs.
57
+ *
58
+ * Not a builder per member of the union — most of the thirteen never appear in a fixture, and
59
+ * writing them all would be surface nobody asked for (YAGNI). These are the four a consumer's
60
+ * fixtures actually contained. A test needing another writes the literal and passes it through
61
+ * {@link createMockWireStream}, which validates all the same.
62
+ */
63
+ declare const wireChunk: {
64
+ /** A text fragment. `id` groups deltas into one message; a fixture rarely cares which. */
65
+ text(delta: string, id?: string): WireChunk;
66
+ /** The error frame. This is the literal a consumer was writing with `as never` on the end. */
67
+ error(errorText: string): WireChunk;
68
+ /** Stream end. */
69
+ finish(): WireChunk;
70
+ /** Stream start. `messageId` is optional in the schema and omitted here for the same reason. */
71
+ start(messageId?: string): WireChunk;
72
+ };
73
+ /**
74
+ * A stream of wire chunks, for driving anything that consumes the wire.
75
+ *
76
+ * Async because every production consumer is: a mock that were synchronous would let a test pass
77
+ * over code that never awaited, which is the class of bug a stream test exists to catch.
78
+ */
79
+ declare function createMockWireStream(chunks: readonly WireChunk[]): AsyncGenerator<WireChunk>;
80
+ /**
81
+ * A stream of presenter output events.
82
+ *
83
+ * Published alongside the wire one, deliberately: a test of a presenter surface should not have to
84
+ * round-trip through the wire to produce a single event. Two vocabularies exist in production, and a
85
+ * seam that admitted only one would push every test of the other back into casts.
86
+ */
87
+ declare function createMockOutputEvents(events: readonly AgentOutputEvent[]): AsyncGenerator<AgentOutputEvent>;
88
+
89
+ /**
90
+ * M85 — assert at the COMPILATION boundary, which is the one with the widest blast radius.
91
+ *
92
+ * The consumer documented this itself: in an agent product, the question that matters is not "did
93
+ * the stream emit the right frames" but **"does this agent have the tools I think it has, and are
94
+ * the dangerous ones gated?"**. A wrong answer there is a shell running unapproved, or a tool the
95
+ * model cannot see and the operator believes it can.
96
+ *
97
+ * ## Why a helper and not `compileAgentDefinition` directly
98
+ *
99
+ * `CompiledAgentOptions` is the shape the SDK adapter consumes — thirty-odd fields, most of which a
100
+ * test does not care about. Asserting against it directly is how 90 occurrences of `vi.mock` over
101
+ * the framework barrel got written: the assertion was too awkward, so the test faked the module
102
+ * instead, pinning itself to export NAMES and detecting no drift whatsoever.
103
+ *
104
+ * ## Capabilities are NOT here, and that is measured
105
+ *
106
+ * `capabilities` is a field of the DEFINITION, not of `CompiledAgentOptions` — the compiler resolves
107
+ * it into tools rather than carrying it through. The DoD named it, and projecting it would have
108
+ * meant reading the definition instead of the compilation, which is a different assertion wearing
109
+ * this function's name: it would report what the author WROTE, not what the agent GOT.
110
+ *
111
+ * This projects the three facts a test actually asserts. It is a READ over the real compiler — never
112
+ * a second one — so a compilation change surfaces here rather than in a fixture that agreed with an
113
+ * older version of the truth.
114
+ */
115
+ /** The facts a test asserts about a compiled agent. */
116
+ interface CompiledInspection {
117
+ /** Tool names, sorted, as the model will see them. */
118
+ readonly toolNames: readonly string[];
119
+ /** Names of the tools that require human approval before running. */
120
+ readonly gatedToolNames: readonly string[];
121
+ /** The model the agent will use, when one is declared. */
122
+ readonly model: string | undefined;
123
+ }
124
+ /**
125
+ * Inspect what a definition compiles to.
126
+ *
127
+ * ```ts
128
+ * expect(inspectCompiled(myAgent).gatedToolNames).toContain('run_shell')
129
+ * ```
130
+ *
131
+ * Sorted output, because a list whose order changes with a decorator's position is a list nobody can
132
+ * diff — and a test that pinned that order would fail on a reordering that changed nothing.
133
+ */
134
+ declare function inspectCompiled(definition: AgentDefinition): CompiledInspection;
135
+
136
+ export { type CompiledInspection, type MockAgentStreamOptions, type MockResponse, type MockStreamEvent, createMockAgentStream, createMockOutputEvents, createMockWireStream, inspectCompiled, wireChunk };
package/dist/testing.js CHANGED
@@ -1,3 +1,6 @@
1
+ import {
2
+ compileAgentDefinition
3
+ } from "./chunk-4VHCH6IZ.js";
1
4
  import {
2
5
  __name
3
6
  } from "./chunk-Z4QWC7IK.js";
@@ -67,7 +70,79 @@ function createMockAgentStream(opts) {
67
70
  });
68
71
  }
69
72
  __name(createMockAgentStream, "createMockAgentStream");
73
+
74
+ // src/testing/mock-wire-stream.ts
75
+ import { wireChunkSchema } from "@theokit/presenter/wire";
76
+ function checked(chunk) {
77
+ const parsed = wireChunkSchema.safeParse(chunk);
78
+ if (!parsed.success) {
79
+ throw new TypeError(`[@theokit/agents/testing] this is not a valid wire chunk: ${parsed.error.message}. A fixture production would reject is a test that proves nothing.`);
80
+ }
81
+ return chunk;
82
+ }
83
+ __name(checked, "checked");
84
+ var wireChunk = {
85
+ /** A text fragment. `id` groups deltas into one message; a fixture rarely cares which. */
86
+ text(delta, id = "text-1") {
87
+ return checked({
88
+ type: "text-delta",
89
+ id,
90
+ delta
91
+ });
92
+ },
93
+ /** The error frame. This is the literal a consumer was writing with `as never` on the end. */
94
+ error(errorText) {
95
+ return checked({
96
+ type: "error",
97
+ errorText
98
+ });
99
+ },
100
+ /** Stream end. */
101
+ finish() {
102
+ return checked({
103
+ type: "finish"
104
+ });
105
+ },
106
+ /** Stream start. `messageId` is optional in the schema and omitted here for the same reason. */
107
+ start(messageId) {
108
+ return checked(messageId === void 0 ? {
109
+ type: "start"
110
+ } : {
111
+ type: "start",
112
+ messageId
113
+ });
114
+ }
115
+ };
116
+ async function* createMockWireStream(chunks) {
117
+ for (const chunk of chunks) {
118
+ yield checked(chunk);
119
+ }
120
+ }
121
+ __name(createMockWireStream, "createMockWireStream");
122
+ async function* createMockOutputEvents(events) {
123
+ for (const event of events) yield event;
124
+ }
125
+ __name(createMockOutputEvents, "createMockOutputEvents");
126
+
127
+ // src/testing/inspect-compiled.ts
128
+ function inspectCompiled(definition) {
129
+ const compiled = compileAgentDefinition(definition);
130
+ const toolNames = compiled.tools.map((tool) => tool.name).sort((a, b) => a.localeCompare(b));
131
+ const gatedToolNames = [
132
+ ...compiled.hitl?.keys() ?? []
133
+ ].sort((a, b) => a.localeCompare(b));
134
+ return {
135
+ toolNames,
136
+ gatedToolNames,
137
+ model: typeof compiled.model === "string" ? compiled.model : void 0
138
+ };
139
+ }
140
+ __name(inspectCompiled, "inspectCompiled");
70
141
  export {
71
- createMockAgentStream
142
+ createMockAgentStream,
143
+ createMockOutputEvents,
144
+ createMockWireStream,
145
+ inspectCompiled,
146
+ wireChunk
72
147
  };
73
148
  //# sourceMappingURL=testing.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/testing/mock-stream.ts"],"mappings":";;;;;AAgDO,SAASA,sBAAsBC,MAA4B;AAChE,SAAO,CAACC,UAAkBC,gBAAwD;IAChF,QAAQC,OAAOC,aAAa,IAAC;AAC3B,YAAMC,QAAQC,QAAO;AACrB,YAAMC,QAAQ,QAAQC,KAAKC,IAAG,CAAA;AAC9B,YAAM;QAAEC,MAAM;QAAeH;QAAOI,WAAWX,KAAKW,aAAa;QAAcC,OAAO;MAAO;AAE7F,UAAIC,cAAc;AAClB,iBAAWC,KAAKd,KAAKe,WAAW;AAC9B,YAAID,EAAEJ,SAAS,UAAUI,EAAEE,SAAS;AAClC,gBAAMC,QAAQH,EAAEE,QAAQE,MAAM,GAAA;AAC9B,qBAAWC,QAAQF,OAAO;AACxB,kBAAM;cAAEP,MAAM;cAAcM,SAASG,OAAO;YAAI;AAChDN,2BAAe;UACjB;QACF,WAAWC,EAAEJ,SAAS,aAAa;AACjC,gBAAMU,SAAS,MAAMZ,KAAKC,IAAG,CAAA,IAAMY,OAAOC,WAAU,EAAGC,MAAM,GAAG,CAAA,CAAA;AAChE,gBAAM;YAAEb,MAAM;YAAaU;YAAQI,UAAUV,EAAEW,QAAQ;YAAWC,OAAOZ,EAAEY,SAAS,CAAC;UAAE;AACvF,gBAAM;YACJhB,MAAM;YACNU;YACAI,UAAUV,EAAEW,QAAQ;YACpBE,QAAQb,EAAEa,UAAU;YACpBC,YAAY;YACZC,SAAS;UACX;AACAhB,yBAAe;QACjB,WAAWC,EAAEJ,SAAS,SAAS;AAC7B,gBAAM;YACJA,MAAM;YACNoB,MAAM;YACNC,SAASjB,EAAEiB,WAAW;YACtBC,WAAW;UACb;AACA;QACF;MACF;AAEA,YAAM;QACJtB,MAAM;QACNuB,QAAQjC,KAAKe,UACVmB,OAAO,CAACpB,MAAMA,EAAEJ,SAAS,MAAA,EACzByB,IAAI,CAACrB,MAAMA,EAAEE,OAAO,EACpBoB,KAAK,GAAA;QACRC,OAAO;UACLC,aAAazB;UACb0B,cAAc1B;UACdA,aAAaA,cAAc;QAC7B;QACAe,YAAY;QACZY,MAAMxC,KAAKwC,QAAQ;MACrB;IACF;EACF;AACF;AAtDgBzC;","names":["createMockAgentStream","opts","_message","_sessionId","Symbol","asyncIterator","Promise","resolve","runId","Date","now","type","agentName","model","totalTokens","r","responses","content","words","split","word","callId","crypto","randomUUID","slice","toolName","name","input","output","durationMs","isError","code","message","retryable","result","filter","map","join","usage","inputTokens","outputTokens","cost"]}
1
+ {"version":3,"sources":["../src/testing/mock-stream.ts","../src/testing/mock-wire-stream.ts","../src/testing/inspect-compiled.ts"],"mappings":"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","names":["createMockAgentStream","opts","_message","_sessionId","Symbol","asyncIterator","Promise","resolve","runId","Date","now","type","agentName","model","totalTokens","r","responses","content","words","split","word","callId","crypto","randomUUID","slice","toolName","name","input","output","durationMs","isError","code","message","retryable","result","filter","map","join","usage","inputTokens","outputTokens","cost","wireChunkSchema","checked","chunk","parsed","wireChunkSchema","safeParse","success","TypeError","error","message","wireChunk","text","delta","id","type","errorText","finish","start","messageId","undefined","createMockWireStream","chunks","createMockOutputEvents","events","event","inspectCompiled","definition","compiled","compileAgentDefinition","toolNames","tools","map","tool","name","sort","a","b","localeCompare","gatedToolNames","hitl","keys","model","undefined"]}
@@ -0,0 +1,133 @@
1
+ import { SandboxProvider, SandboxMode } from '@theokit/sdk/sandbox';
2
+
3
+ /**
4
+ * M78 — the tool scope binder: bind `{ projectRoot, writeRoot, sandbox }` once, so an unconfined
5
+ * shell is unrepresentable.
6
+ *
7
+ * ## The defect this closes
8
+ *
9
+ * The framework shipped the ingredients — `createSandboxBackend`, `resolveSandboxPosture` — and no
10
+ * binder. Measured against `@theokit/sdk-tools@0.26.1`: `projectRoot` is REQUIRED on eleven
11
+ * factories, while `sandbox` is **optional** on three — `createGitDiffTool`, `createGitStatusTool`
12
+ * and, the one that matters, `createShellTool`.
13
+ *
14
+ * An optional sandbox on a shell factory means a scope assembled without one produces an UNCONFINED
15
+ * SHELL with no error and no warning. The consumer that prompted this milestone documented exactly
16
+ * that outcome. And because nothing bound the roots either, every product rediscovered per tool
17
+ * which root each factory accepts — with silence as the failure mode for getting it wrong.
18
+ *
19
+ * ## Why this is framework and not runtime
20
+ *
21
+ * It runs nothing. It applies configuration to factories the SDK owns — the boundary/home half of
22
+ * ADR-0040 § D2, the same category as the approval gate and the ask channel.
23
+ *
24
+ * ## Why ONE generic `bind` and not eleven named wrappers
25
+ *
26
+ * The milestone wants the consumer's registry to become "the declarative map of ten entries it
27
+ * should be". A generic `bind` IS that map:
28
+ *
29
+ * ```ts
30
+ * const registry = {
31
+ * shell: scope.bind(createShellTool)(),
32
+ * read_file: scope.bind(createReadFileTool)(),
33
+ * }
34
+ * ```
35
+ *
36
+ * Eleven named wrappers would add nothing to that and cost two things: a twelfth tool in `sdk-tools`
37
+ * would need a change here (breaking OCP), and each wrapper is one more place to forget the sandbox —
38
+ * the exact failure being closed. Parsimony rung 1: they do not need to exist.
39
+ */
40
+ /** What a sandbox mode permits, in the two terms a tool factory actually needs. */
41
+ interface SandboxWritePolicy {
42
+ /** Whether ANY write is permitted. */
43
+ readonly writes: boolean;
44
+ /** Whether a path outside the project root may be honoured. */
45
+ readonly allowAbsolute: boolean;
46
+ }
47
+ /**
48
+ * The write policy of a sandbox mode.
49
+ *
50
+ * A PROJECTION of the SDK's own `writableRootsFor`, never a second source of truth (G12): products
51
+ * were re-deriving this by hand, and a function that disagreed with the SDK would be a third
52
+ * derivation — worse than the two it replaces. `tool-scope.test.ts` asserts the agreement for every
53
+ * mode.
54
+ *
55
+ * The mapping is not guessable, which is why it is measured rather than assumed:
56
+ *
57
+ * | mode | `writableRootsFor` | meaning |
58
+ * |---|---|---|
59
+ * | `read-only` | `[]` | no writable root |
60
+ * | `workspace-write` | `[cwd, '/tmp']` | writes, confined |
61
+ * | `danger-full-access` | `null` | **unrestricted** — not "no writes" |
62
+ *
63
+ * Reading `null` as "nothing is writable" would forbid writes exactly where everything is allowed.
64
+ */
65
+ declare function sandboxWritePolicy(mode: SandboxMode, cwd: string): SandboxWritePolicy;
66
+ /** The scope fields a bound factory receives. Every field is non-optional by the time it is applied. */
67
+ interface ScopeFields {
68
+ readonly projectRoot: string;
69
+ readonly writeRoot: string;
70
+ readonly sandbox: SandboxProvider;
71
+ }
72
+ interface ToolScopeInput {
73
+ /** Root the tools read from. */
74
+ readonly projectRoot: string;
75
+ /**
76
+ * Root the tools write to. Defaults to `projectRoot` — the conservative reading: a product that
77
+ * never distinguishes the two should not have to say so twice, and the default must not be broader
78
+ * than what was asked for.
79
+ */
80
+ readonly writeRoot?: string;
81
+ /**
82
+ * The confinement. REQUIRED, and that is the entire milestone.
83
+ *
84
+ * Making it optional is what let a scope produce an unconfined shell in silence. A caller who
85
+ * genuinely wants no confinement must say so by passing a `danger-full-access` sandbox — a
86
+ * decision that appears in the code, in a review, and in a log, rather than an omission that
87
+ * appears nowhere.
88
+ */
89
+ readonly sandbox: SandboxProvider;
90
+ /**
91
+ * The mode `policy` is computed from. Optional because the policy is a convenience: a scope whose
92
+ * product never asks about write policy needs no mode.
93
+ */
94
+ readonly mode?: SandboxMode;
95
+ }
96
+ /** Any `sdk-tools` factory: takes an options object, returns a tool. */
97
+ type ToolFactory<TOptions, TTool> = (options: TOptions) => TTool;
98
+ /**
99
+ * Per-tool overrides.
100
+ *
101
+ * The scope fields are optional here — a caller may replace them — but `undefined` is treated as
102
+ * "not supplied", never as "unset". See {@link ToolScope.bind}.
103
+ */
104
+ type Overrides<TOptions> = Omit<TOptions, keyof ScopeFields> & Partial<ScopeFields>;
105
+ interface ToolScope extends ScopeFields {
106
+ /** The write policy of `mode`, when one was supplied. */
107
+ readonly policy: SandboxWritePolicy;
108
+ /**
109
+ * Scope a factory.
110
+ *
111
+ * Returns a function taking that tool's own options. Scope fields are injected; an override may
112
+ * REPLACE one, but an `undefined` override falls back to the scope rather than clearing it.
113
+ *
114
+ * That asymmetry is the point. Variation is legitimate — one tool may need stricter confinement
115
+ * than the rest, which is the risk the milestone flags. Absence is not: `{ sandbox: maybeSandbox }`
116
+ * with an undefined variable is ordinary code, and honouring it would silently unconfine a shell
117
+ * through the one door the type system cannot close.
118
+ */
119
+ bind<TOptions extends Partial<ScopeFields>, TTool>(factory: ToolFactory<TOptions, TTool>): (overrides?: Overrides<TOptions>) => TTool;
120
+ }
121
+ /**
122
+ * Bind a tool scope.
123
+ *
124
+ * ```ts
125
+ * const scope = bindToolScope({ projectRoot, sandbox: await resolveSandbox({ mode }) , mode })
126
+ * const shell = scope.bind(createShellTool)({ name: 'run_shell' })
127
+ * ```
128
+ *
129
+ * Omitting `sandbox` does not compile — see `tests/type/tool-scope.test-d.ts`.
130
+ */
131
+ declare function bindToolScope(input: ToolScopeInput): ToolScope;
132
+
133
+ export { type SandboxWritePolicy, type ToolScope, type ToolScopeInput, bindToolScope, sandboxWritePolicy };
@@ -0,0 +1,61 @@
1
+ import {
2
+ __name
3
+ } from "./chunk-Z4QWC7IK.js";
4
+
5
+ // src/tools/tool-scope.ts
6
+ import { writableRootsFor } from "@theokit/sdk/sandbox";
7
+ function sandboxWritePolicy(mode, cwd) {
8
+ const roots = writableRootsFor(mode, cwd);
9
+ if (roots === null) return {
10
+ writes: true,
11
+ allowAbsolute: true
12
+ };
13
+ if (roots === void 0) {
14
+ throw new TypeError(`[@theokit/agents] unknown sandbox mode ${JSON.stringify(mode)} \u2014 write policy is undefined for it. Expected one of: "read-only", "workspace-write", "danger-full-access". Refusing to guess: guessing permissive would grant writes, and guessing restrictive would silently disable a tool.`);
15
+ }
16
+ return {
17
+ writes: roots.length > 0,
18
+ allowAbsolute: false
19
+ };
20
+ }
21
+ __name(sandboxWritePolicy, "sandboxWritePolicy");
22
+ var BoundToolScope = class BoundToolScope2 {
23
+ static {
24
+ __name(this, "BoundToolScope");
25
+ }
26
+ projectRoot;
27
+ writeRoot;
28
+ sandbox;
29
+ policy;
30
+ constructor(input) {
31
+ this.projectRoot = input.projectRoot;
32
+ this.writeRoot = input.writeRoot ?? input.projectRoot;
33
+ this.sandbox = input.sandbox;
34
+ this.policy = input.mode === void 0 ? {
35
+ writes: false,
36
+ allowAbsolute: false
37
+ } : sandboxWritePolicy(input.mode, this.projectRoot);
38
+ }
39
+ bind(factory) {
40
+ return (overrides) => {
41
+ const merged = {
42
+ ...overrides,
43
+ // AFTER the spread, and each with `??`: an override may replace a scope field, but an
44
+ // explicit `undefined` resolves back to the scope instead of clearing it.
45
+ projectRoot: overrides?.projectRoot ?? this.projectRoot,
46
+ writeRoot: overrides?.writeRoot ?? this.writeRoot,
47
+ sandbox: overrides?.sandbox ?? this.sandbox
48
+ };
49
+ return factory(merged);
50
+ };
51
+ }
52
+ };
53
+ function bindToolScope(input) {
54
+ return new BoundToolScope(input);
55
+ }
56
+ __name(bindToolScope, "bindToolScope");
57
+ export {
58
+ bindToolScope,
59
+ sandboxWritePolicy
60
+ };
61
+ //# sourceMappingURL=tool-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tools/tool-scope.ts"],"mappings":";;;;;AAAA,SAASA,wBAAgE;AAkElE,SAASC,mBAAmBC,MAAmBC,KAAW;AAM/D,QAAMC,QAAQC,iBAAiBH,MAAMC,GAAAA;AAGrC,MAAIC,UAAU,KAAM,QAAO;IAAEE,QAAQ;IAAMC,eAAe;EAAK;AAO/D,MAAIH,UAAUI,QAAW;AACvB,UAAM,IAAIC,UACR,0CAA0CC,KAAKC,UAAUT,IAAAA,CAAAA,qOAG7B;EAEhC;AACA,SAAO;IAAEI,QAAQF,MAAMQ,SAAS;IAAGL,eAAe;EAAM;AAC1D;AAzBgBN;AAiGhB,IAAMY,iBAAN,MAAMA,gBAAAA;EAnKN,OAmKMA;;;EACKC;EACAC;EACAC;EACAC;EAET,YAAYC,OAAuB;AACjC,SAAKJ,cAAcI,MAAMJ;AACzB,SAAKC,YAAYG,MAAMH,aAAaG,MAAMJ;AAC1C,SAAKE,UAAUE,MAAMF;AAGrB,SAAKC,SACHC,MAAMhB,SAASM,SACX;MAAEF,QAAQ;MAAOC,eAAe;IAAM,IACtCN,mBAAmBiB,MAAMhB,MAAM,KAAKY,WAAW;EACvD;EAEAK,KACEC,SAC4C;AAC5C,WAAO,CAACC,cAAAA;AACN,YAAMC,SAAS;QACb,GAAGD;;;QAGHP,aAAaO,WAAWP,eAAe,KAAKA;QAC5CC,WAAWM,WAAWN,aAAa,KAAKA;QACxCC,SAASK,WAAWL,WAAW,KAAKA;MACtC;AACA,aAAOI,QAAQE,MAAAA;IACjB;EACF;AACF;AAYO,SAASC,cAAcL,OAAqB;AACjD,SAAO,IAAIL,eAAeK,KAAAA;AAC5B;AAFgBK;","names":["writableRootsFor","sandboxWritePolicy","mode","cwd","roots","writableRootsFor","writes","allowAbsolute","undefined","TypeError","JSON","stringify","length","BoundToolScope","projectRoot","writeRoot","sandbox","policy","input","bind","factory","overrides","merged","bindToolScope"]}
package/dist/tools.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/tools-entry.ts"],"mappings":";;;AAoBA,SACEA,iBACAC,cACAC,0BACAC,yBACAC,qBACAC,mBACAC,sBACAC,6BACAC,uBACAC,oBACAC,gCACAC,mBACAC,qBACAC,gBACAC,4BACAC,mBACAC,oBACAC,oBACAC,oBACAC,qBACAC,sBACAC,4BACAC,iBACAC,oBACAC,sBACAC,oBACAC,qBACAC,qBACAC,sBACAC,uBACAC,0BACAC,YACAC,YACAC,aACAC,gBACAC,gBACAC,aACAC,kBACAC,aACAC,gBACAC,sBACAC,gBACAC,eACAC,kBACAC,eACAC,kBACAC,sBACAC,gBACAC,qBACAC,iBACAC,UACAC,uBACAC,8BACK;","names":["buildEnvContext","buildRepoMap","CatastrophicCommandError","catastrophicShellReason","commandDenialReason","ContextMatchError","createApplyPatchTool","createBraveWebSearchAdapter","createCurrentTimeTool","createEditFileTool","createGenericHttpSearchAdapter","createGitDiffTool","createGitStatusTool","createGlobTool","createInteractiveShellTool","createListDirTool","createPlanModeTool","createQuestionTool","createReadFileTool","createRunVitestTool","createSearchTextTool","createSessionArtifactStore","createShellTool","createTodolistTool","createUpdatePlanTool","createWebFetchTool","createWebSearchTool","createWriteFileTool","createWriteStdinTool","DEFAULT_TOOL_GUIDANCE","denyCatastrophicCommands","formatCode","formatDiff","formatError","formatFileList","injectGuidance","isBlockedIp","isCommandAllowed","ReadTracker","ReasoningTools","RedirectBlockedError","renderToolList","replaceUnique","resolveAndScreen","screenedFetch","SsrfBlockedError","todoItemsToPlanNodes","truncateOutput","withDefaultGuidance","withDescription","withName","withShellExitGuidance","withToolResultGuidance"]}
1
+ {"version":3,"sources":["../src/tools-entry.ts"],"mappings":";;;AAuBA,SACEA,iBACAC,cACAC,0BACAC,yBACAC,qBACAC,mBACAC,sBACAC,6BACAC,uBACAC,oBACAC,gCACAC,mBACAC,qBACAC,gBACAC,4BACAC,mBACAC,oBACAC,oBACAC,oBACAC,qBACAC,sBACAC,4BACAC,iBACAC,oBACAC,sBACAC,oBACAC,qBACAC,qBACAC,sBACAC,uBACAC,0BACAC,YACAC,YACAC,aACAC,gBACAC,gBACAC,aACAC,kBACAC,aACAC,gBACAC,sBACAC,gBACAC,eACAC,kBACAC,eACAC,kBACAC,sBACAC,gBACAC,qBACAC,iBACAC,UACAC,uBACAC,8BACK;","names":["buildEnvContext","buildRepoMap","CatastrophicCommandError","catastrophicShellReason","commandDenialReason","ContextMatchError","createApplyPatchTool","createBraveWebSearchAdapter","createCurrentTimeTool","createEditFileTool","createGenericHttpSearchAdapter","createGitDiffTool","createGitStatusTool","createGlobTool","createInteractiveShellTool","createListDirTool","createPlanModeTool","createQuestionTool","createReadFileTool","createRunVitestTool","createSearchTextTool","createSessionArtifactStore","createShellTool","createTodolistTool","createUpdatePlanTool","createWebFetchTool","createWebSearchTool","createWriteFileTool","createWriteStdinTool","DEFAULT_TOOL_GUIDANCE","denyCatastrophicCommands","formatCode","formatDiff","formatError","formatFileList","injectGuidance","isBlockedIp","isCommandAllowed","ReadTracker","ReasoningTools","RedirectBlockedError","renderToolList","replaceUnique","resolveAndScreen","screenedFetch","SsrfBlockedError","todoItemsToPlanNodes","truncateOutput","withDefaultGuidance","withDescription","withName","withShellExitGuidance","withToolResultGuidance"]}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * M84 — the runtime-neutral half of cost tracking.
3
+ *
4
+ * ## Why it moved
5
+ *
6
+ * 1 715 LOC of observability and cost lived under `packages/theo/src/server/**`, and `theokit` is
7
+ * the Vite/React web framework. The only real product built on this stack depends on
8
+ * `@theokit/agents`, `@theokit/tui` and `@theokit/presenter`, and never on `theokit` — a grep for
9
+ * `from 'theokit` in it returns zero. So none of it was reachable, and what would have been is
10
+ * HTTP-shaped.
11
+ *
12
+ * What crosses is the vocabulary and the in-memory adapter: a record, a query, a result, and a place
13
+ * to put them. The HTTP wiring (`trackAgentRun`, spans named `http.request`, keying by `requestId`)
14
+ * stays in `theokit`, because that is what it is about.
15
+ *
16
+ * ## `userId` is optional here, and that is the point
17
+ *
18
+ * The HTTP path always has one. A terminal agent has no user — it has a person at a keyboard — and
19
+ * requiring the field forced every terminal product to invent a constant. An invented identifier is
20
+ * worse than an absent one: it looks like data.
21
+ */
22
+ /** Per-LLM-call cost record. */
23
+ interface UsageRecord {
24
+ /** Discriminator. Optional for backward compatibility; absent ⇒ `'llm'`. */
25
+ kind?: 'llm';
26
+ /** Who the cost belongs to. Absent for a single-user surface such as a terminal. */
27
+ userId?: string;
28
+ /** Model id (`claude-sonnet-4-5-20250929`). */
29
+ model: string;
30
+ tokens: {
31
+ input: number;
32
+ output: number;
33
+ };
34
+ /** USD in fractional dollars. */
35
+ costUsd: number;
36
+ timestamp: Date;
37
+ }
38
+ /** Per-tool-invocation record. */
39
+ interface ToolUsageRecord {
40
+ kind: 'tool';
41
+ userId?: string;
42
+ conversationId: string;
43
+ toolName: string;
44
+ /** Unique per invocation; correlates start with end/error. */
45
+ callId: string;
46
+ success: boolean;
47
+ durationMs: number;
48
+ /** Populated only when `success === false`. */
49
+ errorMessage?: string;
50
+ timestamp: Date;
51
+ }
52
+ interface UsageQuery {
53
+ /** Omitted ⇒ every record, which is what a single-user surface wants. */
54
+ userId?: string;
55
+ period?: {
56
+ from: Date;
57
+ to: Date;
58
+ };
59
+ }
60
+ interface UsageResult {
61
+ totalTokens: number;
62
+ totalCostUsd: number;
63
+ runs: number;
64
+ }
65
+ /** Where usage goes. The framework owns the vocabulary; the app owns the storage. */
66
+ interface UsageStorageAdapter {
67
+ readonly name: string;
68
+ record(input: UsageRecord | ToolUsageRecord): Promise<void>;
69
+ getUsage(query: UsageQuery): Promise<UsageResult>;
70
+ }
71
+
72
+ /**
73
+ * M84 — usage in memory.
74
+ *
75
+ * Deliberately does NOT implement `theokit`'s `StorageAdapter`: that is a lifecycle contract of the
76
+ * web framework, and requiring it here is exactly the coupling that made cost tracking unreachable
77
+ * from a terminal product. The `theokit` side extends this one and adds the lifecycle.
78
+ *
79
+ * Concurrency: Node's event loop makes `Array.push` atomic, so concurrent `record()` calls cannot
80
+ * lose data. This is single-process by construction — a multi-instance deploy supplies its own
81
+ * adapter, which is what the interface is for.
82
+ */
83
+ declare class InMemoryUsageStorage implements UsageStorageAdapter {
84
+ #private;
85
+ readonly name = "memory";
86
+ record(input: UsageRecord | ToolUsageRecord): Promise<void>;
87
+ getUsage(query?: UsageQuery): Promise<UsageResult>;
88
+ /**
89
+ * The most recent LLM record, or `undefined`.
90
+ *
91
+ * The question a terminal asks after every turn — "what did that cost?" — and the reason a
92
+ * consumer wrote a ten-line file to answer it. Tool records are excluded: a tool invocation has no
93
+ * token cost of its own, and returning one here would make the footer show zero after every tool.
94
+ */
95
+ latestUsage(): UsageRecord | undefined;
96
+ }
97
+
98
+ export { InMemoryUsageStorage, type ToolUsageRecord, type UsageQuery, type UsageRecord, type UsageResult, type UsageStorageAdapter };
package/dist/usage.js ADDED
@@ -0,0 +1,55 @@
1
+ import {
2
+ __name
3
+ } from "./chunk-Z4QWC7IK.js";
4
+
5
+ // src/usage/in-memory-usage.ts
6
+ var InMemoryUsageStorage = class {
7
+ static {
8
+ __name(this, "InMemoryUsageStorage");
9
+ }
10
+ name = "memory";
11
+ #records = [];
12
+ record(input) {
13
+ const normalised = "kind" in input && input.kind === "tool" ? {
14
+ ...input
15
+ } : {
16
+ ...input,
17
+ kind: "llm"
18
+ };
19
+ this.#records.push(normalised);
20
+ return Promise.resolve();
21
+ }
22
+ getUsage(query = {}) {
23
+ const matching = this.#records.filter((record) => matches(record, query));
24
+ const llm = matching.filter((record) => record.kind !== "tool");
25
+ return Promise.resolve({
26
+ totalTokens: llm.reduce((sum, r) => sum + r.tokens.input + r.tokens.output, 0),
27
+ totalCostUsd: llm.reduce((sum, r) => sum + r.costUsd, 0),
28
+ runs: llm.length
29
+ });
30
+ }
31
+ /**
32
+ * The most recent LLM record, or `undefined`.
33
+ *
34
+ * The question a terminal asks after every turn — "what did that cost?" — and the reason a
35
+ * consumer wrote a ten-line file to answer it. Tool records are excluded: a tool invocation has no
36
+ * token cost of its own, and returning one here would make the footer show zero after every tool.
37
+ */
38
+ latestUsage() {
39
+ for (let i = this.#records.length - 1; i >= 0; i -= 1) {
40
+ const record = this.#records[i];
41
+ if (record.kind !== "tool") return record;
42
+ }
43
+ return void 0;
44
+ }
45
+ };
46
+ function matches(record, query) {
47
+ if (query.userId !== void 0 && record.userId !== query.userId) return false;
48
+ if (query.period === void 0) return true;
49
+ return record.timestamp >= query.period.from && record.timestamp <= query.period.to;
50
+ }
51
+ __name(matches, "matches");
52
+ export {
53
+ InMemoryUsageStorage
54
+ };
55
+ //# sourceMappingURL=usage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/usage/in-memory-usage.ts"],"mappings":";;;;;AAmBO,IAAMA,uBAAN,MAAMA;EAXb,OAWaA;;;EACFC,OAAO;EACP,WAA8C,CAAA;EAEvDC,OAAOC,OAAqD;AAG1D,UAAMC,aACJ,UAAUD,SAASA,MAAME,SAAS,SAAS;MAAE,GAAGF;IAAM,IAAI;MAAE,GAAGA;MAAOE,MAAM;IAAe;AAC7F,SAAK,SAASC,KAAKF,UAAAA;AACnB,WAAOG,QAAQC,QAAO;EACxB;EAEAC,SAASC,QAAoB,CAAC,GAAyB;AACrD,UAAMC,WAAW,KAAK,SAASC,OAAO,CAACV,WAAWW,QAAQX,QAAQQ,KAAAA,CAAAA;AAClE,UAAMI,MAAMH,SAASC,OAAO,CAACV,WAAkCA,OAAOG,SAAS,MAAA;AAC/E,WAAOE,QAAQC,QAAQ;MACrBO,aAAaD,IAAIE,OAAO,CAACC,KAAKC,MAAMD,MAAMC,EAAEC,OAAOhB,QAAQe,EAAEC,OAAOC,QAAQ,CAAA;MAC5EC,cAAcP,IAAIE,OAAO,CAACC,KAAKC,MAAMD,MAAMC,EAAEI,SAAS,CAAA;MACtDC,MAAMT,IAAIU;IACZ,CAAA;EACF;;;;;;;;EASAC,cAAuC;AACrC,aAASC,IAAI,KAAK,SAASF,SAAS,GAAGE,KAAK,GAAGA,KAAK,GAAG;AACrD,YAAMxB,SAAS,KAAK,SAASwB,CAAAA;AAC7B,UAAIxB,OAAOG,SAAS,OAAQ,QAAOH;IACrC;AACA,WAAOyB;EACT;AACF;AAEA,SAASd,QAAQX,QAAuCQ,OAAiB;AAGvE,MAAIA,MAAMkB,WAAWD,UAAazB,OAAO0B,WAAWlB,MAAMkB,OAAQ,QAAO;AACzE,MAAIlB,MAAMmB,WAAWF,OAAW,QAAO;AACvC,SAAOzB,OAAO4B,aAAapB,MAAMmB,OAAOE,QAAQ7B,OAAO4B,aAAapB,MAAMmB,OAAOG;AACnF;AANSnB;","names":["InMemoryUsageStorage","name","record","input","normalised","kind","push","Promise","resolve","getUsage","query","matching","filter","matches","llm","totalTokens","reduce","sum","r","tokens","output","totalCostUsd","costUsd","runs","length","latestUsage","i","undefined","userId","period","timestamp","from","to"]}
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@theokit/agents",
3
- "version": "7.5.0",
3
+ "version": "8.0.0",
4
4
  "description": "AI agents as first-class citizens of the TheoKit pipeline. The fluent agent()/tool() builders compile to SDK Agent.create() (M31 builder-only authoring API).",
5
+ "license": "Apache-2.0",
5
6
  "type": "module",
6
7
  "sideEffects": false,
7
8
  "main": "./dist/index.js",
@@ -50,6 +51,38 @@
50
51
  "./client/react": {
51
52
  "types": "./dist/client-react.d.ts",
52
53
  "import": "./dist/client-react.js"
54
+ },
55
+ "./session": {
56
+ "types": "./dist/session.d.ts",
57
+ "import": "./dist/session.js"
58
+ },
59
+ "./hooks": {
60
+ "types": "./dist/hooks.d.ts",
61
+ "import": "./dist/hooks.js"
62
+ },
63
+ "./ask": {
64
+ "types": "./dist/ask.d.ts",
65
+ "import": "./dist/ask.js"
66
+ },
67
+ "./tool-scope": {
68
+ "types": "./dist/tool-scope.d.ts",
69
+ "import": "./dist/tool-scope.js"
70
+ },
71
+ "./mcp-health": {
72
+ "types": "./dist/mcp-health.d.ts",
73
+ "import": "./dist/mcp-health.js"
74
+ },
75
+ "./commands": {
76
+ "types": "./dist/commands.d.ts",
77
+ "import": "./dist/commands.js"
78
+ },
79
+ "./doctor": {
80
+ "types": "./dist/doctor.d.ts",
81
+ "import": "./dist/doctor.js"
82
+ },
83
+ "./usage": {
84
+ "types": "./dist/usage.d.ts",
85
+ "import": "./dist/usage.js"
53
86
  }
54
87
  },
55
88
  "files": [
@@ -63,23 +96,15 @@
63
96
  "zod": "^4.0.0"
64
97
  },
65
98
  "peerDependenciesMeta": {
66
- "@theokit/sdk-pty": {
67
- "optional": true
68
- },
69
- "@theokit/sdk-tools": {
70
- "optional": true
71
- },
72
99
  "react": {
73
100
  "optional": true
74
101
  }
75
102
  },
76
103
  "devDependencies": {
77
- "@theokit/sdk-pty": "^0.2.0",
78
- "@theokit/sdk-tools": "^0.24.1",
79
104
  "ai": "7.0.14",
80
105
  "tsup": "^8.5.1",
81
106
  "typescript": "^5.9.3",
82
- "vitest": "^3.2.6",
107
+ "vitest": "^4.1.9",
83
108
  "zod": "^4.4.3",
84
109
  "@theokit/http": "1.0.0"
85
110
  },
@@ -87,10 +112,10 @@
87
112
  "node": ">=22.12.0"
88
113
  },
89
114
  "dependencies": {
90
- "@theokit/sdk": "^4.40.0",
115
+ "@theokit/sdk": "^4.49.0",
91
116
  "@theokit/sdk-pty": ">=0.2.0 <1.0.0",
92
117
  "@theokit/sdk-tools": "^0.26.1",
93
- "@theokit/presenter": "0.5.1"
118
+ "@theokit/presenter": "0.7.0"
94
119
  },
95
120
  "scripts": {
96
121
  "build": "tsup",