@theokit/sdk 4.2.6 → 4.2.8

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 (25) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/claude-template/AGENTS.md +73 -55
  3. package/claude-template/CLAUDE.md +16 -1
  4. package/claude-template/dot-claude/rules/theokit-conventions.md +2 -3
  5. package/claude-template/dot-claude/skills/theokit-agent-core/SKILL.md +3 -3
  6. package/claude-template/dot-claude/skills/theokit-auth/SKILL.md +102 -0
  7. package/claude-template/dot-claude/skills/theokit-client/SKILL.md +58 -0
  8. package/claude-template/dot-claude/skills/theokit-compaction/SKILL.md +102 -0
  9. package/claude-template/dot-claude/skills/theokit-concurrency/SKILL.md +68 -0
  10. package/claude-template/dot-claude/skills/theokit-filesystem/SKILL.md +74 -0
  11. package/claude-template/dot-claude/skills/theokit-messages/SKILL.md +58 -0
  12. package/claude-template/dot-claude/skills/theokit-models/SKILL.md +79 -0
  13. package/claude-template/dot-claude/skills/theokit-path-safety/SKILL.md +60 -0
  14. package/claude-template/dot-claude/skills/theokit-persistence/SKILL.md +85 -0
  15. package/claude-template/dot-claude/skills/theokit-project/SKILL.md +55 -0
  16. package/claude-template/dot-claude/skills/theokit-retry/SKILL.md +50 -0
  17. package/claude-template/dot-claude/skills/theokit-sandbox/SKILL.md +93 -0
  18. package/claude-template/dot-claude/skills/theokit-sanitize/SKILL.md +66 -0
  19. package/claude-template/dot-claude/skills/theokit-skills/SKILL.md +68 -0
  20. package/claude-template/dot-claude/skills/theokit-subagents/SKILL.md +109 -0
  21. package/claude-template/dot-claude/skills/theokit-subscriptions/SKILL.md +6 -6
  22. package/claude-template/dot-claude/skills/theokit-task-store/SKILL.md +75 -0
  23. package/claude-template/dot-claude/skills/theokit-tools/SKILL.md +9 -9
  24. package/package.json +1 -1
  25. package/claude-template/dot-claude/skills/theokit-rag/SKILL.md +0 -226
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 4.2.8
4
+
5
+ ### Patch Changes
6
+
7
+ - feat(init-claude): the scaffolded `.claude/` template now covers **every public `@theokit/sdk` subpath**. Added 16 per-module skills — models, subagents (`/a2a` + tool-scope), retry, task-store, sandbox, compaction, messages, auth (`/server/auth` + errors-envelope), sanitize, skills, path-safety, concurrency, persistence, client, filesystem, project — each authored against the shipped type declarations (verified signatures: `Retry.create` executor, `Semaphore.create`, `SubAgent.create`, `Auth.create`, `sanitizeToolInput`, …). The `claude-template-no-drift` gate covers the expanded set.
8
+
9
+ ## 4.2.7
10
+
11
+ ### Patch Changes
12
+
13
+ - fix(init-claude): the scaffolded `.claude/` template (`npx theokit-init-claude`) now teaches the current `X.create()` API instead of the pre-3.0 surface removed by SE36 (#139). `AGENTS.md` + the affected skills/rules were corrected: `defineTool`→`Tool.create`, `defineSubscription`→`Subscription.create`, `createAgentFactory`→`AgentFactory.create`; the tool spec field is `handler` (not `execute`); streaming events are `system`/`user`/`assistant`/`thinking`/`tool_call`/`status`/`task`/`request` (there is no `tool_use`/`tool_result`/`usage`/`error`); assistant text is `event.message.content`; `Agent.prompt(prompt, options)` (prompt first); built-in coding tools import from `@theokit/sdk-tools` (not a `@theokit/sdk/tools` subpath). The phantom `theokit-rag` skill and the non-existent `@theokit/sdk/rag` import were removed. A `tests/lint/claude-template-no-drift.test.ts` gate now fails CI if the scaffold teaches a removed factory, phantom subpath, or non-existent stream event.
14
+
3
15
  ## 4.2.6
4
16
 
5
17
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  # @theokit/sdk — TypeScript SDK for AI Agents
2
2
 
3
- Build AI agents that run locally or in the cloud. Same code, same API, pick your runtime.
3
+ Build AI agents that run locally or in the cloud. Same code, same API, pick your runtime. The exported types are the canonical contract.
4
4
 
5
5
  ## Setup
6
6
 
@@ -13,24 +13,23 @@ Set your API key:
13
13
  export THEOKIT_API_KEY="your-key"
14
14
  ```
15
15
 
16
- ## Import Map
16
+ Node 22.12+ required.
17
+
18
+ ## Import Map (verified subpaths)
17
19
 
18
20
  ```typescript
19
- import { Agent } from "@theokit/sdk"; // Core: Agent, Run, SDKMessage
20
- import { defineTool } from "@theokit/sdk"; // Tool definitions
21
- import { TheokitAgentError } from "@theokit/sdk/errors"; // Error hierarchy
22
- import { Cron } from "@theokit/sdk/cron"; // Scheduled jobs
23
- import { Eval } from "@theokit/sdk/eval"; // Evaluation suite
24
- import { Workflow } from "@theokit/sdk/workflow"; // Multi-step workflows
25
- import { defineSubscription } from "@theokit/sdk/subscription"; // SSE/WebSocket subscriptions
26
- import { VectorRetriever } from "@theokit/sdk/rag"; // RAG: retrievers, rerankers, splitters
27
- import { defineSubAgent } from "@theokit/sdk/a2a"; // Agent-to-agent delegation
28
- import { SandboxBackend } from "@theokit/sdk/sandbox"; // Sandbox backends
29
- import { defineAuth } from "@theokit/sdk/server/auth"; // Authentication
30
- import { TaskStore } from "@theokit/sdk/task-store"; // Task persistence
31
- import { createClient } from "@theokit/sdk/client"; // HTTP client
21
+ import { Agent, Cron, Tool } from "@theokit/sdk"; // core: Agent, Run, Cron, Tool, SDKMessage
22
+ import { TheokitAgentError } from "@theokit/sdk/errors"; // error hierarchy
23
+ import { Workflow } from "@theokit/sdk/workflow"; // multi-step workflows
24
+ import { Eval } from "@theokit/sdk/eval"; // evaluation suite
25
+ import { Subscription } from "@theokit/sdk/subscription"; // SSE / WebSocket subscriptions
26
+ import { SubAgent } from "@theokit/sdk/a2a"; // agent-to-agent delegation
27
+ import { Auth } from "@theokit/sdk/server/auth"; // authentication
28
+ import { TaskStore } from "@theokit/sdk/task-store"; // task persistence
32
29
  ```
33
30
 
31
+ Other public subpaths: `/messages`, `/models`, `/skills`, `/project`, `/subagents`, `/sandbox`, `/client`, `/persistence`, `/retry`, `/concurrency`, `/sanitize`. There is **no** `@theokit/sdk/rag` subpath. Never import from `@theokit/sdk/internal/*` or `@theokit/sdk/dist/*`.
32
+
34
33
  ## Quick Start
35
34
 
36
35
  ```typescript
@@ -42,90 +41,109 @@ const agent = await Agent.create({
42
41
 
43
42
  const run = await agent.send("Summarize this repository");
44
43
  for await (const event of run.stream()) {
45
- if (event.type === "assistant") console.log(event.content);
44
+ if (event.type === "assistant") {
45
+ for (const block of event.message.content) {
46
+ if (block.type === "text") process.stdout.write(block.text);
47
+ }
48
+ }
46
49
  }
47
50
 
48
- agent.dispose(); // Always clean up
51
+ await agent[Symbol.asyncDispose](); // or: await using agent = await Agent.create(...)
49
52
  ```
50
53
 
51
54
  ## Core Patterns
52
55
 
53
56
  ### Agent lifecycle
54
- - `Agent.create(options)` — create an agent (local or cloud)
55
- - `agent.send(prompt)` — send a message, get a Run
56
- - `run.stream()` — AsyncGenerator of SDKMessage events
57
- - `agent.dispose()` — clean up resources (or use `await using`)
58
- - `Agent.prompt(options, prompt)` — one-shot: create, send, dispose
59
-
60
- ### Tool definition
57
+ - `Agent.create(options)` — create an agent (local or cloud); returns immediately, `agent.agentId` is `agent-<uuid>` (local) or `bc-<uuid>` (cloud).
58
+ - `agent.send(prompt)` — send a message, get a `Run` (context is retained across sends).
59
+ - `run.stream()` — `AsyncGenerator` of `SDKMessage` events.
60
+ - `run.wait()` — resolve to `{ status, result, model, durationMs, git? }` after the run ends.
61
+ - `Agent.prompt(prompt, options)` — one-shot (create + send + dispose). **Prompt is the first argument.**
62
+ - `Agent.resume(agentId, { apiKey })` — reattach; runtime auto-detected from the ID prefix.
63
+ - Dispose with `await using`, `await agent[Symbol.asyncDispose]()`, or `agent.close()` (fire-and-forget).
64
+
65
+ ### Tool definition — `Tool.create` with a Zod schema
61
66
  ```typescript
62
- const searchTool = defineTool({
67
+ import { z } from "zod";
68
+ import { Tool } from "@theokit/sdk";
69
+
70
+ const searchTool = Tool.create({
63
71
  name: "search",
64
72
  description: "Search the web",
65
73
  inputSchema: z.object({ query: z.string() }),
66
- execute: async ({ query }) => ({ results: await search(query) }),
74
+ handler: async ({ query }) => JSON.stringify({ results: await search(query) }),
67
75
  });
68
76
  ```
69
77
 
70
- ### Streaming events (SDKMessage)
71
- - `{ type: "assistant", content }` — text from the model
72
- - `{ type: "tool_use", name, input }` — tool call
73
- - `{ type: "tool_result", name, output }` — tool response
74
- - `{ type: "status", status }` — run status change
75
- - `{ type: "error", error }` error event
76
- - `{ type: "usage", tokens }` — token usage update
78
+ The tool spec field is `handler` (returns a string, or a typed value when you set `outputSchema`). Built-in coding tools (`createReadFileTool`, …) live in the separate `@theokit/sdk-tools` package, not a `@theokit/sdk/tools` subpath.
79
+
80
+ `Tool.create` is the canonical factory (uniform `X.create()` API since v3.0). Every public factory follows it: `Provider.create`, `Plugin.create`, `Subscription.create`, `Auth.create`, `SubAgent.create`, `Squad.create`, `Retry.create`. There is **no** `defineTool` / `define*` export those were removed at v3.0.
81
+
82
+ ### Streaming events (`SDKMessage`)
83
+ Discriminate on `type`. All events carry `agent_id` and `run_id`.
84
+ - `{ type: "system" }` — init metadata, once at start (`model?`, `tools?`)
85
+ - `{ type: "user", message: { content } }` — echo of the prompt
86
+ - `{ type: "assistant", message: { content } }` — model output; `content` is a `(TextBlock | ToolUseBlock)[]`
87
+ - `{ type: "thinking", text }` — reasoning content
88
+ - `{ type: "tool_call", call_id, name, status, args?, result? }` — tool lifecycle
89
+ - `{ type: "status", status }` — cloud run lifecycle
90
+ - `{ type: "task" }` / `{ type: "request", request_id }` — task milestones / awaiting input
91
+
92
+ There is no `tool_use` / `tool_result` / `usage` / `error` event. Read assistant text from `event.message.content` (a block array), not `event.content`. Treat `tool_call` `args`/`result` as `unknown`.
77
93
 
78
94
  ### Error handling
79
95
  ```typescript
96
+ import { TheokitAgentError } from "@theokit/sdk/errors";
97
+
80
98
  try {
81
99
  await agent.send("...");
82
100
  } catch (e) {
83
- if (e instanceof TheokitAgentError) {
84
- console.error(e.code, e.message); // typed error with code
85
- }
101
+ if (e instanceof TheokitAgentError) console.error(e.code, e.isRetryable, e.message);
86
102
  }
87
103
  ```
104
+ Subclasses: `AuthenticationError`, `RateLimitError`, `ConfigurationError`, `IntegrationNotConnectedError`, `NetworkError`, `UnknownAgentError`, `UnsupportedRunOperationError`.
88
105
 
89
- ### DI decorators (`@theokit/di` + `@theokit/di-agent`)
106
+ ### Optional: DI decorators (`@theokit/di` + `@theokit/di-agent`)
107
+ Decorators are an **optional** convenience layer in separate packages — the factory API above is canonical and never requires them.
90
108
  ```typescript
91
- import { Injectable, Container } from "@theokit/di";
92
- import { Tool, Workflow, Cron, InjectAgent } from "@theokit/di-agent";
109
+ import { Injectable } from "@theokit/di";
110
+ import { Tool as ToolDecorator, Cron as CronDecorator } from "@theokit/di-agent";
93
111
 
94
112
  @Injectable()
95
113
  class MyService {
96
- @Tool({ name: "search", description: "Search" })
97
- searchTool!: ToolOptions;
114
+ @ToolDecorator({ name: "search", description: "Search" })
115
+ searchTool!: unknown;
98
116
 
99
- @Cron({ schedule: "*/5 * * * *" })
117
+ @CronDecorator({ schedule: "*/5 * * * *" })
100
118
  cleanup() { /* runs every 5 min */ }
101
119
  }
