claude-flow 2.5.0-alpha.141 → 2.7.0-alpha
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/.claude/agents/reasoning/README.md +171 -0
- package/.claude/agents/reasoning/agent.md +816 -0
- package/.claude/agents/reasoning/example-reasoning-agent-template.md +362 -0
- package/.claude/agents/reasoning/goal-planner.md +73 -0
- package/.claude/commands/coordination/README.md +9 -0
- package/.claude/commands/memory/README.md +9 -0
- package/.claude/settings.json +3 -3
- package/.claude/sparc-modes.json +108 -0
- package/README.md +1 -6
- package/bin/claude-flow +1 -1
- package/dist/src/cli/command-registry.js +70 -6
- package/dist/src/cli/command-registry.js.map +1 -1
- package/dist/src/cli/help-formatter.js +0 -3
- package/dist/src/cli/help-formatter.js.map +1 -1
- package/dist/src/cli/help-text.js +53 -5
- package/dist/src/cli/help-text.js.map +1 -1
- package/dist/src/cli/simple-cli.js +182 -172
- package/dist/src/cli/simple-cli.js.map +1 -1
- package/dist/src/cli/simple-commands/agent-booster.js +415 -0
- package/dist/src/cli/simple-commands/agent-booster.js.map +1 -0
- package/dist/src/cli/simple-commands/agent.js +856 -13
- package/dist/src/cli/simple-commands/agent.js.map +1 -1
- package/dist/src/cli/simple-commands/env-template.js +180 -0
- package/dist/src/cli/simple-commands/env-template.js.map +1 -0
- package/dist/src/cli/simple-commands/init/help.js +23 -0
- package/dist/src/cli/simple-commands/init/help.js.map +1 -1
- package/dist/src/cli/simple-commands/init/index.js +63 -0
- package/dist/src/cli/simple-commands/init/index.js.map +1 -1
- package/dist/src/cli/simple-commands/memory.js +307 -16
- package/dist/src/cli/simple-commands/memory.js.map +1 -1
- package/dist/src/cli/simple-commands/proxy.js +304 -0
- package/dist/src/cli/simple-commands/proxy.js.map +1 -0
- package/dist/src/cli/simple-commands/sparc.js +16 -19
- package/dist/src/cli/simple-commands/sparc.js.map +1 -1
- package/dist/src/cli/validation-helper.js.map +1 -1
- package/dist/src/core/version.js +1 -1
- package/dist/src/execution/agent-executor.js +181 -0
- package/dist/src/execution/agent-executor.js.map +1 -0
- package/dist/src/execution/index.js +12 -0
- package/dist/src/execution/index.js.map +1 -0
- package/dist/src/execution/provider-manager.js +110 -0
- package/dist/src/execution/provider-manager.js.map +1 -0
- package/dist/src/hooks/redaction-hook.js +89 -0
- package/dist/src/hooks/redaction-hook.js.map +1 -0
- package/dist/src/memory/swarm-memory.js +340 -421
- package/dist/src/memory/swarm-memory.js.map +1 -1
- package/dist/src/utils/key-redactor.js +108 -0
- package/dist/src/utils/key-redactor.js.map +1 -0
- package/dist/src/utils/metrics-reader.js +37 -39
- package/dist/src/utils/metrics-reader.js.map +1 -1
- package/docs/AGENT-BOOSTER-INTEGRATION.md +407 -0
- package/docs/AGENTIC-FLOW-INTEGRATION-GUIDE.md +753 -0
- package/docs/AGENTIC_FLOW_EXECUTION_FIX_REPORT.md +474 -0
- package/docs/AGENTIC_FLOW_INTEGRATION_STATUS.md +143 -0
- package/docs/AGENTIC_FLOW_MVP_COMPLETE.md +367 -0
- package/docs/AGENTIC_FLOW_SECURITY_TEST_REPORT.md +369 -0
- package/docs/COMMAND-VERIFICATION-REPORT.md +441 -0
- package/docs/COMMIT_SUMMARY.md +247 -0
- package/docs/DEEP_REVIEW_COMPREHENSIVE_REPORT.md +922 -0
- package/docs/DOCKER-VALIDATION-REPORT.md +281 -0
- package/docs/ENV-SETUP-GUIDE.md +270 -0
- package/docs/FINAL_PRE_PUBLISH_VALIDATION.md +823 -0
- package/docs/FINAL_VALIDATION_REPORT.md +165 -0
- package/docs/HOOKS-V2-MODIFICATION.md +146 -0
- package/docs/INDEX.md +568 -0
- package/docs/INTEGRATION_COMPLETE.md +414 -0
- package/docs/MEMORY_REDACTION_TEST_REPORT.md +300 -0
- package/docs/PERFORMANCE-SYSTEMS-STATUS.md +340 -0
- package/docs/PRE_RELEASE_FIXES_REPORT.md +435 -0
- package/docs/README.md +35 -0
- package/docs/REASONING-AGENTS.md +482 -0
- package/docs/REASONINGBANK-AGENT-CREATION-GUIDE.md +813 -0
- package/docs/REASONINGBANK-ANALYSIS-COMPLETE.md +479 -0
- package/docs/REASONINGBANK-BENCHMARK-RESULTS.md +166 -0
- package/docs/REASONINGBANK-BENCHMARK.md +396 -0
- package/docs/REASONINGBANK-CLI-INTEGRATION.md +455 -0
- package/docs/REASONINGBANK-CORE-INTEGRATION.md +658 -0
- package/docs/REASONINGBANK-COST-OPTIMIZATION.md +329 -0
- package/docs/REASONINGBANK-DEMO.md +419 -0
- package/docs/REASONINGBANK-INTEGRATION-COMPLETE.md +249 -0
- package/docs/REASONINGBANK-VALIDATION.md +532 -0
- package/docs/REASONINGBANK_ARCHITECTURE.md +475 -0
- package/docs/REASONINGBANK_INTEGRATION_COMPLETE.md +558 -0
- package/docs/REASONINGBANK_INTEGRATION_PLAN.md +1188 -0
- package/docs/REGRESSION-ANALYSIS-REPORT.md +500 -0
- package/docs/RELEASE_v2.6.0-alpha.2.md +658 -0
- package/docs/api/API_DOCUMENTATION.md +721 -0
- package/docs/architecture/ARCHITECTURE.md +1690 -0
- package/docs/ci-cd/README.md +368 -0
- package/docs/development/DEPLOYMENT.md +2348 -0
- package/docs/development/DEVELOPMENT_WORKFLOW.md +1333 -0
- package/docs/development/build-analysis-report.md +252 -0
- package/docs/development/pair-optimization.md +156 -0
- package/docs/development/token-tracking-status.md +103 -0
- package/docs/development/training-pipeline-demo.md +163 -0
- package/docs/development/training-pipeline-real-only.md +196 -0
- package/docs/epic-sdk-integration.md +1269 -0
- package/docs/experimental/RIEMANN_HYPOTHESIS_PROOF.md +124 -0
- package/docs/experimental/computational_verification.py +436 -0
- package/docs/experimental/novel_approaches.md +560 -0
- package/docs/experimental/riemann_hypothesis_analysis.md +263 -0
- package/docs/experimental/riemann_proof_attempt.md +124 -0
- package/docs/experimental/riemann_synthesis.md +277 -0
- package/docs/experimental/verification_results.json +12 -0
- package/docs/experimental/visualization_insights.md +720 -0
- package/docs/guides/USER_GUIDE.md +1138 -0
- package/docs/guides/token-tracking-guide.md +291 -0
- package/docs/reference/AGENTS.md +1011 -0
- package/docs/reference/MCP_TOOLS.md +2188 -0
- package/docs/reference/SPARC.md +717 -0
- package/docs/reference/SWARM.md +2000 -0
- package/docs/sdk/CLAUDE-CODE-SDK-DEEP-ANALYSIS.md +649 -0
- package/docs/sdk/CLAUDE-FLOW-SDK-INTEGRATION-ANALYSIS.md +242 -0
- package/docs/sdk/INTEGRATION-ROADMAP.md +420 -0
- package/docs/sdk/MCP-TOOLS-UPDATE.md +270 -0
- package/docs/sdk/SDK-ADVANCED-FEATURES-INTEGRATION.md +723 -0
- package/docs/sdk/SDK-ALL-FEATURES-INTEGRATION-MATRIX.md +612 -0
- package/docs/sdk/SDK-INTEGRATION-COMPLETE.md +358 -0
- package/docs/sdk/SDK-INTEGRATION-PHASES-V2.5.md +750 -0
- package/docs/sdk/SDK-LEVERAGE-REAL-FEATURES.md +676 -0
- package/docs/sdk/SDK-VALIDATION-RESULTS.md +400 -0
- package/docs/sdk/epic-sdk-integration.md +1269 -0
- package/docs/setup/remote-setup.md +93 -0
- package/docs/validation/final-validation-summary.md +220 -0
- package/docs/validation/verification-integration.md +190 -0
- package/docs/validation/verification-validation.md +349 -0
- package/docs/wiki/background-commands.md +1213 -0
- package/docs/wiki/session-persistence.md +342 -0
- package/docs/wiki/stream-chain-command.md +537 -0
- package/package.json +4 -2
- package/src/cli/command-registry.js +70 -5
- package/src/cli/help-text.js +26 -5
- package/src/cli/simple-cli.ts +18 -7
- package/src/cli/simple-commands/agent-booster.js +515 -0
- package/src/cli/simple-commands/agent.js +1001 -12
- package/src/cli/simple-commands/agent.ts +137 -0
- package/src/cli/simple-commands/config.ts +127 -0
- package/src/cli/simple-commands/env-template.js +190 -0
- package/src/cli/simple-commands/init/help.js +23 -0
- package/src/cli/simple-commands/init/index.js +84 -6
- package/src/cli/simple-commands/memory.js +363 -16
- package/src/cli/simple-commands/proxy.js +384 -0
- package/src/cli/simple-commands/sparc.js +16 -19
- package/src/execution/agent-executor.ts +306 -0
- package/src/execution/index.ts +19 -0
- package/src/execution/provider-manager.ts +187 -0
- package/src/hooks/redaction-hook.ts +115 -0
- package/src/utils/key-redactor.js +178 -0
- package/src/utils/key-redactor.ts +184 -0
|
@@ -0,0 +1,676 @@
|
|
|
1
|
+
# Leveraging Claude Code SDK for Real Features
|
|
2
|
+
|
|
3
|
+
## SDK Capabilities Analysis
|
|
4
|
+
|
|
5
|
+
### What the SDK Actually Provides
|
|
6
|
+
|
|
7
|
+
From examining `/node_modules/@anthropic-ai/claude-code/sdk.d.ts`, here's what we can **actually** use:
|
|
8
|
+
|
|
9
|
+
#### **1. Query Interface** (Line 365-377)
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
export interface Query extends AsyncGenerator<SDKMessage, void> {
|
|
13
|
+
// Control methods
|
|
14
|
+
interrupt(): Promise<void>;
|
|
15
|
+
setPermissionMode(mode: PermissionMode): Promise<void>;
|
|
16
|
+
setModel(model?: string): Promise<void>;
|
|
17
|
+
supportedCommands(): Promise<SlashCommand[]>;
|
|
18
|
+
supportedModels(): Promise<ModelInfo[]>;
|
|
19
|
+
mcpServerStatus(): Promise<McpServerStatus[]>;
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**What's Real:**
|
|
24
|
+
- ✅ `interrupt()` - Actually stops execution
|
|
25
|
+
- ✅ `setPermissionMode()` - Change permissions mid-execution
|
|
26
|
+
- ✅ `setModel()` - Switch models during conversation
|
|
27
|
+
- ✅ Streaming interface via `AsyncGenerator`
|
|
28
|
+
|
|
29
|
+
**What's Missing:**
|
|
30
|
+
- ❌ No `pause()` method
|
|
31
|
+
- ❌ No `getState()` or `setState()` for snapshots
|
|
32
|
+
- ❌ No `fork()` or session isolation
|
|
33
|
+
- ❌ No checkpoint/rollback primitives
|
|
34
|
+
|
|
35
|
+
#### **2. Options Configuration** (Line 219-258)
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
export type Options = {
|
|
39
|
+
forkSession?: boolean; // ✅ Session forking flag
|
|
40
|
+
resume?: string; // ✅ Resume from session ID
|
|
41
|
+
resumeSessionAt?: string; // ✅ Resume from specific message
|
|
42
|
+
hooks?: Partial<Record<HookEvent, HookCallbackMatcher[]>>; // ✅ Hook system
|
|
43
|
+
mcpServers?: Record<string, McpServerConfig>; // ✅ In-process MCP
|
|
44
|
+
maxTurns?: number;
|
|
45
|
+
permissionMode?: PermissionMode;
|
|
46
|
+
canUseTool?: CanUseTool;
|
|
47
|
+
// ... more options
|
|
48
|
+
};
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**What's Real:**
|
|
52
|
+
- ✅ `forkSession` - Creates new session ID (not true isolation)
|
|
53
|
+
- ✅ `resume` - Resume from session ID
|
|
54
|
+
- ✅ `resumeSessionAt` - Resume from specific message (partial checkpoint!)
|
|
55
|
+
- ✅ `hooks` - Intercept execution at key points
|
|
56
|
+
- ✅ `mcpServers.sdk` - In-process MCP server support
|
|
57
|
+
|
|
58
|
+
#### **3. MCP Tools API** (Line 397-413)
|
|
59
|
+
|
|
60
|
+
```typescript
|
|
61
|
+
export declare function tool<Schema extends ZodRawShape>(
|
|
62
|
+
name: string,
|
|
63
|
+
description: string,
|
|
64
|
+
inputSchema: Schema,
|
|
65
|
+
handler: (args, extra) => Promise<CallToolResult>
|
|
66
|
+
): SdkMcpToolDefinition<Schema>;
|
|
67
|
+
|
|
68
|
+
export declare function createSdkMcpServer(options: {
|
|
69
|
+
name: string;
|
|
70
|
+
version?: string;
|
|
71
|
+
tools?: Array<SdkMcpToolDefinition<any>>;
|
|
72
|
+
}): McpSdkServerConfigWithInstance;
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**What's Real:**
|
|
76
|
+
- ✅ Can create in-process MCP servers
|
|
77
|
+
- ✅ Tools run in same process (no IPC)
|
|
78
|
+
- ✅ Zod schema validation
|
|
79
|
+
- ✅ Direct function calls
|
|
80
|
+
|
|
81
|
+
#### **4. Hook System** (Line 133-218)
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
export const HOOK_EVENTS = [
|
|
85
|
+
"PreToolUse", "PostToolUse", "Notification",
|
|
86
|
+
"UserPromptSubmit", "SessionStart", "SessionEnd",
|
|
87
|
+
"Stop", "SubagentStop", "PreCompact"
|
|
88
|
+
] as const;
|
|
89
|
+
|
|
90
|
+
export type HookCallback = (
|
|
91
|
+
input: HookInput,
|
|
92
|
+
toolUseID: string | undefined,
|
|
93
|
+
options: { signal: AbortSignal }
|
|
94
|
+
) => Promise<HookJSONOutput>;
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**What's Real:**
|
|
98
|
+
- ✅ Can intercept at 9 different lifecycle points
|
|
99
|
+
- ✅ Can modify tool inputs before execution
|
|
100
|
+
- ✅ Can add context after tool execution
|
|
101
|
+
- ✅ Can abort operations
|
|
102
|
+
|
|
103
|
+
#### **5. Message Streaming** (Line 278-364)
|
|
104
|
+
|
|
105
|
+
```typescript
|
|
106
|
+
export type SDKMessage =
|
|
107
|
+
| SDKAssistantMessage // Model responses
|
|
108
|
+
| SDKUserMessage // User inputs
|
|
109
|
+
| SDKResultMessage // Execution results
|
|
110
|
+
| SDKSystemMessage // System info
|
|
111
|
+
| SDKPartialAssistantMessage // Streaming chunks
|
|
112
|
+
| SDKCompactBoundaryMessage; // Compaction events
|
|
113
|
+
|
|
114
|
+
// Each message has:
|
|
115
|
+
{
|
|
116
|
+
uuid: UUID;
|
|
117
|
+
session_id: string;
|
|
118
|
+
// ... message-specific data
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**What's Real:**
|
|
123
|
+
- ✅ Every message has UUID and session_id
|
|
124
|
+
- ✅ Can track full conversation history
|
|
125
|
+
- ✅ Streaming support for real-time updates
|
|
126
|
+
- ✅ Usage tracking (tokens, cost)
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## How to Build Real Features with SDK
|
|
131
|
+
|
|
132
|
+
### **1. Real Session Forking** - Using SDK Primitives
|
|
133
|
+
|
|
134
|
+
**SDK Provides:**
|
|
135
|
+
- `forkSession: true` - New session ID
|
|
136
|
+
- `resume: sessionId` - Resume from session
|
|
137
|
+
- `resumeSessionAt: messageId` - Resume from specific point
|
|
138
|
+
|
|
139
|
+
**Real Implementation:**
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
import { query, type Options, type SDKMessage } from '@anthropic-ai/claude-code';
|
|
143
|
+
|
|
144
|
+
class RealSessionForking {
|
|
145
|
+
private sessions = new Map<string, SessionSnapshot>();
|
|
146
|
+
|
|
147
|
+
async forkSession(baseSessionId: string): Promise<ForkedSession> {
|
|
148
|
+
// 1. Capture current session state
|
|
149
|
+
const snapshot = await this.captureSession(baseSessionId);
|
|
150
|
+
|
|
151
|
+
// 2. Create forked query with SDK's forkSession
|
|
152
|
+
const forkedQuery = query({
|
|
153
|
+
prompt: 'Continue from fork',
|
|
154
|
+
options: {
|
|
155
|
+
forkSession: true, // ✅ SDK creates new session ID
|
|
156
|
+
resume: baseSessionId, // ✅ SDK loads conversation history
|
|
157
|
+
resumeSessionAt: snapshot.lastMessageId, // ✅ SDK resumes from point
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// 3. Extract new session ID from first message
|
|
162
|
+
const firstMessage = await forkedQuery.next();
|
|
163
|
+
const newSessionId = firstMessage.value?.session_id;
|
|
164
|
+
|
|
165
|
+
// 4. Track fork relationship
|
|
166
|
+
this.sessions.set(newSessionId!, {
|
|
167
|
+
parentId: baseSessionId,
|
|
168
|
+
forkedAt: Date.now(),
|
|
169
|
+
messages: [firstMessage.value!],
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
sessionId: newSessionId!,
|
|
174
|
+
query: forkedQuery,
|
|
175
|
+
|
|
176
|
+
// Commit changes back to parent
|
|
177
|
+
async commit() {
|
|
178
|
+
const changes = await this.getChanges(newSessionId!);
|
|
179
|
+
await this.applyToParent(baseSessionId, changes);
|
|
180
|
+
},
|
|
181
|
+
|
|
182
|
+
// Discard fork
|
|
183
|
+
async rollback() {
|
|
184
|
+
this.sessions.delete(newSessionId!);
|
|
185
|
+
await forkedQuery.interrupt();
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Capture session state using SDK message history
|
|
191
|
+
private async captureSession(sessionId: string): Promise<SessionSnapshot> {
|
|
192
|
+
const snapshot = this.sessions.get(sessionId);
|
|
193
|
+
if (!snapshot) throw new Error('Session not found');
|
|
194
|
+
|
|
195
|
+
return {
|
|
196
|
+
sessionId,
|
|
197
|
+
lastMessageId: snapshot.messages[snapshot.messages.length - 1].uuid,
|
|
198
|
+
messageCount: snapshot.messages.length,
|
|
199
|
+
timestamp: Date.now(),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Track all messages for a session
|
|
204
|
+
async trackSession(sessionId: string, query: AsyncGenerator<SDKMessage>) {
|
|
205
|
+
const messages: SDKMessage[] = [];
|
|
206
|
+
|
|
207
|
+
for await (const message of query) {
|
|
208
|
+
messages.push(message);
|
|
209
|
+
|
|
210
|
+
// Update snapshot after each message
|
|
211
|
+
this.sessions.set(sessionId, {
|
|
212
|
+
parentId: null,
|
|
213
|
+
forkedAt: Date.now(),
|
|
214
|
+
messages,
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Usage
|
|
221
|
+
const forker = new RealSessionForking();
|
|
222
|
+
|
|
223
|
+
// Track original session
|
|
224
|
+
const originalQuery = query({ prompt: 'Start task', options: {} });
|
|
225
|
+
await forker.trackSession('original-session', originalQuery);
|
|
226
|
+
|
|
227
|
+
// Fork session (uses SDK's forkSession + resume)
|
|
228
|
+
const fork = await forker.forkSession('original-session');
|
|
229
|
+
|
|
230
|
+
// Work in fork
|
|
231
|
+
for await (const msg of fork.query) {
|
|
232
|
+
console.log('Fork message:', msg);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Commit or rollback
|
|
236
|
+
await fork.commit(); // Merge changes
|
|
237
|
+
// OR
|
|
238
|
+
await fork.rollback(); // Discard fork
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Real Benefits:**
|
|
242
|
+
- ✅ Uses SDK's actual `forkSession` + `resume` + `resumeSessionAt`
|
|
243
|
+
- ✅ True isolation via separate query instances
|
|
244
|
+
- ✅ Commit/rollback semantics
|
|
245
|
+
- ✅ No custom forking logic needed
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
### **2. Real Query Control** - Pause/Resume with SDK
|
|
250
|
+
|
|
251
|
+
**SDK Provides:**
|
|
252
|
+
- `resumeSessionAt: messageId` - Resume from specific point
|
|
253
|
+
- Message UUIDs - Identify exact conversation points
|
|
254
|
+
- Hook system - Intercept and pause
|
|
255
|
+
|
|
256
|
+
**Real Implementation:**
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
import { query, type Query, type SDKMessage } from '@anthropic-ai/claude-code';
|
|
260
|
+
|
|
261
|
+
class RealQueryControl {
|
|
262
|
+
private pausedQueries = new Map<string, PausedQuery>();
|
|
263
|
+
|
|
264
|
+
async pauseQuery(activeQuery: Query, sessionId: string): Promise<string> {
|
|
265
|
+
const messages: SDKMessage[] = [];
|
|
266
|
+
|
|
267
|
+
// 1. Collect all messages up to pause point
|
|
268
|
+
for await (const message of activeQuery) {
|
|
269
|
+
messages.push(message);
|
|
270
|
+
|
|
271
|
+
// Check if pause was requested
|
|
272
|
+
if (this.shouldPause(sessionId)) {
|
|
273
|
+
// 2. Stop iteration (SDK's interrupt happens on break)
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// 3. Save pause state
|
|
279
|
+
const lastMessage = messages[messages.length - 1];
|
|
280
|
+
const pausePoint: PausedQuery = {
|
|
281
|
+
sessionId,
|
|
282
|
+
messages,
|
|
283
|
+
pausedAt: Date.now(),
|
|
284
|
+
resumeFromMessageId: lastMessage.uuid,
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
this.pausedQueries.set(sessionId, pausePoint);
|
|
288
|
+
|
|
289
|
+
// 4. Interrupt the query
|
|
290
|
+
await activeQuery.interrupt();
|
|
291
|
+
|
|
292
|
+
return lastMessage.uuid;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
async resumeQuery(sessionId: string, continuePrompt: string): Promise<Query> {
|
|
296
|
+
const paused = this.pausedQueries.get(sessionId);
|
|
297
|
+
if (!paused) throw new Error('No paused query found');
|
|
298
|
+
|
|
299
|
+
// 1. Resume using SDK's resumeSessionAt
|
|
300
|
+
const resumedQuery = query({
|
|
301
|
+
prompt: continuePrompt,
|
|
302
|
+
options: {
|
|
303
|
+
resume: sessionId,
|
|
304
|
+
resumeSessionAt: paused.resumeFromMessageId, // ✅ SDK resumes from exact point!
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// 2. Clean up paused state
|
|
309
|
+
this.pausedQueries.delete(sessionId);
|
|
310
|
+
|
|
311
|
+
return resumedQuery;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Pause control flag
|
|
315
|
+
private pauseRequests = new Set<string>();
|
|
316
|
+
|
|
317
|
+
requestPause(sessionId: string) {
|
|
318
|
+
this.pauseRequests.add(sessionId);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
private shouldPause(sessionId: string): boolean {
|
|
322
|
+
return this.pauseRequests.has(sessionId);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Usage
|
|
327
|
+
const controller = new RealQueryControl();
|
|
328
|
+
|
|
329
|
+
// Start query
|
|
330
|
+
const activeQuery = query({
|
|
331
|
+
prompt: 'Long running task',
|
|
332
|
+
options: { sessionId: 'my-session' }
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Request pause (in another thread/callback)
|
|
336
|
+
setTimeout(() => controller.requestPause('my-session'), 5000);
|
|
337
|
+
|
|
338
|
+
// Pause will happen during iteration
|
|
339
|
+
const pausePoint = await controller.pauseQuery(activeQuery, 'my-session');
|
|
340
|
+
|
|
341
|
+
console.log('Paused at message:', pausePoint);
|
|
342
|
+
|
|
343
|
+
// Resume later (even after restart!)
|
|
344
|
+
const resumed = await controller.resumeQuery('my-session', 'Continue task');
|
|
345
|
+
|
|
346
|
+
for await (const msg of resumed) {
|
|
347
|
+
console.log('Resumed:', msg);
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**Real Benefits:**
|
|
352
|
+
- ✅ True pause - breaks iteration and saves state
|
|
353
|
+
- ✅ True resume - SDK's `resumeSessionAt` continues from exact point
|
|
354
|
+
- ✅ Persistent - can save pause state to disk and resume after restart
|
|
355
|
+
- ✅ No fake "pause" - actually uses SDK primitives
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
### **3. Real Context Checkpoints** - Using SDK Messages
|
|
360
|
+
|
|
361
|
+
**SDK Provides:**
|
|
362
|
+
- Message UUIDs - Unique identifiers for every message
|
|
363
|
+
- Full message history - Complete conversation state
|
|
364
|
+
- `resumeSessionAt` - Jump to any message in history
|
|
365
|
+
|
|
366
|
+
**Real Implementation:**
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
import { query, type SDKMessage } from '@anthropic-ai/claude-code';
|
|
370
|
+
|
|
371
|
+
class RealCheckpointManager {
|
|
372
|
+
private checkpoints = new Map<string, Checkpoint>();
|
|
373
|
+
|
|
374
|
+
async createCheckpoint(
|
|
375
|
+
sessionId: string,
|
|
376
|
+
messages: SDKMessage[],
|
|
377
|
+
description: string
|
|
378
|
+
): Promise<string> {
|
|
379
|
+
// Get last message UUID as checkpoint ID
|
|
380
|
+
const lastMessage = messages[messages.length - 1];
|
|
381
|
+
const checkpointId = lastMessage.uuid;
|
|
382
|
+
|
|
383
|
+
// Save checkpoint with full state
|
|
384
|
+
const checkpoint: Checkpoint = {
|
|
385
|
+
id: checkpointId,
|
|
386
|
+
sessionId,
|
|
387
|
+
description,
|
|
388
|
+
timestamp: Date.now(),
|
|
389
|
+
|
|
390
|
+
// Only store message IDs (efficient!)
|
|
391
|
+
messageIds: messages.map(m => m.uuid),
|
|
392
|
+
|
|
393
|
+
// Store any additional metadata
|
|
394
|
+
metadata: {
|
|
395
|
+
turnCount: messages.filter(m => m.type === 'assistant').length,
|
|
396
|
+
totalTokens: this.calculateTokens(messages),
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
this.checkpoints.set(checkpointId, checkpoint);
|
|
401
|
+
|
|
402
|
+
// Optionally persist to disk
|
|
403
|
+
await this.persist(checkpoint);
|
|
404
|
+
|
|
405
|
+
return checkpointId;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
async rollbackToCheckpoint(checkpointId: string, newPrompt: string): Promise<Query> {
|
|
409
|
+
const checkpoint = this.checkpoints.get(checkpointId);
|
|
410
|
+
if (!checkpoint) throw new Error('Checkpoint not found');
|
|
411
|
+
|
|
412
|
+
// Use SDK's resumeSessionAt to jump to checkpoint!
|
|
413
|
+
const rolledBackQuery = query({
|
|
414
|
+
prompt: newPrompt,
|
|
415
|
+
options: {
|
|
416
|
+
resume: checkpoint.sessionId,
|
|
417
|
+
resumeSessionAt: checkpointId, // ✅ SDK rewinds to this message
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
return rolledBackQuery;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Auto-checkpoint on important events using hooks
|
|
425
|
+
async enableAutoCheckpoint(sessionId: string) {
|
|
426
|
+
return query({
|
|
427
|
+
prompt: 'Task',
|
|
428
|
+
options: {
|
|
429
|
+
hooks: {
|
|
430
|
+
PostToolUse: [{
|
|
431
|
+
async hooks(input) {
|
|
432
|
+
// Create checkpoint after each tool use
|
|
433
|
+
if (input.tool_name === 'Edit' || input.tool_name === 'Write') {
|
|
434
|
+
await this.createCheckpoint(
|
|
435
|
+
sessionId,
|
|
436
|
+
this.getMessages(sessionId),
|
|
437
|
+
`After ${input.tool_name}: ${input.tool_input.file_path}`
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
return { continue: true };
|
|
441
|
+
}
|
|
442
|
+
}]
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
private calculateTokens(messages: SDKMessage[]): number {
|
|
449
|
+
return messages
|
|
450
|
+
.filter(m => m.type === 'assistant')
|
|
451
|
+
.reduce((sum, m) => {
|
|
452
|
+
if ('usage' in m) {
|
|
453
|
+
return sum + m.usage.input_tokens + m.usage.output_tokens;
|
|
454
|
+
}
|
|
455
|
+
return sum;
|
|
456
|
+
}, 0);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
private async persist(checkpoint: Checkpoint) {
|
|
460
|
+
const fs = await import('fs/promises');
|
|
461
|
+
await fs.writeFile(
|
|
462
|
+
`.checkpoints/${checkpoint.id}.json`,
|
|
463
|
+
JSON.stringify(checkpoint, null, 2)
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
// Usage
|
|
469
|
+
const checkpointMgr = new RealCheckpointManager();
|
|
470
|
+
|
|
471
|
+
// Start task and track messages
|
|
472
|
+
const messages: SDKMessage[] = [];
|
|
473
|
+
const taskQuery = query({ prompt: 'Complex task', options: {} });
|
|
474
|
+
|
|
475
|
+
for await (const msg of taskQuery) {
|
|
476
|
+
messages.push(msg);
|
|
477
|
+
|
|
478
|
+
// Create checkpoint after important messages
|
|
479
|
+
if (msg.type === 'assistant') {
|
|
480
|
+
await checkpointMgr.createCheckpoint('session-1', messages, 'After step');
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Later: rollback to checkpoint
|
|
485
|
+
const checkpointId = messages[5].uuid; // 6th message
|
|
486
|
+
const rolledBack = await checkpointMgr.rollbackToCheckpoint(
|
|
487
|
+
checkpointId,
|
|
488
|
+
'Try different approach'
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
// Conversation continues from message 6!
|
|
492
|
+
for await (const msg of rolledBack) {
|
|
493
|
+
console.log('After rollback:', msg);
|
|
494
|
+
}
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
**Real Benefits:**
|
|
498
|
+
- ✅ True rollback - SDK's `resumeSessionAt` actually rewinds
|
|
499
|
+
- ✅ Efficient storage - Only store message IDs
|
|
500
|
+
- ✅ Git-like - Can jump to any point in history
|
|
501
|
+
- ✅ Hook integration - Auto-checkpoint on events
|
|
502
|
+
|
|
503
|
+
---
|
|
504
|
+
|
|
505
|
+
### **4. Real In-Process MCP** - Using SDK's createSdkMcpServer
|
|
506
|
+
|
|
507
|
+
**SDK Provides:**
|
|
508
|
+
- `createSdkMcpServer()` - Create in-process server
|
|
509
|
+
- `tool()` - Define tools with Zod schemas
|
|
510
|
+
- Direct function calls - No IPC
|
|
511
|
+
|
|
512
|
+
**Real Implementation:**
|
|
513
|
+
|
|
514
|
+
```typescript
|
|
515
|
+
import {
|
|
516
|
+
createSdkMcpServer,
|
|
517
|
+
tool,
|
|
518
|
+
query
|
|
519
|
+
} from '@anthropic-ai/claude-code';
|
|
520
|
+
import { z } from 'zod';
|
|
521
|
+
|
|
522
|
+
// Create in-process MCP server
|
|
523
|
+
const myServer = createSdkMcpServer({
|
|
524
|
+
name: 'my-tools',
|
|
525
|
+
version: '1.0.0',
|
|
526
|
+
tools: [
|
|
527
|
+
// Tool with schema validation
|
|
528
|
+
tool(
|
|
529
|
+
'calculate',
|
|
530
|
+
'Perform calculation',
|
|
531
|
+
{
|
|
532
|
+
operation: z.enum(['add', 'subtract', 'multiply', 'divide']),
|
|
533
|
+
a: z.number(),
|
|
534
|
+
b: z.number(),
|
|
535
|
+
},
|
|
536
|
+
async (args) => {
|
|
537
|
+
// Direct function call - no IPC, no serialization!
|
|
538
|
+
const { operation, a, b } = args;
|
|
539
|
+
let result: number;
|
|
540
|
+
|
|
541
|
+
switch (operation) {
|
|
542
|
+
case 'add': result = a + b; break;
|
|
543
|
+
case 'subtract': result = a - b; break;
|
|
544
|
+
case 'multiply': result = a * b; break;
|
|
545
|
+
case 'divide': result = a / b; break;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
return {
|
|
549
|
+
content: [{ type: 'text', text: `Result: ${result}` }]
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
),
|
|
553
|
+
|
|
554
|
+
// Complex tool with object schema
|
|
555
|
+
tool(
|
|
556
|
+
'process_data',
|
|
557
|
+
'Process complex data structure',
|
|
558
|
+
{
|
|
559
|
+
data: z.array(z.object({
|
|
560
|
+
id: z.string(),
|
|
561
|
+
value: z.number(),
|
|
562
|
+
})),
|
|
563
|
+
transformType: z.enum(['sum', 'average', 'max']),
|
|
564
|
+
},
|
|
565
|
+
async (args) => {
|
|
566
|
+
// Direct access to JavaScript objects - no serialization!
|
|
567
|
+
const values = args.data.map(d => d.value);
|
|
568
|
+
let result: number;
|
|
569
|
+
|
|
570
|
+
switch (args.transformType) {
|
|
571
|
+
case 'sum':
|
|
572
|
+
result = values.reduce((a, b) => a + b, 0);
|
|
573
|
+
break;
|
|
574
|
+
case 'average':
|
|
575
|
+
result = values.reduce((a, b) => a + b, 0) / values.length;
|
|
576
|
+
break;
|
|
577
|
+
case 'max':
|
|
578
|
+
result = Math.max(...values);
|
|
579
|
+
break;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
return {
|
|
583
|
+
content: [{ type: 'text', text: `Result: ${result}` }]
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
)
|
|
587
|
+
]
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
// Use in-process server
|
|
591
|
+
const response = query({
|
|
592
|
+
prompt: 'Calculate 5 + 3',
|
|
593
|
+
options: {
|
|
594
|
+
mcpServers: {
|
|
595
|
+
'my-tools': myServer // ✅ SDK uses in-process, no IPC!
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
for await (const msg of response) {
|
|
601
|
+
console.log(msg);
|
|
602
|
+
}
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
**Real Benefits:**
|
|
606
|
+
- ✅ Zero IPC overhead - truly in-process
|
|
607
|
+
- ✅ Zod validation - type-safe tool inputs
|
|
608
|
+
- ✅ Direct object access - no JSON serialization
|
|
609
|
+
- ✅ SDK handles everything - no custom MCP protocol
|
|
610
|
+
|
|
611
|
+
**Performance Comparison:**
|
|
612
|
+
|
|
613
|
+
```typescript
|
|
614
|
+
// Benchmark real speedup
|
|
615
|
+
async function benchmarkInProcess() {
|
|
616
|
+
const iterations = 1000;
|
|
617
|
+
const complexData = Array.from({ length: 1000 }, (_, i) => ({
|
|
618
|
+
id: `item-${i}`,
|
|
619
|
+
value: Math.random()
|
|
620
|
+
}));
|
|
621
|
+
|
|
622
|
+
// In-process
|
|
623
|
+
const inProcessStart = Date.now();
|
|
624
|
+
for (let i = 0; i < iterations; i++) {
|
|
625
|
+
await myServer.instance.callTool('process_data', {
|
|
626
|
+
data: complexData,
|
|
627
|
+
transformType: 'sum'
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
const inProcessTime = Date.now() - inProcessStart;
|
|
631
|
+
|
|
632
|
+
// stdio MCP (for comparison)
|
|
633
|
+
// Would require: JSON.stringify(complexData) -> IPC -> JSON.parse -> handler
|
|
634
|
+
// Estimated: 50-100ms per call vs <1ms for in-process
|
|
635
|
+
|
|
636
|
+
console.log(`In-process: ${inProcessTime}ms (${inProcessTime/iterations}ms per call)`);
|
|
637
|
+
console.log(`Expected stdio: ~${iterations * 50}ms (50ms per call)`);
|
|
638
|
+
console.log(`Real speedup: ~${(iterations * 50) / inProcessTime}x`);
|
|
639
|
+
}
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
---
|
|
643
|
+
|
|
644
|
+
## Summary: What SDK Enables
|
|
645
|
+
|
|
646
|
+
| Feature | SDK Primitive | Real Implementation |
|
|
647
|
+
|---------|--------------|---------------------|
|
|
648
|
+
| **Session Forking** | `forkSession` + `resume` + `resumeSessionAt` | Create forks with commit/rollback |
|
|
649
|
+
| **Query Control** | `resumeSessionAt` + message UUIDs | True pause/resume from exact point |
|
|
650
|
+
| **Checkpoints** | `resumeSessionAt` + message history | Git-like rollback to any message |
|
|
651
|
+
| **In-Process MCP** | `createSdkMcpServer` + `tool` | Zero-IPC tools with Zod validation |
|
|
652
|
+
| **Hook Integration** | 9 hook events | Auto-checkpoint, state capture |
|
|
653
|
+
|
|
654
|
+
## Implementation Priority with SDK
|
|
655
|
+
|
|
656
|
+
**Week 1: SDK-Powered Checkpoints**
|
|
657
|
+
- Use `resumeSessionAt` for rollback
|
|
658
|
+
- Track message UUIDs
|
|
659
|
+
- Hook-based auto-checkpointing
|
|
660
|
+
|
|
661
|
+
**Week 2: Real Query Control**
|
|
662
|
+
- Pause with state capture
|
|
663
|
+
- Resume using `resumeSessionAt`
|
|
664
|
+
- Persistent pause state
|
|
665
|
+
|
|
666
|
+
**Week 3: Session Forking**
|
|
667
|
+
- Use SDK's `forkSession` + `resume`
|
|
668
|
+
- Add commit/rollback logic
|
|
669
|
+
- Parent-child tracking
|
|
670
|
+
|
|
671
|
+
**Week 4: In-Process MCP Optimization**
|
|
672
|
+
- Build tool library with `createSdkMcpServer`
|
|
673
|
+
- Benchmark vs stdio
|
|
674
|
+
- Production hardening
|
|
675
|
+
|
|
676
|
+
The SDK actually provides **90% of what we need** - we just need to use it correctly instead of reinventing it!
|