open-claude-agent-sdk 0.9.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 (96) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +141 -0
  3. package/dist/api/MessageQueue.d.ts +39 -0
  4. package/dist/api/MessageQueue.d.ts.map +1 -0
  5. package/dist/api/MessageQueue.js +90 -0
  6. package/dist/api/MessageQueue.js.map +1 -0
  7. package/dist/api/MessageRouter.d.ts +41 -0
  8. package/dist/api/MessageRouter.d.ts.map +1 -0
  9. package/dist/api/MessageRouter.js +95 -0
  10. package/dist/api/MessageRouter.js.map +1 -0
  11. package/dist/api/ProcessFactory.d.ts +23 -0
  12. package/dist/api/ProcessFactory.d.ts.map +1 -0
  13. package/dist/api/ProcessFactory.js +103 -0
  14. package/dist/api/ProcessFactory.js.map +1 -0
  15. package/dist/api/QueryImpl.d.ts +103 -0
  16. package/dist/api/QueryImpl.d.ts.map +1 -0
  17. package/dist/api/QueryImpl.js +417 -0
  18. package/dist/api/QueryImpl.js.map +1 -0
  19. package/dist/api/query.d.ts +32 -0
  20. package/dist/api/query.d.ts.map +1 -0
  21. package/dist/api/query.js +31 -0
  22. package/dist/api/query.js.map +1 -0
  23. package/dist/core/argBuilder.d.ts +16 -0
  24. package/dist/core/argBuilder.d.ts.map +1 -0
  25. package/dist/core/argBuilder.js +204 -0
  26. package/dist/core/argBuilder.js.map +1 -0
  27. package/dist/core/control.d.ts +66 -0
  28. package/dist/core/control.d.ts.map +1 -0
  29. package/dist/core/control.js +222 -0
  30. package/dist/core/control.js.map +1 -0
  31. package/dist/core/hookConfig.d.ts +31 -0
  32. package/dist/core/hookConfig.d.ts.map +1 -0
  33. package/dist/core/hookConfig.js +45 -0
  34. package/dist/core/hookConfig.js.map +1 -0
  35. package/dist/core/mcpBridge.d.ts +29 -0
  36. package/dist/core/mcpBridge.d.ts.map +1 -0
  37. package/dist/core/mcpBridge.js +71 -0
  38. package/dist/core/mcpBridge.js.map +1 -0
  39. package/dist/core/spawn.d.ts +33 -0
  40. package/dist/core/spawn.d.ts.map +1 -0
  41. package/dist/core/spawn.js +102 -0
  42. package/dist/core/spawn.js.map +1 -0
  43. package/dist/index.d.ts +9 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +9 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/mcp/index.d.ts +6 -0
  48. package/dist/mcp/index.d.ts.map +1 -0
  49. package/dist/mcp/index.js +6 -0
  50. package/dist/mcp/index.js.map +1 -0
  51. package/dist/mcp-entry.d.ts +22 -0
  52. package/dist/mcp-entry.d.ts.map +1 -0
  53. package/dist/mcp-entry.js +22 -0
  54. package/dist/mcp-entry.js.map +1 -0
  55. package/dist/mcp.d.ts +101 -0
  56. package/dist/mcp.d.ts.map +1 -0
  57. package/dist/mcp.js +78 -0
  58. package/dist/mcp.js.map +1 -0
  59. package/dist/query.d.ts +19 -0
  60. package/dist/query.d.ts.map +1 -0
  61. package/dist/query.js +18 -0
  62. package/dist/query.js.map +1 -0
  63. package/dist/tools/index.d.ts +6 -0
  64. package/dist/tools/index.d.ts.map +1 -0
  65. package/dist/tools/index.js +6 -0
  66. package/dist/tools/index.js.map +1 -0
  67. package/dist/types/control.d.ts +149 -0
  68. package/dist/types/control.d.ts.map +1 -0
  69. package/dist/types/control.js +40 -0
  70. package/dist/types/control.js.map +1 -0
  71. package/dist/types/index.d.ts +53 -0
  72. package/dist/types/index.d.ts.map +1 -0
  73. package/dist/types/index.js +11 -0
  74. package/dist/types/index.js.map +1 -0
  75. package/package.json +85 -0
  76. package/src/api/MessageQueue.ts +99 -0
  77. package/src/api/MessageRouter.ts +112 -0
  78. package/src/api/ProcessFactory.ts +124 -0
  79. package/src/api/QueryImpl.ts +543 -0
  80. package/src/api/query.ts +36 -0
  81. package/src/core/argBuilder.ts +236 -0
  82. package/src/core/control.ts +295 -0
  83. package/src/core/hookConfig.ts +70 -0
  84. package/src/core/mcpBridge.ts +81 -0
  85. package/src/core/spawn.ts +125 -0
  86. package/src/index.ts +12 -0
  87. package/src/mcp/index.ts +6 -0
  88. package/src/mcp-entry.ts +22 -0
  89. package/src/mcp.ts +148 -0
  90. package/src/query.ts +21 -0
  91. package/src/tools/README.md +171 -0
  92. package/src/tools/capture-cli.cjs +202 -0
  93. package/src/tools/index.ts +6 -0
  94. package/src/tools/proxy-cli.cjs +162 -0
  95. package/src/types/control.ts +196 -0
  96. package/src/types/index.ts +204 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 open-claude contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,141 @@