102
120
  ```
103
121
 
104
- ### Gateways
122
+ ### Optional: Gateways
105
123
  ```typescript
106
124
  import { defineGateway } from "@theokit/gateway-telegram"; // or -slack, -discord, etc.
107
125
  const gateway = defineGateway({ token: process.env.BOT_TOKEN });
108
126
  ```
109
127
 
110
- Available: telegram, slack, discord, whatsapp, teams, email, sms, mattermost, line, matrix.
111
-
112
128
  ## Anti-patterns
113
129
 
114
- - NEVER import from `@theokit/sdk/internal/...` internal paths are not public API
115
- - NEVER import from `@theokit/sdk/dist/...` — use the exports map above
116
- - NEVER forget `agent.dispose()` — causes resource leaks
117
- - NEVER use `new Agent()` — always use `Agent.create()`
118
- - NEVER use `any` for tool input schemas use Zod schemas
130
+ - NEVER `new Agent()`always `await Agent.create()`.
131
+ - NEVER author `defineTool` / `defineSubscription` / `defineAuth` / `defineSubAgent` — use `Tool.create` / `Subscription.create` / `Auth.create` / `SubAgent.create`.
132
+ - NEVER switch on `tool_use` / `tool_result` / `usage` / `error` stream events they don't exist; use `tool_call` / `assistant` / `thinking` / `status`.
133
+ - NEVER read assistant text as `event.content`it's `event.message.content`.
134
+ - NEVER import from `@theokit/sdk/internal/*`, `@theokit/sdk/dist/*`, or `@theokit/sdk/rag` (no such subpath).
135
+ - NEVER forget disposal (`await using` / `Symbol.asyncDispose` / `close()`) — it leaks the runtime.
136
+ - NEVER use `any` for tool input schemas — use Zod schemas.
119
137
 
120
138
  ## Packages
121
139
 
122
140
  | Package | Purpose |
123
141
  |---------|---------|
124
- | `@theokit/sdk` | Core SDK (Agent, Run, Tools, Memory, Streaming) |
125
- | `@theokit/di` | Dependency injection container |
126
- | `@theokit/di-agent` | 15 agentic decorators for DI |
127
- | `@theokit/gateway-*` | Platform gateways (Telegram, Slack, etc.) |
128
- | `@theokit/react` | React hooks for agent UIs |
142
+ | `@theokit/sdk` | Core SDK (Agent, Run, Tool, Cron, streaming, memory, workflows, eval, subscriptions) |
143
+ | `@theokit/di` | Dependency injection container (optional) |
144
+ | `@theokit/di-agent` | Agentic decorators for DI (optional) |
145
+ | `@theokit/gateway-*` | Platform gateways — telegram, slack, discord, etc. (optional) |
146
+ | `@theokit/react` | React hooks for agent UIs (optional) |
129
147
 
130
148
  ## Configuration
131
149
 
@@ -16,7 +16,6 @@ These skills inject TheoKit knowledge automatically when you edit files matching
16
16
  | `theokit-di` | `*container*`, `*inject*`, `*provider*`, `*module*` |
17
17
  | `theokit-di-agent` | `*decorator*`, `*Decorator*`, `di-agent*` |
18
18
  | `theokit-gateways` | `*gateway*`, `*telegram*`, `*slack*`, `*discord*` |
19
- | `theokit-rag` | `*retriev*`, `*rerank*`, `*splitter*`, `*rag*` |
20
19
  | `theokit-workflows` | `*workflow*`, `*Workflow*`, `*step*` |
21
20
  | `theokit-eval` | `*eval*`, `*Eval*`, `*scorer*` |
22
21
  | `theokit-cron` | `*cron*`, `*Cron*`, `*job*`, `*schedule*` |
@@ -25,6 +24,22 @@ These skills inject TheoKit knowledge automatically when you edit files matching
25
24
  | `theokit-config` | `.theokit/**`, `config.*`, `theo.config.*` |
26
25
  | `theokit-streaming` | `*stream*`, `*Stream*`, `*SDKMessage*` |
27
26
  | `theokit-budget` | `*budget*`, `*Budget*`, `*cost*`, `*token*` |
27
+ | `theokit-models` | `*model*`, `*Model*` |
28
+ | `theokit-subagents` | `*subagent*`, `*a2a*`, `*delegat*` |
29
+ | `theokit-retry` | `*retry*`, `*Retry*` |
30
+ | `theokit-task-store` | `*task-store*`, `*taskstore*`, `*TaskStore*` |
31
+ | `theokit-sandbox` | `*sandbox*`, `*Sandbox*` |
32
+ | `theokit-compaction` | `*compact*`, `*Compact*` |
33
+ | `theokit-messages` | `*message*`, `*Message*` |
34
+ | `theokit-auth` | `*auth*`, `*Auth*`, `*envelope*` |
35
+ | `theokit-sanitize` | `*sanitize*`, `*Sanitize*` |
36
+ | `theokit-skills` | `*skill*`, `*Skill*` |
37
+ | `theokit-path-safety` | `*path-safety*`, `*pathsafety*` |
38
+ | `theokit-concurrency` | `*concurren*`, `*semaphore*`, `*Semaphore*` |
39
+ | `theokit-persistence` | `*persist*`, `*Persist*` |
40
+ | `theokit-client` | `*client*`, `*Client*` |
41
+ | `theokit-filesystem` | `*filesystem*`, `*Filesystem*` |
42
+ | `theokit-project` | `*project*`, `*Project*` |
28
43
 
29
44
  ### Settings
30
45
 
@@ -6,10 +6,9 @@
6
6
  - Use `Agent.prompt()` for one-shot operations (auto-disposes)
7
7
 
8
8
  ## Imports
9
- - Use `@theokit/sdk` for core (Agent, defineTool, Memory)
9
+ - Use `@theokit/sdk` for core (Agent, Tool, Cron, Memory)
10
10
  - Use `@theokit/sdk/errors` for error types
11
11
  - Use `@theokit/sdk/subscription` for SSE/WebSocket
12
- - Use `@theokit/sdk/rag` for retrievers, rerankers, splitters
13
12
  - Use `@theokit/sdk/cron` for scheduled jobs
14
13
  - Use `@theokit/sdk/eval` for evaluation
15
14
  - Use `@theokit/sdk/workflow` for workflows
@@ -18,7 +17,7 @@
18
17
 
19
18
  ## Tools
20
19
  - Tool `inputSchema` MUST use Zod schemas — NEVER `any` or untyped objects
21
- - Tool `execute` MUST return a serializable value
20
+ - Tool `handler` MUST return a string (or a value matching `outputSchema` when set)
22
21
 
23
22
  ## DI
24
23
  - Use `@Injectable()` + `@Inject()` from `@theokit/di`
@@ -129,12 +129,12 @@ const { items, nextCursor } = await Agent.list({ runtime: "local", cwd: process.
129
129
  const { items: runs } = await Agent.listRuns(agentId);
130
130
  ```
131
131
 
132
- ## createAgentFactory
132
+ ## AgentFactory.create
133
133
 
134
134
  ```typescript
135
- import { createAgentFactory } from "@theokit/sdk";
135
+ import { AgentFactory } from "@theokit/sdk";
136
136
 
137
- const factory = createAgentFactory({
137
+ const factory = AgentFactory.create({
138
138
  apiKey: process.env.THEOKIT_API_KEY!,
139
139
  model: { id: "claude-sonnet-4-6" },
140
140
  local: { cwd: process.cwd() },
@@ -0,0 +1,102 @@
1
+ ---
2
+ user-invocable: false
3
+ paths:
4
+ - "**/*auth*"
5
+ - "**/*Auth*"
6
+ - "**/*envelope*"
7
+ description: TheoKit SDK server auth — Auth.create orchestrator, validateReturnTo, and the cross-layer error envelope
8
+ ---
9
+
10
+ # TheoKit Server Auth
11
+
12
+ Server-side auth orchestrator and the cross-layer error envelope. These live
13
+ under the `@theokit/sdk/server/*` sub-paths (not the main barrel). Concrete
14
+ OAuth/email providers ship in opt-in `@theokit/auth-*` packages — the SDK only
15
+ defines the orchestrator contract.
16
+
17
+ ## `Auth.create` — session + provider orchestrator
18
+
19
+ ```typescript
20
+ import {
21
+ Auth,
22
+ validateReturnTo,
23
+ AuthConfigError,
24
+ AuthProviderNotFoundError,
25
+ AuthCallbackError,
26
+ AuthCancelledError,
27
+ AuthSecretTooShortError,
28
+ } from "@theokit/sdk/server/auth";
29
+ import type {
30
+ AuthProvider,
31
+ SessionManager,
32
+ AuthOrchestrator,
33
+ } from "@theokit/sdk/server/auth";
34
+ ```
35
+
36
+ `Auth.create(opts)` returns an `AuthOrchestrator<TSession>` with 5 methods.
37
+ `providers` is optional — an empty list is the manual-`signIn`-only escape hatch.
38
+
39
+ ```typescript
40
+ const auth: AuthOrchestrator<Session> = Auth.create<Session>({
41
+ session, // your SessionManager<Session> implementation
42
+ providers: [githubProvider], // AuthProvider<Profile>[] from a @theokit/auth-* package
43
+ onSignIn: async ({ profile, provider }) => {
44
+ return toSession(profile, provider); // returns the TSession to persist
45
+ },
46
+ onSignOut: async (session) => {
47
+ /* revoke, audit, etc. */
48
+ },
49
+ });
50
+
51
+ // OAuth flow (node:http req/res):
52
+ const redirect = await auth.startSignIn("github", req, { returnTo: "/dashboard" });
53
+ const { session, returnTo } = await auth.finishSignIn("github", req, res); // rotates session id (OWASP A07)
54
+ const current = await auth.getSession(req);
55
+ await auth.signOut(res);
56
+
57
+ // Escape hatch — persist a session directly, skipping the OAuth flow:
58
+ const s = await auth.signIn(externalProfile, "github", req, res);
59
+ ```
60
+
61
+ ## `validateReturnTo` — open-redirect guard (OWASP A01)
62
+
63
+ Returns a safe same-origin path. Cross-origin, protocol-relative (`//evil.com`),
64
+ empty, and defensive cases all collapse to `"/"`.
65
+
66
+ ```typescript
67
+ const safe = validateReturnTo(returnTo, new URL("https://app.example.com"));
68
+ // "/dashboard" -> kept; "https://evil.com" -> "/"; undefined -> "/"
69
+ ```
70
+
71
+ Typed errors: `AuthConfigError`, `AuthProviderNotFoundError`, `AuthCallbackError`,
72
+ `AuthCancelledError`, `AuthSecretTooShortError`.
73
+
74
+ ## Error envelope — cross-layer boundary translation
75
+
76
+ ```typescript
77
+ import {
78
+ toEnvelope,
79
+ fromEnvelope,
80
+ MemoryAdapterError,
81
+ } from "@theokit/sdk/server/errors-envelope";
82
+ import type {
83
+ TheokitErrorEnvelope,
84
+ TheokitErrorCode,
85
+ } from "@theokit/sdk/server/errors-envelope";
86
+ ```
87
+
88
+ `toEnvelope` translates any SDK error (or arbitrary thrown value) into the wire
89
+ envelope at egress; `fromEnvelope` reconstructs SDK class identity at ingress so
90
+ `instanceof` checks keep working across an IPC/serialization boundary.
91
+
92
+ ```typescript
93
+ try {
94
+ await agent.send(prompt);
95
+ } catch (err) {
96
+ const envelope: TheokitErrorEnvelope = toEnvelope(err); // { code, message, meta?, ext? }
97
+ send(envelope); // code is a TheokitErrorCode, e.g. "RATE_LIMITED"
98
+ }
99
+
100
+ // Inbound edge (e.g. worker receiving the envelope):
101
+ const restored = fromEnvelope(envelope); // a TheokitAgentError subclass
102
+ ```
@@ -0,0 +1,58 @@
1
+ ---
2
+ user-invocable: false
3
+ paths:
4
+ - "**/*client*"
5
+ - "**/*Client*"
6
+ description: TheoKit SDK low-level HTTP client — TheoKitClient (DEPRECATED; prefer the Agent façade)
7
+ ---
8
+
9
+ # TheoKit Client
10
+
11
+ `TheoKitClient` is a browser-safe, zero-Node-dependency HTTP client (native
12
+ `fetch` + manual SSE parsing) for a legacy server-adapter contract.
13
+
14
+ > DEPRECATED since 2.x — the `@theokit/sdk/client` sub-path consumes a legacy
15
+ > server-adapter HTTP contract (`POST /agent/send`, `GET /agent/stream`) that the
16
+ > ecosystem no longer produces, and will be removed in the next major. For
17
+ > in-process runs use the `Agent` façade (`@theokit/sdk`); for HTTP, use the
18
+ > framework's typed `POST /api/agents/<name>` client. Reach for this only when
19
+ > maintaining an existing integration against the old contract.
20
+
21
+ ```ts
22
+ import { TheoKitClient } from "@theokit/sdk/client";
23
+ import type { ClientOptions, SendResponse, StreamEvent } from "@theokit/sdk/client";
24
+ ```
25
+
26
+ ## Construct
27
+
28
+ The constructor takes `ClientOptions` — `baseUrl` (required), optional `basePath`
29
+ and `headers`.
30
+
31
+ ```ts
32
+ const client = new TheoKitClient({
33
+ baseUrl: "https://adapter.example.com",
34
+ basePath: "/agent", // optional
35
+ headers: { authorization: "Bearer …" }, // optional
36
+ });
37
+ ```
38
+
39
+ ## Send (one-shot)
40
+
41
+ `send(input)` POSTs and resolves a `SendResponse` (`{ status, output?, error? }`).
42
+
43
+ ```ts
44
+ const res: SendResponse = await client.send("summarize the repo");
45
+ if (res.error) throw new Error(res.error);
46
+ console.log(res.status, res.output);
47
+ ```
48
+
49
+ ## Stream (SSE)
50
+
51
+ `stream(input)` returns an `AsyncGenerator<StreamEvent>`; each `StreamEvent` has a
52
+ `type` and an optional `text` (plus arbitrary extra fields).
53
+
54
+ ```ts
55
+ for await (const event of client.stream("build the changelog")) {
56
+ if (event.type === "text" && event.text) process.stdout.write(event.text);
57
+ }
58
+ ```
@@ -0,0 +1,102 @@
1
+ ---
2
+ user-invocable: false
3
+ paths:
4
+ - "**/*compact*"
5
+ - "**/*Compact*"
6
+ description: TheoKit SDK compaction reference — compactTranscript, shouldCompact, checkpoints, context-overflow
7
+ ---
8
+
9
+ # TheoKit Compaction
10
+
11
+ Public context-management helpers. Every function is pure and never mutates its
12
+ input. A `CompressibleMessage` is `{ role: "user" | "assistant" | "system"; content: string }`.
13
+
14
+ ```typescript
15
+ import {
16
+ compactTranscript,
17
+ shouldCompact,
18
+ estimateTokens,
19
+ buildCheckpoint,
20
+ filterFromLatestCheckpoint,
21
+ isContextOverflowError,
22
+ CHECKPOINT_MARKER,
23
+ SUMMARY_TEMPLATE,
24
+ type CompactTranscriptOptions,
25
+ type ShouldCompactInput,
26
+ type CompressibleMessage,
27
+ } from "@theokit/sdk/compaction";
28
+ ```
29
+
30
+ ## Pre-call gate — `estimateTokens` + `shouldCompact`
31
+
32
+ `estimateTokens` is a tokenizer-free `ceil(text.length / 4)` heuristic — a cheap
33
+ gate, NOT exact tokenization. `shouldCompact` is pure: the caller supplies the
34
+ model's window.
35
+
36
+ ```typescript
37
+ const estimated = estimateTokens(transcript.map((m) => m.content).join("\n"));
38
+
39
+ const input: ShouldCompactInput = {
40
+ estimated,
41
+ contextWindow: 200_000,
42
+ buffer: 8_000, // headroom to reserve (output + safety margin)
43
+ maxOutput: 4_000, // optional; separate response reservation (default 0)
44
+ };
45
+
46
+ if (shouldCompact(input)) {
47
+ // compact before sending — see below
48
+ }
49
+ ```
50
+
51
+ ## `compactTranscript` — summarize the older window
52
+
53
+ Default `keepRecent` mode keeps the last N turns verbatim (default 6) and
54
+ preserves leading system prompts. The older window is summarized via the
55
+ caller-supplied `summarize` callback (or dropped if omitted). With `failSafe`, a
56
+ thrown summarizer returns the ORIGINAL transcript instead of propagating.
57
+
58
+ ```typescript
59
+ const opts: CompactTranscriptOptions = {
60
+ keepRecent: 6, // OR keepTokens: 40_000 (token-budget mode, takes precedence)
61
+ failSafe: true,
62
+ summarize: async (older: CompressibleMessage[], template: string) => {
63
+ // template is SUMMARY_TEMPLATE unless overridden via summaryTemplate
64
+ const summary = await callYourModel(template, older);
65
+ return { role: "system", content: summary };
66
+ },
67
+ };
68
+
69
+ const compacted = await compactTranscript(transcript, opts);
70
+ ```
71
+
72
+ ## Checkpoints — mark and filter
73
+
74
+ `buildCheckpoint` produces a `system` turn whose content starts with
75
+ `CHECKPOINT_MARKER`. `filterFromLatestCheckpoint` returns turns relative to the
76
+ most recent marker (`include: "after"` excludes it — the default; `"from"`
77
+ includes it).
78
+
79
+ ```typescript
80
+ const marked = [...transcript, buildCheckpoint("milestone: tests green")];
81
+
82
+ const recent = filterFromLatestCheckpoint(marked); // after (exclusive)
83
+ const withHead = filterFromLatestCheckpoint(marked, { include: "from" });
84
+ ```
85
+
86
+ ## Context-overflow detection
87
+
88
+ `isContextOverflowError` is `true` only for a `TheokitAgentError` reporting the
89
+ typed `context_too_long` code — never a brittle message regex.
90
+
91
+ ```typescript
92
+ try {
93
+ await agent.send(prompt);
94
+ } catch (err) {
95
+ if (isContextOverflowError(err)) {
96
+ const compacted = await compactTranscript(transcript, { keepRecent: 4 });
97
+ // retry with the compacted transcript
98
+ } else {
99
+ throw err;
100
+ }
101
+ }
102
+ ```
@@ -0,0 +1,68 @@
1
+ ---
2
+ user-invocable: false
3
+ description: Bound in-process parallelism with Semaphore.create and mapWithConcurrency from @theokit/sdk/concurrency.
4
+ paths:
5
+ - "**/*concurren*"
6
+ - "**/*semaphore*"
7
+ - "**/*Semaphore*"
8
+ ---
9
+
10
+ # TheoKit SDK -- Concurrency
11
+
12
+ In-house concurrency helpers (no `p-limit`/`p-map` dependency). `Semaphore.create(permits)` builds an N-permit async counting gate; `mapWithConcurrency` runs an async mapper over items with bounded parallelism while preserving input order.
13
+
14
+ ## Import
15
+
16
+ ```typescript
17
+ import { Semaphore, mapWithConcurrency } from "@theokit/sdk/concurrency";
18
+ import type { AsyncSemaphore } from "@theokit/sdk/concurrency";
19
+ ```
20
+
21
+ ## Signatures
22
+
23
+ ```typescript
24
+ class Semaphore {
25
+ static create(permits: number): AsyncSemaphore; // canonical factory (ADR 0015)
26
+ }
27
+
28
+ interface AsyncSemaphore {
29
+ acquire(): Promise<() => void>; // returns a release fn; call it exactly once
30
+ inFlight(): number; // permits currently held
31
+ pending(): number; // in-flight + queued waiters
32
+ }
33
+
34
+ function mapWithConcurrency<T, R>(
35
+ items: ReadonlyArray<T>,
36
+ concurrency: number, // positive integer; validated
37
+ fn: (item: T, index: number, signal: AbortSignal) => Promise<R>,
38
+ options?: { signal?: AbortSignal },
39
+ ): Promise<R[]>; // ordered; fail-fast; throws ConfigurationError on bad concurrency
40
+ ```
41
+
42
+ ## Semaphore -- release in a finally
43
+
44
+ ```typescript
45
+ const sem = Semaphore.create(4); // at most 4 in flight
46
+
47
+ async function guarded<T>(task: () => Promise<T>): Promise<T> {
48
+ const release = await sem.acquire();
49
+ try {
50
+ return await task();
51
+ } finally {
52
+ release(); // release exactly once (idempotent, but leaking it consumes a permit)
53
+ }
54
+ }
55
+ ```
56
+
57
+ ## mapWithConcurrency -- ordered bounded map
58
+
59
+ ```typescript
60
+ const controller = new AbortController();
61
+ const results = await mapWithConcurrency(
62
+ ["a", "b", "c"],
63
+ 2, // max 2 concurrent fetches
64
+ async (url, _index, signal) => (await fetch(url, { signal })).json(),
65
+ { signal: controller.signal },
66
+ );
67
+ // results align with input order; rejects on the first task error
68
+ ```