@scottwalker/claude-connector 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +444 -0
  3. package/dist/builder/args-builder.d.ts +64 -0
  4. package/dist/builder/args-builder.d.ts.map +1 -0
  5. package/dist/builder/args-builder.js +134 -0
  6. package/dist/builder/args-builder.js.map +1 -0
  7. package/dist/builder/index.d.ts +2 -0
  8. package/dist/builder/index.d.ts.map +1 -0
  9. package/dist/builder/index.js +2 -0
  10. package/dist/builder/index.js.map +1 -0
  11. package/dist/client/claude.d.ts +120 -0
  12. package/dist/client/claude.d.ts.map +1 -0
  13. package/dist/client/claude.js +182 -0
  14. package/dist/client/claude.js.map +1 -0
  15. package/dist/client/session.d.ts +64 -0
  16. package/dist/client/session.d.ts.map +1 -0
  17. package/dist/client/session.js +128 -0
  18. package/dist/client/session.js.map +1 -0
  19. package/dist/errors/errors.d.ts +52 -0
  20. package/dist/errors/errors.d.ts.map +1 -0
  21. package/dist/errors/errors.js +78 -0
  22. package/dist/errors/errors.js.map +1 -0
  23. package/dist/errors/index.d.ts +2 -0
  24. package/dist/errors/index.d.ts.map +1 -0
  25. package/dist/errors/index.js +2 -0
  26. package/dist/errors/index.js.map +1 -0
  27. package/dist/executor/cli-executor.d.ts +35 -0
  28. package/dist/executor/cli-executor.d.ts.map +1 -0
  29. package/dist/executor/cli-executor.js +223 -0
  30. package/dist/executor/cli-executor.js.map +1 -0
  31. package/dist/executor/index.d.ts +4 -0
  32. package/dist/executor/index.d.ts.map +1 -0
  33. package/dist/executor/index.js +3 -0
  34. package/dist/executor/index.js.map +1 -0
  35. package/dist/executor/interface.d.ts +65 -0
  36. package/dist/executor/interface.d.ts.map +1 -0
  37. package/dist/executor/interface.js +2 -0
  38. package/dist/executor/interface.js.map +1 -0
  39. package/dist/executor/sdk-executor.d.ts +102 -0
  40. package/dist/executor/sdk-executor.d.ts.map +1 -0
  41. package/dist/executor/sdk-executor.js +256 -0
  42. package/dist/executor/sdk-executor.js.map +1 -0
  43. package/dist/index.d.ts +49 -0
  44. package/dist/index.d.ts.map +1 -0
  45. package/dist/index.js +49 -0
  46. package/dist/index.js.map +1 -0
  47. package/dist/parser/index.d.ts +3 -0
  48. package/dist/parser/index.d.ts.map +1 -0
  49. package/dist/parser/index.js +3 -0
  50. package/dist/parser/index.js.map +1 -0
  51. package/dist/parser/json-parser.d.ts +22 -0
  52. package/dist/parser/json-parser.d.ts.map +1 -0
  53. package/dist/parser/json-parser.js +87 -0
  54. package/dist/parser/json-parser.js.map +1 -0
  55. package/dist/parser/stream-parser.d.ts +21 -0
  56. package/dist/parser/stream-parser.d.ts.map +1 -0
  57. package/dist/parser/stream-parser.js +84 -0
  58. package/dist/parser/stream-parser.js.map +1 -0
  59. package/dist/scheduler/index.d.ts +2 -0
  60. package/dist/scheduler/index.d.ts.map +1 -0
  61. package/dist/scheduler/index.js +2 -0
  62. package/dist/scheduler/index.js.map +1 -0
  63. package/dist/scheduler/scheduler.d.ts +65 -0
  64. package/dist/scheduler/scheduler.d.ts.map +1 -0
  65. package/dist/scheduler/scheduler.js +134 -0
  66. package/dist/scheduler/scheduler.js.map +1 -0
  67. package/dist/types/client.d.ts +184 -0
  68. package/dist/types/client.d.ts.map +1 -0
  69. package/dist/types/client.js +2 -0
  70. package/dist/types/client.js.map +1 -0
  71. package/dist/types/index.d.ts +4 -0
  72. package/dist/types/index.d.ts.map +1 -0
  73. package/dist/types/index.js +2 -0
  74. package/dist/types/index.js.map +1 -0
  75. package/dist/types/result.d.ts +94 -0
  76. package/dist/types/result.d.ts.map +1 -0
  77. package/dist/types/result.js +2 -0
  78. package/dist/types/result.js.map +1 -0
  79. package/dist/types/session.d.ts +37 -0
  80. package/dist/types/session.d.ts.map +1 -0
  81. package/dist/types/session.js +2 -0
  82. package/dist/types/session.js.map +1 -0
  83. package/dist/utils/index.d.ts +2 -0
  84. package/dist/utils/index.d.ts.map +1 -0
  85. package/dist/utils/index.js +2 -0
  86. package/dist/utils/index.js.map +1 -0
  87. package/dist/utils/validation.d.ts +15 -0
  88. package/dist/utils/validation.d.ts.map +1 -0
  89. package/dist/utils/validation.js +45 -0
  90. package/dist/utils/validation.js.map +1 -0
  91. package/package.json +62 -0
