@deepstrike/sdk 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # DeepStrike Node.js SDK
2
2
 
3
- Agent framework built on a Rust kernel. The kernel handles loop control, context compression, skill selection, and termination — the SDK handles all I/O.
3
+ Agent framework built on a Rust kernel. The kernel handles loop control, context compression, skill routing, governance, signal prioritization — the SDK handles all I/O.
4
4
 
5
5
  ## Install
6
6
 
@@ -15,21 +15,25 @@ Requires Node.js 18+. The Rust kernel is distributed as a pre-built native addon
15
15
  ## Quick start
16
16
 
17
17
  ```typescript
18
- import { Agent, AnthropicProvider, tool } from "@deepstrike/sdk"
18
+ import { Agent, OpenAIProvider, tool } from "@deepstrike/sdk"
19
+
20
+ const provider = new OpenAIProvider({
21
+ apiKey: process.env.OPENAI_API_KEY,
22
+ model: "gpt-5-mini",
23
+ baseUrl: "https://api.openai.com/v1",
24
+ })
19
25
 
20
26
  const add = tool("add", "Add two numbers.", {
21
27
  type: "object",
22
28
  properties: { x: { type: "number" }, y: { type: "number" } },
23
29
  required: ["x", "y"],
24
- }, async ({ x, y }) => String((x as number) + (y as number)))
30
+ }, async ({ x, y }) => String(Number(x) + Number(y)))
25
31
 
26
- const agent = new Agent(
27
- new AnthropicProvider("sk-..."),
28
- { maxTokens: 32_000, maxTurns: 10 },
29
- )
32
+ const agent = new Agent(provider, { maxTokens: 4096 })
30
33
  agent.register(add)
31
34
 
32
- await agent.run("What is 2 + 3?")
35
+ const result = await agent.run("What is 17 + 28?")
36
+ console.log(result) // "done in 2 turns (completed)"
33
37
  ```
34
38
 
35
39
  Streaming:
@@ -38,63 +42,44 @@ Streaming:
38
42
  for await (const event of agent.runStreaming("Summarize README.md")) {
39
43
  if (event.type === "text_delta") process.stdout.write(event.delta)
40
44
  else if (event.type === "tool_call") console.log(`\n[→ ${event.name}]`)
45
+ else if (event.type === "tool_result") console.log(` = ${event.content}`)
41
46
  else if (event.type === "done") console.log(`\ndone in ${event.iterations} turns (${event.status})`)
42
47
  }
43
48
  ```
44
49
 
45
50
  ---
46
51
 
47
- ## Architecture
48
-
49
- ```
50
- src/
51
- ├── index.ts # Public exports
52
- ├── agent.ts # Agent — top-level entry point
53
- ├── types.ts # Shared type definitions
54
- ├── providers/ # LLM adapters (HTTP + streaming)
55
- ├── tools/ # tool() helper, executeTools, built-ins
56
- ├── skills/ # SkillLoader — .md file loading
57
- ├── memory/ # WorkingMemory + MemorySource/Extractor interfaces
58
- ├── knowledge/ # KnowledgeSource interface
59
- ├── harness/ # SinglePassHarness, EvalLoopHarness, QualityGate
60
- ├── signals/ # RuntimeSignal, SignalSource, ScheduledPrompt
61
- └── safety/ # PermissionManager
62
- ```
63
-
64
- The kernel (`@deepstrike/core`, Rust/NAPI) owns:
65
- - `LoopStateMachine` — drives `call_llm → execute_tools → load_skills → done`
66
- - `ContextEngine` — 5-partition context with pressure-based compression
67
- - `Governance` — tool veto authority
68
- - `SignalRouter` — external interrupt queue
69
-
70
- ---
71
-
72
52
  ## Providers
73
53
 
74
54
  | Class | Backend | Notes |
75
55
  |-------|---------|-------|
76
- | `AnthropicProvider` | Anthropic API | Native SSE, `ThinkingDelta` support |
77
56
  | `OpenAIProvider` | OpenAI API | SSE tool-call accumulation |
57
+ | `AnthropicProvider` | Anthropic API | Native SSE, `ThinkingDelta` support |
78
58
  | `QwenProvider` | DashScope | `enable_thinking` via extensions |
79
59
  | `DeepSeekProvider` | DeepSeek API | Reasoner models strip tools automatically |
80
60
  | `MiniMaxProvider` | MiniMax API | M1 reasoning via `expose_reasoning` |
81
61
  | `OllamaProvider` | Local Ollama | `http://localhost:11434` default |
62
+ | `KimiProvider` | Moonshot API | |
82
63
 
