@agentxjs/claude-driver 1.9.9-dev → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +132 -0
- package/dist/index.d.ts +13 -5
- package/dist/index.js +34 -10
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
- package/src/ClaudeDriver.ts +30 -16
- package/src/buildOptions.ts +30 -4
package/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# @agentxjs/claude-driver
|
|
2
|
+
|
|
3
|
+
Claude-specific driver for AgentX with native Claude Code features. **For most cases, use `@agentxjs/mono-driver` instead** — it supports multiple providers and is the default. Only use claude-driver if you need Claude Code-specific features like built-in permission management or CLI session resume.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Use claude-driver when you specifically need:
|
|
8
|
+
|
|
9
|
+
- Claude Code SDK subprocess execution
|
|
10
|
+
- Built-in permission management from Claude Code
|
|
11
|
+
- Claude Code CLI integration
|
|
12
|
+
- Session continuity via Claude's native session resume
|
|
13
|
+
|
|
14
|
+
## Quick Start
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
import { createClaudeDriver } from "@agentxjs/claude-driver";
|
|
18
|
+
|
|
19
|
+
const driver = createClaudeDriver({
|
|
20
|
+
apiKey: process.env.ANTHROPIC_API_KEY!,
|
|
21
|
+
agentId: "my-agent",
|
|
22
|
+
systemPrompt: "You are a helpful assistant.",
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
await driver.initialize();
|
|
26
|
+
|
|
27
|
+
for await (const event of driver.receive({ content: "Hello!" })) {
|
|
28
|
+
if (event.type === "text_delta") {
|
|
29
|
+
process.stdout.write(event.data.text);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
await driver.dispose();
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## API Reference
|
|
37
|
+
|
|
38
|
+
### `createClaudeDriver(config: ClaudeDriverConfig): Driver`
|
|
39
|
+
|
|
40
|
+
Factory function. Returns a `Driver` conforming to `@agentxjs/core/driver`.
|
|
41
|
+
|
|
42
|
+
### ClaudeDriver
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
class ClaudeDriver implements Driver {
|
|
46
|
+
readonly name: string; // "ClaudeDriver"
|
|
47
|
+
readonly sessionId: string | null; // captured from SDK after first message
|
|
48
|
+
readonly state: DriverState; // "idle" | "active" | "disposed"
|
|
49
|
+
|
|
50
|
+
initialize(): Promise<void>;
|
|
51
|
+
receive(message: UserMessage): AsyncIterable<DriverStreamEvent>;
|
|
52
|
+
interrupt(): void;
|
|
53
|
+
dispose(): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Exported Types
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
// Main
|
|
61
|
+
export { ClaudeDriver, createClaudeDriver, ClaudeDriverOptions, ClaudeDriverConfig };
|
|
62
|
+
|
|
63
|
+
// Re-exported from @agentxjs/core/driver
|
|
64
|
+
export type { Driver, DriverConfig, DriverState, CreateDriver, DriverStreamEvent, StopReason };
|
|
65
|
+
|
|
66
|
+
// Internal utilities (advanced)
|
|
67
|
+
export { SDKQueryLifecycle, buildSDKContent, buildSDKUserMessage };
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Configuration
|
|
71
|
+
|
|
72
|
+
### ClaudeDriverConfig
|
|
73
|
+
|
|
74
|
+
`ClaudeDriverConfig` = `DriverConfig<ClaudeDriverOptions>`.
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
createClaudeDriver({
|
|
78
|
+
// Base DriverConfig
|
|
79
|
+
apiKey: "sk-ant-xxxxx", // required
|
|
80
|
+
agentId: "my-agent", // required
|
|
81
|
+
model: "claude-sonnet-4-20250514",
|
|
82
|
+
systemPrompt: "You are ...",
|
|
83
|
+
baseUrl: "https://api.anthropic.com",
|
|
84
|
+
cwd: "/path/to/workdir",
|
|
85
|
+
mcpServers: { ... },
|
|
86
|
+
resumeSessionId: "prev-session-id",
|
|
87
|
+
onSessionIdCaptured: (id) => save(id),
|
|
88
|
+
|
|
89
|
+
// ClaudeDriver-specific
|
|
90
|
+
options: {
|
|
91
|
+
claudeCodePath: "/usr/local/bin/claude", // auto-resolved if omitted
|
|
92
|
+
maxTurns: 10, // SDK default if omitted
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### ClaudeDriverOptions
|
|
98
|
+
|
|
99
|
+
| Field | Type | Default | Description |
|
|
100
|
+
| ---------------- | -------- | ---------------------------------------------- | ------------------------------ |
|
|
101
|
+
| `claudeCodePath` | `string` | Auto-resolved from `@anthropic-ai/claude-code` | Path to Claude Code executable |
|
|
102
|
+
| `maxTurns` | `number` | SDK default | Max agentic loop turns |
|
|
103
|
+
|
|
104
|
+
### Session Resumption
|
|
105
|
+
|
|
106
|
+
```typescript
|
|
107
|
+
let savedSessionId: string;
|
|
108
|
+
|
|
109
|
+
const driver = createClaudeDriver({
|
|
110
|
+
apiKey: "...",
|
|
111
|
+
agentId: "my-agent",
|
|
112
|
+
onSessionIdCaptured: (id) => {
|
|
113
|
+
savedSessionId = id;
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// ... use driver, then dispose ...
|
|
118
|
+
|
|
119
|
+
// Resume later
|
|
120
|
+
const resumed = createClaudeDriver({
|
|
121
|
+
apiKey: "...",
|
|
122
|
+
agentId: "my-agent",
|
|
123
|
+
resumeSessionId: savedSessionId,
|
|
124
|
+
});
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Environment Variables
|
|
128
|
+
|
|
129
|
+
| Variable | Description |
|
|
130
|
+
| -------------------- | --------------------------------------------------- |
|
|
131
|
+
| `ANTHROPIC_API_KEY` | Claude API key (can also use `apiKey` config) |
|
|
132
|
+
| `ANTHROPIC_BASE_URL` | Custom API endpoint (can also use `baseUrl` config) |
|
package/dist/index.d.ts
CHANGED
|
@@ -37,12 +37,18 @@ import { McpServerConfig, SDKMessage, SDKUserMessage } from '@anthropic-ai/claud
|
|
|
37
37
|
*
|
|
38
38
|
* @example
|
|
39
39
|
* ```typescript
|
|
40
|
+
* // Zero-config: claudeCodePath is auto-resolved from installed package
|
|
41
|
+
* const config: DriverConfig<ClaudeDriverOptions> = {
|
|
42
|
+
* apiKey: "...",
|
|
43
|
+
* agentId: "my-agent",
|
|
44
|
+
* };
|
|
45
|
+
*
|
|
46
|
+
* // Custom path (optional, only if needed)
|
|
40
47
|
* const config: DriverConfig<ClaudeDriverOptions> = {
|
|
41
48
|
* apiKey: "...",
|
|
42
49
|
* agentId: "my-agent",
|
|
43
50
|
* options: {
|
|
44
|
-
* claudeCodePath: "/
|
|
45
|
-
* maxTurns: 10,
|
|
51
|
+
* claudeCodePath: "/custom/path/to/claude",
|
|
46
52
|
* }
|
|
47
53
|
* };
|
|
48
54
|
* ```
|
|
@@ -51,9 +57,11 @@ interface ClaudeDriverOptions {
|
|
|
51
57
|
/**
|
|
52
58
|
* Path to Claude Code executable
|
|
53
59
|
*
|
|
54
|
-
* If not provided,
|
|
55
|
-
*
|
|
56
|
-
*
|
|
60
|
+
* If not provided, will automatically resolve from the installed
|
|
61
|
+
* `@anthropic-ai/claude-code` package (zero-config).
|
|
62
|
+
*
|
|
63
|
+
* Only specify this when you need to use a custom Claude Code installation
|
|
64
|
+
* (e.g., a different version or a custom binary location).
|
|
57
65
|
*/
|
|
58
66
|
claudeCodePath?: string;
|
|
59
67
|
/**
|
package/dist/index.js
CHANGED
|
@@ -238,7 +238,19 @@ import {
|
|
|
238
238
|
import { Subject } from "rxjs";
|
|
239
239
|
|
|
240
240
|
// src/buildOptions.ts
|
|
241
|
+
import { createRequire } from "module";
|
|
241
242
|
var logger = createLogger("claude-driver/buildOptions");
|
|
243
|
+
function getDefaultClaudeCodePath() {
|
|
244
|
+
try {
|
|
245
|
+
const require2 = createRequire(import.meta.url);
|
|
246
|
+
const cliPath = require2.resolve("@anthropic-ai/claude-code/cli.js");
|
|
247
|
+
logger.debug("Resolved default Claude Code path", { path: cliPath });
|
|
248
|
+
return cliPath;
|
|
249
|
+
} catch (error) {
|
|
250
|
+
logger.warn("Failed to resolve @anthropic-ai/claude-code/cli.js", { error });
|
|
251
|
+
return void 0;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
242
254
|
function buildOptions(context, abortController) {
|
|
243
255
|
const options = {
|
|
244
256
|
abortController,
|
|
@@ -279,9 +291,13 @@ function buildOptions(context, abortController) {
|
|
|
279
291
|
options.stderr = (data) => {
|
|
280
292
|
logger.info("SDK stderr", { data: data.trim() });
|
|
281
293
|
};
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
294
|
+
const claudeCodePath = context.claudeCodePath || getDefaultClaudeCodePath();
|
|
295
|
+
if (claudeCodePath) {
|
|
296
|
+
options.pathToClaudeCodeExecutable = claudeCodePath;
|
|
297
|
+
logger.info("Claude Code path configured", {
|
|
298
|
+
path: claudeCodePath,
|
|
299
|
+
source: context.claudeCodePath ? "user-provided" : "auto-resolved"
|
|
300
|
+
});
|
|
285
301
|
}
|
|
286
302
|
if (context.model) options.model = context.model;
|
|
287
303
|
if (context.systemPrompt) options.systemPrompt = context.systemPrompt;
|
|
@@ -661,12 +677,16 @@ var ClaudeDriver = class {
|
|
|
661
677
|
this.currentTurnSubject = turnSubject;
|
|
662
678
|
let isComplete = false;
|
|
663
679
|
let turnError = null;
|
|
664
|
-
this.setupTurnCallbacks(
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
680
|
+
this.setupTurnCallbacks(
|
|
681
|
+
turnSubject,
|
|
682
|
+
() => {
|
|
683
|
+
isComplete = true;
|
|
684
|
+
},
|
|
685
|
+
(error) => {
|
|
686
|
+
turnError = error;
|
|
687
|
+
isComplete = true;
|
|
688
|
+
}
|
|
689
|
+
);
|
|
670
690
|
const sessionId = this._sessionId || "default";
|
|
671
691
|
const sdkMessage = buildSDKUserMessage(message, sessionId);
|
|
672
692
|
logger3.debug("Sending message to Claude", {
|
|
@@ -674,7 +694,11 @@ var ClaudeDriver = class {
|
|
|
674
694
|
agentId: this.config.agentId
|
|
675
695
|
});
|
|
676
696
|
this.queryLifecycle.send(sdkMessage);
|
|
677
|
-
yield* this.yieldFromSubject(
|
|
697
|
+
yield* this.yieldFromSubject(
|
|
698
|
+
turnSubject,
|
|
699
|
+
() => isComplete,
|
|
700
|
+
() => turnError
|
|
701
|
+
);
|
|
678
702
|
} finally {
|
|
679
703
|
this._state = "idle";
|
|
680
704
|
this.currentTurnSubject = null;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ClaudeDriver.ts","../../../node_modules/commonxjs/dist/src/logger/ConsoleLogger.ts","../../../node_modules/commonxjs/dist/src/logger/LoggerFactoryImpl.ts","../src/helpers.ts","../src/SDKQueryLifecycle.ts","../src/buildOptions.ts","../src/observableToAsyncIterable.ts"],"sourcesContent":["/**\n * ClaudeDriver - Claude SDK Driver Implementation\n *\n * Implements the new Driver interface with clear input/output boundaries:\n * - receive(message) returns AsyncIterable<DriverStreamEvent>\n * - No EventBus dependency\n * - Single session communication\n *\n * ```\n * UserMessage\n * │\n * ▼\n * ┌─────────────────┐\n * │ ClaudeDriver │\n * │ │\n * │ receive() │──► AsyncIterable<DriverStreamEvent>\n * │ │ │\n * │ ▼ │\n * │ SDK Query │\n * └─────────────────┘\n * │\n * ▼\n * Claude SDK\n * ```\n */\n\nimport type {\n Driver,\n DriverConfig,\n DriverState,\n DriverStreamEvent,\n StopReason,\n} from \"@agentxjs/core/driver\";\nimport type { UserMessage } from \"@agentxjs/core/agent\";\nimport type { SDKMessage, SDKPartialAssistantMessage } from \"@anthropic-ai/claude-agent-sdk\";\nimport { Subject } from \"rxjs\";\nimport { createLogger } from \"commonxjs/logger\";\nimport { buildSDKUserMessage } from \"./helpers\";\nimport { SDKQueryLifecycle } from \"./SDKQueryLifecycle\";\n\nconst logger = createLogger(\"claude-driver/ClaudeDriver\");\n\n// ============================================================================\n// ClaudeDriver-specific Options\n// ============================================================================\n\n/**\n * ClaudeDriver-specific options\n *\n * These options are specific to the Claude SDK and are passed via\n * the `options` field of DriverConfig.\n *\n * @example\n * ```typescript\n * const config: DriverConfig<ClaudeDriverOptions> = {\n * apiKey: \"...\",\n * agentId: \"my-agent\",\n * options: {\n * claudeCodePath: \"/usr/local/bin/claude\",\n * maxTurns: 10,\n * }\n * };\n * ```\n */\nexport interface ClaudeDriverOptions {\n /**\n * Path to Claude Code executable\n *\n * If not provided, the SDK will use its default path resolution.\n * This is useful when running in containers or custom environments\n * where Claude Code is installed at a non-standard location.\n */\n claudeCodePath?: string;\n\n /**\n * Maximum number of turns (agentic loops) before stopping\n *\n * Default is determined by the SDK.\n */\n maxTurns?: number;\n}\n\n/**\n * ClaudeDriverConfig - DriverConfig with ClaudeDriverOptions\n */\nexport type ClaudeDriverConfig = DriverConfig<ClaudeDriverOptions>;\n\n/**\n * ClaudeDriver - Driver implementation for Claude SDK\n *\n * Implements the new Driver interface:\n * - receive() returns AsyncIterable<DriverStreamEvent>\n * - Clear input/output boundaries for recording/playback\n * - Single session communication\n */\nexport class ClaudeDriver implements Driver {\n readonly name = \"ClaudeDriver\";\n\n private _sessionId: string | null = null;\n private _state: DriverState = \"idle\";\n\n private readonly config: ClaudeDriverConfig;\n private queryLifecycle: SDKQueryLifecycle | null = null;\n\n // For interrupt handling\n private currentTurnSubject: Subject<DriverStreamEvent> | null = null;\n\n constructor(config: ClaudeDriverConfig) {\n this.config = config;\n }\n\n // ============================================================================\n // Driver Interface Properties\n // ============================================================================\n\n get sessionId(): string | null {\n return this._sessionId;\n }\n\n get state(): DriverState {\n return this._state;\n }\n\n // ============================================================================\n // Lifecycle Methods\n // ============================================================================\n\n /**\n * Initialize the Driver\n *\n * Starts SDK subprocess and MCP servers.\n * Must be called before receive().\n */\n async initialize(): Promise<void> {\n if (this._state !== \"idle\") {\n throw new Error(`Cannot initialize: Driver is in \"${this._state}\" state`);\n }\n\n logger.info(\"Initializing ClaudeDriver\", { agentId: this.config.agentId });\n\n // SDKQueryLifecycle will be created lazily on first receive()\n // This allows configuration to be validated early without starting subprocess\n\n logger.info(\"ClaudeDriver initialized\");\n }\n\n /**\n * Dispose and cleanup resources\n *\n * Stops SDK subprocess and MCP servers.\n * Driver cannot be used after dispose().\n */\n async dispose(): Promise<void> {\n if (this._state === \"disposed\") {\n return;\n }\n\n logger.info(\"Disposing ClaudeDriver\", { agentId: this.config.agentId });\n\n // Complete any pending turn\n if (this.currentTurnSubject) {\n this.currentTurnSubject.complete();\n this.currentTurnSubject = null;\n }\n\n // Dispose SDK lifecycle\n if (this.queryLifecycle) {\n this.queryLifecycle.dispose();\n this.queryLifecycle = null;\n }\n\n this._state = \"disposed\";\n logger.info(\"ClaudeDriver disposed\");\n }\n\n // ============================================================================\n // Core Methods\n // ============================================================================\n\n /**\n * Receive a user message and return stream of events\n *\n * This is the main method for communication.\n * Returns an AsyncIterable that yields DriverStreamEvent.\n *\n * @param message - User message to send\n * @returns AsyncIterable of stream events\n */\n async *receive(message: UserMessage): AsyncIterable<DriverStreamEvent> {\n if (this._state === \"disposed\") {\n throw new Error(\"Cannot receive: Driver is disposed\");\n }\n\n if (this._state === \"active\") {\n throw new Error(\"Cannot receive: Driver is already processing a message\");\n }\n\n this._state = \"active\";\n\n try {\n // Ensure SDK lifecycle is initialized\n await this.ensureLifecycle();\n\n // Create Subject for this turn's events\n const turnSubject = new Subject<DriverStreamEvent>();\n this.currentTurnSubject = turnSubject;\n\n // Track completion\n let isComplete = false;\n let turnError: Error | null = null;\n\n // Setup callbacks to convert SDK events to DriverStreamEvent\n this.setupTurnCallbacks(turnSubject, () => {\n isComplete = true;\n }, (error) => {\n turnError = error;\n isComplete = true;\n });\n\n // Build and send SDK message\n const sessionId = this._sessionId || \"default\";\n const sdkMessage = buildSDKUserMessage(message, sessionId);\n\n logger.debug(\"Sending message to Claude\", {\n content: typeof message.content === \"string\"\n ? message.content.substring(0, 80)\n : \"[structured]\",\n agentId: this.config.agentId,\n });\n\n this.queryLifecycle!.send(sdkMessage);\n\n // Yield events from Subject\n yield* this.yieldFromSubject(turnSubject, () => isComplete, () => turnError);\n\n } finally {\n this._state = \"idle\";\n this.currentTurnSubject = null;\n }\n }\n\n /**\n * Interrupt current operation\n *\n * Stops the current receive() operation gracefully.\n * The AsyncIterable will emit an \"interrupted\" event and complete.\n */\n interrupt(): void {\n if (this._state !== \"active\") {\n logger.debug(\"Interrupt called but no active operation\");\n return;\n }\n\n logger.debug(\"Interrupting ClaudeDriver\");\n\n // Emit interrupted event\n if (this.currentTurnSubject) {\n this.currentTurnSubject.next({\n type: \"interrupted\",\n timestamp: Date.now(),\n data: { reason: \"user\" },\n });\n this.currentTurnSubject.complete();\n }\n\n // Interrupt SDK\n if (this.queryLifecycle) {\n this.queryLifecycle.interrupt();\n }\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n /**\n * Ensure SDK lifecycle is initialized\n */\n private async ensureLifecycle(): Promise<void> {\n if (this.queryLifecycle && this.queryLifecycle.initialized) {\n return;\n }\n\n // Create new lifecycle with driver-specific options\n this.queryLifecycle = new SDKQueryLifecycle(\n {\n apiKey: this.config.apiKey,\n baseUrl: this.config.baseUrl,\n model: this.config.model,\n systemPrompt: this.config.systemPrompt,\n cwd: this.config.cwd,\n resumeSessionId: this.config.resumeSessionId,\n mcpServers: this.config.mcpServers,\n // Pass driver-specific options\n claudeCodePath: this.config.options?.claudeCodePath,\n },\n {\n onSessionIdCaptured: (sessionId) => {\n this._sessionId = sessionId;\n this.config.onSessionIdCaptured?.(sessionId);\n },\n }\n );\n\n await this.queryLifecycle.initialize();\n }\n\n /**\n * Setup callbacks for a single turn\n */\n private setupTurnCallbacks(\n subject: Subject<DriverStreamEvent>,\n onComplete: () => void,\n onError: (error: Error) => void\n ): void {\n if (!this.queryLifecycle) return;\n\n // Context for tracking content block state\n const blockContext = {\n currentBlockType: null as \"text\" | \"tool_use\" | null,\n currentToolId: null as string | null,\n currentToolName: null as string | null,\n lastStopReason: null as string | null,\n accumulatedToolInput: \"\" as string,\n };\n\n // Update lifecycle callbacks for this turn\n this.queryLifecycle.setCallbacks({\n onStreamEvent: (msg: SDKMessage) => {\n const event = this.convertStreamEvent(msg as SDKPartialAssistantMessage, blockContext);\n if (event) {\n subject.next(event);\n }\n },\n\n onUserMessage: (msg: SDKMessage) => {\n const events = this.convertUserMessage(msg);\n for (const event of events) {\n subject.next(event);\n }\n },\n\n onResult: (msg: SDKMessage) => {\n const resultMsg = msg as { is_error?: boolean; error?: { message?: string } };\n\n if (resultMsg.is_error) {\n subject.next({\n type: \"error\",\n timestamp: Date.now(),\n data: {\n message: resultMsg.error?.message || \"Unknown error\",\n errorCode: \"sdk_error\",\n },\n });\n }\n\n subject.complete();\n onComplete();\n },\n\n onError: (error: Error) => {\n subject.next({\n type: \"error\",\n timestamp: Date.now(),\n data: {\n message: error.message,\n errorCode: \"runtime_error\",\n },\n });\n subject.complete();\n onError(error);\n },\n });\n }\n\n /**\n * Convert SDK stream_event to DriverStreamEvent\n */\n private convertStreamEvent(\n sdkMsg: SDKPartialAssistantMessage,\n blockContext: {\n currentBlockType: \"text\" | \"tool_use\" | null;\n currentToolId: string | null;\n currentToolName: string | null;\n lastStopReason: string | null;\n accumulatedToolInput: string;\n }\n ): DriverStreamEvent | null {\n const event = sdkMsg.event;\n const timestamp = Date.now();\n\n switch (event.type) {\n case \"message_start\":\n return {\n type: \"message_start\",\n timestamp,\n data: {\n messageId: event.message.id,\n model: event.message.model,\n },\n };\n\n case \"content_block_start\": {\n const contentBlock = event.content_block as { type: string; id?: string; name?: string };\n\n if (contentBlock.type === \"text\") {\n blockContext.currentBlockType = \"text\";\n // text_content_block_start is internal, don't emit\n return null;\n } else if (contentBlock.type === \"tool_use\") {\n blockContext.currentBlockType = \"tool_use\";\n blockContext.currentToolId = contentBlock.id || null;\n blockContext.currentToolName = contentBlock.name || null;\n blockContext.accumulatedToolInput = \"\";\n return {\n type: \"tool_use_start\",\n timestamp,\n data: {\n toolCallId: contentBlock.id || \"\",\n toolName: contentBlock.name || \"\",\n },\n };\n }\n return null;\n }\n\n case \"content_block_delta\": {\n const delta = event.delta as { type: string; text?: string; partial_json?: string };\n\n if (delta.type === \"text_delta\") {\n return {\n type: \"text_delta\",\n timestamp,\n data: { text: delta.text || \"\" },\n };\n } else if (delta.type === \"input_json_delta\") {\n blockContext.accumulatedToolInput += delta.partial_json || \"\";\n return {\n type: \"input_json_delta\",\n timestamp,\n data: { partialJson: delta.partial_json || \"\" },\n };\n }\n return null;\n }\n\n case \"content_block_stop\":\n if (blockContext.currentBlockType === \"tool_use\" && blockContext.currentToolId) {\n // Parse accumulated JSON\n let input: Record<string, unknown> = {};\n try {\n if (blockContext.accumulatedToolInput) {\n input = JSON.parse(blockContext.accumulatedToolInput);\n }\n } catch {\n logger.warn(\"Failed to parse tool input JSON\", {\n input: blockContext.accumulatedToolInput,\n });\n }\n\n const event: DriverStreamEvent = {\n type: \"tool_use_stop\",\n timestamp,\n data: {\n toolCallId: blockContext.currentToolId,\n toolName: blockContext.currentToolName || \"\",\n input,\n },\n };\n\n // Reset block context\n blockContext.currentBlockType = null;\n blockContext.currentToolId = null;\n blockContext.currentToolName = null;\n blockContext.accumulatedToolInput = \"\";\n\n return event;\n }\n // Reset for text blocks too\n blockContext.currentBlockType = null;\n return null;\n\n case \"message_delta\": {\n const msgDelta = event.delta as { stop_reason?: string };\n if (msgDelta.stop_reason) {\n blockContext.lastStopReason = msgDelta.stop_reason;\n }\n return null;\n }\n\n case \"message_stop\":\n return {\n type: \"message_stop\",\n timestamp,\n data: {\n stopReason: this.mapStopReason(blockContext.lastStopReason),\n },\n };\n\n default:\n return null;\n }\n }\n\n /**\n * Convert SDK user message (contains tool_result)\n */\n private convertUserMessage(msg: SDKMessage): DriverStreamEvent[] {\n const events: DriverStreamEvent[] = [];\n const sdkMsg = msg as { message?: { content?: unknown[] } };\n\n if (!sdkMsg.message || !Array.isArray(sdkMsg.message.content)) {\n return events;\n }\n\n for (const block of sdkMsg.message.content) {\n if (block && typeof block === \"object\" && \"type\" in block && block.type === \"tool_result\") {\n const toolResultBlock = block as unknown as {\n tool_use_id: string;\n content: unknown;\n is_error?: boolean;\n };\n\n events.push({\n type: \"tool_result\",\n timestamp: Date.now(),\n data: {\n toolCallId: toolResultBlock.tool_use_id,\n result: toolResultBlock.content,\n isError: toolResultBlock.is_error,\n },\n });\n }\n }\n\n return events;\n }\n\n /**\n * Map SDK stop reason to our StopReason type\n */\n private mapStopReason(sdkReason: string | null): StopReason {\n switch (sdkReason) {\n case \"end_turn\":\n return \"end_turn\";\n case \"max_tokens\":\n return \"max_tokens\";\n case \"tool_use\":\n return \"tool_use\";\n case \"stop_sequence\":\n return \"stop_sequence\";\n default:\n return \"other\";\n }\n }\n\n /**\n * Yield events from Subject as AsyncIterable\n */\n private async *yieldFromSubject(\n subject: Subject<DriverStreamEvent>,\n _isComplete: () => boolean,\n getError: () => Error | null\n ): AsyncIterable<DriverStreamEvent> {\n const queue: DriverStreamEvent[] = [];\n let resolve: ((value: IteratorResult<DriverStreamEvent>) => void) | null = null;\n let done = false;\n\n const subscription = subject.subscribe({\n next: (value) => {\n if (resolve) {\n resolve({ value, done: false });\n resolve = null;\n } else {\n queue.push(value);\n }\n },\n complete: () => {\n done = true;\n if (resolve) {\n resolve({ value: undefined as unknown as DriverStreamEvent, done: true });\n resolve = null;\n }\n },\n error: (_err) => {\n done = true;\n // Error is handled via getError()\n },\n });\n\n try {\n while (!done || queue.length > 0) {\n const error = getError();\n if (error) {\n throw error;\n }\n\n if (queue.length > 0) {\n yield queue.shift()!;\n } else if (!done) {\n const result = await new Promise<IteratorResult<DriverStreamEvent>>((res) => {\n resolve = res;\n });\n\n if (!result.done) {\n yield result.value;\n }\n }\n }\n } finally {\n subscription.unsubscribe();\n }\n }\n}\n\n/**\n * CreateDriver function for ClaudeDriver\n *\n * Factory function that creates a ClaudeDriver instance.\n * Conforms to the CreateDriver type from @agentxjs/core/driver.\n *\n * @example\n * ```typescript\n * import { createClaudeDriver } from \"@agentxjs/claude-driver\";\n *\n * const driver = createClaudeDriver({\n * apiKey: process.env.ANTHROPIC_API_KEY!,\n * agentId: \"my-agent\",\n * systemPrompt: \"You are helpful\",\n * options: {\n * claudeCodePath: \"/usr/local/bin/claude\",\n * },\n * });\n *\n * await driver.initialize();\n *\n * for await (const event of driver.receive({ content: \"Hello\" })) {\n * if (event.type === \"text_delta\") {\n * process.stdout.write(event.data.text);\n * }\n * }\n *\n * await driver.dispose();\n * ```\n */\nexport function createClaudeDriver(config: ClaudeDriverConfig): Driver {\n return new ClaudeDriver(config);\n}\n","/**\n * ConsoleLogger - Default logger implementation\n *\n * Simple console-based logger with color support.\n * Used as fallback when no custom LoggerFactory is provided.\n */\n\nimport type { Logger, LogContext, LogLevel } from \"./types\";\n\nexport interface ConsoleLoggerOptions {\n level?: LogLevel;\n colors?: boolean;\n timestamps?: boolean;\n}\n\nexport class ConsoleLogger implements Logger {\n readonly name: string;\n readonly level: LogLevel;\n private readonly colors: boolean;\n private readonly timestamps: boolean;\n\n private static readonly COLORS = {\n DEBUG: \"\\x1b[36m\",\n INFO: \"\\x1b[32m\",\n WARN: \"\\x1b[33m\",\n ERROR: \"\\x1b[31m\",\n RESET: \"\\x1b[0m\",\n };\n\n constructor(name: string, options: ConsoleLoggerOptions = {}) {\n this.name = name;\n this.level = options.level ?? \"info\";\n this.colors = options.colors ?? this.isNodeEnvironment();\n this.timestamps = options.timestamps ?? true;\n }\n\n debug(message: string, context?: LogContext): void {\n if (this.isDebugEnabled()) {\n this.log(\"DEBUG\", message, context);\n }\n }\n\n info(message: string, context?: LogContext): void {\n if (this.isInfoEnabled()) {\n this.log(\"INFO\", message, context);\n }\n }\n\n warn(message: string, context?: LogContext): void {\n if (this.isWarnEnabled()) {\n this.log(\"WARN\", message, context);\n }\n }\n\n error(message: string | Error, context?: LogContext): void {\n if (this.isErrorEnabled()) {\n if (message instanceof Error) {\n this.log(\"ERROR\", message.message, { ...context, stack: message.stack });\n } else {\n this.log(\"ERROR\", message, context);\n }\n }\n }\n\n isDebugEnabled(): boolean {\n return this.getLevelValue(this.level) <= this.getLevelValue(\"debug\");\n }\n\n isInfoEnabled(): boolean {\n return this.getLevelValue(this.level) <= this.getLevelValue(\"info\");\n }\n\n isWarnEnabled(): boolean {\n return this.getLevelValue(this.level) <= this.getLevelValue(\"warn\");\n }\n\n isErrorEnabled(): boolean {\n return this.getLevelValue(this.level) <= this.getLevelValue(\"error\");\n }\n\n private getLevelValue(level: LogLevel): number {\n const levels: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n };\n return levels[level];\n }\n\n private log(level: string, message: string, context?: LogContext): void {\n const parts: string[] = [];\n\n if (this.timestamps) {\n parts.push(new Date().toISOString());\n }\n\n if (this.colors) {\n const color = ConsoleLogger.COLORS[level as keyof typeof ConsoleLogger.COLORS];\n parts.push(`${color}${level.padEnd(5)}${ConsoleLogger.COLORS.RESET}`);\n } else {\n parts.push(level.padEnd(5));\n }\n\n parts.push(`[${this.name}]`);\n parts.push(message);\n\n const logLine = parts.join(\" \");\n const consoleMethod = this.getConsoleMethod(level);\n\n if (context && Object.keys(context).length > 0) {\n consoleMethod(logLine, context);\n } else {\n consoleMethod(logLine);\n }\n }\n\n private getConsoleMethod(level: string): (...args: unknown[]) => void {\n switch (level) {\n case \"DEBUG\":\n return console.debug.bind(console);\n case \"INFO\":\n return console.info.bind(console);\n case \"WARN\":\n return console.warn.bind(console);\n case \"ERROR\":\n return console.error.bind(console);\n default:\n return console.log.bind(console);\n }\n }\n\n private isNodeEnvironment(): boolean {\n return typeof process !== \"undefined\" && process.versions?.node !== undefined;\n }\n}\n","/**\n * LoggerFactoryImpl - Central factory for creating logger instances\n *\n * Implements lazy initialization pattern:\n * - createLogger() can be called at module level (before config)\n * - Real logger is created on first use\n * - External LoggerFactory can be injected via Runtime\n */\n\nimport type { Logger, LoggerFactory, LogContext, LogLevel } from \"./types\";\nimport { ConsoleLogger, type ConsoleLoggerOptions } from \"./ConsoleLogger\";\n\n// External factory injected via Runtime\nlet externalFactory: LoggerFactory | null = null;\n\n// Version counter to invalidate cached real loggers\nlet factoryVersion = 0;\n\nexport interface LoggerFactoryConfig {\n defaultImplementation?: (name: string) => Logger;\n defaultLevel?: LogLevel;\n consoleOptions?: Omit<ConsoleLoggerOptions, \"level\">;\n}\n\n/**\n * Internal LoggerFactory implementation\n *\n * Uses lazy proxy pattern to allow module-level createLogger() calls.\n */\nexport class LoggerFactoryImpl {\n private static loggers: Map<string, Logger> = new Map();\n private static config: LoggerFactoryConfig = {\n defaultLevel: \"info\",\n };\n\n static getLogger(nameOrClass: string | (new (...args: unknown[]) => unknown)): Logger {\n const name = typeof nameOrClass === \"string\" ? nameOrClass : nameOrClass.name;\n\n if (this.loggers.has(name)) {\n return this.loggers.get(name)!;\n }\n\n const lazyLogger = this.createLazyLogger(name);\n this.loggers.set(name, lazyLogger);\n return lazyLogger;\n }\n\n static configure(config: LoggerFactoryConfig): void {\n this.config = { ...this.config, ...config };\n }\n\n static reset(): void {\n this.loggers.clear();\n this.config = { defaultLevel: \"info\" };\n externalFactory = null;\n factoryVersion++; // Invalidate all cached real loggers\n }\n\n private static createLazyLogger(name: string): Logger {\n let realLogger: Logger | null = null;\n let loggerVersion = -1; // Track which factory version created this logger\n\n const getRealLogger = (): Logger => {\n // Recreate logger if factory version changed (setLoggerFactory was called)\n if (!realLogger || loggerVersion !== factoryVersion) {\n realLogger = this.createLogger(name);\n loggerVersion = factoryVersion;\n }\n return realLogger;\n };\n\n return {\n name,\n level: this.config.defaultLevel || \"info\",\n debug: (message: string, context?: LogContext) => getRealLogger().debug(message, context),\n info: (message: string, context?: LogContext) => getRealLogger().info(message, context),\n warn: (message: string, context?: LogContext) => getRealLogger().warn(message, context),\n error: (message: string | Error, context?: LogContext) =>\n getRealLogger().error(message, context),\n isDebugEnabled: () => getRealLogger().isDebugEnabled(),\n isInfoEnabled: () => getRealLogger().isInfoEnabled(),\n isWarnEnabled: () => getRealLogger().isWarnEnabled(),\n isErrorEnabled: () => getRealLogger().isErrorEnabled(),\n };\n }\n\n private static createLogger(name: string): Logger {\n if (externalFactory) {\n return externalFactory.getLogger(name);\n }\n\n if (this.config.defaultImplementation) {\n return this.config.defaultImplementation(name);\n }\n\n return new ConsoleLogger(name, {\n level: this.config.defaultLevel,\n ...this.config.consoleOptions,\n });\n }\n}\n\n/**\n * Set external LoggerFactory (called by Runtime initialization)\n */\nexport function setLoggerFactory(factory: LoggerFactory): void {\n externalFactory = factory;\n LoggerFactoryImpl.reset();\n externalFactory = factory;\n}\n\n/**\n * Create a logger instance\n *\n * Safe to call at module level before Runtime is configured.\n * Uses lazy initialization - actual logger is created on first use.\n *\n * @param name - Logger name (hierarchical, e.g., \"engine/AgentEngine\")\n * @returns Logger instance (lazy proxy)\n */\nexport function createLogger(name: string): Logger {\n return LoggerFactoryImpl.getLogger(name);\n}\n","/**\n * Helper functions for Claude Driver\n */\n\nimport type { UserMessage, ContentPart, TextPart, ImagePart, FilePart } from \"@agentxjs/core/agent\";\nimport type { SDKUserMessage } from \"@anthropic-ai/claude-agent-sdk\";\n\n/**\n * Claude API content block types\n */\ntype ClaudeTextBlock = {\n type: \"text\";\n text: string;\n};\n\ntype ClaudeImageBlock = {\n type: \"image\";\n source: {\n type: \"base64\";\n media_type: string;\n data: string;\n };\n};\n\ntype ClaudeDocumentBlock = {\n type: \"document\";\n source: {\n type: \"base64\";\n media_type: string;\n data: string;\n };\n};\n\ntype ClaudeContentBlock = ClaudeTextBlock | ClaudeImageBlock | ClaudeDocumentBlock;\n\n/**\n * Type guards for ContentPart discrimination\n */\nfunction isTextPart(part: ContentPart): part is TextPart {\n return part.type === \"text\";\n}\n\nfunction isImagePart(part: ContentPart): part is ImagePart {\n return part.type === \"image\";\n}\n\nfunction isFilePart(part: ContentPart): part is FilePart {\n return part.type === \"file\";\n}\n\n/**\n * Build SDK content from UserMessage\n *\n * Converts AgentX ContentPart[] to Claude API format:\n * - Pure text messages return as string (for efficiency)\n * - Mixed content returns as ClaudeContentBlock[]\n */\nexport function buildSDKContent(message: UserMessage): string | ClaudeContentBlock[] {\n // String content - return as-is\n if (typeof message.content === \"string\") {\n return message.content;\n }\n\n // Not an array - return empty string\n if (!Array.isArray(message.content)) {\n return \"\";\n }\n\n const parts = message.content as ContentPart[];\n\n // Check if we have only text parts\n const hasNonTextParts = parts.some((p) => !isTextPart(p));\n\n if (!hasNonTextParts) {\n // Pure text - return as string for efficiency\n return parts\n .filter(isTextPart)\n .map((p) => p.text)\n .join(\"\\n\");\n }\n\n // Mixed content - return as content blocks\n return parts.map((part): ClaudeContentBlock => {\n if (isTextPart(part)) {\n return {\n type: \"text\",\n text: part.text,\n };\n }\n\n if (isImagePart(part)) {\n return {\n type: \"image\",\n source: {\n type: \"base64\",\n media_type: part.mediaType,\n data: part.data,\n },\n };\n }\n\n if (isFilePart(part)) {\n // PDF and other files use \"document\" type in Claude API\n return {\n type: \"document\",\n source: {\n type: \"base64\",\n media_type: part.mediaType,\n data: part.data,\n },\n };\n }\n\n // Unknown type - return empty text block\n return { type: \"text\", text: \"\" };\n });\n}\n\n/**\n * Build SDK UserMessage from AgentX UserMessage\n */\nexport function buildSDKUserMessage(message: UserMessage, sessionId: string): SDKUserMessage {\n return {\n type: \"user\",\n message: { role: \"user\", content: buildSDKContent(message) },\n parent_tool_use_id: null,\n session_id: sessionId,\n };\n}\n","/**\n * SDKQueryLifecycle - Manages Claude SDK query lifecycle\n *\n * This class encapsulates the low-level SDK interaction:\n * - Query initialization and lazy loading\n * - Background listener for SDK responses\n * - Interrupt and cleanup operations\n *\n * It emits events via callbacks, allowing the parent Driver\n * to handle business logic like timeout management.\n */\n\nimport {\n query,\n type SDKUserMessage,\n type Query,\n type SDKMessage,\n type McpServerConfig,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport { Subject } from \"rxjs\";\nimport { createLogger } from \"commonxjs/logger\";\nimport { buildOptions, type EnvironmentContext } from \"./buildOptions\";\nimport { observableToAsyncIterable } from \"./observableToAsyncIterable\";\n\nconst logger = createLogger(\"claude-driver/SDKQueryLifecycle\");\n\n/**\n * Callbacks for SDK events\n */\nexport interface SDKQueryCallbacks {\n /** Called when a stream_event is received */\n onStreamEvent?: (msg: SDKMessage) => void;\n /** Called when a user message is received (contains tool_result) */\n onUserMessage?: (msg: SDKMessage) => void;\n /** Called when a result is received */\n onResult?: (msg: SDKMessage) => void;\n /** Called when session ID is captured */\n onSessionIdCaptured?: (sessionId: string) => void;\n /** Called when an error occurs */\n onError?: (error: Error) => void;\n /** Called when the listener exits (normally or due to error) */\n onListenerExit?: (reason: \"normal\" | \"abort\" | \"error\") => void;\n}\n\n/**\n * Configuration for SDKQueryLifecycle\n */\nexport interface SDKQueryConfig {\n apiKey: string;\n baseUrl?: string;\n model?: string;\n systemPrompt?: string;\n cwd?: string;\n resumeSessionId?: string;\n mcpServers?: Record<string, McpServerConfig>;\n claudeCodePath?: string;\n}\n\n/**\n * SDKQueryLifecycle - Manages the lifecycle of a Claude SDK query\n *\n * Responsibilities:\n * - Lazy initialization of SDK query\n * - Background listener for SDK responses\n * - Interrupt and cleanup operations\n * - Resource management (subprocess termination)\n */\nexport class SDKQueryLifecycle {\n private readonly config: SDKQueryConfig;\n private _callbacks: SDKQueryCallbacks;\n\n private promptSubject = new Subject<SDKUserMessage>();\n private claudeQuery: Query | null = null;\n private isInitialized = false;\n private abortController: AbortController | null = null;\n private capturedSessionId: string | null = null;\n\n constructor(config: SDKQueryConfig, callbacks: SDKQueryCallbacks = {}) {\n this.config = config;\n this._callbacks = callbacks;\n }\n\n /**\n * Get current callbacks (for reading/modification)\n */\n get callbacks(): SDKQueryCallbacks {\n return this._callbacks;\n }\n\n /**\n * Update callbacks\n *\n * Allows changing callbacks after initialization.\n * Useful for per-turn callback setup.\n */\n setCallbacks(callbacks: Partial<SDKQueryCallbacks>): void {\n this._callbacks = { ...this._callbacks, ...callbacks };\n }\n\n /**\n * Check if the query is initialized\n */\n get initialized(): boolean {\n return this.isInitialized;\n }\n\n /**\n * Warmup the SDK query (pre-initialize)\n *\n * Call this early to start the SDK subprocess before the first message.\n * This reduces latency for the first user message.\n *\n * @returns Promise that resolves when SDK is ready\n */\n async warmup(): Promise<void> {\n logger.info(\"Warming up SDKQueryLifecycle\");\n await this.initialize();\n logger.info(\"SDKQueryLifecycle warmup complete\");\n }\n\n /**\n * Initialize the SDK query (lazy initialization)\n *\n * Creates the query and starts the background listener.\n * Safe to call multiple times - will only initialize once.\n */\n async initialize(): Promise<void> {\n if (this.isInitialized) return;\n\n logger.info(\"Initializing SDKQueryLifecycle\");\n\n this.abortController = new AbortController();\n\n const context: EnvironmentContext = {\n apiKey: this.config.apiKey,\n baseUrl: this.config.baseUrl,\n model: this.config.model,\n systemPrompt: this.config.systemPrompt,\n cwd: this.config.cwd,\n resume: this.config.resumeSessionId,\n mcpServers: this.config.mcpServers,\n claudeCodePath: this.config.claudeCodePath,\n };\n\n const sdkOptions = buildOptions(context, this.abortController);\n const promptStream = observableToAsyncIterable<SDKUserMessage>(this.promptSubject);\n\n this.claudeQuery = query({\n prompt: promptStream,\n options: sdkOptions,\n });\n\n this.isInitialized = true;\n\n // Start background listener\n this.startBackgroundListener();\n\n logger.info(\"SDKQueryLifecycle initialized\");\n }\n\n /**\n * Send a message to the SDK\n *\n * Must call initialize() first.\n */\n send(message: SDKUserMessage): void {\n if (!this.isInitialized) {\n throw new Error(\"SDKQueryLifecycle not initialized. Call initialize() first.\");\n }\n this.promptSubject.next(message);\n }\n\n /**\n * Interrupt the current SDK operation\n */\n interrupt(): void {\n if (this.claudeQuery) {\n logger.debug(\"Interrupting SDK query\");\n this.claudeQuery.interrupt().catch((err) => {\n logger.debug(\"SDK interrupt() error (may be expected)\", { error: err });\n });\n }\n }\n\n /**\n * Reset state and cleanup resources\n *\n * This properly terminates the Claude subprocess by:\n * 1. Completing the prompt stream (signals end of input)\n * 2. Interrupting any ongoing operation\n * 3. Resetting state for potential reuse\n */\n reset(): void {\n logger.debug(\"Resetting SDKQueryLifecycle\");\n\n // 1. Complete the prompt stream first (signals end of input to subprocess)\n this.promptSubject.complete();\n\n // 2. Interrupt any ongoing operation\n if (this.claudeQuery) {\n this.claudeQuery.interrupt().catch((err) => {\n logger.debug(\"SDK interrupt() during reset (may be expected)\", { error: err });\n });\n }\n\n // 3. Reset state for potential reuse\n this.isInitialized = false;\n this.claudeQuery = null;\n this.abortController = null;\n this.promptSubject = new Subject<SDKUserMessage>();\n }\n\n /**\n * Dispose and cleanup all resources\n *\n * Should be called when the lifecycle is no longer needed.\n */\n dispose(): void {\n logger.debug(\"Disposing SDKQueryLifecycle\");\n\n // Interrupt first\n if (this.claudeQuery) {\n this.claudeQuery.interrupt().catch((err) => {\n logger.debug(\"SDK interrupt() during dispose (may be expected)\", { error: err });\n });\n }\n\n // Abort controller\n if (this.abortController) {\n this.abortController.abort();\n }\n\n // Reset state\n this.reset();\n\n logger.debug(\"SDKQueryLifecycle disposed\");\n }\n\n /**\n * Start the background listener for SDK responses\n */\n private startBackgroundListener(): void {\n (async () => {\n try {\n for await (const sdkMsg of this.claudeQuery!) {\n logger.debug(\"SDK message received\", {\n type: sdkMsg.type,\n subtype: (sdkMsg as { subtype?: string }).subtype,\n sessionId: sdkMsg.session_id,\n });\n\n // Capture session ID (only once, on first occurrence)\n if (\n sdkMsg.session_id &&\n this._callbacks.onSessionIdCaptured &&\n this.capturedSessionId !== sdkMsg.session_id\n ) {\n this.capturedSessionId = sdkMsg.session_id;\n this._callbacks.onSessionIdCaptured(sdkMsg.session_id);\n }\n\n // Forward stream_event\n if (sdkMsg.type === \"stream_event\") {\n this._callbacks.onStreamEvent?.(sdkMsg);\n }\n\n // Forward user message (contains tool_result)\n if (sdkMsg.type === \"user\") {\n this._callbacks.onUserMessage?.(sdkMsg);\n }\n\n // Handle result\n if (sdkMsg.type === \"result\") {\n logger.info(\"SDK result received\", {\n subtype: (sdkMsg as { subtype?: string }).subtype,\n is_error: (sdkMsg as { is_error?: boolean }).is_error,\n });\n this._callbacks.onResult?.(sdkMsg);\n }\n }\n\n // Normal exit\n this._callbacks.onListenerExit?.(\"normal\");\n } catch (error) {\n if (this.isAbortError(error)) {\n logger.debug(\"Background listener aborted (expected during interrupt)\");\n this._callbacks.onListenerExit?.(\"abort\");\n } else {\n logger.error(\"Background listener error\", { error });\n this._callbacks.onError?.(error instanceof Error ? error : new Error(String(error)));\n this._callbacks.onListenerExit?.(\"error\");\n }\n\n // Always reset state on any error\n this.reset();\n }\n })();\n }\n\n /**\n * Check if an error is an abort error\n */\n private isAbortError(error: unknown): boolean {\n if (error instanceof Error) {\n if (error.name === \"AbortError\") return true;\n if (error.message.includes(\"aborted\")) return true;\n if (error.message.includes(\"abort\")) return true;\n }\n return false;\n }\n}\n","/**\n * Build Claude SDK Options from Driver Config\n *\n * Converts driver configuration to Claude SDK Options format.\n */\n\nimport type { Options, McpServerConfig } from \"@anthropic-ai/claude-agent-sdk\";\nimport { createLogger } from \"commonxjs/logger\";\n\nconst logger = createLogger(\"claude-driver/buildOptions\");\n\n/**\n * Environment context for Claude SDK\n */\nexport interface EnvironmentContext {\n apiKey: string;\n baseUrl?: string;\n model?: string;\n systemPrompt?: string;\n cwd?: string;\n permissionMode?: \"default\" | \"acceptEdits\" | \"bypassPermissions\" | \"plan\";\n resume?: string;\n maxTurns?: number;\n maxThinkingTokens?: number;\n mcpServers?: Record<string, McpServerConfig>;\n claudeCodePath?: string;\n}\n\n/**\n * Build Claude SDK options from environment context\n */\nexport function buildOptions(\n context: EnvironmentContext,\n abortController: AbortController\n): Options {\n const options: Options = {\n abortController,\n includePartialMessages: true,\n };\n\n // Working directory\n if (context.cwd) {\n options.cwd = context.cwd;\n }\n\n // Environment variables - must include PATH for subprocess to find node\n const env: Record<string, string> = {};\n // Copy all process.env values, filtering out undefined\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined) {\n env[key] = value;\n }\n }\n // Ensure PATH is set (critical for subprocess to find node)\n if (!env.PATH && process.env.PATH) {\n env.PATH = process.env.PATH;\n }\n\n // Mark process as AgentX environment for identification and debugging\n env.AGENTX_ENVIRONMENT = \"true\";\n\n if (context.baseUrl) {\n env.ANTHROPIC_BASE_URL = context.baseUrl;\n }\n if (context.apiKey) {\n env.ANTHROPIC_API_KEY = context.apiKey;\n }\n options.env = env;\n\n logger.info(\"buildOptions called\", {\n hasPath: !!env.PATH,\n pathLength: env.PATH?.length,\n hasApiKey: !!env.ANTHROPIC_API_KEY,\n hasBaseUrl: !!env.ANTHROPIC_BASE_URL,\n baseUrl: env.ANTHROPIC_BASE_URL,\n model: context.model,\n permissionMode: context.permissionMode || \"bypassPermissions\",\n cwd: context.cwd,\n systemPrompt: context.systemPrompt,\n mcpServers: context.mcpServers ? Object.keys(context.mcpServers) : [],\n });\n\n // Capture stderr from SDK subprocess for debugging\n options.stderr = (data: string) => {\n logger.info(\"SDK stderr\", { data: data.trim() });\n };\n\n // Set Claude Code executable path if provided\n if (context.claudeCodePath) {\n options.pathToClaudeCodeExecutable = context.claudeCodePath;\n logger.info(\"Claude Code path configured\", { path: context.claudeCodePath });\n }\n\n // Model configuration\n if (context.model) options.model = context.model;\n if (context.systemPrompt) options.systemPrompt = context.systemPrompt;\n if (context.maxTurns) options.maxTurns = context.maxTurns;\n if (context.maxThinkingTokens) options.maxThinkingTokens = context.maxThinkingTokens;\n\n // Session control\n if (context.resume) options.resume = context.resume;\n\n // MCP servers\n if (context.mcpServers) {\n options.mcpServers = context.mcpServers;\n logger.info(\"MCP servers configured\", {\n serverNames: Object.keys(context.mcpServers),\n });\n }\n\n // Permission system\n if (context.permissionMode) {\n options.permissionMode = context.permissionMode;\n // Required when using bypassPermissions mode\n if (context.permissionMode === \"bypassPermissions\") {\n options.allowDangerouslySkipPermissions = true;\n }\n } else {\n // Default to bypass permissions (agent runs autonomously)\n options.permissionMode = \"bypassPermissions\";\n options.allowDangerouslySkipPermissions = true;\n }\n\n logger.info(\"SDK Options built\", {\n model: options.model,\n systemPrompt: options.systemPrompt,\n permissionMode: options.permissionMode,\n cwd: options.cwd,\n resume: options.resume,\n maxTurns: options.maxTurns,\n mcpServers: options.mcpServers ? Object.keys(options.mcpServers) : [],\n });\n\n return options;\n}\n","/**\n * Convert RxJS Observable to AsyncIterable\n *\n * Utility for converting Observable streams to AsyncIterable\n * for use with SDKs that accept AsyncIterable input.\n */\n\nimport type { Observable } from \"rxjs\";\n\nexport async function* observableToAsyncIterable<T>(observable: Observable<T>): AsyncIterable<T> {\n const queue: T[] = [];\n let resolve: ((value: IteratorResult<T>) => void) | null = null;\n let reject: ((error: Error) => void) | null = null;\n let done = false;\n let error: Error | null = null;\n\n const subscription = observable.subscribe({\n next: (value) => {\n if (resolve) {\n resolve({ value, done: false });\n resolve = null;\n reject = null;\n } else {\n queue.push(value);\n }\n },\n error: (err) => {\n error = err instanceof Error ? err : new Error(String(err));\n done = true;\n if (reject) {\n reject(error);\n resolve = null;\n reject = null;\n }\n },\n complete: () => {\n done = true;\n if (resolve) {\n resolve({ value: undefined as unknown as T, done: true });\n resolve = null;\n reject = null;\n }\n },\n });\n\n try {\n while (!done || queue.length > 0) {\n if (error) {\n throw error;\n }\n\n if (queue.length > 0) {\n yield queue.shift()!;\n } else if (!done) {\n const result = await new Promise<{ value: T; done: false } | { done: true }>((res, rej) => {\n resolve = (iterResult) => {\n if (iterResult.done) {\n done = true;\n res({ done: true });\n } else {\n res({ value: iterResult.value, done: false });\n }\n };\n reject = rej;\n });\n\n if (!result.done) {\n yield result.value;\n }\n }\n }\n } finally {\n subscription.unsubscribe();\n }\n}\n"],"mappings":"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","names":["Subject","logger","logger","Subject","event"]}
|
|
1
|
+
{"version":3,"sources":["../src/ClaudeDriver.ts","../../../node_modules/commonxjs/dist/src/logger/ConsoleLogger.ts","../../../node_modules/commonxjs/dist/src/logger/LoggerFactoryImpl.ts","../src/helpers.ts","../src/SDKQueryLifecycle.ts","../src/buildOptions.ts","../src/observableToAsyncIterable.ts"],"sourcesContent":["/**\n * ClaudeDriver - Claude SDK Driver Implementation\n *\n * Implements the new Driver interface with clear input/output boundaries:\n * - receive(message) returns AsyncIterable<DriverStreamEvent>\n * - No EventBus dependency\n * - Single session communication\n *\n * ```\n * UserMessage\n * │\n * ▼\n * ┌─────────────────┐\n * │ ClaudeDriver │\n * │ │\n * │ receive() │──► AsyncIterable<DriverStreamEvent>\n * │ │ │\n * │ ▼ │\n * │ SDK Query │\n * └─────────────────┘\n * │\n * ▼\n * Claude SDK\n * ```\n */\n\nimport type {\n Driver,\n DriverConfig,\n DriverState,\n DriverStreamEvent,\n StopReason,\n} from \"@agentxjs/core/driver\";\nimport type { UserMessage } from \"@agentxjs/core/agent\";\nimport type { SDKMessage, SDKPartialAssistantMessage } from \"@anthropic-ai/claude-agent-sdk\";\nimport { Subject } from \"rxjs\";\nimport { createLogger } from \"commonxjs/logger\";\nimport { buildSDKUserMessage } from \"./helpers\";\nimport { SDKQueryLifecycle } from \"./SDKQueryLifecycle\";\n\nconst logger = createLogger(\"claude-driver/ClaudeDriver\");\n\n// ============================================================================\n// ClaudeDriver-specific Options\n// ============================================================================\n\n/**\n * ClaudeDriver-specific options\n *\n * These options are specific to the Claude SDK and are passed via\n * the `options` field of DriverConfig.\n *\n * @example\n * ```typescript\n * // Zero-config: claudeCodePath is auto-resolved from installed package\n * const config: DriverConfig<ClaudeDriverOptions> = {\n * apiKey: \"...\",\n * agentId: \"my-agent\",\n * };\n *\n * // Custom path (optional, only if needed)\n * const config: DriverConfig<ClaudeDriverOptions> = {\n * apiKey: \"...\",\n * agentId: \"my-agent\",\n * options: {\n * claudeCodePath: \"/custom/path/to/claude\",\n * }\n * };\n * ```\n */\nexport interface ClaudeDriverOptions {\n /**\n * Path to Claude Code executable\n *\n * If not provided, will automatically resolve from the installed\n * `@anthropic-ai/claude-code` package (zero-config).\n *\n * Only specify this when you need to use a custom Claude Code installation\n * (e.g., a different version or a custom binary location).\n */\n claudeCodePath?: string;\n\n /**\n * Maximum number of turns (agentic loops) before stopping\n *\n * Default is determined by the SDK.\n */\n maxTurns?: number;\n}\n\n/**\n * ClaudeDriverConfig - DriverConfig with ClaudeDriverOptions\n */\nexport type ClaudeDriverConfig = DriverConfig<ClaudeDriverOptions>;\n\n/**\n * ClaudeDriver - Driver implementation for Claude SDK\n *\n * Implements the new Driver interface:\n * - receive() returns AsyncIterable<DriverStreamEvent>\n * - Clear input/output boundaries for recording/playback\n * - Single session communication\n */\nexport class ClaudeDriver implements Driver {\n readonly name = \"ClaudeDriver\";\n\n private _sessionId: string | null = null;\n private _state: DriverState = \"idle\";\n\n private readonly config: ClaudeDriverConfig;\n private queryLifecycle: SDKQueryLifecycle | null = null;\n\n // For interrupt handling\n private currentTurnSubject: Subject<DriverStreamEvent> | null = null;\n\n constructor(config: ClaudeDriverConfig) {\n this.config = config;\n }\n\n // ============================================================================\n // Driver Interface Properties\n // ============================================================================\n\n get sessionId(): string | null {\n return this._sessionId;\n }\n\n get state(): DriverState {\n return this._state;\n }\n\n // ============================================================================\n // Lifecycle Methods\n // ============================================================================\n\n /**\n * Initialize the Driver\n *\n * Starts SDK subprocess and MCP servers.\n * Must be called before receive().\n */\n async initialize(): Promise<void> {\n if (this._state !== \"idle\") {\n throw new Error(`Cannot initialize: Driver is in \"${this._state}\" state`);\n }\n\n logger.info(\"Initializing ClaudeDriver\", { agentId: this.config.agentId });\n\n // SDKQueryLifecycle will be created lazily on first receive()\n // This allows configuration to be validated early without starting subprocess\n\n logger.info(\"ClaudeDriver initialized\");\n }\n\n /**\n * Dispose and cleanup resources\n *\n * Stops SDK subprocess and MCP servers.\n * Driver cannot be used after dispose().\n */\n async dispose(): Promise<void> {\n if (this._state === \"disposed\") {\n return;\n }\n\n logger.info(\"Disposing ClaudeDriver\", { agentId: this.config.agentId });\n\n // Complete any pending turn\n if (this.currentTurnSubject) {\n this.currentTurnSubject.complete();\n this.currentTurnSubject = null;\n }\n\n // Dispose SDK lifecycle\n if (this.queryLifecycle) {\n this.queryLifecycle.dispose();\n this.queryLifecycle = null;\n }\n\n this._state = \"disposed\";\n logger.info(\"ClaudeDriver disposed\");\n }\n\n // ============================================================================\n // Core Methods\n // ============================================================================\n\n /**\n * Receive a user message and return stream of events\n *\n * This is the main method for communication.\n * Returns an AsyncIterable that yields DriverStreamEvent.\n *\n * @param message - User message to send\n * @returns AsyncIterable of stream events\n */\n async *receive(message: UserMessage): AsyncIterable<DriverStreamEvent> {\n if (this._state === \"disposed\") {\n throw new Error(\"Cannot receive: Driver is disposed\");\n }\n\n if (this._state === \"active\") {\n throw new Error(\"Cannot receive: Driver is already processing a message\");\n }\n\n this._state = \"active\";\n\n try {\n // Ensure SDK lifecycle is initialized\n await this.ensureLifecycle();\n\n // Create Subject for this turn's events\n const turnSubject = new Subject<DriverStreamEvent>();\n this.currentTurnSubject = turnSubject;\n\n // Track completion\n let isComplete = false;\n let turnError: Error | null = null;\n\n // Setup callbacks to convert SDK events to DriverStreamEvent\n this.setupTurnCallbacks(\n turnSubject,\n () => {\n isComplete = true;\n },\n (error) => {\n turnError = error;\n isComplete = true;\n }\n );\n\n // Build and send SDK message\n const sessionId = this._sessionId || \"default\";\n const sdkMessage = buildSDKUserMessage(message, sessionId);\n\n logger.debug(\"Sending message to Claude\", {\n content:\n typeof message.content === \"string\" ? message.content.substring(0, 80) : \"[structured]\",\n agentId: this.config.agentId,\n });\n\n this.queryLifecycle!.send(sdkMessage);\n\n // Yield events from Subject\n yield* this.yieldFromSubject(\n turnSubject,\n () => isComplete,\n () => turnError\n );\n } finally {\n this._state = \"idle\";\n this.currentTurnSubject = null;\n }\n }\n\n /**\n * Interrupt current operation\n *\n * Stops the current receive() operation gracefully.\n * The AsyncIterable will emit an \"interrupted\" event and complete.\n */\n interrupt(): void {\n if (this._state !== \"active\") {\n logger.debug(\"Interrupt called but no active operation\");\n return;\n }\n\n logger.debug(\"Interrupting ClaudeDriver\");\n\n // Emit interrupted event\n if (this.currentTurnSubject) {\n this.currentTurnSubject.next({\n type: \"interrupted\",\n timestamp: Date.now(),\n data: { reason: \"user\" },\n });\n this.currentTurnSubject.complete();\n }\n\n // Interrupt SDK\n if (this.queryLifecycle) {\n this.queryLifecycle.interrupt();\n }\n }\n\n // ============================================================================\n // Private Methods\n // ============================================================================\n\n /**\n * Ensure SDK lifecycle is initialized\n */\n private async ensureLifecycle(): Promise<void> {\n if (this.queryLifecycle && this.queryLifecycle.initialized) {\n return;\n }\n\n // Create new lifecycle with driver-specific options\n this.queryLifecycle = new SDKQueryLifecycle(\n {\n apiKey: this.config.apiKey,\n baseUrl: this.config.baseUrl,\n model: this.config.model,\n systemPrompt: this.config.systemPrompt,\n cwd: this.config.cwd,\n resumeSessionId: this.config.resumeSessionId,\n mcpServers: this.config.mcpServers,\n // Pass driver-specific options\n claudeCodePath: this.config.options?.claudeCodePath,\n },\n {\n onSessionIdCaptured: (sessionId) => {\n this._sessionId = sessionId;\n this.config.onSessionIdCaptured?.(sessionId);\n },\n }\n );\n\n await this.queryLifecycle.initialize();\n }\n\n /**\n * Setup callbacks for a single turn\n */\n private setupTurnCallbacks(\n subject: Subject<DriverStreamEvent>,\n onComplete: () => void,\n onError: (error: Error) => void\n ): void {\n if (!this.queryLifecycle) return;\n\n // Context for tracking content block state\n const blockContext = {\n currentBlockType: null as \"text\" | \"tool_use\" | null,\n currentToolId: null as string | null,\n currentToolName: null as string | null,\n lastStopReason: null as string | null,\n accumulatedToolInput: \"\" as string,\n };\n\n // Update lifecycle callbacks for this turn\n this.queryLifecycle.setCallbacks({\n onStreamEvent: (msg: SDKMessage) => {\n const event = this.convertStreamEvent(msg as SDKPartialAssistantMessage, blockContext);\n if (event) {\n subject.next(event);\n }\n },\n\n onUserMessage: (msg: SDKMessage) => {\n const events = this.convertUserMessage(msg);\n for (const event of events) {\n subject.next(event);\n }\n },\n\n onResult: (msg: SDKMessage) => {\n const resultMsg = msg as { is_error?: boolean; error?: { message?: string } };\n\n if (resultMsg.is_error) {\n subject.next({\n type: \"error\",\n timestamp: Date.now(),\n data: {\n message: resultMsg.error?.message || \"Unknown error\",\n errorCode: \"sdk_error\",\n },\n });\n }\n\n subject.complete();\n onComplete();\n },\n\n onError: (error: Error) => {\n subject.next({\n type: \"error\",\n timestamp: Date.now(),\n data: {\n message: error.message,\n errorCode: \"runtime_error\",\n },\n });\n subject.complete();\n onError(error);\n },\n });\n }\n\n /**\n * Convert SDK stream_event to DriverStreamEvent\n */\n private convertStreamEvent(\n sdkMsg: SDKPartialAssistantMessage,\n blockContext: {\n currentBlockType: \"text\" | \"tool_use\" | null;\n currentToolId: string | null;\n currentToolName: string | null;\n lastStopReason: string | null;\n accumulatedToolInput: string;\n }\n ): DriverStreamEvent | null {\n const event = sdkMsg.event;\n const timestamp = Date.now();\n\n switch (event.type) {\n case \"message_start\":\n return {\n type: \"message_start\",\n timestamp,\n data: {\n messageId: event.message.id,\n model: event.message.model,\n },\n };\n\n case \"content_block_start\": {\n const contentBlock = event.content_block as { type: string; id?: string; name?: string };\n\n if (contentBlock.type === \"text\") {\n blockContext.currentBlockType = \"text\";\n // text_content_block_start is internal, don't emit\n return null;\n } else if (contentBlock.type === \"tool_use\") {\n blockContext.currentBlockType = \"tool_use\";\n blockContext.currentToolId = contentBlock.id || null;\n blockContext.currentToolName = contentBlock.name || null;\n blockContext.accumulatedToolInput = \"\";\n return {\n type: \"tool_use_start\",\n timestamp,\n data: {\n toolCallId: contentBlock.id || \"\",\n toolName: contentBlock.name || \"\",\n },\n };\n }\n return null;\n }\n\n case \"content_block_delta\": {\n const delta = event.delta as { type: string; text?: string; partial_json?: string };\n\n if (delta.type === \"text_delta\") {\n return {\n type: \"text_delta\",\n timestamp,\n data: { text: delta.text || \"\" },\n };\n } else if (delta.type === \"input_json_delta\") {\n blockContext.accumulatedToolInput += delta.partial_json || \"\";\n return {\n type: \"input_json_delta\",\n timestamp,\n data: { partialJson: delta.partial_json || \"\" },\n };\n }\n return null;\n }\n\n case \"content_block_stop\":\n if (blockContext.currentBlockType === \"tool_use\" && blockContext.currentToolId) {\n // Parse accumulated JSON\n let input: Record<string, unknown> = {};\n try {\n if (blockContext.accumulatedToolInput) {\n input = JSON.parse(blockContext.accumulatedToolInput);\n }\n } catch {\n logger.warn(\"Failed to parse tool input JSON\", {\n input: blockContext.accumulatedToolInput,\n });\n }\n\n const event: DriverStreamEvent = {\n type: \"tool_use_stop\",\n timestamp,\n data: {\n toolCallId: blockContext.currentToolId,\n toolName: blockContext.currentToolName || \"\",\n input,\n },\n };\n\n // Reset block context\n blockContext.currentBlockType = null;\n blockContext.currentToolId = null;\n blockContext.currentToolName = null;\n blockContext.accumulatedToolInput = \"\";\n\n return event;\n }\n // Reset for text blocks too\n blockContext.currentBlockType = null;\n return null;\n\n case \"message_delta\": {\n const msgDelta = event.delta as { stop_reason?: string };\n if (msgDelta.stop_reason) {\n blockContext.lastStopReason = msgDelta.stop_reason;\n }\n return null;\n }\n\n case \"message_stop\":\n return {\n type: \"message_stop\",\n timestamp,\n data: {\n stopReason: this.mapStopReason(blockContext.lastStopReason),\n },\n };\n\n default:\n return null;\n }\n }\n\n /**\n * Convert SDK user message (contains tool_result)\n */\n private convertUserMessage(msg: SDKMessage): DriverStreamEvent[] {\n const events: DriverStreamEvent[] = [];\n const sdkMsg = msg as { message?: { content?: unknown[] } };\n\n if (!sdkMsg.message || !Array.isArray(sdkMsg.message.content)) {\n return events;\n }\n\n for (const block of sdkMsg.message.content) {\n if (block && typeof block === \"object\" && \"type\" in block && block.type === \"tool_result\") {\n const toolResultBlock = block as unknown as {\n tool_use_id: string;\n content: unknown;\n is_error?: boolean;\n };\n\n events.push({\n type: \"tool_result\",\n timestamp: Date.now(),\n data: {\n toolCallId: toolResultBlock.tool_use_id,\n result: toolResultBlock.content,\n isError: toolResultBlock.is_error,\n },\n });\n }\n }\n\n return events;\n }\n\n /**\n * Map SDK stop reason to our StopReason type\n */\n private mapStopReason(sdkReason: string | null): StopReason {\n switch (sdkReason) {\n case \"end_turn\":\n return \"end_turn\";\n case \"max_tokens\":\n return \"max_tokens\";\n case \"tool_use\":\n return \"tool_use\";\n case \"stop_sequence\":\n return \"stop_sequence\";\n default:\n return \"other\";\n }\n }\n\n /**\n * Yield events from Subject as AsyncIterable\n */\n private async *yieldFromSubject(\n subject: Subject<DriverStreamEvent>,\n _isComplete: () => boolean,\n getError: () => Error | null\n ): AsyncIterable<DriverStreamEvent> {\n const queue: DriverStreamEvent[] = [];\n let resolve: ((value: IteratorResult<DriverStreamEvent>) => void) | null = null;\n let done = false;\n\n const subscription = subject.subscribe({\n next: (value) => {\n if (resolve) {\n resolve({ value, done: false });\n resolve = null;\n } else {\n queue.push(value);\n }\n },\n complete: () => {\n done = true;\n if (resolve) {\n resolve({ value: undefined as unknown as DriverStreamEvent, done: true });\n resolve = null;\n }\n },\n error: (_err) => {\n done = true;\n // Error is handled via getError()\n },\n });\n\n try {\n while (!done || queue.length > 0) {\n const error = getError();\n if (error) {\n throw error;\n }\n\n if (queue.length > 0) {\n yield queue.shift()!;\n } else if (!done) {\n const result = await new Promise<IteratorResult<DriverStreamEvent>>((res) => {\n resolve = res;\n });\n\n if (!result.done) {\n yield result.value;\n }\n }\n }\n } finally {\n subscription.unsubscribe();\n }\n }\n}\n\n/**\n * CreateDriver function for ClaudeDriver\n *\n * Factory function that creates a ClaudeDriver instance.\n * Conforms to the CreateDriver type from @agentxjs/core/driver.\n *\n * @example\n * ```typescript\n * import { createClaudeDriver } from \"@agentxjs/claude-driver\";\n *\n * const driver = createClaudeDriver({\n * apiKey: process.env.ANTHROPIC_API_KEY!,\n * agentId: \"my-agent\",\n * systemPrompt: \"You are helpful\",\n * options: {\n * claudeCodePath: \"/usr/local/bin/claude\",\n * },\n * });\n *\n * await driver.initialize();\n *\n * for await (const event of driver.receive({ content: \"Hello\" })) {\n * if (event.type === \"text_delta\") {\n * process.stdout.write(event.data.text);\n * }\n * }\n *\n * await driver.dispose();\n * ```\n */\nexport function createClaudeDriver(config: ClaudeDriverConfig): Driver {\n return new ClaudeDriver(config);\n}\n","/**\n * ConsoleLogger - Default logger implementation\n *\n * Simple console-based logger with color support.\n * Used as fallback when no custom LoggerFactory is provided.\n */\n\nimport type { Logger, LogContext, LogLevel } from \"./types\";\n\nexport interface ConsoleLoggerOptions {\n level?: LogLevel;\n colors?: boolean;\n timestamps?: boolean;\n}\n\nexport class ConsoleLogger implements Logger {\n readonly name: string;\n readonly level: LogLevel;\n private readonly colors: boolean;\n private readonly timestamps: boolean;\n\n private static readonly COLORS = {\n DEBUG: \"\\x1b[36m\",\n INFO: \"\\x1b[32m\",\n WARN: \"\\x1b[33m\",\n ERROR: \"\\x1b[31m\",\n RESET: \"\\x1b[0m\",\n };\n\n constructor(name: string, options: ConsoleLoggerOptions = {}) {\n this.name = name;\n this.level = options.level ?? \"info\";\n this.colors = options.colors ?? this.isNodeEnvironment();\n this.timestamps = options.timestamps ?? true;\n }\n\n debug(message: string, context?: LogContext): void {\n if (this.isDebugEnabled()) {\n this.log(\"DEBUG\", message, context);\n }\n }\n\n info(message: string, context?: LogContext): void {\n if (this.isInfoEnabled()) {\n this.log(\"INFO\", message, context);\n }\n }\n\n warn(message: string, context?: LogContext): void {\n if (this.isWarnEnabled()) {\n this.log(\"WARN\", message, context);\n }\n }\n\n error(message: string | Error, context?: LogContext): void {\n if (this.isErrorEnabled()) {\n if (message instanceof Error) {\n this.log(\"ERROR\", message.message, { ...context, stack: message.stack });\n } else {\n this.log(\"ERROR\", message, context);\n }\n }\n }\n\n isDebugEnabled(): boolean {\n return this.getLevelValue(this.level) <= this.getLevelValue(\"debug\");\n }\n\n isInfoEnabled(): boolean {\n return this.getLevelValue(this.level) <= this.getLevelValue(\"info\");\n }\n\n isWarnEnabled(): boolean {\n return this.getLevelValue(this.level) <= this.getLevelValue(\"warn\");\n }\n\n isErrorEnabled(): boolean {\n return this.getLevelValue(this.level) <= this.getLevelValue(\"error\");\n }\n\n private getLevelValue(level: LogLevel): number {\n const levels: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n };\n return levels[level];\n }\n\n private log(level: string, message: string, context?: LogContext): void {\n const parts: string[] = [];\n\n if (this.timestamps) {\n parts.push(new Date().toISOString());\n }\n\n if (this.colors) {\n const color = ConsoleLogger.COLORS[level as keyof typeof ConsoleLogger.COLORS];\n parts.push(`${color}${level.padEnd(5)}${ConsoleLogger.COLORS.RESET}`);\n } else {\n parts.push(level.padEnd(5));\n }\n\n parts.push(`[${this.name}]`);\n parts.push(message);\n\n const logLine = parts.join(\" \");\n const consoleMethod = this.getConsoleMethod(level);\n\n if (context && Object.keys(context).length > 0) {\n consoleMethod(logLine, context);\n } else {\n consoleMethod(logLine);\n }\n }\n\n private getConsoleMethod(level: string): (...args: unknown[]) => void {\n switch (level) {\n case \"DEBUG\":\n return console.debug.bind(console);\n case \"INFO\":\n return console.info.bind(console);\n case \"WARN\":\n return console.warn.bind(console);\n case \"ERROR\":\n return console.error.bind(console);\n default:\n return console.log.bind(console);\n }\n }\n\n private isNodeEnvironment(): boolean {\n return typeof process !== \"undefined\" && process.versions?.node !== undefined;\n }\n}\n","/**\n * LoggerFactoryImpl - Central factory for creating logger instances\n *\n * Implements lazy initialization pattern:\n * - createLogger() can be called at module level (before config)\n * - Real logger is created on first use\n * - External LoggerFactory can be injected via Runtime\n */\n\nimport type { Logger, LoggerFactory, LogContext, LogLevel } from \"./types\";\nimport { ConsoleLogger, type ConsoleLoggerOptions } from \"./ConsoleLogger\";\n\n// External factory injected via Runtime\nlet externalFactory: LoggerFactory | null = null;\n\n// Version counter to invalidate cached real loggers\nlet factoryVersion = 0;\n\nexport interface LoggerFactoryConfig {\n defaultImplementation?: (name: string) => Logger;\n defaultLevel?: LogLevel;\n consoleOptions?: Omit<ConsoleLoggerOptions, \"level\">;\n}\n\n/**\n * Internal LoggerFactory implementation\n *\n * Uses lazy proxy pattern to allow module-level createLogger() calls.\n */\nexport class LoggerFactoryImpl {\n private static loggers: Map<string, Logger> = new Map();\n private static config: LoggerFactoryConfig = {\n defaultLevel: \"info\",\n };\n\n static getLogger(nameOrClass: string | (new (...args: unknown[]) => unknown)): Logger {\n const name = typeof nameOrClass === \"string\" ? nameOrClass : nameOrClass.name;\n\n if (this.loggers.has(name)) {\n return this.loggers.get(name)!;\n }\n\n const lazyLogger = this.createLazyLogger(name);\n this.loggers.set(name, lazyLogger);\n return lazyLogger;\n }\n\n static configure(config: LoggerFactoryConfig): void {\n this.config = { ...this.config, ...config };\n }\n\n static reset(): void {\n this.loggers.clear();\n this.config = { defaultLevel: \"info\" };\n externalFactory = null;\n factoryVersion++; // Invalidate all cached real loggers\n }\n\n private static createLazyLogger(name: string): Logger {\n let realLogger: Logger | null = null;\n let loggerVersion = -1; // Track which factory version created this logger\n\n const getRealLogger = (): Logger => {\n // Recreate logger if factory version changed (setLoggerFactory was called)\n if (!realLogger || loggerVersion !== factoryVersion) {\n realLogger = this.createLogger(name);\n loggerVersion = factoryVersion;\n }\n return realLogger;\n };\n\n return {\n name,\n level: this.config.defaultLevel || \"info\",\n debug: (message: string, context?: LogContext) => getRealLogger().debug(message, context),\n info: (message: string, context?: LogContext) => getRealLogger().info(message, context),\n warn: (message: string, context?: LogContext) => getRealLogger().warn(message, context),\n error: (message: string | Error, context?: LogContext) =>\n getRealLogger().error(message, context),\n isDebugEnabled: () => getRealLogger().isDebugEnabled(),\n isInfoEnabled: () => getRealLogger().isInfoEnabled(),\n isWarnEnabled: () => getRealLogger().isWarnEnabled(),\n isErrorEnabled: () => getRealLogger().isErrorEnabled(),\n };\n }\n\n private static createLogger(name: string): Logger {\n if (externalFactory) {\n return externalFactory.getLogger(name);\n }\n\n if (this.config.defaultImplementation) {\n return this.config.defaultImplementation(name);\n }\n\n return new ConsoleLogger(name, {\n level: this.config.defaultLevel,\n ...this.config.consoleOptions,\n });\n }\n}\n\n/**\n * Set external LoggerFactory (called by Runtime initialization)\n */\nexport function setLoggerFactory(factory: LoggerFactory): void {\n externalFactory = factory;\n LoggerFactoryImpl.reset();\n externalFactory = factory;\n}\n\n/**\n * Create a logger instance\n *\n * Safe to call at module level before Runtime is configured.\n * Uses lazy initialization - actual logger is created on first use.\n *\n * @param name - Logger name (hierarchical, e.g., \"engine/AgentEngine\")\n * @returns Logger instance (lazy proxy)\n */\nexport function createLogger(name: string): Logger {\n return LoggerFactoryImpl.getLogger(name);\n}\n","/**\n * Helper functions for Claude Driver\n */\n\nimport type { UserMessage, ContentPart, TextPart, ImagePart, FilePart } from \"@agentxjs/core/agent\";\nimport type { SDKUserMessage } from \"@anthropic-ai/claude-agent-sdk\";\n\n/**\n * Claude API content block types\n */\ntype ClaudeTextBlock = {\n type: \"text\";\n text: string;\n};\n\ntype ClaudeImageBlock = {\n type: \"image\";\n source: {\n type: \"base64\";\n media_type: string;\n data: string;\n };\n};\n\ntype ClaudeDocumentBlock = {\n type: \"document\";\n source: {\n type: \"base64\";\n media_type: string;\n data: string;\n };\n};\n\ntype ClaudeContentBlock = ClaudeTextBlock | ClaudeImageBlock | ClaudeDocumentBlock;\n\n/**\n * Type guards for ContentPart discrimination\n */\nfunction isTextPart(part: ContentPart): part is TextPart {\n return part.type === \"text\";\n}\n\nfunction isImagePart(part: ContentPart): part is ImagePart {\n return part.type === \"image\";\n}\n\nfunction isFilePart(part: ContentPart): part is FilePart {\n return part.type === \"file\";\n}\n\n/**\n * Build SDK content from UserMessage\n *\n * Converts AgentX ContentPart[] to Claude API format:\n * - Pure text messages return as string (for efficiency)\n * - Mixed content returns as ClaudeContentBlock[]\n */\nexport function buildSDKContent(message: UserMessage): string | ClaudeContentBlock[] {\n // String content - return as-is\n if (typeof message.content === \"string\") {\n return message.content;\n }\n\n // Not an array - return empty string\n if (!Array.isArray(message.content)) {\n return \"\";\n }\n\n const parts = message.content as ContentPart[];\n\n // Check if we have only text parts\n const hasNonTextParts = parts.some((p) => !isTextPart(p));\n\n if (!hasNonTextParts) {\n // Pure text - return as string for efficiency\n return parts\n .filter(isTextPart)\n .map((p) => p.text)\n .join(\"\\n\");\n }\n\n // Mixed content - return as content blocks\n return parts.map((part): ClaudeContentBlock => {\n if (isTextPart(part)) {\n return {\n type: \"text\",\n text: part.text,\n };\n }\n\n if (isImagePart(part)) {\n return {\n type: \"image\",\n source: {\n type: \"base64\",\n media_type: part.mediaType,\n data: part.data,\n },\n };\n }\n\n if (isFilePart(part)) {\n // PDF and other files use \"document\" type in Claude API\n return {\n type: \"document\",\n source: {\n type: \"base64\",\n media_type: part.mediaType,\n data: part.data,\n },\n };\n }\n\n // Unknown type - return empty text block\n return { type: \"text\", text: \"\" };\n });\n}\n\n/**\n * Build SDK UserMessage from AgentX UserMessage\n */\nexport function buildSDKUserMessage(message: UserMessage, sessionId: string): SDKUserMessage {\n return {\n type: \"user\",\n message: { role: \"user\", content: buildSDKContent(message) },\n parent_tool_use_id: null,\n session_id: sessionId,\n };\n}\n","/**\n * SDKQueryLifecycle - Manages Claude SDK query lifecycle\n *\n * This class encapsulates the low-level SDK interaction:\n * - Query initialization and lazy loading\n * - Background listener for SDK responses\n * - Interrupt and cleanup operations\n *\n * It emits events via callbacks, allowing the parent Driver\n * to handle business logic like timeout management.\n */\n\nimport {\n query,\n type SDKUserMessage,\n type Query,\n type SDKMessage,\n type McpServerConfig,\n} from \"@anthropic-ai/claude-agent-sdk\";\nimport { Subject } from \"rxjs\";\nimport { createLogger } from \"commonxjs/logger\";\nimport { buildOptions, type EnvironmentContext } from \"./buildOptions\";\nimport { observableToAsyncIterable } from \"./observableToAsyncIterable\";\n\nconst logger = createLogger(\"claude-driver/SDKQueryLifecycle\");\n\n/**\n * Callbacks for SDK events\n */\nexport interface SDKQueryCallbacks {\n /** Called when a stream_event is received */\n onStreamEvent?: (msg: SDKMessage) => void;\n /** Called when a user message is received (contains tool_result) */\n onUserMessage?: (msg: SDKMessage) => void;\n /** Called when a result is received */\n onResult?: (msg: SDKMessage) => void;\n /** Called when session ID is captured */\n onSessionIdCaptured?: (sessionId: string) => void;\n /** Called when an error occurs */\n onError?: (error: Error) => void;\n /** Called when the listener exits (normally or due to error) */\n onListenerExit?: (reason: \"normal\" | \"abort\" | \"error\") => void;\n}\n\n/**\n * Configuration for SDKQueryLifecycle\n */\nexport interface SDKQueryConfig {\n apiKey: string;\n baseUrl?: string;\n model?: string;\n systemPrompt?: string;\n cwd?: string;\n resumeSessionId?: string;\n mcpServers?: Record<string, McpServerConfig>;\n claudeCodePath?: string;\n}\n\n/**\n * SDKQueryLifecycle - Manages the lifecycle of a Claude SDK query\n *\n * Responsibilities:\n * - Lazy initialization of SDK query\n * - Background listener for SDK responses\n * - Interrupt and cleanup operations\n * - Resource management (subprocess termination)\n */\nexport class SDKQueryLifecycle {\n private readonly config: SDKQueryConfig;\n private _callbacks: SDKQueryCallbacks;\n\n private promptSubject = new Subject<SDKUserMessage>();\n private claudeQuery: Query | null = null;\n private isInitialized = false;\n private abortController: AbortController | null = null;\n private capturedSessionId: string | null = null;\n\n constructor(config: SDKQueryConfig, callbacks: SDKQueryCallbacks = {}) {\n this.config = config;\n this._callbacks = callbacks;\n }\n\n /**\n * Get current callbacks (for reading/modification)\n */\n get callbacks(): SDKQueryCallbacks {\n return this._callbacks;\n }\n\n /**\n * Update callbacks\n *\n * Allows changing callbacks after initialization.\n * Useful for per-turn callback setup.\n */\n setCallbacks(callbacks: Partial<SDKQueryCallbacks>): void {\n this._callbacks = { ...this._callbacks, ...callbacks };\n }\n\n /**\n * Check if the query is initialized\n */\n get initialized(): boolean {\n return this.isInitialized;\n }\n\n /**\n * Warmup the SDK query (pre-initialize)\n *\n * Call this early to start the SDK subprocess before the first message.\n * This reduces latency for the first user message.\n *\n * @returns Promise that resolves when SDK is ready\n */\n async warmup(): Promise<void> {\n logger.info(\"Warming up SDKQueryLifecycle\");\n await this.initialize();\n logger.info(\"SDKQueryLifecycle warmup complete\");\n }\n\n /**\n * Initialize the SDK query (lazy initialization)\n *\n * Creates the query and starts the background listener.\n * Safe to call multiple times - will only initialize once.\n */\n async initialize(): Promise<void> {\n if (this.isInitialized) return;\n\n logger.info(\"Initializing SDKQueryLifecycle\");\n\n this.abortController = new AbortController();\n\n const context: EnvironmentContext = {\n apiKey: this.config.apiKey,\n baseUrl: this.config.baseUrl,\n model: this.config.model,\n systemPrompt: this.config.systemPrompt,\n cwd: this.config.cwd,\n resume: this.config.resumeSessionId,\n mcpServers: this.config.mcpServers,\n claudeCodePath: this.config.claudeCodePath,\n };\n\n const sdkOptions = buildOptions(context, this.abortController);\n const promptStream = observableToAsyncIterable<SDKUserMessage>(this.promptSubject);\n\n this.claudeQuery = query({\n prompt: promptStream,\n options: sdkOptions,\n });\n\n this.isInitialized = true;\n\n // Start background listener\n this.startBackgroundListener();\n\n logger.info(\"SDKQueryLifecycle initialized\");\n }\n\n /**\n * Send a message to the SDK\n *\n * Must call initialize() first.\n */\n send(message: SDKUserMessage): void {\n if (!this.isInitialized) {\n throw new Error(\"SDKQueryLifecycle not initialized. Call initialize() first.\");\n }\n this.promptSubject.next(message);\n }\n\n /**\n * Interrupt the current SDK operation\n */\n interrupt(): void {\n if (this.claudeQuery) {\n logger.debug(\"Interrupting SDK query\");\n this.claudeQuery.interrupt().catch((err) => {\n logger.debug(\"SDK interrupt() error (may be expected)\", { error: err });\n });\n }\n }\n\n /**\n * Reset state and cleanup resources\n *\n * This properly terminates the Claude subprocess by:\n * 1. Completing the prompt stream (signals end of input)\n * 2. Interrupting any ongoing operation\n * 3. Resetting state for potential reuse\n */\n reset(): void {\n logger.debug(\"Resetting SDKQueryLifecycle\");\n\n // 1. Complete the prompt stream first (signals end of input to subprocess)\n this.promptSubject.complete();\n\n // 2. Interrupt any ongoing operation\n if (this.claudeQuery) {\n this.claudeQuery.interrupt().catch((err) => {\n logger.debug(\"SDK interrupt() during reset (may be expected)\", { error: err });\n });\n }\n\n // 3. Reset state for potential reuse\n this.isInitialized = false;\n this.claudeQuery = null;\n this.abortController = null;\n this.promptSubject = new Subject<SDKUserMessage>();\n }\n\n /**\n * Dispose and cleanup all resources\n *\n * Should be called when the lifecycle is no longer needed.\n */\n dispose(): void {\n logger.debug(\"Disposing SDKQueryLifecycle\");\n\n // Interrupt first\n if (this.claudeQuery) {\n this.claudeQuery.interrupt().catch((err) => {\n logger.debug(\"SDK interrupt() during dispose (may be expected)\", { error: err });\n });\n }\n\n // Abort controller\n if (this.abortController) {\n this.abortController.abort();\n }\n\n // Reset state\n this.reset();\n\n logger.debug(\"SDKQueryLifecycle disposed\");\n }\n\n /**\n * Start the background listener for SDK responses\n */\n private startBackgroundListener(): void {\n (async () => {\n try {\n for await (const sdkMsg of this.claudeQuery!) {\n logger.debug(\"SDK message received\", {\n type: sdkMsg.type,\n subtype: (sdkMsg as { subtype?: string }).subtype,\n sessionId: sdkMsg.session_id,\n });\n\n // Capture session ID (only once, on first occurrence)\n if (\n sdkMsg.session_id &&\n this._callbacks.onSessionIdCaptured &&\n this.capturedSessionId !== sdkMsg.session_id\n ) {\n this.capturedSessionId = sdkMsg.session_id;\n this._callbacks.onSessionIdCaptured(sdkMsg.session_id);\n }\n\n // Forward stream_event\n if (sdkMsg.type === \"stream_event\") {\n this._callbacks.onStreamEvent?.(sdkMsg);\n }\n\n // Forward user message (contains tool_result)\n if (sdkMsg.type === \"user\") {\n this._callbacks.onUserMessage?.(sdkMsg);\n }\n\n // Handle result\n if (sdkMsg.type === \"result\") {\n logger.info(\"SDK result received\", {\n subtype: (sdkMsg as { subtype?: string }).subtype,\n is_error: (sdkMsg as { is_error?: boolean }).is_error,\n });\n this._callbacks.onResult?.(sdkMsg);\n }\n }\n\n // Normal exit\n this._callbacks.onListenerExit?.(\"normal\");\n } catch (error) {\n if (this.isAbortError(error)) {\n logger.debug(\"Background listener aborted (expected during interrupt)\");\n this._callbacks.onListenerExit?.(\"abort\");\n } else {\n logger.error(\"Background listener error\", { error });\n this._callbacks.onError?.(error instanceof Error ? error : new Error(String(error)));\n this._callbacks.onListenerExit?.(\"error\");\n }\n\n // Always reset state on any error\n this.reset();\n }\n })();\n }\n\n /**\n * Check if an error is an abort error\n */\n private isAbortError(error: unknown): boolean {\n if (error instanceof Error) {\n if (error.name === \"AbortError\") return true;\n if (error.message.includes(\"aborted\")) return true;\n if (error.message.includes(\"abort\")) return true;\n }\n return false;\n }\n}\n","/**\n * Build Claude SDK Options from Driver Config\n *\n * Converts driver configuration to Claude SDK Options format.\n */\n\nimport type { Options, McpServerConfig } from \"@anthropic-ai/claude-agent-sdk\";\nimport { createLogger } from \"commonxjs/logger\";\nimport { createRequire } from \"node:module\";\n\nconst logger = createLogger(\"claude-driver/buildOptions\");\n\n/**\n * Get the default Claude Code CLI path from the installed package\n *\n * Resolves the path to `@anthropic-ai/claude-code/cli.js` using Node.js module resolution.\n * This allows zero-config deployment when claude-code is installed as a dependency.\n *\n * @returns The resolved path to cli.js, or undefined if resolution fails\n */\nfunction getDefaultClaudeCodePath(): string | undefined {\n try {\n const require = createRequire(import.meta.url);\n const cliPath = require.resolve(\"@anthropic-ai/claude-code/cli.js\");\n logger.debug(\"Resolved default Claude Code path\", { path: cliPath });\n return cliPath;\n } catch (error) {\n logger.warn(\"Failed to resolve @anthropic-ai/claude-code/cli.js\", { error });\n return undefined;\n }\n}\n\n/**\n * Environment context for Claude SDK\n */\nexport interface EnvironmentContext {\n apiKey: string;\n baseUrl?: string;\n model?: string;\n systemPrompt?: string;\n cwd?: string;\n permissionMode?: \"default\" | \"acceptEdits\" | \"bypassPermissions\" | \"plan\";\n resume?: string;\n maxTurns?: number;\n maxThinkingTokens?: number;\n mcpServers?: Record<string, McpServerConfig>;\n claudeCodePath?: string;\n}\n\n/**\n * Build Claude SDK options from environment context\n */\nexport function buildOptions(\n context: EnvironmentContext,\n abortController: AbortController\n): Options {\n const options: Options = {\n abortController,\n includePartialMessages: true,\n };\n\n // Working directory\n if (context.cwd) {\n options.cwd = context.cwd;\n }\n\n // Environment variables - must include PATH for subprocess to find node\n const env: Record<string, string> = {};\n // Copy all process.env values, filtering out undefined\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined) {\n env[key] = value;\n }\n }\n // Ensure PATH is set (critical for subprocess to find node)\n if (!env.PATH && process.env.PATH) {\n env.PATH = process.env.PATH;\n }\n\n // Mark process as AgentX environment for identification and debugging\n env.AGENTX_ENVIRONMENT = \"true\";\n\n if (context.baseUrl) {\n env.ANTHROPIC_BASE_URL = context.baseUrl;\n }\n if (context.apiKey) {\n env.ANTHROPIC_API_KEY = context.apiKey;\n }\n options.env = env;\n\n logger.info(\"buildOptions called\", {\n hasPath: !!env.PATH,\n pathLength: env.PATH?.length,\n hasApiKey: !!env.ANTHROPIC_API_KEY,\n hasBaseUrl: !!env.ANTHROPIC_BASE_URL,\n baseUrl: env.ANTHROPIC_BASE_URL,\n model: context.model,\n permissionMode: context.permissionMode || \"bypassPermissions\",\n cwd: context.cwd,\n systemPrompt: context.systemPrompt,\n mcpServers: context.mcpServers ? Object.keys(context.mcpServers) : [],\n });\n\n // Capture stderr from SDK subprocess for debugging\n options.stderr = (data: string) => {\n logger.info(\"SDK stderr\", { data: data.trim() });\n };\n\n // Set Claude Code executable path\n // Priority: user-provided path > auto-resolved from installed package\n const claudeCodePath = context.claudeCodePath || getDefaultClaudeCodePath();\n if (claudeCodePath) {\n options.pathToClaudeCodeExecutable = claudeCodePath;\n logger.info(\"Claude Code path configured\", {\n path: claudeCodePath,\n source: context.claudeCodePath ? \"user-provided\" : \"auto-resolved\",\n });\n }\n\n // Model configuration\n if (context.model) options.model = context.model;\n if (context.systemPrompt) options.systemPrompt = context.systemPrompt;\n if (context.maxTurns) options.maxTurns = context.maxTurns;\n if (context.maxThinkingTokens) options.maxThinkingTokens = context.maxThinkingTokens;\n\n // Session control\n if (context.resume) options.resume = context.resume;\n\n // MCP servers\n if (context.mcpServers) {\n options.mcpServers = context.mcpServers;\n logger.info(\"MCP servers configured\", {\n serverNames: Object.keys(context.mcpServers),\n });\n }\n\n // Permission system\n if (context.permissionMode) {\n options.permissionMode = context.permissionMode;\n // Required when using bypassPermissions mode\n if (context.permissionMode === \"bypassPermissions\") {\n options.allowDangerouslySkipPermissions = true;\n }\n } else {\n // Default to bypass permissions (agent runs autonomously)\n options.permissionMode = \"bypassPermissions\";\n options.allowDangerouslySkipPermissions = true;\n }\n\n logger.info(\"SDK Options built\", {\n model: options.model,\n systemPrompt: options.systemPrompt,\n permissionMode: options.permissionMode,\n cwd: options.cwd,\n resume: options.resume,\n maxTurns: options.maxTurns,\n mcpServers: options.mcpServers ? Object.keys(options.mcpServers) : [],\n });\n\n return options;\n}\n","/**\n * Convert RxJS Observable to AsyncIterable\n *\n * Utility for converting Observable streams to AsyncIterable\n * for use with SDKs that accept AsyncIterable input.\n */\n\nimport type { Observable } from \"rxjs\";\n\nexport async function* observableToAsyncIterable<T>(observable: Observable<T>): AsyncIterable<T> {\n const queue: T[] = [];\n let resolve: ((value: IteratorResult<T>) => void) | null = null;\n let reject: ((error: Error) => void) | null = null;\n let done = false;\n let error: Error | null = null;\n\n const subscription = observable.subscribe({\n next: (value) => {\n if (resolve) {\n resolve({ value, done: false });\n resolve = null;\n reject = null;\n } else {\n queue.push(value);\n }\n },\n error: (err) => {\n error = err instanceof Error ? err : new Error(String(err));\n done = true;\n if (reject) {\n reject(error);\n resolve = null;\n reject = null;\n }\n },\n complete: () => {\n done = true;\n if (resolve) {\n resolve({ value: undefined as unknown as T, done: true });\n resolve = null;\n reject = null;\n }\n },\n });\n\n try {\n while (!done || queue.length > 0) {\n if (error) {\n throw error;\n }\n\n if (queue.length > 0) {\n yield queue.shift()!;\n } else if (!done) {\n const result = await new Promise<{ value: T; done: false } | { done: true }>((res, rej) => {\n resolve = (iterResult) => {\n if (iterResult.done) {\n done = true;\n res({ done: true });\n } else {\n res({ value: iterResult.value, done: false });\n }\n };\n reject = rej;\n });\n\n if (!result.done) {\n yield result.value;\n }\n }\n }\n } finally {\n subscription.unsubscribe();\n }\n}\n"],"mappings":"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","names":["Subject","require","logger","logger","Subject","event"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentxjs/claude-driver",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -18,11 +18,12 @@
|
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "tsup",
|
|
20
20
|
"typecheck": "tsc --noEmit",
|
|
21
|
-
"test": "
|
|
21
|
+
"test": "echo 'No tests yet'"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@agentxjs/core": "
|
|
24
|
+
"@agentxjs/core": "^2.0.0",
|
|
25
25
|
"@anthropic-ai/claude-agent-sdk": "^0.2.29",
|
|
26
|
+
"@anthropic-ai/claude-code": "^2.1.31",
|
|
26
27
|
"rxjs": "^7.8.2"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
package/src/ClaudeDriver.ts
CHANGED
|
@@ -52,12 +52,18 @@ const logger = createLogger("claude-driver/ClaudeDriver");
|
|
|
52
52
|
*
|
|
53
53
|
* @example
|
|
54
54
|
* ```typescript
|
|
55
|
+
* // Zero-config: claudeCodePath is auto-resolved from installed package
|
|
56
|
+
* const config: DriverConfig<ClaudeDriverOptions> = {
|
|
57
|
+
* apiKey: "...",
|
|
58
|
+
* agentId: "my-agent",
|
|
59
|
+
* };
|
|
60
|
+
*
|
|
61
|
+
* // Custom path (optional, only if needed)
|
|
55
62
|
* const config: DriverConfig<ClaudeDriverOptions> = {
|
|
56
63
|
* apiKey: "...",
|
|
57
64
|
* agentId: "my-agent",
|
|
58
65
|
* options: {
|
|
59
|
-
* claudeCodePath: "/
|
|
60
|
-
* maxTurns: 10,
|
|
66
|
+
* claudeCodePath: "/custom/path/to/claude",
|
|
61
67
|
* }
|
|
62
68
|
* };
|
|
63
69
|
* ```
|
|
@@ -66,9 +72,11 @@ export interface ClaudeDriverOptions {
|
|
|
66
72
|
/**
|
|
67
73
|
* Path to Claude Code executable
|
|
68
74
|
*
|
|
69
|
-
* If not provided,
|
|
70
|
-
*
|
|
71
|
-
*
|
|
75
|
+
* If not provided, will automatically resolve from the installed
|
|
76
|
+
* `@anthropic-ai/claude-code` package (zero-config).
|
|
77
|
+
*
|
|
78
|
+
* Only specify this when you need to use a custom Claude Code installation
|
|
79
|
+
* (e.g., a different version or a custom binary location).
|
|
72
80
|
*/
|
|
73
81
|
claudeCodePath?: string;
|
|
74
82
|
|
|
@@ -210,29 +218,35 @@ export class ClaudeDriver implements Driver {
|
|
|
210
218
|
let turnError: Error | null = null;
|
|
211
219
|
|
|
212
220
|
// Setup callbacks to convert SDK events to DriverStreamEvent
|
|
213
|
-
this.setupTurnCallbacks(
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
221
|
+
this.setupTurnCallbacks(
|
|
222
|
+
turnSubject,
|
|
223
|
+
() => {
|
|
224
|
+
isComplete = true;
|
|
225
|
+
},
|
|
226
|
+
(error) => {
|
|
227
|
+
turnError = error;
|
|
228
|
+
isComplete = true;
|
|
229
|
+
}
|
|
230
|
+
);
|
|
219
231
|
|
|
220
232
|
// Build and send SDK message
|
|
221
233
|
const sessionId = this._sessionId || "default";
|
|
222
234
|
const sdkMessage = buildSDKUserMessage(message, sessionId);
|
|
223
235
|
|
|
224
236
|
logger.debug("Sending message to Claude", {
|
|
225
|
-
content:
|
|
226
|
-
? message.content.substring(0, 80)
|
|
227
|
-
: "[structured]",
|
|
237
|
+
content:
|
|
238
|
+
typeof message.content === "string" ? message.content.substring(0, 80) : "[structured]",
|
|
228
239
|
agentId: this.config.agentId,
|
|
229
240
|
});
|
|
230
241
|
|
|
231
242
|
this.queryLifecycle!.send(sdkMessage);
|
|
232
243
|
|
|
233
244
|
// Yield events from Subject
|
|
234
|
-
yield* this.yieldFromSubject(
|
|
235
|
-
|
|
245
|
+
yield* this.yieldFromSubject(
|
|
246
|
+
turnSubject,
|
|
247
|
+
() => isComplete,
|
|
248
|
+
() => turnError
|
|
249
|
+
);
|
|
236
250
|
} finally {
|
|
237
251
|
this._state = "idle";
|
|
238
252
|
this.currentTurnSubject = null;
|
package/src/buildOptions.ts
CHANGED
|
@@ -6,9 +6,30 @@
|
|
|
6
6
|
|
|
7
7
|
import type { Options, McpServerConfig } from "@anthropic-ai/claude-agent-sdk";
|
|
8
8
|
import { createLogger } from "commonxjs/logger";
|
|
9
|
+
import { createRequire } from "node:module";
|
|
9
10
|
|
|
10
11
|
const logger = createLogger("claude-driver/buildOptions");
|
|
11
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Get the default Claude Code CLI path from the installed package
|
|
15
|
+
*
|
|
16
|
+
* Resolves the path to `@anthropic-ai/claude-code/cli.js` using Node.js module resolution.
|
|
17
|
+
* This allows zero-config deployment when claude-code is installed as a dependency.
|
|
18
|
+
*
|
|
19
|
+
* @returns The resolved path to cli.js, or undefined if resolution fails
|
|
20
|
+
*/
|
|
21
|
+
function getDefaultClaudeCodePath(): string | undefined {
|
|
22
|
+
try {
|
|
23
|
+
const require = createRequire(import.meta.url);
|
|
24
|
+
const cliPath = require.resolve("@anthropic-ai/claude-code/cli.js");
|
|
25
|
+
logger.debug("Resolved default Claude Code path", { path: cliPath });
|
|
26
|
+
return cliPath;
|
|
27
|
+
} catch (error) {
|
|
28
|
+
logger.warn("Failed to resolve @anthropic-ai/claude-code/cli.js", { error });
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
12
33
|
/**
|
|
13
34
|
* Environment context for Claude SDK
|
|
14
35
|
*/
|
|
@@ -85,10 +106,15 @@ export function buildOptions(
|
|
|
85
106
|
logger.info("SDK stderr", { data: data.trim() });
|
|
86
107
|
};
|
|
87
108
|
|
|
88
|
-
// Set Claude Code executable path
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
109
|
+
// Set Claude Code executable path
|
|
110
|
+
// Priority: user-provided path > auto-resolved from installed package
|
|
111
|
+
const claudeCodePath = context.claudeCodePath || getDefaultClaudeCodePath();
|
|
112
|
+
if (claudeCodePath) {
|
|
113
|
+
options.pathToClaudeCodeExecutable = claudeCodePath;
|
|
114
|
+
logger.info("Claude Code path configured", {
|
|
115
|
+
path: claudeCodePath,
|
|
116
|
+
source: context.claudeCodePath ? "user-provided" : "auto-resolved",
|
|
117
|
+
});
|
|
92
118
|
}
|
|
93
119
|
|
|
94
120
|
// Model configuration
|