@agentskit/adapters 0.16.0 → 0.17.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 +129 -2
- package/dist/cli/index.cjs +220 -59
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +146 -11
- package/dist/cli/index.d.ts +146 -11
- package/dist/cli/index.js +214 -59
- package/dist/cli/index.js.map +1 -1
- package/dist/langchain-bridge.cjs +232 -0
- package/dist/langchain-bridge.cjs.map +1 -0
- package/dist/langchain-bridge.d.cts +77 -0
- package/dist/langchain-bridge.d.ts +77 -0
- package/dist/langchain-bridge.js +229 -0
- package/dist/langchain-bridge.js.map +1 -0
- package/package.json +18 -6
package/dist/cli/index.js
CHANGED
|
@@ -318,6 +318,162 @@ async function abortableWrite(handle, input, signal) {
|
|
|
318
318
|
if (onError) handle.child.stdin.removeListener("error", onError);
|
|
319
319
|
}
|
|
320
320
|
}
|
|
321
|
+
var cliError = (message, cause) => new AdapterError({ code: ErrorCodes.AK_ADAPTER_STREAM_FAILED, message, cause });
|
|
322
|
+
function isRecord(value) {
|
|
323
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
324
|
+
}
|
|
325
|
+
function parseCliJsonResponse(value) {
|
|
326
|
+
if (!isRecord(value)) throw cliError("CLI JSON response must be an object");
|
|
327
|
+
const chunks = [];
|
|
328
|
+
if (typeof value.text === "string") chunks.push({ type: "text", content: value.text });
|
|
329
|
+
if (typeof value.reasoning === "string") chunks.push({ type: "reasoning", content: value.reasoning });
|
|
330
|
+
if (Array.isArray(value.toolCalls)) {
|
|
331
|
+
for (const item of value.toolCalls) {
|
|
332
|
+
if (!isRecord(item) || typeof item.id !== "string" || typeof item.name !== "string" || typeof item.args !== "string") {
|
|
333
|
+
throw cliError("CLI JSON toolCalls must contain string id, name, and args fields");
|
|
334
|
+
}
|
|
335
|
+
JSON.parse(item.args);
|
|
336
|
+
chunks.push({ type: "tool_call", toolCall: { id: item.id, name: item.name, args: item.args } });
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
if (value.usage !== void 0) {
|
|
340
|
+
if (!isRecord(value.usage)) {
|
|
341
|
+
throw cliError("CLI JSON usage must contain numeric promptTokens, completionTokens, and totalTokens");
|
|
342
|
+
}
|
|
343
|
+
const promptTokens = value.usage.promptTokens;
|
|
344
|
+
const completionTokens = value.usage.completionTokens;
|
|
345
|
+
const totalTokens = value.usage.totalTokens;
|
|
346
|
+
if (typeof promptTokens !== "number" || typeof completionTokens !== "number" || typeof totalTokens !== "number") {
|
|
347
|
+
throw cliError("CLI JSON usage must contain numeric promptTokens, completionTokens, and totalTokens");
|
|
348
|
+
}
|
|
349
|
+
chunks.push({ type: "usage", usage: { promptTokens, completionTokens, totalTokens } });
|
|
350
|
+
}
|
|
351
|
+
if (value.metadata !== void 0) {
|
|
352
|
+
if (!isRecord(value.metadata)) throw cliError("CLI JSON metadata must be an object");
|
|
353
|
+
if (chunks.length === 0) throw cliError("CLI JSON response contains no semantic output");
|
|
354
|
+
chunks[chunks.length - 1] = { ...chunks[chunks.length - 1], metadata: value.metadata };
|
|
355
|
+
}
|
|
356
|
+
if (chunks.length === 0) throw cliError("CLI JSON response contains no semantic output");
|
|
357
|
+
return chunks;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// src/cli/prompt.ts
|
|
361
|
+
function serializeCliPrompt(request, options = {}) {
|
|
362
|
+
const blocks = [];
|
|
363
|
+
const system = request.context?.systemPrompt;
|
|
364
|
+
if (options.system !== false && system) blocks.push(`[system]
|
|
365
|
+
${system}`);
|
|
366
|
+
const tools = request.context?.tools;
|
|
367
|
+
if (options.tools !== false && tools && tools.length > 0) blocks.push(`[tools]
|
|
368
|
+
${describeTools(tools)}`);
|
|
369
|
+
const messages = request.messages.filter((message) => message.role !== "system" || options.system !== false);
|
|
370
|
+
if (blocks.length === 0 && messages.length === 1 && messages[0].role === "user") return `${messages[0].content}
|
|
371
|
+
`;
|
|
372
|
+
for (const message of messages) blocks.push(`[${message.role}]
|
|
373
|
+
${message.content}`);
|
|
374
|
+
return `${blocks.join("\n\n")}
|
|
375
|
+
`;
|
|
376
|
+
}
|
|
377
|
+
function serializeCliMessages(request) {
|
|
378
|
+
return serializeCliPrompt(request, { system: false, tools: false });
|
|
379
|
+
}
|
|
380
|
+
function buildCliSystemPrompt(request) {
|
|
381
|
+
const parts = [];
|
|
382
|
+
if (request.context?.systemPrompt) parts.push(request.context.systemPrompt);
|
|
383
|
+
const tools = request.context?.tools;
|
|
384
|
+
if (tools && tools.length > 0) parts.push(describeTools(tools));
|
|
385
|
+
return parts.length > 0 ? parts.join("\n\n") : void 0;
|
|
386
|
+
}
|
|
387
|
+
function claudeCodeRequestArgs(request) {
|
|
388
|
+
const system = buildCliSystemPrompt(request);
|
|
389
|
+
return system ? ["--append-system-prompt", system] : [];
|
|
390
|
+
}
|
|
391
|
+
var TOOL_CONTRACT = [
|
|
392
|
+
"The application running you exposes the tools listed below; it executes them, not you.",
|
|
393
|
+
"To call one or more of them, reply with only a single JSON object",
|
|
394
|
+
'{"text"?: string, "toolCalls": [{"id": string, "name": string, "args": string}]} where `args` is a JSON-encoded',
|
|
395
|
+
"string of the tool arguments and `id` is any unique string. When no tool call is needed, reply with plain text."
|
|
396
|
+
].join(" ");
|
|
397
|
+
function describeTools(tools) {
|
|
398
|
+
const definitions = tools.map((tool) => ({ name: tool.name, description: tool.description, schema: tool.schema }));
|
|
399
|
+
return `${TOOL_CONTRACT}
|
|
400
|
+
${JSON.stringify(definitions, null, 2)}`;
|
|
401
|
+
}
|
|
402
|
+
function isRecord2(value) {
|
|
403
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
404
|
+
}
|
|
405
|
+
function claudeCodeError(message, cause) {
|
|
406
|
+
return new AdapterError({
|
|
407
|
+
code: ErrorCodes.AK_ADAPTER_STREAM_FAILED,
|
|
408
|
+
message,
|
|
409
|
+
cause,
|
|
410
|
+
hint: 'Run `claude -p --output-format json "ping"` manually to inspect the envelope emitted by the installed Claude Code version.'
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
function number(value) {
|
|
414
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
415
|
+
}
|
|
416
|
+
var RESPONSE_KEYS = ["text", "reasoning", "toolCalls"];
|
|
417
|
+
var FENCE = "```";
|
|
418
|
+
function unfence(text) {
|
|
419
|
+
if (!text.startsWith(FENCE) || !text.endsWith(FENCE) || text.length < FENCE.length * 2) return text;
|
|
420
|
+
let inner = text.slice(FENCE.length, text.length - FENCE.length);
|
|
421
|
+
if (inner.startsWith("json")) inner = inner.slice("json".length);
|
|
422
|
+
return inner.trim();
|
|
423
|
+
}
|
|
424
|
+
function embeddedResponse(result) {
|
|
425
|
+
const candidate = unfence(result.trim());
|
|
426
|
+
if (!candidate.startsWith("{") || !candidate.endsWith("}")) return void 0;
|
|
427
|
+
let value;
|
|
428
|
+
try {
|
|
429
|
+
value = JSON.parse(candidate);
|
|
430
|
+
} catch {
|
|
431
|
+
return void 0;
|
|
432
|
+
}
|
|
433
|
+
if (!isRecord2(value) || !RESPONSE_KEYS.some((key) => key in value)) return void 0;
|
|
434
|
+
return value;
|
|
435
|
+
}
|
|
436
|
+
function parseClaudeCodeJsonResponse(value) {
|
|
437
|
+
if (!isRecord2(value) || value.type !== "result") throw claudeCodeError("Claude Code JSON output must be a `result` envelope");
|
|
438
|
+
const result = typeof value.result === "string" ? value.result : "";
|
|
439
|
+
if (value.is_error === true || typeof value.subtype === "string" && value.subtype !== "success") {
|
|
440
|
+
throw claudeCodeError(`Claude Code returned ${String(value.subtype ?? "error")}${result ? `: ${result}` : ""}`);
|
|
441
|
+
}
|
|
442
|
+
const chunks = [];
|
|
443
|
+
const structured = isRecord2(value.structured_output) ? value.structured_output : void 0;
|
|
444
|
+
if (structured && RESPONSE_KEYS.some((key) => key in structured)) {
|
|
445
|
+
chunks.push(...parseCliJsonResponse(structured));
|
|
446
|
+
} else if (structured) {
|
|
447
|
+
chunks.push({ type: "text", content: JSON.stringify(structured) });
|
|
448
|
+
} else {
|
|
449
|
+
const embedded = embeddedResponse(result);
|
|
450
|
+
if (embedded) chunks.push(...parseCliJsonResponse(embedded));
|
|
451
|
+
else if (result) chunks.push({ type: "text", content: result });
|
|
452
|
+
}
|
|
453
|
+
if (isRecord2(value.usage)) {
|
|
454
|
+
const promptTokens = number(value.usage.input_tokens) + number(value.usage.cache_creation_input_tokens) + number(value.usage.cache_read_input_tokens);
|
|
455
|
+
const completionTokens = number(value.usage.output_tokens);
|
|
456
|
+
chunks.push({ type: "usage", usage: { promptTokens, completionTokens, totalTokens: promptTokens + completionTokens } });
|
|
457
|
+
}
|
|
458
|
+
if (chunks.length === 0) throw claudeCodeError("Claude Code JSON output contains no semantic output");
|
|
459
|
+
const metadata = {};
|
|
460
|
+
for (const key of ["session_id", "total_cost_usd", "duration_ms", "num_turns", "subtype"]) {
|
|
461
|
+
if (value[key] !== void 0) metadata[key] = value[key];
|
|
462
|
+
}
|
|
463
|
+
const last = chunks[chunks.length - 1];
|
|
464
|
+
chunks[chunks.length - 1] = { ...last, metadata: { ...last.metadata, ...metadata } };
|
|
465
|
+
return chunks;
|
|
466
|
+
}
|
|
467
|
+
function parseClaudeCodeJsonOutput(stdout) {
|
|
468
|
+
const trimmed = stdout.trim();
|
|
469
|
+
try {
|
|
470
|
+
return JSON.parse(trimmed);
|
|
471
|
+
} catch (error) {
|
|
472
|
+
const start = trimmed.lastIndexOf("\n{");
|
|
473
|
+
if (start < 0) throw claudeCodeError(`Claude Code stdout is not a JSON envelope: ${error instanceof Error ? error.message : String(error)}`, error);
|
|
474
|
+
return JSON.parse(trimmed.slice(start + 1));
|
|
475
|
+
}
|
|
476
|
+
}
|
|
321
477
|
var MODES = ["review-safe", "trusted-local", "restricted-environment"];
|
|
322
478
|
var CAPABILITIES = /* @__PURE__ */ new Set([
|
|
323
479
|
"streaming",
|
|
@@ -340,9 +496,13 @@ var manifests = [
|
|
|
340
496
|
capabilities: { streaming: true, nativeAuth: true },
|
|
341
497
|
supportedModes: MODES,
|
|
342
498
|
credentialEnv: ["OPENAI_API_KEY", "CODEX_API_KEY"],
|
|
343
|
-
docsUrl: "https://github.com/openai/codex"
|
|
499
|
+
docsUrl: "https://github.com/openai/codex",
|
|
500
|
+
serializeRequest: serializeCliPrompt
|
|
344
501
|
},
|
|
345
502
|
{
|
|
503
|
+
// Plain-text transport: streams Claude Code's final answer as text.
|
|
504
|
+
// No structured output, reasoning, or tool calls; use `claude-code-json`
|
|
505
|
+
// for those.
|
|
346
506
|
id: "claude-code",
|
|
347
507
|
name: "Claude Code",
|
|
348
508
|
command: "claude",
|
|
@@ -352,7 +512,27 @@ var manifests = [
|
|
|
352
512
|
capabilities: { streaming: true, nativeAuth: true },
|
|
353
513
|
supportedModes: MODES,
|
|
354
514
|
credentialEnv: ["ANTHROPIC_API_KEY"],
|
|
355
|
-
docsUrl: "https://docs.anthropic.com/en/docs/claude-code/cli-usage"
|
|
515
|
+
docsUrl: "https://docs.anthropic.com/en/docs/claude-code/cli-usage",
|
|
516
|
+
serializeRequest: serializeCliMessages,
|
|
517
|
+
requestArgs: claudeCodeRequestArgs
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
// Structured transport: one `claude -p --output-format json` envelope per
|
|
521
|
+
// request, parsed into text, tool_call, and usage chunks. Not streaming.
|
|
522
|
+
id: "claude-code-json",
|
|
523
|
+
name: "Claude Code (JSON output)",
|
|
524
|
+
command: "claude",
|
|
525
|
+
args: ["-p", "--output-format", "json"],
|
|
526
|
+
diagnosticArgs: ["--version"],
|
|
527
|
+
protocol: "exec-json",
|
|
528
|
+
capabilities: { structuredOutput: true, nativeAuth: true },
|
|
529
|
+
supportedModes: MODES,
|
|
530
|
+
credentialEnv: ["ANTHROPIC_API_KEY"],
|
|
531
|
+
docsUrl: "https://docs.anthropic.com/en/docs/claude-code/cli-usage",
|
|
532
|
+
serializeRequest: serializeCliMessages,
|
|
533
|
+
requestArgs: claudeCodeRequestArgs,
|
|
534
|
+
parseOutput: parseClaudeCodeJsonOutput,
|
|
535
|
+
parse: parseClaudeCodeJsonResponse
|
|
356
536
|
},
|
|
357
537
|
{
|
|
358
538
|
id: "grok",
|
|
@@ -395,13 +575,14 @@ function validateArgs(values, label) {
|
|
|
395
575
|
if (value.includes("\0")) throw manifestError(`CLI manifest ${label} contains a null byte`);
|
|
396
576
|
}
|
|
397
577
|
}
|
|
398
|
-
function
|
|
578
|
+
function isRecord3(value) {
|
|
399
579
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
400
580
|
}
|
|
401
581
|
function validateCapabilities(manifest) {
|
|
402
|
-
|
|
582
|
+
const declared = manifest.capabilities;
|
|
583
|
+
for (const capability of Object.keys(declared)) {
|
|
403
584
|
if (!CAPABILITIES.has(capability)) throw manifestError(`CLI manifest declares unknown capability: ${capability}`);
|
|
404
|
-
if (
|
|
585
|
+
if (declared[capability] !== true) throw manifestError(`CLI manifest capability ${capability} must be true or omitted`);
|
|
405
586
|
}
|
|
406
587
|
const unsupportedByProtocol = {
|
|
407
588
|
"exec-text": ["structuredOutput", "reasoning", "tools", "mcp", "plugins", "terminal"],
|
|
@@ -409,11 +590,11 @@ function validateCapabilities(manifest) {
|
|
|
409
590
|
acp: ["tools", "mcp", "plugins", "terminal"]
|
|
410
591
|
};
|
|
411
592
|
for (const capability of unsupportedByProtocol[manifest.protocol]) {
|
|
412
|
-
if (
|
|
593
|
+
if (declared[capability] === true) throw manifestError(`CLI manifest ${manifest.id} declares unsupported ${capability} for ${manifest.protocol}`);
|
|
413
594
|
}
|
|
414
595
|
}
|
|
415
596
|
function validateCliProviderManifest(manifest) {
|
|
416
|
-
if (!
|
|
597
|
+
if (!isRecord3(manifest)) throw manifestError("CLI manifest must be an object");
|
|
417
598
|
if (typeof manifest.id !== "string" || typeof manifest.name !== "string" || typeof manifest.command !== "string") {
|
|
418
599
|
throw manifestError("CLI manifest id, name, and command must be strings");
|
|
419
600
|
}
|
|
@@ -423,7 +604,7 @@ function validateCliProviderManifest(manifest) {
|
|
|
423
604
|
if (manifest.protocol !== "exec-text" && manifest.protocol !== "exec-json" && manifest.protocol !== "acp") {
|
|
424
605
|
throw manifestError("CLI manifest protocol is unsupported");
|
|
425
606
|
}
|
|
426
|
-
if (!
|
|
607
|
+
if (!isRecord3(manifest.capabilities) || !Array.isArray(manifest.supportedModes)) throw manifestError("CLI manifest capabilities and supportedModes are required");
|
|
427
608
|
if (!manifest.supportedModes.every((value) => typeof value === "string")) throw manifestError("CLI manifest supportedModes must be a string array");
|
|
428
609
|
const candidate = manifest;
|
|
429
610
|
nonEmpty(candidate.id, "id");
|
|
@@ -450,6 +631,12 @@ function validateCliProviderManifest(manifest) {
|
|
|
450
631
|
}
|
|
451
632
|
}
|
|
452
633
|
if (candidate.docsUrl !== void 0 && typeof candidate.docsUrl !== "string") throw manifestError(`CLI manifest ${candidate.id} docsUrl must be a string`);
|
|
634
|
+
for (const key of ["serializeRequest", "requestArgs", "parseOutput", "parse"]) {
|
|
635
|
+
if (candidate[key] !== void 0 && typeof candidate[key] !== "function") throw manifestError(`CLI manifest ${candidate.id} ${key} must be a function`);
|
|
636
|
+
if ((key === "parseOutput" || key === "parse") && candidate[key] !== void 0 && candidate.protocol !== "exec-json") {
|
|
637
|
+
throw manifestError(`CLI manifest ${candidate.id} declares ${key}, which only applies to the exec-json protocol`);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
453
640
|
validateCapabilities(candidate);
|
|
454
641
|
}
|
|
455
642
|
function listCliProviderManifests() {
|
|
@@ -469,9 +656,12 @@ function resolveCliManifest(manifest, options = {}) {
|
|
|
469
656
|
validateCliProviderManifest(manifest);
|
|
470
657
|
const mode = options.mode ?? "review-safe";
|
|
471
658
|
if (!manifest.supportedModes.includes(mode)) throw manifestError(`CLI manifest ${manifest.id} does not support mode: ${mode}`);
|
|
659
|
+
const args = [...manifest.args, ...options.args ?? []];
|
|
660
|
+
const requestArgs = manifest.requestArgs;
|
|
472
661
|
return {
|
|
473
662
|
command: manifest.command,
|
|
474
|
-
args
|
|
663
|
+
args,
|
|
664
|
+
buildArgs: requestArgs ? (request) => [...args, ...requestArgs(request)] : void 0,
|
|
475
665
|
mode,
|
|
476
666
|
cwd: options.cwd,
|
|
477
667
|
env: options.env,
|
|
@@ -481,7 +671,10 @@ function resolveCliManifest(manifest, options = {}) {
|
|
|
481
671
|
providerId: manifest.id,
|
|
482
672
|
protocol: manifest.protocol,
|
|
483
673
|
onDiagnostic: options.onDiagnostic,
|
|
484
|
-
requiredCapabilities: options.requiredCapabilities
|
|
674
|
+
requiredCapabilities: options.requiredCapabilities,
|
|
675
|
+
serializeRequest: manifest.serializeRequest,
|
|
676
|
+
parseOutput: manifest.parseOutput,
|
|
677
|
+
parse: manifest.parse
|
|
485
678
|
};
|
|
486
679
|
}
|
|
487
680
|
function adapterCapabilities(manifest) {
|
|
@@ -507,7 +700,6 @@ function manifestCapabilities(manifest) {
|
|
|
507
700
|
// src/cli/index.ts
|
|
508
701
|
var defaultSerialize = (request) => `${JSON.stringify(request)}
|
|
509
702
|
`;
|
|
510
|
-
var cliError = (message, cause) => new AdapterError({ code: ErrorCodes.AK_ADAPTER_STREAM_FAILED, message, cause });
|
|
511
703
|
function createFactory(capabilities, run) {
|
|
512
704
|
return {
|
|
513
705
|
capabilities,
|
|
@@ -591,43 +783,6 @@ async function* runText(request, signal, options) {
|
|
|
591
783
|
await closeProcess(handle);
|
|
592
784
|
}
|
|
593
785
|
}
|
|
594
|
-
function isRecord2(value) {
|
|
595
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
596
|
-
}
|
|
597
|
-
function standardJsonParser(value) {
|
|
598
|
-
if (!isRecord2(value)) throw cliError("CLI JSON response must be an object");
|
|
599
|
-
const chunks = [];
|
|
600
|
-
if (typeof value.text === "string") chunks.push({ type: "text", content: value.text });
|
|
601
|
-
if (typeof value.reasoning === "string") chunks.push({ type: "reasoning", content: value.reasoning });
|
|
602
|
-
if (Array.isArray(value.toolCalls)) {
|
|
603
|
-
for (const item of value.toolCalls) {
|
|
604
|
-
if (!isRecord2(item) || typeof item.id !== "string" || typeof item.name !== "string" || typeof item.args !== "string") {
|
|
605
|
-
throw cliError("CLI JSON toolCalls must contain string id, name, and args fields");
|
|
606
|
-
}
|
|
607
|
-
JSON.parse(item.args);
|
|
608
|
-
chunks.push({ type: "tool_call", toolCall: { id: item.id, name: item.name, args: item.args } });
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
if (value.usage !== void 0) {
|
|
612
|
-
if (!isRecord2(value.usage)) {
|
|
613
|
-
throw cliError("CLI JSON usage must contain numeric promptTokens, completionTokens, and totalTokens");
|
|
614
|
-
}
|
|
615
|
-
const promptTokens = value.usage.promptTokens;
|
|
616
|
-
const completionTokens = value.usage.completionTokens;
|
|
617
|
-
const totalTokens = value.usage.totalTokens;
|
|
618
|
-
if (typeof promptTokens !== "number" || typeof completionTokens !== "number" || typeof totalTokens !== "number") {
|
|
619
|
-
throw cliError("CLI JSON usage must contain numeric promptTokens, completionTokens, and totalTokens");
|
|
620
|
-
}
|
|
621
|
-
chunks.push({ type: "usage", usage: { promptTokens, completionTokens, totalTokens } });
|
|
622
|
-
}
|
|
623
|
-
if (value.metadata !== void 0) {
|
|
624
|
-
if (!isRecord2(value.metadata)) throw cliError("CLI JSON metadata must be an object");
|
|
625
|
-
if (chunks.length === 0) throw cliError("CLI JSON response contains no semantic output");
|
|
626
|
-
chunks[chunks.length - 1] = { ...chunks[chunks.length - 1], metadata: value.metadata };
|
|
627
|
-
}
|
|
628
|
-
if (chunks.length === 0) throw cliError("CLI JSON response contains no semantic output");
|
|
629
|
-
return chunks;
|
|
630
|
-
}
|
|
631
786
|
function normalizeJsonChunks(chunks) {
|
|
632
787
|
if (chunks.length === 0) throw cliError("CLI JSON parser returned no chunks");
|
|
633
788
|
if (chunks.some((chunk) => !isStreamChunk(chunk))) throw cliError("CLI JSON parser returned an invalid stream chunk");
|
|
@@ -639,7 +794,7 @@ function normalizeJsonChunks(chunks) {
|
|
|
639
794
|
return last.type === "done" || last.type === "error" ? [...chunks] : [...chunks, { type: "done" }];
|
|
640
795
|
}
|
|
641
796
|
function isStreamChunk(value) {
|
|
642
|
-
return
|
|
797
|
+
return isRecord(value) && typeof value.type === "string" && (/* @__PURE__ */ new Set([
|
|
643
798
|
"text",
|
|
644
799
|
"tool_call",
|
|
645
800
|
"tool_result",
|
|
@@ -664,20 +819,20 @@ async function* runJson(request, signal, options) {
|
|
|
664
819
|
} catch (error) {
|
|
665
820
|
throw cliError(`CLI returned malformed JSON: ${error instanceof Error ? error.message : String(error)}`, error);
|
|
666
821
|
}
|
|
667
|
-
const chunks = normalizeJsonChunks((options.parse ??
|
|
822
|
+
const chunks = normalizeJsonChunks((options.parse ?? parseCliJsonResponse)(value));
|
|
668
823
|
for (const chunk of chunks) yield chunk;
|
|
669
824
|
} finally {
|
|
670
825
|
await closeProcess(handle);
|
|
671
826
|
}
|
|
672
827
|
}
|
|
673
828
|
function parseAcpMessage(value) {
|
|
674
|
-
if (!
|
|
829
|
+
if (!isRecord(value) || value.jsonrpc !== "2.0") throw cliError("ACP message must be a JSON-RPC 2.0 object");
|
|
675
830
|
if (typeof value.method === "string") {
|
|
676
831
|
if (value.id === void 0) return { kind: "notification", method: value.method, params: value.params };
|
|
677
832
|
return { kind: "request", method: value.method };
|
|
678
833
|
}
|
|
679
834
|
if (typeof value.id === "string" || typeof value.id === "number" || value.id === null) {
|
|
680
|
-
if (value.error !== void 0 && !
|
|
835
|
+
if (value.error !== void 0 && !isRecord(value.error)) throw cliError("ACP error response is malformed");
|
|
681
836
|
return { kind: "response", id: value.id, result: value.result, error: value.error };
|
|
682
837
|
}
|
|
683
838
|
throw cliError("ACP message has no method or response id");
|
|
@@ -730,12 +885,12 @@ ${request.context.systemPrompt}
|
|
|
730
885
|
${message.content}`).join("\n\n");
|
|
731
886
|
}
|
|
732
887
|
function acpUpdateChunk(params, sessionId) {
|
|
733
|
-
if (!
|
|
888
|
+
if (!isRecord(params) || params.sessionId !== sessionId || !isRecord(params.update)) return void 0;
|
|
734
889
|
const update = params.update;
|
|
735
|
-
if (update.sessionUpdate === "agent_message_chunk" &&
|
|
890
|
+
if (update.sessionUpdate === "agent_message_chunk" && isRecord(update.content) && update.content.type === "text" && typeof update.content.text === "string") {
|
|
736
891
|
return { type: "text", content: update.content.text };
|
|
737
892
|
}
|
|
738
|
-
if (update.sessionUpdate === "agent_thought_chunk" &&
|
|
893
|
+
if (update.sessionUpdate === "agent_thought_chunk" && isRecord(update.content) && update.content.type === "text" && typeof update.content.text === "string") {
|
|
739
894
|
return { type: "reasoning", content: update.content.text };
|
|
740
895
|
}
|
|
741
896
|
if (update.sessionUpdate === "tool_call" || update.sessionUpdate === "tool_call_update") {
|
|
@@ -758,14 +913,14 @@ async function* runAcp(request, signal, options) {
|
|
|
758
913
|
clientInfo: options.clientInfo ?? { name: "@agentskit/adapters", version: "0.16.0" }
|
|
759
914
|
}), signal);
|
|
760
915
|
const initialize = await nextAcpResponse(iterator, initializeId);
|
|
761
|
-
if (!
|
|
916
|
+
if (!isRecord(initialize.result) || initialize.result.protocolVersion !== 1) throw cliError("ACP agent did not negotiate protocol version 1");
|
|
762
917
|
const sessionIdRequest = nextId();
|
|
763
918
|
await abortableWrite(handle, acpRequest(sessionIdRequest, "session/new", {
|
|
764
919
|
cwd: options.cwd ?? process.cwd(),
|
|
765
920
|
mcpServers: []
|
|
766
921
|
}), signal);
|
|
767
922
|
const sessionResponse = await nextAcpResponse(iterator, sessionIdRequest);
|
|
768
|
-
if (!
|
|
923
|
+
if (!isRecord(sessionResponse.result) || typeof sessionResponse.result.sessionId !== "string") throw cliError("ACP session/new response has no sessionId");
|
|
769
924
|
const sessionId = sessionResponse.result.sessionId;
|
|
770
925
|
const promptId = nextId();
|
|
771
926
|
await abortableWrite(handle, acpRequest(promptId, "session/prompt", {
|
|
@@ -778,7 +933,7 @@ async function* runAcp(request, signal, options) {
|
|
|
778
933
|
if (next.done) throw cliError("ACP process closed before session/prompt completed");
|
|
779
934
|
if (next.value.kind === "response" && next.value.id === promptId) {
|
|
780
935
|
if (next.value.error) throw cliError(`ACP prompt failed: ${next.value.error.message ?? "unknown error"}`);
|
|
781
|
-
if (!
|
|
936
|
+
if (!isRecord(next.value.result) || next.value.result.stopReason !== "end_turn") throw cliError("ACP prompt did not complete with end_turn");
|
|
782
937
|
break;
|
|
783
938
|
}
|
|
784
939
|
if (next.value.kind === "request") throw cliError(`ACP agent request is unsupported in this adapter: ${next.value.method}`);
|
|
@@ -823,6 +978,6 @@ function createAcpCliAdapter(options) {
|
|
|
823
978
|
}, (request, signal) => runAcp(request, signal, options));
|
|
824
979
|
}
|
|
825
980
|
|
|
826
|
-
export { createAcpCliAdapter, createCliAdapter, createJsonCliAdapter, diagnoseCliProvider, diagnoseCliProviderManifest, getCliProviderManifest, listCliProviderManifests, manifestCapabilities,
|
|
981
|
+
export { buildCliSystemPrompt, claudeCodeRequestArgs, createAcpCliAdapter, createCliAdapter, createJsonCliAdapter, diagnoseCliProvider, diagnoseCliProviderManifest, getCliProviderManifest, listCliProviderManifests, manifestCapabilities, parseClaudeCodeJsonOutput, parseClaudeCodeJsonResponse, parseCliJsonResponse, resolveCliManifest, serializeCliMessages, serializeCliPrompt, validateCliProviderManifest };
|
|
827
982
|
//# sourceMappingURL=index.js.map
|
|
828
983
|
//# sourceMappingURL=index.js.map
|