83
- ```typescript
84
- import { AnthropicProvider } from "@deepstrike/sdk"
64
+ All providers accept `RetryConfig` for exponential backoff and share a `CircuitBreaker`.
85
65
 
86
- const provider = new AnthropicProvider("sk-...", "claude-opus-4-7", {
87
- maxRetries: 5,
88
- baseDelay: 2000,
89
- })
90
- ```
66
+ ---
91
67
 
92
- Thinking / reasoning:
68
+ ## Agent options
93
69
 
94
70
  ```typescript
95
- for await (const event of agent.runStreaming("...", undefined, { enable_thinking: true })) {
96
- if (event.type === "thinking_delta") process.stdout.write(event.delta)
97
- }
71
+ const agent = new Agent(provider, {
72
+ maxTokens: 4096, // context window size
73
+ maxTurns: 25, // max turns (default 25)
74
+ timeoutMs: 60_000, // timeout in ms
75
+ extensions: { temperature: 0.1 }, // pass-through to LLM
76
+ skillDir: "./skills", // skill .md files directory
77
+ knowledgeSource: myKS, // KnowledgeSource implementation
78
+ signalSource: rx, // SignalSource for external signals
79
+ dreamStore: myStore, // DreamStore for long-term memory
80
+ agentId: "my-agent", // required with dreamStore for memory meta-tool
81
+ governance: gov, // Governance pipeline instance
82
+ })
98
83
  ```
99
84
 
100
85
  ---