@@ -0,0 +1,256 @@
1
+ import { EventEmitter } from 'node:events';
2
+ /**
3
+ * Executor implementation using the Claude Agent SDK (V2 API).
4
+ *
5
+ * ## Why this exists
6
+ *
7
+ * The CLI executor (`CliExecutor`) spawns a new `claude` process for every query.
8
+ * Each spawn has a cold-start cost: loading the CLI, authenticating, initializing
9
+ * tools and MCP servers. For interactive use this delay is noticeable (5-15s).
10
+ *
11
+ * `SdkExecutor` solves this by creating a **persistent SDK session** via
12
+ * `unstable_v2_createSession()`. The session stays warm — subsequent queries
13
+ * use `session.send()` + `session.stream()` with near-zero overhead.
14
+ *
15
+ * ## Lifecycle
16
+ *
17
+ * ```
18
+ * const executor = new SdkExecutor({ model: 'sonnet' })
19
+ * await executor.init() // warm up (emits stage events)
20
+ * executor.execute(args, opts) // fast — session already running
21
+ * executor.execute(args, opts) // fast
22
+ * executor.close() // cleanup
23
+ * ```
24
+ *
25
+ * ## Initialization events
26
+ *
27
+ * Subscribe to stage events for UI feedback:
28
+ * ```
29
+ * executor.on('init:stage', (stage, message) => {
30
+ * console.log(`[${stage}] ${message}`)
31
+ * })
32
+ * executor.on('init:ready', () => console.log('Ready!'))
33
+ * ```
34
+ */
35
+ export class SdkExecutor extends EventEmitter {
36
+ sdkModule = null;
37
+ session = null;
38
+ _ready = false;
39
+ initPromise = null;
40
+ sdkOptions;
41
+ constructor(options) {
42
+ super();
43
+ this.sdkOptions = options;
44
+ }
45
+ /** Whether the session is initialized and ready for queries. */
46
+ get ready() {
47
+ return this._ready;
48
+ }
49
+ /**
50
+ * Initialize the SDK session (warm up).
51
+ *
52
+ * This imports the SDK, creates a persistent session, and waits for
53
+ * the `system/init` message confirming Claude Code is ready.
54
+ *
55
+ * Call this once at startup. Subsequent queries will be fast.
56
+ * Safe to call multiple times — only initializes once.
57
+ */
58
+ async init() {
59
+ if (this._ready)
60
+ return;
61
+ if (this.initPromise)
62
+ return this.initPromise;
63
+ this.initPromise = this.doInit();
64
+ return this.initPromise;
65
+ }
66
+ async execute(args, options) {
67
+ await this.ensureReady();
68
+ const prompt = extractPrompt(args);
69
+ await this.session.send(prompt);
70
+ let resultText = '';
71
+ let sessionId = '';
72
+ let usage = { inputTokens: 0, outputTokens: 0 };
73
+ let cost = null;
74
+ let durationMs = 0;
75
+ let structured = null;
76
+ for await (const msg of this.session.stream()) {
77
+ const parsed = this.mapMessage(msg);
78
+ if (!parsed)
79
+ continue;
80
+ if (parsed.type === 'text') {
81
+ resultText += parsed.text;
82
+ }
83
+ else if (parsed.type === 'result') {
84
+ resultText = parsed.text || resultText;
85
+ sessionId = parsed.sessionId;
86
+ usage = parsed.usage;
87
+ cost = parsed.cost;
88
+ durationMs = parsed.durationMs;
89
+ }
90
+ }
91
+ return {
92
+ text: resultText,
93
+ sessionId,
94
+ usage,
95
+ cost,
96
+ durationMs,
97
+ messages: [],
98
+ structured,
99
+ raw: {},
100
+ };
101
+ }
102
+ async *stream(args, options) {
103
+ await this.ensureReady();
104
+ const prompt = extractPrompt(args);
105
+ await this.session.send(prompt);
106
+ for await (const msg of this.session.stream()) {
107
+ const event = this.mapMessage(msg);
108
+ if (event)
109
+ yield event;
110
+ }
111
+ }
112
+ abort() {
113
+ // SDK sessions don't have a per-query abort — close the whole session
114
+ this.close();
115
+ }
116
+ /**
117
+ * Close the SDK session and free resources.
118
+ */
119
+ close() {
120
+ if (this.session) {
121
+ this.session.close();
122
+ this.session = null;
123
+ }
124
+ this._ready = false;
125
+ this.initPromise = null;
126
+ }
127
+ // ── Private ───────────────────────────────────────────────────────
128
+ async doInit() {
129
+ try {
130
+ // Stage 1: Import SDK
131
+ this.emit('init:stage', 'importing', 'Loading Claude Agent SDK...');
132
+ this.sdkModule = await import('@anthropic-ai/claude-agent-sdk');
133
+ // Stage 2: Create session
134
+ this.emit('init:stage', 'creating', 'Creating persistent session...');
135
+ const sessionOptions = {
136
+ model: this.sdkOptions.model ?? 'sonnet',
137
+ permissionMode: this.sdkOptions.permissionMode,
138
+ allowedTools: this.sdkOptions.allowedTools,
139
+ disallowedTools: this.sdkOptions.disallowedTools,
140
+ };
141
+ if (this.sdkOptions.pathToClaudeCodeExecutable) {
142
+ sessionOptions.pathToClaudeCodeExecutable = this.sdkOptions.pathToClaudeCodeExecutable;
143
+ }
144
+ if (this.sdkOptions.env) {
145
+ sessionOptions.env = { ...process.env, ...this.sdkOptions.env };
146
+ }
147
+ this.session = this.sdkModule.unstable_v2_createSession(sessionOptions);
148
+ // Stage 3: Warm up — send a no-op to trigger initialization, wait for init message
149
+ this.emit('init:stage', 'connecting', 'Waiting for Claude Code to initialize...');
150
+ // The session initializes on first send+stream
151
+ await this.session.send('.');
152
+ for await (const msg of this.session.stream()) {
153
+ if (msg.type === 'system' && 'subtype' in msg && msg.subtype === 'init') {
154
+ const sysMsg = msg;
155
+ this.emit('init:stage', 'connecting', `Connected: model=${sysMsg['model']}, tools=${sysMsg['tools']?.length ?? 0}`);
156
+ }
157
+ if (msg.type === 'result') {
158
+ break;
159
+ }
160
+ }
161
+ // Stage 4: Ready
162
+ this._ready = true;
163
+ this.emit('init:stage', 'ready', 'Session is warm and ready');
164
+ this.emit('init:ready');
165
+ }
166
+ catch (err) {
167
+ const error = err instanceof Error ? err : new Error(String(err));
168
+ this.emit('init:error', error);
169
+ throw error;
170
+ }
171
+ }
172
+ async ensureReady() {
173
+ if (!this._ready) {
174
+ await this.init();
175
+ }
176
+ }
177
+ /**
178
+ * Map an SDK message to our StreamEvent type.
179
+ */
180
+ mapMessage(msg) {
181
+ switch (msg.type) {
182
+ case 'assistant': {
183
+ const assistantMsg = msg;
184
+ const message = assistantMsg['message'];
185
+ const content = message?.['content'];
186
+ if (!content?.length)
187
+ return null;
188
+ const lastBlock = content[content.length - 1];
189
+ if (lastBlock['type'] === 'text' && typeof lastBlock['text'] === 'string') {
190
+ return { type: 'text', text: lastBlock['text'] };
191
+ }
192
+ if (lastBlock['type'] === 'tool_use') {
193
+ return {
194
+ type: 'tool_use',
195
+ toolName: String(lastBlock['name'] ?? ''),
196
+ toolInput: lastBlock['input'] ?? {},
197
+ };
198
+ }
199
+ return null;
200
+ }
201
+ case 'result': {
202
+ const result = msg;
203
+ const usage = result['usage'];
204
+ return {
205
+ type: 'result',
206
+ text: typeof result['result'] === 'string' ? result['result'] : '',
207
+ sessionId: String(result['session_id'] ?? ''),
208
+ usage: {
209
+ inputTokens: typeof usage?.['input_tokens'] === 'number' ? usage['input_tokens'] : 0,
210
+ outputTokens: typeof usage?.['output_tokens'] === 'number' ? usage['output_tokens'] : 0,
211
+ },
212
+ cost: typeof result['total_cost_usd'] === 'number' ? result['total_cost_usd'] : null,
213
+ durationMs: typeof result['duration_ms'] === 'number' ? result['duration_ms'] : 0,
214
+ };
215
+ }
216
+ default:
217
+ return null;
218
+ }
219
+ }
220
+ }
221
+ /**
222
+ * Extract the prompt string from a CLI args array.
223
+ * In our args format, the prompt is the first positional argument
224
+ * (after --print and --output-format flags).
225
+ */
226
+ function extractPrompt(args) {
227
+ // The prompt is typically the argument right after '--print', '--output-format', 'json/stream-json'
228
+ // In buildArgs: ['--print', '--output-format', 'json', <prompt>, ...flags]
229
+ // Find the first arg that doesn't start with '--' and isn't a flag value
230
+ let skipNext = false;
231
+ for (const arg of args) {
232
+ if (skipNext) {
233
+ skipNext = false;
234
+ continue;
235
+ }
236
+ if (arg.startsWith('--')) {
237
+ // Flags that take a value
238
+ if ([
239
+ '--output-format', '--model', '--fallback-model', '--permission-mode',
240
+ '--system-prompt', '--append-system-prompt', '--max-turns', '--max-budget-usd',
241
+ '--add-dir', '--mcp-config', '--agents', '--json-schema', '--worktree',
242
+ '--resume', '--session-id', '--allowedTools', '--disallowedTools',
243
+ ].includes(arg)) {
244
+ skipNext = true;
245
+ }
246
+ continue;
247
+ }
248
+ // Skip format values
249
+ if (arg === 'json' || arg === 'stream-json' || arg === 'text')
250
+ continue;
251
+ // This should be the prompt
252
+ return arg;
253
+ }
254
+ return '';
255
+ }
256
+ //# sourceMappingURL=sdk-executor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sdk-executor.js","sourceRoot":"","sources":["../../src/executor/sdk-executor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * # claude-connector
3
+ *
4
+ * Programmatic Node.js interface for Claude Code CLI.
5
+ *
6
+ * ## Quick start
7
+ *
8
+ * ```ts
9
+ * import { Claude } from 'claude-connector'
10
+ *
11
+ * const claude = new Claude({ model: 'sonnet' })
12
+ * const result = await claude.query('Find bugs in auth.ts')
13
+ * console.log(result.text)
14
+ * ```
15
+ *
16
+ * ## Architecture
17
+ *
18
+ * ```
19
+ * ┌─────────┐ ┌─────────────┐ ┌────────────┐ ┌─────────────┐
20
+ * │ Claude │────>│ ArgsBuilder │────>│ IExecutor │────>│ CLI Process │
21
+ * │ (facade) │ │ (options→ │ │ (abstract) │ │ (claude -p) │
22
+ * │ │ │ CLI args) │ │ │ │ │
23
+ * └─────────┘ └─────────────┘ └────────────┘ └─────────────┘
24
+ * │ ▲
25
+ * │ │
26
+ * ▼ ┌─────┴──────┐
27
+ * ┌─────────┐ │CliExecutor │ (default implementation)
28
+ * │ Session │ │ SdkExecutor │ (future)
29
+ * │ Scheduler│ │ HttpExecutor│ (future)
30
+ * └─────────┘ └────────────┘
31
+ * ```
32
+ *
33
+ * @module
34
+ */
35
+ export { Claude } from './client/claude.js';
36
+ export { Session } from './client/session.js';
37
+ export type { IExecutor, ExecuteOptions } from './executor/interface.js';
38
+ export { CliExecutor } from './executor/cli-executor.js';
39
+ export { SdkExecutor } from './executor/sdk-executor.js';
40
+ export type { SdkExecutorOptions, SdkExecutorEvents, InitStage } from './executor/sdk-executor.js';
41
+ export { Scheduler, ScheduledJob } from './scheduler/scheduler.js';
42
+ export type { ScheduledJobEvents } from './scheduler/scheduler.js';
43
+ export { buildArgs, mergeOptions, resolveEnv } from './builder/args-builder.js';
44
+ export type { ResolvedOptions } from './builder/args-builder.js';
45
+ export { parseJsonResult } from './parser/json-parser.js';
46
+ export { parseStreamLine } from './parser/stream-parser.js';
47
+ export { ClaudeConnectorError, CliNotFoundError, CliExecutionError, CliTimeoutError, ParseError, ValidationError, } from './errors/errors.js';
48
+ export type { ClientOptions, QueryOptions, PermissionMode, EffortLevel, McpServerConfig, AgentConfig, HookEntry, HookMatcher, HooksConfig, QueryResult, StreamEvent, StreamTextEvent, StreamToolUseEvent, StreamResultEvent, StreamErrorEvent, StreamSystemEvent, TokenUsage, Message, ContentBlock, TextBlock, ToolUseBlock, ToolResultBlock, SessionOptions, SessionInfo, } from './types/index.js';
49
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAG9C,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzE,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,YAAY,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAGnG,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACnE,YAAY,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAChF,YAAY,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAGjE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAG5D,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EACV,aAAa,EACb,YAAY,EACZ,cAAc,EACd,WAAW,EACX,eAAe,EACf,WAAW,EACX,SAAS,EACT,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,OAAO,EACP,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,eAAe,EACf,cAAc,EACd,WAAW,GACZ,MAAM,kBAAkB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,49 @@
1
+ /**
2
+ * # claude-connector
3
+ *
4
+ * Programmatic Node.js interface for Claude Code CLI.
5
+ *
6
+ * ## Quick start
7
+ *
8
+ * ```ts
9
+ * import { Claude } from 'claude-connector'
10
+ *
11
+ * const claude = new Claude({ model: 'sonnet' })
12
+ * const result = await claude.query('Find bugs in auth.ts')
13
+ * console.log(result.text)
14
+ * ```
15
+ *
16
+ * ## Architecture
17
+ *
18
+ * ```
19
+ * ┌─────────┐ ┌─────────────┐ ┌────────────┐ ┌─────────────┐
20
+ * │ Claude │────>│ ArgsBuilder │────>│ IExecutor │────>│ CLI Process │
21
+ * │ (facade) │ │ (options→ │ │ (abstract) │ │ (claude -p) │
22
+ * │ │ │ CLI args) │ │ │ │ │
23
+ * └─────────┘ └─────────────┘ └────────────┘ └─────────────┘
24
+ * │ ▲
25
+ * │ │
26
+ * ▼ ┌─────┴──────┐
27
+ * ┌─────────┐ │CliExecutor │ (default implementation)
28
+ * │ Session │ │ SdkExecutor │ (future)
29
+ * │ Scheduler│ │ HttpExecutor│ (future)
30
+ * └─────────┘ └────────────┘
31
+ * ```
32
+ *
33
+ * @module
34
+ */
35
+ // ── Main client ───────────────────────────────────────────────────
36
+ export { Claude } from './client/claude.js';
37
+ export { Session } from './client/session.js';
38
+ export { CliExecutor } from './executor/cli-executor.js';
39
+ export { SdkExecutor } from './executor/sdk-executor.js';
40
+ // ── Scheduler ─────────────────────────────────────────────────────
41
+ export { Scheduler, ScheduledJob } from './scheduler/scheduler.js';
42
+ // ── Builder ───────────────────────────────────────────────────────
43
+ export { buildArgs, mergeOptions, resolveEnv } from './builder/args-builder.js';
44
+ // ── Parsers ───────────────────────────────────────────────────────
45
+ export { parseJsonResult } from './parser/json-parser.js';
46
+ export { parseStreamLine } from './parser/stream-parser.js';
47
+ // ── Errors ────────────────────────────────────────────────────────
48
+ export { ClaudeConnectorError, CliNotFoundError, CliExecutionError, CliTimeoutError, ParseError, ValidationError, } from './errors/errors.js';
49
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAEH,qEAAqE;AACrE,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAI9C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAGzD,qEAAqE;AACrE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAGnE,qEAAqE;AACrE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAGhF,qEAAqE;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,qEAAqE;AACrE,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,UAAU,EACV,eAAe,GAChB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { parseJsonResult } from './json-parser.js';
2
+ export { parseStreamLine } from './stream-parser.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { parseJsonResult } from './json-parser.js';
2
+ export { parseStreamLine } from './stream-parser.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parser/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { QueryResult } from '../types/index.js';
2
+ /**
3
+ * Parses the JSON output from `claude -p --output-format json`.
4
+ *
5
+ * ## Expected CLI output structure
6
+ *
7
+ * ```json
8
+ * {
9
+ * "session_id": "uuid",
10
+ * "result": "text response",
11
+ * "messages": [...],
12
+ * "usage": { "input_tokens": N, "output_tokens": N },
13
+ * "duration_ms": N,
14
+ * "total_cost_usd": N | null
15
+ * }
16
+ * ```
17
+ *
18
+ * The parser is intentionally lenient — it extracts known fields and passes
19
+ * the rest through as `raw`. This way new CLI fields don't break the parser.
20
+ */
21
+ export declare function parseJsonResult(stdout: string): QueryResult;
22
+ //# sourceMappingURL=json-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-parser.d.ts","sourceRoot":"","sources":["../../src/parser/json-parser.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAuB,MAAM,mBAAmB,CAAC;AAE1E;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,CA0B3D"}
@@ -0,0 +1,87 @@
1
+ import { ParseError } from '../errors/errors.js';
2
+ /**
3
+ * Parses the JSON output from `claude -p --output-format json`.
4
+ *
5
+ * ## Expected CLI output structure
6
+ *
7
+ * ```json
8
+ * {
9
+ * "session_id": "uuid",
10
+ * "result": "text response",
11
+ * "messages": [...],
12
+ * "usage": { "input_tokens": N, "output_tokens": N },
13
+ * "duration_ms": N,
14
+ * "total_cost_usd": N | null
15
+ * }
16
+ * ```
17
+ *
18
+ * The parser is intentionally lenient — it extracts known fields and passes
19
+ * the rest through as `raw`. This way new CLI fields don't break the parser.
20
+ */
21
+ export function parseJsonResult(stdout) {
22
+ const trimmed = stdout.trim();
23
+ if (!trimmed) {
24
+ throw new ParseError('Empty output from CLI', stdout);
25
+ }
26
+ let json;
27
+ try {
28
+ json = JSON.parse(trimmed);
29
+ }
30
+ catch {
31
+ throw new ParseError(`Failed to parse CLI JSON output: ${trimmed.slice(0, 200)}`, stdout);
32
+ }
33
+ const usage = parseUsage(json['usage']);
34
+ const messages = parseMessages(json['messages']);
35
+ return {
36
+ text: typeof json['result'] === 'string' ? json['result'] : extractText(json),
37
+ sessionId: String(json['session_id'] ?? ''),
38
+ usage,
39
+ cost: typeof json['total_cost_usd'] === 'number' ? json['total_cost_usd'] : null,
40
+ durationMs: typeof json['duration_ms'] === 'number' ? json['duration_ms'] : 0,
41
+ messages,
42
+ structured: json['structured_output'] ?? null,
43
+ raw: json,
44
+ };
45
+ }
46
+ function parseUsage(raw) {
47
+ if (raw && typeof raw === 'object') {
48
+ const obj = raw;
49
+ return {
50
+ inputTokens: typeof obj['input_tokens'] === 'number' ? obj['input_tokens'] : 0,
51
+ outputTokens: typeof obj['output_tokens'] === 'number' ? obj['output_tokens'] : 0,
52
+ };
53
+ }
54
+ return { inputTokens: 0, outputTokens: 0 };
55
+ }
56
+ function parseMessages(raw) {
57
+ if (!Array.isArray(raw))
58
+ return [];
59
+ return raw.map((msg) => ({
60
+ role: msg['role'],
61
+ content: typeof msg['content'] === 'string' ? msg['content'] : msg['content'],
62
+ }));
63
+ }
64
+ /**
65
+ * Fallback text extraction when 'result' field is missing.
66
+ * Looks for the last assistant message content.
67
+ */
68
+ function extractText(json) {
69
+ const messages = json['messages'];
70
+ if (!Array.isArray(messages))
71
+ return '';
72
+ for (let i = messages.length - 1; i >= 0; i--) {
73
+ const msg = messages[i];
74
+ if (msg['role'] === 'assistant') {
75
+ if (typeof msg['content'] === 'string')
76
+ return msg['content'];
77
+ if (Array.isArray(msg['content'])) {
78
+ const textBlocks = msg['content']
79
+ .filter((b) => b['type'] === 'text')
80
+ .map((b) => b['text']);
81
+ return textBlocks.join('');
82
+ }
83
+ }
84
+ }
85
+ return '';
86
+ }
87
+ //# sourceMappingURL=json-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-parser.js","sourceRoot":"","sources":["../../src/parser/json-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { StreamEvent } from '../types/index.js';
2
+ /**
3
+ * Parses a single line of NDJSON from `claude -p --output-format stream-json`.
4
+ *
5
+ * ## Stream format
6
+ *
7
+ * Each line is a self-contained JSON object. The structure varies:
8
+ *
9
+ * ```jsonl
10
+ * {"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"..."}]}}
11
+ * {"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","name":"Read","input":{...}}]}}
12
+ * {"type":"result","session_id":"...","usage":{...},"duration_ms":...}
13
+ * ```
14
+ *
15
+ * The parser maps these into the typed {@link StreamEvent} union.
16
+ * Unknown event types are forwarded as `system` events for extensibility.
17
+ *
18
+ * @returns Parsed event, or `null` if the line should be skipped.
19
+ */
20
+ export declare function parseStreamLine(line: string): StreamEvent | null;
21
+ //# sourceMappingURL=stream-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-parser.d.ts","sourceRoot":"","sources":["../../src/parser/stream-parser.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAiChE"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Parses a single line of NDJSON from `claude -p --output-format stream-json`.
3
+ *
4
+ * ## Stream format
5
+ *
6
+ * Each line is a self-contained JSON object. The structure varies:
7
+ *
8
+ * ```jsonl
9
+ * {"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"..."}]}}
10
+ * {"type":"assistant","message":{"role":"assistant","content":[{"type":"tool_use","name":"Read","input":{...}}]}}
11
+ * {"type":"result","session_id":"...","usage":{...},"duration_ms":...}
12
+ * ```
13
+ *
14
+ * The parser maps these into the typed {@link StreamEvent} union.
15
+ * Unknown event types are forwarded as `system` events for extensibility.
16
+ *
17
+ * @returns Parsed event, or `null` if the line should be skipped.
18
+ */
19
+ export function parseStreamLine(line) {
20
+ let json;
21
+ try {
22
+ json = JSON.parse(line);
23
+ }
24
+ catch {
25
+ // Malformed line — skip gracefully
26
+ return null;
27
+ }
28
+ const type = json['type'];
29
+ if (type === 'result') {
30
+ return parseResultEvent(json);
31
+ }
32
+ if (type === 'assistant') {
33
+ return parseAssistantEvent(json);
34
+ }
35
+ if (type === 'error') {
36
+ return {
37
+ type: 'error',
38
+ message: String(json['message'] ?? json['error'] ?? 'Unknown error'),
39
+ code: typeof json['code'] === 'string' ? json['code'] : undefined,
40
+ };
41
+ }
42
+ // Forward unknown types as system events
43
+ return {
44
+ type: 'system',
45
+ subtype: String(type ?? 'unknown'),
46
+ data: json,
47
+ };
48
+ }
49
+ function parseResultEvent(json) {
50
+ const usage = json['usage'];
51
+ return {
52
+ type: 'result',
53
+ text: typeof json['result'] === 'string' ? json['result'] : '',
54
+ sessionId: String(json['session_id'] ?? ''),
55
+ usage: {
56
+ inputTokens: typeof usage?.['input_tokens'] === 'number' ? usage['input_tokens'] : 0,
57
+ outputTokens: typeof usage?.['output_tokens'] === 'number' ? usage['output_tokens'] : 0,
58
+ },
59
+ cost: typeof json['total_cost_usd'] === 'number' ? json['total_cost_usd'] : null,
60
+ durationMs: typeof json['duration_ms'] === 'number' ? json['duration_ms'] : 0,
61
+ };
62
+ }
63
+ function parseAssistantEvent(json) {
64
+ const message = json['message'];
65
+ if (!message)
66
+ return null;
67
+ const content = message['content'];
68
+ if (!Array.isArray(content) || content.length === 0)
69
+ return null;
70
+ // Process the last content block (most relevant for streaming)
71
+ const block = content[content.length - 1];
72
+ if (block['type'] === 'text' && typeof block['text'] === 'string') {
73
+ return { type: 'text', text: block['text'] };
74
+ }
75
+ if (block['type'] === 'tool_use') {
76
+ return {
77
+ type: 'tool_use',
78
+ toolName: String(block['name'] ?? ''),
79
+ toolInput: block['input'] ?? {},
80
+ };
81
+ }
82
+ return null;
83
+ }
84
+ //# sourceMappingURL=stream-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stream-parser.js","sourceRoot":"","sources":["../../src/parser/stream-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { Scheduler, ScheduledJob, type ScheduledJobEvents } from './scheduler.js';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scheduler/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { Scheduler, ScheduledJob } from './scheduler.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scheduler/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,YAAY,EAA2B,MAAM,gBAAgB,CAAC"}