1
+ # Open Claude Agent SDK
2
+
3
+ A compatible open-source replacement for `@anthropic-ai/claude-agent-sdk` — thin wrapper that uses your local Claude CLI.
4
+
5
+ ## Why?
6
+
7
+ | | Open SDK | Official SDK |
8
+ |---|---|---|
9
+ | **Source** | Open, readable TypeScript | Closed, minified |
10
+ | **How it works** | Spawns local CLI | Bundles CLI |
11
+ | **Debuggable** | Breakpoints, source maps | Minified blob |
12
+ | **AI-friendly** | Agents can read source | Agents can't parse minified code |
13
+ | **Type compatible** | Yes (re-exports) | - |
14
+ | **Streaming** | Yes | Yes |
15
+ | **Multi-turn** | Yes | Yes |
16
+ | **MCP servers** | Yes | Yes |
17
+ | **Subagents** | Yes | Yes |
18
+ | **Hooks** | Yes | Yes |
19
+
20
+ Same API, same types — open and debuggable.
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ bun add open-claude-agent-sdk
26
+
27
+ # Requires Claude CLI
28
+ npm install -g @anthropic-ai/claude-code
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ```typescript
34
+ import { query } from 'open-claude-agent-sdk';
35
+
36
+ for await (const msg of query({
37
+ prompt: 'Write a haiku about coding',
38
+ options: { maxTurns: 3 }
39
+ })) {
40
+ if (msg.type === 'assistant') {
41
+ console.log(msg.message.content);
42
+ }
43
+ if (msg.type === 'result') break;
44
+ }
45
+ ```
46
+
47
+ Drop-in replacement — just change the import:
48
+
49
+ ```diff
50
+ - import { query } from '@anthropic-ai/claude-agent-sdk';
51
+ + import { query } from 'open-claude-agent-sdk';
52
+ ```
53
+
54
+ ## Features
55
+
56
+ ### Core
57
+
58
+ - **Query modes** — one-shot, multi-turn (AsyncIterable + streamInput), streaming
59
+ - **Control methods** — interrupt, close, setModel, setPermissionMode, setMaxThinkingTokens
60
+ - **Query methods** — supportedCommands, supportedModels, accountInfo, mcpServerStatus
61
+ - **Structured outputs** — JSON schema with `outputFormat`
62
+ - **Extended thinking** — `maxThinkingTokens` option
63
+ - **System prompts** — string, preset (`claude_code`), preset with append
64
+ - **Permission callbacks** — `canUseTool` with allow/deny/selective/async
65
+ - **AbortController** — signal-based cancellation
66
+ - **Session management** — resume, fork, continue, custom sessionId
67
+ - **Cost tracking** — `total_cost_usd`, usage, modelUsage
68
+
69
+ ### MCP Servers
70
+
71
+ - **In-process SDK servers** — `createSdkMcpServer()` + `tool()` helper with Zod schemas
72
+ - **Process-based servers** — stdio MCP server config via `mcpServers` option
73
+ - **Control methods** — `reconnectMcpServer()`, `toggleMcpServer()`, `setMcpServers()`
74
+
75
+ ### Subagents & Hooks
76
+
77
+ - **Programmatic subagents** — `agents` option, Task tool invocation, `parent_tool_use_id`
78
+ - **Hooks** — 10 of 15 events tested E2E (PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, Stop, SubagentStart, SubagentStop, plus matchers)
79
+ - **Skills & commands** — via `settingSources` + `.claude/` directories
80
+ - **Output styles** — custom styles via `.claude/output-styles/`
81
+ - **Sandbox** — sandbox configuration pass-through
82
+
83
+ ### Open SDK Extensions
84
+
85
+ Extra convenience methods beyond the official SDK:
86
+
87
+ ```typescript
88
+ import { query, type ExtendedQuery } from 'open-claude-agent-sdk';
89
+
90
+ const q = query({ prompt: '...' }) as ExtendedQuery;
91
+
92
+ await q.availableOutputStyles(); // string[]
93
+ await q.currentOutputStyle(); // string
94
+ ```
95
+
96
+ ### Not Yet Implemented
97
+
98
+ - `rewindFiles()` — no CLI protocol support
99
+ - Agent teams — experimental, no env var support
100
+ - V2 API (`unstable_v2_*`) — experimental preview
101
+
102
+ See [FEATURES.md](./docs/planning/FEATURES.md) for full status matrix.
103
+
104
+ ## Demos
105
+
106
+ Three demo apps ported from the official SDK, running on both SDKs:
107
+
108
+ ```bash
109
+ # Hello world
110
+ bun demos/open/hello-world/hello-world.ts
111
+
112
+ # Interactive chat (has its own dev server)
113
+ cd demos/open/simple-chatapp && npm install && npm run dev
114
+
115
+ # Resume generator
116
+ bun demos/open/resume-generator/resume-generator.ts
117
+ ```
118
+
119
+ ## Testing
120
+
121
+ ```bash
122
+ # Integration tests (primary)
123
+ bun test tests/integration/
124
+
125
+ # Unit tests (SDK compatibility)
126
+ bun test tests/unit/
127
+
128
+ # Type check
129
+ bun run typecheck
130
+ ```
131
+
132
+ ## Documentation
133
+
134
+ - [API Reference](./docs/api/API.md) — query function, message types, examples
135
+ - [Options Reference](./docs/api/OPTIONS.md) — all query options
136
+ - [Feature Matrix](./docs/planning/FEATURES.md) — full feature comparison
137
+ - [Migration Guide](./docs/guides/MIGRATION.md) — migrate from official SDK
138
+
139
+ ## License
140
+
141
+ MIT
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Generic async message queue with iterator protocol support
3
+ *
4
+ * Handles the producer-consumer pattern for streaming messages:
5
+ * - Producer: pushes messages via push()
6
+ * - Consumer: awaits messages via next() (AsyncIterator protocol)
7
+ *
8
+ * @internal
9
+ */
10
+ export declare class MessageQueue<T> {
11
+ private queue;
12
+ private waiters;
13
+ private done;
14
+ private error;
15
+ /**
16
+ * Add a message to the queue
17
+ * If there are waiting consumers, resolves the first one immediately
18
+ */
19
+ push(item: T): void;
20
+ /**
21
+ * Mark the queue as complete (no more messages)
22
+ * @param error Optional error to propagate to consumers
23
+ */
24
+ complete(error?: Error): void;
25
+ /**
26
+ * Get the next message (AsyncIterator protocol)
27
+ * Waits if no messages are available
28
+ */
29
+ next(): Promise<IteratorResult<T>>;
30
+ /**
31
+ * Check if the queue is completed
32
+ */
33
+ isDone(): boolean;
34
+ /**
35
+ * Get the current error (if any)
36
+ */
37
+ getError(): Error | null;
38
+ }
39
+ //# sourceMappingURL=MessageQueue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageQueue.d.ts","sourceRoot":"","sources":["../../src/api/MessageQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,qBAAa,YAAY,CAAC,CAAC;IACzB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,OAAO,CAGP;IACR,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,KAAK,CAAsB;IAEnC;;;OAGG;IACH,IAAI,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAanB;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI;IAkB7B;;;OAGG;IACG,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;IAuBxC;;OAEG;IACH,MAAM,IAAI,OAAO;IAIjB;;OAEG;IACH,QAAQ,IAAI,KAAK,GAAG,IAAI;CAGzB"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Generic async message queue with iterator protocol support
3
+ *
4
+ * Handles the producer-consumer pattern for streaming messages:
5
+ * - Producer: pushes messages via push()
6
+ * - Consumer: awaits messages via next() (AsyncIterator protocol)
7
+ *
8
+ * @internal
9
+ */
10
+ export class MessageQueue {
11
+ queue = [];
12
+ waiters = [];
13
+ done = false;
14
+ error = null;
15
+ /**
16
+ * Add a message to the queue
17
+ * If there are waiting consumers, resolves the first one immediately
18
+ */
19
+ push(item) {
20
+ if (this.done)
21
+ return; // Ignore pushes after completion
22
+ // If someone is waiting, resolve immediately
23
+ if (this.waiters.length > 0) {
24
+ // biome-ignore lint/style/noNonNullAssertion: length > 0 guarantees shift returns a value
25
+ const waiter = this.waiters.shift();
26
+ waiter.resolve({ value: item, done: false });
27
+ }
28
+ else {
29
+ this.queue.push(item);
30
+ }
31
+ }
32
+ /**
33
+ * Mark the queue as complete (no more messages)
34
+ * @param error Optional error to propagate to consumers
35
+ */
36
+ complete(error) {
37
+ if (this.done)
38
+ return;
39
+ this.done = true;
40
+ this.error = error ?? null;
41
+ // Resolve all waiting consumers
42
+ const waiters = this.waiters.splice(0);
43
+ for (const waiter of waiters) {
44
+ if (this.error) {
45
+ waiter.reject(this.error);
46
+ }
47
+ else {
48
+ // biome-ignore lint/suspicious/noExplicitAny: IteratorResult requires undefined for done=true
49
+ waiter.resolve({ value: undefined, done: true });
50
+ }
51
+ }
52
+ }
53
+ /**
54
+ * Get the next message (AsyncIterator protocol)
55
+ * Waits if no messages are available
56
+ */
57
+ async next() {
58
+ // Return from queue if available
59
+ if (this.queue.length > 0) {
60
+ // biome-ignore lint/style/noNonNullAssertion: length > 0 guarantees shift returns a value
61
+ const item = this.queue.shift();
62
+ return { value: item, done: false };
63
+ }
64
+ // If done, return completion or throw error
65
+ if (this.done) {
66
+ if (this.error) {
67
+ throw this.error;
68
+ }
69
+ // biome-ignore lint/suspicious/noExplicitAny: IteratorResult requires undefined for done=true
70
+ return { value: undefined, done: true };
71
+ }
72
+ // Wait for next message
73
+ return new Promise((resolve, reject) => {
74
+ this.waiters.push({ resolve, reject });
75
+ });
76
+ }
77
+ /**
78
+ * Check if the queue is completed
79
+ */
80
+ isDone() {
81
+ return this.done;
82
+ }
83
+ /**
84
+ * Get the current error (if any)
85
+ */
86
+ getError() {
87
+ return this.error;
88
+ }
89
+ }
90
+ //# sourceMappingURL=MessageQueue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageQueue.js","sourceRoot":"","sources":["../../src/api/MessageQueue.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,OAAO,YAAY;IACf,KAAK,GAAQ,EAAE,CAAC;IAChB,OAAO,GAGV,EAAE,CAAC;IACA,IAAI,GAAG,KAAK,CAAC;IACb,KAAK,GAAiB,IAAI,CAAC;IAEnC;;;OAGG;IACH,IAAI,CAAC,IAAO;QACV,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO,CAAC,iCAAiC;QAExD,6CAA6C;QAC7C,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,0FAA0F;YAC1F,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAG,CAAC;YACrC,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,QAAQ,CAAC,KAAa;QACpB,IAAI,IAAI,CAAC,IAAI;YAAE,OAAO;QAEtB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,IAAI,CAAC;QAE3B,gCAAgC;QAChC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACvC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC5B,CAAC;iBAAM,CAAC;gBACN,8FAA8F;gBAC9F,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,SAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI;QACR,iCAAiC;QACjC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1B,0FAA0F;YAC1F,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC;YACjC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QACtC,CAAC;QAED,4CAA4C;QAC5C,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,CAAC,KAAK,CAAC;YACnB,CAAC;YACD,8FAA8F;YAC9F,OAAO,EAAE,KAAK,EAAE,SAAgB,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;QACjD,CAAC;QAED,wBAAwB;QACxB,OAAO,IAAI,OAAO,CAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,MAAM;QACJ,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;CACF"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Message router for stdout processing
3
+ *
4
+ * Reads NDJSON from stdout and routes messages:
5
+ * - control_request → controlHandler
6
+ * - control_response → filtered (internal protocol)
7
+ * - regular messages → onMessage callback
8
+ *
9
+ * @internal
10
+ */
11
+ import type { Readable } from 'node:stream';
12
+ import type { ControlProtocolHandler } from '../core/control.ts';
13
+ import type { SDKMessage } from '../types/index.ts';
14
+ export type MessageCallback = (msg: SDKMessage) => void;
15
+ export type DoneCallback = (error?: Error) => void;
16
+ export type ControlResponsePayload = {
17
+ subtype: string;
18
+ request_id: string;
19
+ response?: Record<string, unknown>;
20
+ error?: string;
21
+ };
22
+ export type ControlResponseCallback = (response: ControlResponsePayload) => void;
23
+ export declare class MessageRouter {
24
+ private stdout;
25
+ private controlHandler;
26
+ private onMessage;
27
+ private onDone;
28
+ private onControlResponse?;
29
+ private readline;
30
+ constructor(stdout: Readable, controlHandler: ControlProtocolHandler, onMessage: MessageCallback, onDone: DoneCallback, onControlResponse?: ControlResponseCallback | undefined);
31
+ /**
32
+ * Start reading from stdout and routing messages
33
+ * This runs in the background until the stream ends
34
+ */
35
+ startReading(): Promise<void>;
36
+ /**
37
+ * Close the readline interface
38
+ */
39
+ close(): void;
40
+ }
41
+ //# sourceMappingURL=MessageRouter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageRouter.d.ts","sourceRoot":"","sources":["../../src/api/MessageRouter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAEjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE,UAAU,KAAK,IAAI,CAAC;AACxD,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;AACnD,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AACF,MAAM,MAAM,uBAAuB,GAAG,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAAI,CAAC;AAMjF,qBAAa,aAAa;IAItB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,cAAc;IACtB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,iBAAiB,CAAC;IAP5B,OAAO,CAAC,QAAQ,CAA0B;gBAGhC,MAAM,EAAE,QAAQ,EAChB,cAAc,EAAE,sBAAsB,EACtC,SAAS,EAAE,eAAe,EAC1B,MAAM,EAAE,YAAY,EACpB,iBAAiB,CAAC,EAAE,uBAAuB,YAAA;IAGrD;;;OAGG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAwDnC;;OAEG;IACH,KAAK,IAAI,IAAI;CAMd"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Message router for stdout processing
3
+ *
4
+ * Reads NDJSON from stdout and routes messages:
5
+ * - control_request → controlHandler
6
+ * - control_response → filtered (internal protocol)
7
+ * - regular messages → onMessage callback
8
+ *
9
+ * @internal
10
+ */
11
+ import { createInterface } from 'node:readline';
12
+ import { MessageType } from "../types/control.js";
13
+ export class MessageRouter {
14
+ stdout;
15
+ controlHandler;
16
+ onMessage;
17
+ onDone;
18
+ onControlResponse;
19
+ readline = null;
20
+ constructor(stdout, controlHandler, onMessage, onDone, onControlResponse) {
21
+ this.stdout = stdout;
22
+ this.controlHandler = controlHandler;
23
+ this.onMessage = onMessage;
24
+ this.onDone = onDone;
25
+ this.onControlResponse = onControlResponse;
26
+ }
27
+ /**
28
+ * Start reading from stdout and routing messages
29
+ * This runs in the background until the stream ends
30
+ */
31
+ async startReading() {
32
+ try {
33
+ this.readline = createInterface({
34
+ input: this.stdout,
35
+ crlfDelay: Infinity,
36
+ });
37
+ for await (const line of this.readline) {
38
+ if (!line.trim())
39
+ continue;
40
+ // Debug: log raw line
41
+ if (process.env.DEBUG_HOOKS) {
42
+ console.error('[DEBUG] Raw line:', line.substring(0, 200));
43
+ }
44
+ try {
45
+ const msg = JSON.parse(line);
46
+ // Debug: log message type
47
+ if (process.env.DEBUG_HOOKS) {
48
+ console.error('[DEBUG] Message type:', msg.type);
49
+ }
50
+ if (msg.type === MessageType.CONTROL_REQUEST) {
51
+ if (process.env.DEBUG_HOOKS) {
52
+ console.error('[DEBUG] !!! CONTROL REQUEST !!!:', msg.request?.subtype);
53
+ }
54
+ // Handle control request internally (don't yield to user)
55
+ await this.controlHandler.handleControlRequest(msg);
56
+ }
57
+ else if (msg.type === MessageType.CONTROL_RESPONSE) {
58
+ // Route control_response to callback if provided, otherwise filter silently
59
+ if (process.env.DEBUG_HOOKS) {
60
+ console.error('[DEBUG] control_response received');
61
+ }
62
+ if (this.onControlResponse) {
63
+ this.onControlResponse(msg.response);
64
+ }
65
+ }
66
+ else {
67
+ // Regular message - pass to callback
68
+ this.onMessage(msg);
69
+ }
70
+ }
71
+ catch (parseError) {
72
+ // Log but don't crash on parse errors
73
+ const errMsg = parseError instanceof Error ? parseError.message : String(parseError);
74
+ console.error('Failed to parse line:', line.substring(0, 200), '-', errMsg);
75
+ }
76
+ }
77
+ }
78
+ catch (err) {
79
+ this.onDone(err instanceof Error ? err : new Error(String(err)));
80
+ return;
81
+ }
82
+ // Stream ended normally
83
+ this.onDone();
84
+ }
85
+ /**
86
+ * Close the readline interface
87
+ */
88
+ close() {
89
+ if (this.readline) {
90
+ this.readline.close();
91
+ this.readline = null;
92
+ }
93
+ }
94
+ }
95
+ //# sourceMappingURL=MessageRouter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageRouter.js","sourceRoot":"","sources":["../../src/api/MessageRouter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Process factory for dependency injection
3
+ *
4
+ * Allows unit tests to inject mock processes without spawning real CLI.
5
+ *
6
+ * @internal
7
+ */
8
+ import type { ChildProcess } from 'node:child_process';
9
+ import type { Options } from '../types/index.ts';
10
+ /**
11
+ * Interface for creating CLI processes
12
+ * Allows dependency injection for testing
13
+ */
14
+ export interface ProcessFactory {
15
+ spawn(options: Options): ChildProcess;
16
+ }
17
+ /**
18
+ * Default implementation that spawns real Claude CLI
19
+ */
20
+ export declare class DefaultProcessFactory implements ProcessFactory {
21
+ spawn(options: Options): ChildProcess;
22
+ }
23
+ //# sourceMappingURL=ProcessFactory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProcessFactory.d.ts","sourceRoot":"","sources":["../../src/api/ProcessFactory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAGvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAAC;CACvC;AAiBD;;GAEG;AACH,qBAAa,qBAAsB,YAAW,cAAc;IAC1D,KAAK,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY;CAmFtC"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Process factory for dependency injection
3
+ *
4
+ * Allows unit tests to inject mock processes without spawning real CLI.
5
+ *
6
+ * @internal
7
+ */
8
+ import { buildCliArgs } from "../core/argBuilder.js";
9
+ import { detectClaudeBinary, spawnClaude } from "../core/spawn.js";
10
+ /**
11
+ * Check if a path is a native binary (not a JS file)
12
+ * Matches official SDK: if NOT .js/.mjs/.tsx/.ts/.jsx, it's a native binary
13
+ */
14
+ function isNativeBinary(path) {
15
+ return !['.js', '.mjs', '.tsx', '.ts', '.jsx'].some((ext) => path.endsWith(ext));
16
+ }
17
+ /**
18
+ * Get default JavaScript runtime
19
+ */
20
+ function getDefaultExecutable() {
21
+ return typeof process.versions.bun !== 'undefined' ? 'bun' : 'node';
22
+ }
23
+ /**
24
+ * Default implementation that spawns real Claude CLI
25
+ */
26
+ export class DefaultProcessFactory {
27
+ spawn(options) {
28
+ const args = buildCliArgs({ ...options, prompt: '' });
29
+ // Build environment with enableFileCheckpointing support
30
+ const env = { ...(options.env ?? {}) };
31
+ if (options.enableFileCheckpointing) {
32
+ env.CLAUDE_CODE_ENABLE_SDK_FILE_CHECKPOINTING = 'true';
33
+ }
34
+ // Custom spawn function takes priority
35
+ if (options.spawnClaudeCodeProcess) {
36
+ const scriptPath = detectClaudeBinary(options);
37
+ const native = isNativeBinary(scriptPath);
38
+ const executable = options.executable ?? getDefaultExecutable();
39
+ const executableArgs = options.executableArgs ?? [];
40
+ const command = native ? scriptPath : executable;
41
+ const spawnArgs = native
42
+ ? [...executableArgs, ...args]
43
+ : [...executableArgs, scriptPath, ...args];
44
+ // Build full env for SpawnOptions
45
+ const fullEnv = { ...process.env, ...env };
46
+ if (!fullEnv.CLAUDE_CODE_ENTRYPOINT)
47
+ fullEnv.CLAUDE_CODE_ENTRYPOINT = 'sdk-ts';
48
+ delete fullEnv.NODE_OPTIONS;
49
+ if (fullEnv.DEBUG_CLAUDE_AGENT_SDK)
50
+ fullEnv.DEBUG = '1';
51
+ else
52
+ delete fullEnv.DEBUG;
53
+ const spawnedProcess = options.spawnClaudeCodeProcess({
54
+ command,
55
+ args: spawnArgs,
56
+ cwd: options.cwd,
57
+ env: fullEnv,
58
+ signal: AbortSignal.timeout(3600000), // 1 hour default
59
+ });
60
+ // Wrap SpawnedProcess to ChildProcess-compatible object
61
+ return spawnedProcess;
62
+ }
63
+ const scriptPath = detectClaudeBinary(options);
64
+ // When executable is explicitly set, use it as the command with script as arg
65
+ if (options.executable) {
66
+ const executableArgs = options.executableArgs ?? [];
67
+ const fullArgs = [...executableArgs, scriptPath, ...args];
68
+ return spawnClaude(options.executable, fullArgs, {
69
+ cwd: options.cwd,
70
+ env,
71
+ stderr: options.stderr,
72
+ });
73
+ }
74
+ // Default: use detected binary directly (shebang handles runtime)
75
+ const executableArgs = options.executableArgs ?? [];
76
+ if (isNativeBinary(scriptPath)) {
77
+ // Native binary: command is the binary, executableArgs before CLI args
78
+ const fullArgs = [...executableArgs, ...args];
79
+ return spawnClaude(scriptPath, fullArgs, {
80
+ cwd: options.cwd,
81
+ env,
82
+ stderr: options.stderr,
83
+ });
84
+ }
85
+ // JS file with executableArgs: need explicit runtime
86
+ if (executableArgs.length > 0) {
87
+ const executable = getDefaultExecutable();
88
+ const fullArgs = [...executableArgs, scriptPath, ...args];
89
+ return spawnClaude(executable, fullArgs, {
90
+ cwd: options.cwd,
91
+ env,
92
+ stderr: options.stderr,
93
+ });
94
+ }
95
+ // JS file without executableArgs: use script directly (shebang handles runtime)
96
+ return spawnClaude(scriptPath, args, {
97
+ cwd: options.cwd,
98
+ env,
99
+ stderr: options.stderr,
100
+ });
101
+ }
102
+ }
103
+ //# sourceMappingURL=ProcessFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProcessFactory.js","sourceRoot":"","sources":["../../src/api/ProcessFactory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAWnE;;;GAGG;AACH,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO,CAAC,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AACnF,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB;IAC3B,OAAO,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,KAAK,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;AACtE,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,qBAAqB;IAChC,KAAK,CAAC,OAAgB;QACpB,MAAM,IAAI,GAAG,YAAY,CAAC,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;QAEtD,yDAAyD;QACzD,MAAM,GAAG,GAAuC,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,CAAC;QAC3E,IAAI,OAAO,CAAC,uBAAuB,EAAE,CAAC;YACpC,GAAG,CAAC,yCAAyC,GAAG,MAAM,CAAC;QACzD,CAAC;QAED,uCAAuC;QACvC,IAAI,OAAO,CAAC,sBAAsB,EAAE,CAAC;YACnC,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;YAC/C,MAAM,MAAM,GAAG,cAAc,CAAC,UAAU,CAAC,CAAC;YAC1C,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,oBAAoB,EAAE,CAAC;YAChE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;YACpD,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;YACjD,MAAM,SAAS,GAAG,MAAM;gBACtB,CAAC,CAAC,CAAC,GAAG,cAAc,EAAE,GAAG,IAAI,CAAC;gBAC9B,CAAC,CAAC,CAAC,GAAG,cAAc,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;YAE7C,kCAAkC;YAClC,MAAM,OAAO,GAAuC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;YAC/E,IAAI,CAAC,OAAO,CAAC,sBAAsB;gBAAE,OAAO,CAAC,sBAAsB,GAAG,QAAQ,CAAC;YAC/E,OAAO,OAAO,CAAC,YAAY,CAAC;YAC5B,IAAI,OAAO,CAAC,sBAAsB;gBAAE,OAAO,CAAC,KAAK,GAAG,GAAG,CAAC;;gBACnD,OAAO,OAAO,CAAC,KAAK,CAAC;YAE1B,MAAM,cAAc,GAAG,OAAO,CAAC,sBAAsB,CAAC;gBACpD,OAAO;gBACP,IAAI,EAAE,SAAS;gBACf,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,GAAG,EAAE,OAAO;gBACZ,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,iBAAiB;aACxD,CAAC,CAAC;YAEH,wDAAwD;YACxD,OAAO,cAAyC,CAAC;QACnD,CAAC;QAED,MAAM,UAAU,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;QAE/C,8EAA8E;QAC9E,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;YACpD,MAAM,QAAQ,GAAG,CAAC,GAAG,cAAc,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;YAC1D,OAAO,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,EAAE;gBAC/C,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,GAAG;gBACH,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC,CAAC;QACL,CAAC;QAED,kEAAkE;QAClE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;QAEpD,IAAI,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,uEAAuE;YACvE,MAAM,QAAQ,GAAG,CAAC,GAAG,cAAc,EAAE,GAAG,IAAI,CAAC,CAAC;YAC9C,OAAO,WAAW,CAAC,UAAU,EAAE,QAAQ,EAAE;gBACvC,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,GAAG;gBACH,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC,CAAC;QACL,CAAC;QAED,qDAAqD;QACrD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,oBAAoB,EAAE,CAAC;YAC1C,MAAM,QAAQ,GAAG,CAAC,GAAG,cAAc,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC;YAC1D,OAAO,WAAW,CAAC,UAAU,EAAE,QAAQ,EAAE;gBACvC,GAAG,EAAE,OAAO,CAAC,GAAG;gBAChB,GAAG;gBACH,MAAM,EAAE,OAAO,CAAC,MAAM;aACvB,CAAC,CAAC;QACL,CAAC;QAED,gFAAgF;QAChF,OAAO,WAAW,CAAC,UAAU,EAAE,IAAI,EAAE;YACnC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,GAAG;YACH,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC;IACL,CAAC;CACF"}