@cleocode/adapters 2026.4.92 → 2026.4.94
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/dist/index.js +40795 -18064
- package/dist/index.js.map +4 -4
- package/dist/providers/claude-sdk/index.d.ts +10 -4
- package/dist/providers/claude-sdk/index.d.ts.map +1 -1
- package/dist/providers/claude-sdk/spawn.d.ts +29 -28
- package/dist/providers/claude-sdk/spawn.d.ts.map +1 -1
- package/dist/providers/openai-sdk/adapter.d.ts +18 -17
- package/dist/providers/openai-sdk/adapter.d.ts.map +1 -1
- package/dist/providers/openai-sdk/guardrails.d.ts +71 -18
- package/dist/providers/openai-sdk/guardrails.d.ts.map +1 -1
- package/dist/providers/openai-sdk/handoff.d.ts +51 -21
- package/dist/providers/openai-sdk/handoff.d.ts.map +1 -1
- package/dist/providers/openai-sdk/index.d.ts +8 -5
- package/dist/providers/openai-sdk/index.d.ts.map +1 -1
- package/dist/providers/openai-sdk/install.d.ts +1 -1
- package/dist/providers/openai-sdk/spawn.d.ts +54 -21
- package/dist/providers/openai-sdk/spawn.d.ts.map +1 -1
- package/dist/providers/openai-sdk/tracing.d.ts +87 -21
- package/dist/providers/openai-sdk/tracing.d.ts.map +1 -1
- package/dist/providers/shared/sdk-result-mapper.d.ts +9 -7
- package/dist/providers/shared/sdk-result-mapper.d.ts.map +1 -1
- package/package.json +6 -5
- package/src/__tests__/harness-interop.test.ts +451 -0
- package/src/providers/claude-sdk/__tests__/spawn.test.ts +100 -265
- package/src/providers/claude-sdk/index.ts +10 -4
- package/src/providers/claude-sdk/spawn.ts +69 -106
- package/src/providers/openai-sdk/__tests__/openai-sdk-spawn.test.ts +134 -103
- package/src/providers/openai-sdk/adapter.ts +19 -18
- package/src/providers/openai-sdk/guardrails.ts +106 -25
- package/src/providers/openai-sdk/handoff.ts +73 -37
- package/src/providers/openai-sdk/index.ts +28 -4
- package/src/providers/openai-sdk/install.ts +1 -1
- package/src/providers/openai-sdk/manifest.json +4 -4
- package/src/providers/openai-sdk/spawn.ts +213 -48
- package/src/providers/openai-sdk/tracing.ts +105 -22
- package/src/providers/shared/sdk-result-mapper.ts +9 -7
|
@@ -1,32 +1,50 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tests for ClaudeSDKSpawnProvider
|
|
2
|
+
* Tests for ClaudeSDKSpawnProvider — Vercel AI SDK edition.
|
|
3
3
|
*
|
|
4
|
-
* The SDK `
|
|
4
|
+
* The Vercel AI SDK `generateText` call is mocked via a CLEO-native mock
|
|
5
|
+
* that returns a deterministic response. Tests run without a real
|
|
5
6
|
* ANTHROPIC_API_KEY or network connection.
|
|
6
7
|
*
|
|
7
|
-
* @task T581
|
|
8
|
+
* @task T581 (original)
|
|
9
|
+
* @task T933 (SDK consolidation — Vercel AI SDK migration)
|
|
8
10
|
*/
|
|
9
11
|
|
|
10
12
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
11
13
|
import { ClaudeSDKSpawnProvider } from '../spawn.js';
|
|
12
14
|
|
|
13
15
|
// ---------------------------------------------------------------------------
|
|
14
|
-
// Mock
|
|
16
|
+
// Mock Vercel AI SDK surface
|
|
15
17
|
// ---------------------------------------------------------------------------
|
|
16
18
|
|
|
17
|
-
/**
|
|
18
|
-
|
|
19
|
+
/** Shared mock state tracked across tests. */
|
|
20
|
+
const { mockState } = vi.hoisted(() => {
|
|
19
21
|
return {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
22
|
+
mockState: {
|
|
23
|
+
text: 'mocked claude response',
|
|
24
|
+
shouldThrow: false,
|
|
25
|
+
lastCall: null as null | { model: unknown; prompt: string },
|
|
24
26
|
},
|
|
25
27
|
};
|
|
26
|
-
}
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Mock the '@ai-sdk/anthropic' surface: createAnthropic returns a factory
|
|
31
|
+
// function that produces a LanguageModel stand-in. CLEO only consumes the
|
|
32
|
+
// return value as an opaque handle passed to generateText.
|
|
33
|
+
vi.mock('@ai-sdk/anthropic', () => ({
|
|
34
|
+
createAnthropic: vi.fn((_config: { apiKey: string }) => {
|
|
35
|
+
return (modelId: string) => ({ __cleoMockModel: true, modelId });
|
|
36
|
+
}),
|
|
37
|
+
}));
|
|
27
38
|
|
|
28
|
-
|
|
29
|
-
|
|
39
|
+
// Mock 'ai' generateText to drive deterministic test outputs.
|
|
40
|
+
vi.mock('ai', () => ({
|
|
41
|
+
generateText: vi.fn(async ({ model, prompt }: { model: unknown; prompt: string }) => {
|
|
42
|
+
mockState.lastCall = { model, prompt };
|
|
43
|
+
if (mockState.shouldThrow) {
|
|
44
|
+
throw new Error('mock AI SDK error');
|
|
45
|
+
}
|
|
46
|
+
return { text: mockState.text };
|
|
47
|
+
}),
|
|
30
48
|
}));
|
|
31
49
|
|
|
32
50
|
// Mock CANT enrichment so tests don't need the cleo CLI.
|
|
@@ -36,15 +54,6 @@ vi.mock('../../../cant-context.js', () => ({
|
|
|
36
54
|
),
|
|
37
55
|
}));
|
|
38
56
|
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
|
-
// Helpers
|
|
41
|
-
// ---------------------------------------------------------------------------
|
|
42
|
-
|
|
43
|
-
async function getQueryMock() {
|
|
44
|
-
const { query } = await import('@anthropic-ai/claude-agent-sdk');
|
|
45
|
-
return query as ReturnType<typeof vi.fn>;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
57
|
// ---------------------------------------------------------------------------
|
|
49
58
|
// Tests
|
|
50
59
|
// ---------------------------------------------------------------------------
|
|
@@ -54,10 +63,14 @@ describe('ClaudeSDKSpawnProvider', () => {
|
|
|
54
63
|
|
|
55
64
|
beforeEach(() => {
|
|
56
65
|
provider = new ClaudeSDKSpawnProvider();
|
|
66
|
+
mockState.shouldThrow = false;
|
|
67
|
+
mockState.text = 'mocked claude response';
|
|
68
|
+
mockState.lastCall = null;
|
|
57
69
|
});
|
|
58
70
|
|
|
59
71
|
afterEach(() => {
|
|
60
72
|
vi.restoreAllMocks();
|
|
73
|
+
mockState.shouldThrow = false;
|
|
61
74
|
});
|
|
62
75
|
|
|
63
76
|
// -------------------------------------------------------------------------
|
|
@@ -71,13 +84,9 @@ describe('ClaudeSDKSpawnProvider', () => {
|
|
|
71
84
|
});
|
|
72
85
|
|
|
73
86
|
it('returns false when no credentials are available', async () => {
|
|
74
|
-
// Mock fs.existsSync to return false for all key paths so no tier
|
|
75
|
-
// resolves (env var, stored key file, or OAuth credentials file).
|
|
76
|
-
const { existsSync } = await import('node:fs');
|
|
77
87
|
const saved = process.env.ANTHROPIC_API_KEY;
|
|
78
88
|
delete process.env.ANTHROPIC_API_KEY;
|
|
79
|
-
|
|
80
|
-
// Use vi.mock for node:fs to prevent reading real ~/.claude/.credentials.json
|
|
89
|
+
// Mock node:fs so the stored-key file and OAuth creds both fail to resolve.
|
|
81
90
|
vi.doMock('node:fs', () => ({
|
|
82
91
|
existsSync: vi.fn().mockReturnValue(false),
|
|
83
92
|
readFileSync: vi.fn().mockImplementation(() => {
|
|
@@ -85,7 +94,6 @@ describe('ClaudeSDKSpawnProvider', () => {
|
|
|
85
94
|
}),
|
|
86
95
|
}));
|
|
87
96
|
try {
|
|
88
|
-
// Re-import spawn module with mocked fs to get fresh resolver state
|
|
89
97
|
vi.resetModules();
|
|
90
98
|
const { ClaudeSDKSpawnProvider: FreshProvider } = await import('../spawn.js');
|
|
91
99
|
const freshProvider = new FreshProvider();
|
|
@@ -153,48 +161,15 @@ describe('ClaudeSDKSpawnProvider', () => {
|
|
|
153
161
|
// -------------------------------------------------------------------------
|
|
154
162
|
|
|
155
163
|
describe('spawn() — success', () => {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
mcp_servers: [],
|
|
166
|
-
model: 'claude-sonnet-4-5',
|
|
167
|
-
permissionMode: 'bypassPermissions',
|
|
168
|
-
cwd: '/tmp',
|
|
169
|
-
slash_commands: [],
|
|
170
|
-
output_style: 'auto',
|
|
171
|
-
},
|
|
172
|
-
{
|
|
173
|
-
type: 'assistant',
|
|
174
|
-
session_id: 'sess-abc',
|
|
175
|
-
message: {
|
|
176
|
-
content: [
|
|
177
|
-
{ type: 'text', text: 'Hello from' },
|
|
178
|
-
{ type: 'text', text: ' the SDK.' },
|
|
179
|
-
],
|
|
180
|
-
},
|
|
181
|
-
},
|
|
182
|
-
{
|
|
183
|
-
type: 'result',
|
|
184
|
-
subtype: 'success',
|
|
185
|
-
session_id: 'sess-abc',
|
|
186
|
-
result: 'Done.',
|
|
187
|
-
is_error: false,
|
|
188
|
-
duration_ms: 100,
|
|
189
|
-
duration_api_ms: 80,
|
|
190
|
-
num_turns: 1,
|
|
191
|
-
total_cost_usd: 0.001,
|
|
192
|
-
usage: {},
|
|
193
|
-
modelUsage: {},
|
|
194
|
-
permission_denials: [],
|
|
195
|
-
},
|
|
196
|
-
]),
|
|
197
|
-
);
|
|
164
|
+
beforeEach(() => {
|
|
165
|
+
process.env.ANTHROPIC_API_KEY = 'test-key';
|
|
166
|
+
});
|
|
167
|
+
afterEach(() => {
|
|
168
|
+
delete process.env.ANTHROPIC_API_KEY;
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it('returns completed status with generated output', async () => {
|
|
172
|
+
mockState.text = 'Hello from the SDK.';
|
|
198
173
|
|
|
199
174
|
const result = await provider.spawn({
|
|
200
175
|
taskId: 'T001',
|
|
@@ -205,113 +180,44 @@ describe('ClaudeSDKSpawnProvider', () => {
|
|
|
205
180
|
expect(result.status).toBe('completed');
|
|
206
181
|
expect(result.providerId).toBe('claude-sdk');
|
|
207
182
|
expect(result.taskId).toBe('T001');
|
|
208
|
-
expect(result.output).
|
|
209
|
-
expect(result.output).toContain('the SDK.');
|
|
210
|
-
expect(result.output).toContain('Done.');
|
|
183
|
+
expect(result.output).toBe('Hello from the SDK.');
|
|
211
184
|
expect(result.exitCode).toBe(0);
|
|
212
185
|
expect(result.startTime).toBeTruthy();
|
|
213
186
|
expect(result.endTime).toBeTruthy();
|
|
214
187
|
});
|
|
215
188
|
|
|
216
|
-
it('
|
|
217
|
-
const queryMock = await getQueryMock();
|
|
218
|
-
queryMock.mockReturnValue(
|
|
219
|
-
makeQueryIterator([
|
|
220
|
-
{
|
|
221
|
-
type: 'result',
|
|
222
|
-
subtype: 'success',
|
|
223
|
-
session_id: 'sess-xyz',
|
|
224
|
-
result: '',
|
|
225
|
-
is_error: false,
|
|
226
|
-
duration_ms: 10,
|
|
227
|
-
duration_api_ms: 8,
|
|
228
|
-
num_turns: 1,
|
|
229
|
-
total_cost_usd: 0,
|
|
230
|
-
usage: {},
|
|
231
|
-
modelUsage: {},
|
|
232
|
-
permission_denials: [],
|
|
233
|
-
},
|
|
234
|
-
]),
|
|
235
|
-
);
|
|
236
|
-
|
|
189
|
+
it('forwards the enriched prompt to generateText', async () => {
|
|
237
190
|
await provider.spawn({
|
|
238
191
|
taskId: 'T002',
|
|
239
|
-
prompt: '
|
|
240
|
-
options: { toolAllowlist: ['Read', 'Grep'] },
|
|
192
|
+
prompt: 'Describe the project.',
|
|
241
193
|
});
|
|
242
194
|
|
|
243
|
-
expect(
|
|
244
|
-
expect.objectContaining({
|
|
245
|
-
options: expect.objectContaining({
|
|
246
|
-
allowedTools: ['Read', 'Grep'],
|
|
247
|
-
}),
|
|
248
|
-
}),
|
|
249
|
-
);
|
|
195
|
+
expect(mockState.lastCall?.prompt).toBe('Describe the project.');
|
|
250
196
|
});
|
|
251
197
|
|
|
252
|
-
it('uses default
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
duration_ms: 10,
|
|
263
|
-
duration_api_ms: 8,
|
|
264
|
-
num_turns: 1,
|
|
265
|
-
total_cost_usd: 0,
|
|
266
|
-
usage: {},
|
|
267
|
-
modelUsage: {},
|
|
268
|
-
permission_denials: [],
|
|
269
|
-
},
|
|
270
|
-
]),
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
await provider.spawn({ taskId: 'T003', prompt: 'Default tools.' });
|
|
274
|
-
|
|
275
|
-
expect(queryMock).toHaveBeenCalledWith(
|
|
276
|
-
expect.objectContaining({
|
|
277
|
-
options: expect.objectContaining({
|
|
278
|
-
allowedTools: expect.arrayContaining(['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep']),
|
|
279
|
-
}),
|
|
280
|
-
}),
|
|
281
|
-
);
|
|
198
|
+
it('uses the default model when none is specified', async () => {
|
|
199
|
+
await provider.spawn({
|
|
200
|
+
taskId: 'T003',
|
|
201
|
+
prompt: 'Default model.',
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const model = mockState.lastCall?.model as
|
|
205
|
+
| { __cleoMockModel: true; modelId: string }
|
|
206
|
+
| undefined;
|
|
207
|
+
expect(model?.modelId).toBe('claude-sonnet-4-5');
|
|
282
208
|
});
|
|
283
209
|
|
|
284
|
-
it('
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
duration_api_ms: 4,
|
|
296
|
-
num_turns: 1,
|
|
297
|
-
total_cost_usd: 0,
|
|
298
|
-
usage: {},
|
|
299
|
-
modelUsage: {},
|
|
300
|
-
permission_denials: [],
|
|
301
|
-
},
|
|
302
|
-
]),
|
|
303
|
-
);
|
|
304
|
-
|
|
305
|
-
await provider.spawn({ taskId: 'T004', prompt: 'Permissions.' });
|
|
306
|
-
|
|
307
|
-
expect(queryMock).toHaveBeenCalledWith(
|
|
308
|
-
expect.objectContaining({
|
|
309
|
-
options: expect.objectContaining({
|
|
310
|
-
permissionMode: 'bypassPermissions',
|
|
311
|
-
allowDangerouslySkipPermissions: true,
|
|
312
|
-
}),
|
|
313
|
-
}),
|
|
314
|
-
);
|
|
210
|
+
it('uses the requested model when provided in options', async () => {
|
|
211
|
+
await provider.spawn({
|
|
212
|
+
taskId: 'T004',
|
|
213
|
+
prompt: 'Override model.',
|
|
214
|
+
options: { model: 'claude-sonnet-4-6' },
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const model = mockState.lastCall?.model as
|
|
218
|
+
| { __cleoMockModel: true; modelId: string }
|
|
219
|
+
| undefined;
|
|
220
|
+
expect(model?.modelId).toBe('claude-sonnet-4-6');
|
|
315
221
|
});
|
|
316
222
|
});
|
|
317
223
|
|
|
@@ -320,114 +226,43 @@ describe('ClaudeSDKSpawnProvider', () => {
|
|
|
320
226
|
// -------------------------------------------------------------------------
|
|
321
227
|
|
|
322
228
|
describe('spawn() — error handling', () => {
|
|
323
|
-
it('returns failed status
|
|
324
|
-
const
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
expect(result.error).toContain('Something went wrong');
|
|
229
|
+
it('returns failed status when no Anthropic credentials exist', async () => {
|
|
230
|
+
const saved = process.env.ANTHROPIC_API_KEY;
|
|
231
|
+
delete process.env.ANTHROPIC_API_KEY;
|
|
232
|
+
vi.doMock('node:fs', () => ({
|
|
233
|
+
existsSync: vi.fn().mockReturnValue(false),
|
|
234
|
+
readFileSync: vi.fn().mockImplementation(() => {
|
|
235
|
+
throw new Error('mocked: file not found');
|
|
236
|
+
}),
|
|
237
|
+
}));
|
|
238
|
+
try {
|
|
239
|
+
vi.resetModules();
|
|
240
|
+
const { ClaudeSDKSpawnProvider: FreshProvider } = await import('../spawn.js');
|
|
241
|
+
const freshProvider = new FreshProvider();
|
|
242
|
+
const result = await freshProvider.spawn({
|
|
243
|
+
taskId: 'T005',
|
|
244
|
+
prompt: 'No creds.',
|
|
245
|
+
});
|
|
246
|
+
expect(result.status).toBe('failed');
|
|
247
|
+
expect(result.exitCode).toBe(1);
|
|
248
|
+
expect(result.error).toContain('No Anthropic credentials');
|
|
249
|
+
} finally {
|
|
250
|
+
vi.resetModules();
|
|
251
|
+
vi.doUnmock('node:fs');
|
|
252
|
+
if (saved !== undefined) process.env.ANTHROPIC_API_KEY = saved;
|
|
253
|
+
}
|
|
349
254
|
});
|
|
350
255
|
|
|
351
|
-
it('returns failed status when
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
throw new Error('Network error');
|
|
355
|
-
});
|
|
256
|
+
it('returns failed status when generateText throws', async () => {
|
|
257
|
+
process.env.ANTHROPIC_API_KEY = 'test-key';
|
|
258
|
+
mockState.shouldThrow = true;
|
|
356
259
|
|
|
357
260
|
const result = await provider.spawn({ taskId: 'T006', prompt: 'Throw.' });
|
|
358
261
|
|
|
359
262
|
expect(result.status).toBe('failed');
|
|
360
263
|
expect(result.exitCode).toBe(1);
|
|
361
|
-
expect(result.error).toContain('
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
it('returns failed status when error_max_turns reached', async () => {
|
|
365
|
-
const queryMock = await getQueryMock();
|
|
366
|
-
queryMock.mockReturnValue(
|
|
367
|
-
makeQueryIterator([
|
|
368
|
-
{
|
|
369
|
-
type: 'result',
|
|
370
|
-
subtype: 'error_max_turns',
|
|
371
|
-
session_id: 'sess-max',
|
|
372
|
-
is_error: true,
|
|
373
|
-
errors: [],
|
|
374
|
-
duration_ms: 200,
|
|
375
|
-
duration_api_ms: 180,
|
|
376
|
-
num_turns: 10,
|
|
377
|
-
total_cost_usd: 0.05,
|
|
378
|
-
usage: {},
|
|
379
|
-
modelUsage: {},
|
|
380
|
-
permission_denials: [],
|
|
381
|
-
},
|
|
382
|
-
]),
|
|
383
|
-
);
|
|
384
|
-
|
|
385
|
-
const result = await provider.spawn({ taskId: 'T007', prompt: 'Max turns.' });
|
|
386
|
-
|
|
387
|
-
expect(result.status).toBe('failed');
|
|
388
|
-
expect(result.exitCode).toBe(1);
|
|
389
|
-
});
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
// -------------------------------------------------------------------------
|
|
393
|
-
// Session resume
|
|
394
|
-
// -------------------------------------------------------------------------
|
|
395
|
-
|
|
396
|
-
describe('spawn() — session resume', () => {
|
|
397
|
-
it('passes resume option when resumeSessionId is provided', async () => {
|
|
398
|
-
const queryMock = await getQueryMock();
|
|
399
|
-
queryMock.mockReturnValue(
|
|
400
|
-
makeQueryIterator([
|
|
401
|
-
{
|
|
402
|
-
type: 'result',
|
|
403
|
-
subtype: 'success',
|
|
404
|
-
session_id: 'sess-resume',
|
|
405
|
-
result: 'resumed',
|
|
406
|
-
is_error: false,
|
|
407
|
-
duration_ms: 20,
|
|
408
|
-
duration_api_ms: 15,
|
|
409
|
-
num_turns: 1,
|
|
410
|
-
total_cost_usd: 0,
|
|
411
|
-
usage: {},
|
|
412
|
-
modelUsage: {},
|
|
413
|
-
permission_denials: [],
|
|
414
|
-
},
|
|
415
|
-
]),
|
|
416
|
-
);
|
|
417
|
-
|
|
418
|
-
await provider.spawn({
|
|
419
|
-
taskId: 'T008',
|
|
420
|
-
prompt: 'Continue work.',
|
|
421
|
-
options: { resumeSessionId: 'prior-session-id' },
|
|
422
|
-
});
|
|
423
|
-
|
|
424
|
-
expect(queryMock).toHaveBeenCalledWith(
|
|
425
|
-
expect.objectContaining({
|
|
426
|
-
options: expect.objectContaining({
|
|
427
|
-
resume: 'prior-session-id',
|
|
428
|
-
}),
|
|
429
|
-
}),
|
|
430
|
-
);
|
|
264
|
+
expect(result.error).toContain('mock AI SDK error');
|
|
265
|
+
delete process.env.ANTHROPIC_API_KEY;
|
|
431
266
|
});
|
|
432
267
|
});
|
|
433
268
|
});
|
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @packageDocumentation
|
|
3
3
|
*
|
|
4
|
-
* Claude
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Claude SDK spawn provider for CLEO — Vercel AI SDK edition.
|
|
5
|
+
*
|
|
6
|
+
* Uses `@ai-sdk/anthropic` via the Vercel AI SDK (`ai` v6) instead of the
|
|
7
|
+
* legacy `@anthropic-ai/claude-agent-sdk`. CLEO retains its own orchestration
|
|
8
|
+
* primitives (composeSpawnPayload, playbook runtime, agent registry); this
|
|
9
|
+
* provider exposes the LLM bridge for programmatic subagent execution with
|
|
10
|
+
* structured output and session tracking.
|
|
7
11
|
*
|
|
8
12
|
* Enabled via `provider.claude.mode = 'sdk'` in CLEO config.
|
|
9
13
|
*
|
|
10
|
-
* @task T581
|
|
14
|
+
* @task T581 (original)
|
|
15
|
+
* @task T933 (SDK consolidation — Vercel AI SDK migration)
|
|
16
|
+
* @see ADR-052 — SDK consolidation decision
|
|
11
17
|
*/
|
|
12
18
|
|
|
13
19
|
export type { McpServerMap, McpStdioConfig } from './mcp-registry.js';
|