@@ -102,195 +87,177 @@ for await (const event of agent.runStreaming("...", undefined, { enable_thinking
102
87
  ## Tools
103
88
 
104
89
  ```typescript
105
- import { tool, Agent } from "@deepstrike/sdk"
90
+ import { tool, readFile } from "@deepstrike/sdk"
106
91
 
107
- const search = tool("search", "Search the knowledge base.", {
108
- type: "object",
109
- properties: { query: { type: "string" }, topK: { type: "number" } },
110
- required: ["query"],
111
- }, async ({ query, topK }) => mySearch(query as string, topK as number))
112
-
113
- agent.register(search)
92
+ agent.register(tool("search", "Search.", schema, async (args) => ...))
93
+ agent.register(readFile()) // built-in: read files from disk
114
94
  agent.unregister("search")
115
- agent.blockTool("bash") // governance veto — permanent for this agent instance
95
+ agent.blockTool("bash") // governance veto
116
96
  ```
117
97
 
118
- Built-in tools: `readFile`.
119
-
120
98
  ---
121
99
 
122
100
  ## Skills
123
101
 
124
- Skills are `.md` files with YAML frontmatter. The kernel selects and injects them automatically.
102
+ Skills are `.md` files with YAML frontmatter. Set `skillDir` on the agent — the kernel auto-injects a `skill` meta-tool, and the LLM loads skills by name on demand.
103
+
104
+ ```typescript
105
+ const agent = new Agent(provider, { maxTokens: 4096, skillDir: "./skills" })
106
+ ```
125
107
 
126
108
  ```markdown
127
109
  ---
128
- name: debug
129
- description: Step-by-step debugging guide
130
- when_to_use: error, traceback, exception
131
- effort: 2
132
- estimated_tokens: 800
110
+ name: summarize
111
+ description: Summarize text into 2-3 concise bullet points
112
+ when_to_use: When you need to condense long text
113
+ effort: 1
133
114
  ---
134
-
135
- ## Debug protocol
136
- 1. Read the traceback carefully ...
137
- ```
138
-
139
- ```typescript
140
- import { Agent, SkillLoader } from "@deepstrike/sdk"
141
-
142
- const loader = new SkillLoader("~/.deepstrike/skills")
143
- const agent = new Agent(provider, { maxTokens: 32_000, maxTurns: 10, skillLoader: loader })
115
+ 1. Identify the 2-3 most important points
116
+ 2. Express each as a concise bullet
144
117
  ```
145
118
 
146
119
  ---
147
120
 
148
- ## Memory
121
+ ## Knowledge
149
122
 
150
- Implement `MemorySource` to inject persistent context before a run, and `MemoryExtractor` to persist what was learned after.
123
+ Implement `KnowledgeSource` to connect any RAG system. The kernel injects a `knowledge` meta-tool that the LLM calls on demand.
151
124
 
152
125
  ```typescript
153
- import type { MemorySource, MemoryExtractor } from "@deepstrike/sdk"
154
-
155
- class MyMemorySource implements MemorySource {
156
- async load(goal: string): Promise<string[]> {
157
- return db.query(goal)
158
- }
159
- }
160
-
161
- class MyMemoryExtractor implements MemoryExtractor {
162
- async extract(goal: string, finalText: string, turns: number): Promise<void> {
163
- await db.save(goal, finalText)
164
- }
165
- }
166
-
167
126
  const agent = new Agent(provider, {
168
- maxTokens: 32_000,
169
- maxTurns: 10,
170
- memorySource: new MyMemorySource(),
171
- memoryExtractor: new MyMemoryExtractor(),
127
+ maxTokens: 4096,
128
+ knowledgeSource: {
129
+ async retrieve(query: string, topK: number): Promise<string[]> {
130
+ return vectorDb.search(query, topK)
131
+ }
132
+ }
172
133
  })
173
134
  ```
174
135
 
175
- `WorkingMemory` is an in-process scratch pad for within-run state:
136
+ ---
137
+
138
+ ## Memory
139
+
140
+ ### WorkingMemory (in-session scratch pad)
176
141
 
177
142
  ```typescript
178
143
  import { WorkingMemory } from "@deepstrike/sdk"
179
-
180
144
  const mem = new WorkingMemory()
181
145
  mem.set("step", 1)
182
- mem.get("step") // 1
146
+ mem.get("step") // 1
147
+ mem.clear()
183
148
  ```
184
149
 
185
- ---
186
-
187
- ## Knowledge
188
-
189
- Inject run-scoped evidence (RAG results, API responses) without polluting long-term memory:
150
+ ### DreamStore (long-term memory + dreaming pipeline)
190
151
 
191
152
  ```typescript
192
- import type { KnowledgeSource } from "@deepstrike/sdk"
153
+ import type { DreamStore } from "@deepstrike/sdk"
193
154
 
194
- class VectorSearch implements KnowledgeSource {
195
- async retrieve(goal: string, topK = 5): Promise<string[]> {
196
- return vectorDb.search(goal, topK)
197
- }
155
+ class MyStore implements DreamStore {
156
+ async loadSessions(agentId) { ... }
157
+ async loadMemories(agentId) { ... }
158
+ async commit(agentId, result, existing) { ... }
159
+ async search(agentId, query, topK) { ... }
198
160
  }
199
161
 
200
162
  const agent = new Agent(provider, {
201
- maxTokens: 32_000,
202
- maxTurns: 10,
203
- knowledgeSource: new VectorSearch(),
163
+ maxTokens: 4096,
164
+ dreamStore: new MyStore(),
165
+ agentId: "my-agent", // enables `memory` meta-tool
204
166
  })
205
- ```
206
167
 
207
- Snippets are prepended as a system message before the first LLM call.
168
+ // In-session: LLM calls memory(query) → DreamStore.search()
169
+ // Post-session: trigger memory consolidation
170
+ const result = await agent.dream("my-agent", Date.now())
171
+ ```
208
172
 
209
173
  ---
210
174
 
211
- ## Harness
175
+ ## Governance
212
176
 
213
- Control how runs are attempted:
177
+ ### SDK PermissionManager
214
178
 
215
179
  ```typescript
216
- import { Agent, SinglePassHarness, EvalLoopHarness, HarnessRequest } from "@deepstrike/sdk"
217
- import type { QualityGate, HarnessOutcome } from "@deepstrike/sdk"
180
+ import { PermissionManager, PermissionMode } from "@deepstrike/sdk"
218
181
 
219
- // Single pass
220
- const harness = new SinglePassHarness(agent)
221
- const outcome = await harness.run({ goal: "Write a haiku" })
182
+ const pm = new PermissionManager(PermissionMode.DEFAULT)
183
+ pm.grant("fs", "read")
184
+ pm.grantWithApproval("db", "write", "Needs DBA approval")
185
+ pm.revoke("db", "drop")
186
+ pm.evaluate("fs", "read") // { allowed: true, ... }
187
+ ```
222
188
 
223
- // Eval loop — retry until QualityGate passes (max 3 attempts)
224
- class LengthGate implements QualityGate {
225
- async evaluate(request: HarnessRequest, outcome: HarnessOutcome): Promise<boolean> {
226
- return outcome.result.length > 50
227
- }
228
- }
189
+ ### Kernel Governance (full pipeline)
190
+
191
+ ```typescript
192
+ import { Governance } from "@deepstrike/sdk"
229
193
 
230
- const evalHarness = new EvalLoopHarness(agent, new LengthGate(), 3)
231
- const result = await evalHarness.run({ goal: "Write a haiku" })
232
- console.log(result.passed, result.iterations)
194
+ const gov = new Governance("allow")
195
+ gov.addPermissionRule("danger.*", "deny")
196
+ gov.blockTool("rm_rf")
197
+ gov.setRateLimit("api_call", 10, 60_000)
198
+
199
+ const agent = new Agent(provider, { maxTokens: 4096, governance: gov })
200
+ // Every tool call goes through: Permission → Veto → RateLimit → Constraint → Audit
233
201
  ```
234
202
 
235
203
  ---
236
204
 
237
- ## Signals & interrupts
205
+ ## Signals
238
206
 
239
207
  ```typescript
240
- import { ScheduledPrompt } from "@deepstrike/sdk"
241
- import type { SignalSource, RuntimeSignal } from "@deepstrike/sdk"
208
+ import { SignalGateway, ScheduledPrompt } from "@deepstrike/sdk"
242
209
 
243
- // Interrupt a running agent
244
- setTimeout(() => agent.interrupt(), 30_000)
210
+ const gw = new SignalGateway()
211
+ const rx = gw.subscribe()
245
212
 
246
- // Convert a scheduled prompt to a RuntimeSignal
247
- const prompt = new ScheduledPrompt("Daily standup summary", 1_700_000_000_000)
248
- const signal = prompt.toSignal()
249
- // signal.kind === "scheduled"
250
- // signal.payload === { goal: "Daily standup summary", criteria: [], runAtMs: ... }
251
- ```
213
+ gw.schedule(new ScheduledPrompt("standup", Date.now() + 3600_000))
214
+ gw.ingest({ kind: "interrupt", payload: {}, priority: 10 })
252
215
 
253
- Implement `SignalSource` to feed signals from any external source:
216
+ const agent = new Agent(provider, { maxTokens: 4096, signalSource: rx })
217
+ // kind="interrupt" → immediately stops the running agent
254
218
 
255
- ```typescript
256
- class WebhookSource implements SignalSource {
257
- async nextSignal(): Promise<RuntimeSignal | null> {
258
- const event = await webhookQueue.get()
259
- return { kind: "external", payload: event }
260
- }
261
- }
219
+ agent.interrupt() // also works directly
220
+ gw.destroy()
262
221
  ```
263
222
 
264
223
  ---
265
224
 
266
- ## Permissions
225
+ ## Harness (evaluation framework)
267
226
 
268
227
  ```typescript
269
- import { PermissionManager, PermissionMode } from "@deepstrike/sdk"
228
+ import { SinglePassHarness, EvalLoopHarness, HarnessLoop } from "@deepstrike/sdk"
270
229
 
271
- const pm = new PermissionManager(PermissionMode.DEFAULT)
272
- pm.grant("bash", "execute")
273
- pm.grant("fs", "*") // wildcard: all actions on fs
274
- pm.revoke("bash", "execute")
230
+ // 1. SinglePass — run once, always passes
231
+ const outcome = await new SinglePassHarness(agent).run({ goal: "Say hello" })
275
232
 
276
- const decision = pm.evaluate("bash", "execute")
277
- decision.allowed // boolean
278
- decision.reason // string
279
- ```
233
+ // 2. EvalLoop — retry until QualityGate passes
234
+ const harness = new EvalLoopHarness(agent, {
235
+ gate: async (req, out) => out.result.includes("hello"),
236
+ maxAttempts: 3,
237
+ })
280
238
 
281
- Modes: `DEFAULT` (evaluate grants), `PLAN` (block all), `AUTO` (allow all).
239
+ // 3. HarnessLoop — LLM-as-judge with feedback injection + skill extraction
240
+ const loop = new HarnessLoop(agent, {
241
+ evalProvider,
242
+ maxAttempts: 3,
243
+ skillDir: "./skills",
244
+ })
245
+ const out = await loop.run({ goal: "Write a haiku", criteria: ["Must be 3 lines"] })
246
+ console.log(out.passed, out.feedback)
247
+ ```
282
248
 
283
249
  ---
284
250
 
285
251
  ## Stream events
286
252
 
287
- | Event type | Fields |
288
- |------------|--------|
289
- | `text_delta` | `delta: string` |
290
- | `thinking_delta` | `delta: string` |
291
- | `tool_call` | `id, name, arguments` |
292
- | `tool_result` | `callId, name, content, isError` |
293
- | `done` | `iterations, totalTokens, status` |
294
- | `error` | `message: string` |
295
-
296
- `status` mirrors the kernel termination reason: `completed` / `max_turns` / `token_budget` / `timeout` / `user_abort` / `error`.
253
+ | Event type | Key fields |
254
+ |------------|------------|
255
+ | `text_delta` | `delta` |
256
+ | `thinking_delta` | `delta` |
257
+ | `tool_call` | `id`, `name`, `arguments` |
258
+ | `tool_result` | `callId`, `content`, `isError` |
259
+ | `permission_request` | `toolName`, `reason` |
260
+ | `done` | `iterations`, `totalTokens`, `status` |
261
+ | `error` | `message` |
262
+
263
+ `status`: `completed` · `max_turns` · `token_budget` · `timeout` · `user_abort` · `error`
package/dist/agent.d.ts CHANGED
@@ -9,8 +9,8 @@ export interface AgentOptions {
9
9
  timeoutMs?: number;
10
10
  extensions?: Record<string, unknown>;
11
11
  /**
12
- * Directory containing skill `.md` files. The kernel will auto-inject a
13
- * `skill` meta-tool so the model can load any skill by name on demand.
12
+ * Directory containing skill `.md` files. The kernel auto-injects a `skill`
13
+ * meta-tool so the model can load any skill by name on demand.
14
14
  */
15
15
  skillDir?: string;
16
16
  knowledgeSource?: KnowledgeSource;
@@ -19,15 +19,19 @@ export interface AgentOptions {
19
19
  dreamStore?: DreamStore;
20
20
  /**
21
21
  * Stable identifier for this agent. Required to enable in-session memory retrieval
22
- * when `dreamStore` is configured — the kernel injects a `memory` meta-tool and
23
- * the SDK calls `dreamStore.search(agentId, query)` on demand.
22
+ * when `dreamStore` is configured.
24
23
  */
25
24
  agentId?: string;
26
- /** Governance instance from @deepstrike/core for permission checks on tool calls. */
25
+ /**
26
+ * Kernel Governance instance (from `@deepstrike/core`) or any object implementing
27
+ * `evaluate(toolName: string, argsJson: string): { kind: string; reason?: string; retryAfterMs?: number }`.
28
+ * When provided, every tool call is evaluated through the full pipeline.
29
+ */
27
30
  governance?: {
28
- evaluate(toolName: string, args: string): {
31
+ evaluate(toolName: string, argsJson: string): {
29
32
  kind: string;
30
33
  reason?: string;
34
+ retryAfterMs?: number;
31
35
  };
32
36
  };
33
37
  }
@@ -35,7 +39,6 @@ export declare class Agent {
35
39
  private readonly provider;
36
40
  private readonly options;
37
41
  private tools;
38
- private blockedTools;
39
42
  private extensions;
40
43
  private skillDir?;
41
44
  private knowledgeSource?;
@@ -43,20 +46,30 @@ export declare class Agent {
43
46
  private dreamStore?;
44
47
  private interrupted;
45
48
  private pendingInterrupt;
49
+ private _turn;
50
+ private _pressure;
46
51
  constructor(provider: LLMProvider, options: AgentOptions);
52
+ /** Current turn index within the active run (0 before a run starts). */
53
+ get turn(): number;
54
+ /** Context pressure ratio [0–1] from the kernel. Values > 0.8 trigger compression. */
55
+ get pressure(): number;
47
56
  interrupt(): void;
48
57
  register(...tools: RegisteredTool[]): this;
49
58
  unregister(name: string): this;
50
- blockTool(name: string): this;
59
+ /**
60
+ * Collect the full text response and return it.
61
+ * For richer control (streaming, tool events, token counts) use `runStreaming`.
62
+ */
51
63
  run(goal: string, criteria?: string[], extensions?: Record<string, unknown>): Promise<string>;
52
64
  runStreaming(goal: string, criteria?: string[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
53
65
  /**
54
- * Trigger an idle dreaming cycle for the given agent.
66
+ * Trigger the idle dreaming cycle for this agent.
67
+ * Requires `dreamStore` and `agentId` to be configured.
55
68
  *
56
- * Phase 1 — kernel rule-based analysis + LLM prompt assembly (kernel, pure computation)
57
- * Phase 2 — LLM synthesis call (SDK, I/O here)
58
- * Phase 3 — kernel parses + curates results (kernel, pure computation)
59
- * Phase 4 — commit delta to DreamStore (SDK, I/O here)
69
+ * Phase 1 — kernel rule-based analysis + LLM prompt assembly
70
+ * Phase 2 — LLM synthesis call (I/O)
71
+ * Phase 3 — kernel parses + curates results
72
+ * Phase 4 — commit delta to DreamStore (I/O)
60
73
  */
61
74
  dream(agentId: string, nowMs?: number): Promise<DreamResult>;
62
75
  }