@agentproto/driver-agent-cli 0.2.0 → 0.3.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/dist/{chunk-YQHVLX6O.mjs → chunk-KHHRPQ2Q.mjs} +379 -41
- package/dist/chunk-KHHRPQ2Q.mjs.map +1 -0
- package/dist/index.d.ts +193 -13
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/manifest/index.d.ts +2 -2
- package/dist/manifest/index.mjs +2 -2
- package/dist/{schema-CCSzIDMJ.d.ts → schema-Ds8jc9fL.d.ts} +136 -2
- package/package.json +2 -2
- package/dist/chunk-YQHVLX6O.mjs.map +0 -1
|
@@ -2,8 +2,11 @@ import { z } from 'zod';
|
|
|
2
2
|
import { Writable, Readable } from 'stream';
|
|
3
3
|
import { createAcpClient } from '@agentproto/acp/client';
|
|
4
4
|
import { spawn } from 'child_process';
|
|
5
|
+
import { existsSync, readFileSync, mkdirSync, writeFileSync, rmSync, rmdirSync, mkdtempSync } from 'fs';
|
|
5
6
|
import { createInterface } from 'readline';
|
|
7
|
+
import { join } from 'path';
|
|
6
8
|
import { randomUUID } from 'crypto';
|
|
9
|
+
import { tmpdir } from 'os';
|
|
7
10
|
import { createDoctype } from '@agentproto/define-doctype';
|
|
8
11
|
|
|
9
12
|
/**
|
|
@@ -150,6 +153,11 @@ var authSchema = z.object({
|
|
|
150
153
|
var sessionSchema = z.object({
|
|
151
154
|
mode: z.enum(["ephemeral", "persistent", "resumable"]).default("ephemeral"),
|
|
152
155
|
idle_timeout_ms: z.number().int().min(1e3).default(6e5),
|
|
156
|
+
// No default: undefined disables the per-turn watchdog entirely. Only
|
|
157
|
+
// adapters known to sometimes drop the final `prompt` response (e.g.
|
|
158
|
+
// hermes) should declare this — applying it broadly would risk
|
|
159
|
+
// false-positiving on another adapter's legitimately long turns.
|
|
160
|
+
turn_idle_timeout_ms: z.number().int().min(1e3).optional(),
|
|
153
161
|
max_turns: z.number().int().positive().optional(),
|
|
154
162
|
context_carryover: z.boolean().default(true)
|
|
155
163
|
}).strict();
|
|
@@ -225,6 +233,16 @@ var mcpBlockSchema = z.object({
|
|
|
225
233
|
transport: z.enum(["stdio", "http", "sse"]),
|
|
226
234
|
url: z.string().url().optional()
|
|
227
235
|
}).strict();
|
|
236
|
+
var printConfigSchema = z.object({
|
|
237
|
+
prompt_flag: z.string().optional(),
|
|
238
|
+
output_format: z.array(z.string()).optional(),
|
|
239
|
+
pre_prompt: z.array(z.string()).optional(),
|
|
240
|
+
resume: z.object({
|
|
241
|
+
flag: z.string(),
|
|
242
|
+
kind: z.enum(["value", "boolean"])
|
|
243
|
+
}).strict().optional(),
|
|
244
|
+
event_schema: z.enum(["claude-stream-json", "mastra-jsonl"]).optional()
|
|
245
|
+
}).strict().optional();
|
|
228
246
|
var agentCliFrontmatterSchema = z.object({
|
|
229
247
|
name: z.string().min(1).max(80),
|
|
230
248
|
id: z.string().regex(ID_PATTERN),
|
|
@@ -242,6 +260,7 @@ var agentCliFrontmatterSchema = z.object({
|
|
|
242
260
|
acp: z.string().optional(),
|
|
243
261
|
mcp: mcpBlockSchema.optional(),
|
|
244
262
|
adapter: z.string().regex(ADAPTER_PATTERN).optional(),
|
|
263
|
+
print: printConfigSchema,
|
|
245
264
|
session: sessionSchema.optional(),
|
|
246
265
|
models: modelsSchema.optional(),
|
|
247
266
|
capabilities: capabilitiesSchema.optional(),
|
|
@@ -325,6 +344,21 @@ var autoAllowPermissionHandler = ({
|
|
|
325
344
|
const allow = options.find((o) => typeof o.kind === "string" && o.kind.startsWith("allow_")) ?? options[0];
|
|
326
345
|
return { outcome: { outcome: "selected", optionId: allow.optionId } };
|
|
327
346
|
};
|
|
347
|
+
var PLAN_MODE_EXIT_TOOL_CALL_KIND = "switch_mode";
|
|
348
|
+
var planModePermissionHandler = (params) => {
|
|
349
|
+
const { options, toolCall } = params;
|
|
350
|
+
if (!options || options.length === 0) {
|
|
351
|
+
return { outcome: { outcome: "cancelled" } };
|
|
352
|
+
}
|
|
353
|
+
if (toolCall?.kind === PLAN_MODE_EXIT_TOOL_CALL_KIND) {
|
|
354
|
+
const keepPlanning = options.find((o) => o.kind === "reject_once");
|
|
355
|
+
return keepPlanning ? { outcome: { outcome: "selected", optionId: keepPlanning.optionId } } : { outcome: { outcome: "cancelled" } };
|
|
356
|
+
}
|
|
357
|
+
return autoAllowPermissionHandler(params);
|
|
358
|
+
};
|
|
359
|
+
function defaultPermissionHandlerForMode(requestedMode) {
|
|
360
|
+
return requestedMode === "plan" ? planModePermissionHandler : autoAllowPermissionHandler;
|
|
361
|
+
}
|
|
328
362
|
function createAcpProtocolArm(options) {
|
|
329
363
|
const { child, cwd } = options;
|
|
330
364
|
if (!child.stdin || !child.stdout) {
|
|
@@ -342,7 +376,7 @@ function createAcpProtocolArm(options) {
|
|
|
342
376
|
return session?.sessionId;
|
|
343
377
|
},
|
|
344
378
|
async connect(opts) {
|
|
345
|
-
const permissionHandler = options.onPermissionRequest ??
|
|
379
|
+
const permissionHandler = options.onPermissionRequest ?? defaultPermissionHandlerForMode(options.requestedMode);
|
|
346
380
|
client = await createAcpClient({
|
|
347
381
|
output,
|
|
348
382
|
input,
|
|
@@ -350,6 +384,8 @@ function createAcpProtocolArm(options) {
|
|
|
350
384
|
capabilities: {
|
|
351
385
|
fs: { readTextFile: true, writeTextFile: true }
|
|
352
386
|
},
|
|
387
|
+
onActivity: opts.onActivity,
|
|
388
|
+
turnIdleTimeoutMs: opts.turnIdleTimeoutMs,
|
|
353
389
|
// Wire the permission handler so the agent's `session/request_permission`
|
|
354
390
|
// callbacks get a real answer instead of bubbling up as
|
|
355
391
|
// "AcpClient.requestPermission: no handler configured" → which
|
|
@@ -395,9 +431,29 @@ function createAcpProtocolArm(options) {
|
|
|
395
431
|
}
|
|
396
432
|
};
|
|
397
433
|
}
|
|
434
|
+
|
|
435
|
+
// src/mcp-servers.ts
|
|
436
|
+
function toFileBasedMcpServers(servers) {
|
|
437
|
+
if (!servers || servers.length === 0) return void 0;
|
|
438
|
+
const out = {};
|
|
439
|
+
for (const s of servers) {
|
|
440
|
+
out[s.name] = s.transport === "stdio" ? { command: s.ref ?? "" } : { url: s.ref ?? "" };
|
|
441
|
+
}
|
|
442
|
+
return out;
|
|
443
|
+
}
|
|
444
|
+
var DEFAULT_OUTPUT = ["--output-format", "stream-json"];
|
|
445
|
+
var DEFAULT_PRE_PROMPT = ["--no-interactive"];
|
|
446
|
+
var DEFAULT_RESUME = { flag: "--resume", kind: "value" };
|
|
398
447
|
function createPrintSession(opts) {
|
|
448
|
+
const config = opts.printConfig;
|
|
449
|
+
const outputFormat = config?.output_format ?? DEFAULT_OUTPUT;
|
|
450
|
+
const prePrompt = config?.pre_prompt ?? DEFAULT_PRE_PROMPT;
|
|
451
|
+
const promptFlag = config?.prompt_flag;
|
|
452
|
+
const resumeCfg = config?.resume ?? DEFAULT_RESUME;
|
|
453
|
+
const eventSchema = config?.event_schema ?? "claude-stream-json";
|
|
399
454
|
let sessionId = opts.resumeSessionId ?? "";
|
|
400
455
|
let activeChild = null;
|
|
456
|
+
const mcpRestore = setupMcpConfigFile(opts, eventSchema);
|
|
401
457
|
return {
|
|
402
458
|
get sessionId() {
|
|
403
459
|
return sessionId;
|
|
@@ -406,13 +462,18 @@ function createPrintSession(opts) {
|
|
|
406
462
|
const prompt = extractPromptText(message);
|
|
407
463
|
const args = [
|
|
408
464
|
...opts.baseArgs,
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
"stream-json",
|
|
412
|
-
"--no-interactive",
|
|
413
|
-
...sessionId ? ["--resume", sessionId] : [],
|
|
414
|
-
prompt
|
|
465
|
+
...outputFormat,
|
|
466
|
+
...prePrompt
|
|
415
467
|
];
|
|
468
|
+
if (sessionId) {
|
|
469
|
+
args.push(resumeCfg.flag);
|
|
470
|
+
if (resumeCfg.kind === "value") args.push(sessionId);
|
|
471
|
+
}
|
|
472
|
+
if (promptFlag) {
|
|
473
|
+
args.push(promptFlag, prompt);
|
|
474
|
+
} else {
|
|
475
|
+
args.push(prompt);
|
|
476
|
+
}
|
|
416
477
|
const child = spawn(opts.bin, args, {
|
|
417
478
|
cwd: opts.cwd,
|
|
418
479
|
env: opts.env,
|
|
@@ -430,9 +491,11 @@ function createPrintSession(opts) {
|
|
|
430
491
|
}
|
|
431
492
|
});
|
|
432
493
|
try {
|
|
433
|
-
if (!child.stdout)
|
|
494
|
+
if (!child.stdout)
|
|
495
|
+
throw new Error("print-arm: child has no stdout pipe");
|
|
434
496
|
const rl = createInterface({ input: child.stdout, crlfDelay: Infinity });
|
|
435
497
|
let capturedSessionId = "";
|
|
498
|
+
const mastraState = eventSchema === "mastra-jsonl" ? createMastraMapperState() : void 0;
|
|
436
499
|
for await (const line of rl) {
|
|
437
500
|
if (!line.trim()) continue;
|
|
438
501
|
let evt;
|
|
@@ -441,21 +504,21 @@ function createPrintSession(opts) {
|
|
|
441
504
|
} catch {
|
|
442
505
|
continue;
|
|
443
506
|
}
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
}
|
|
507
|
+
const csid = captureSessionId(evt, eventSchema);
|
|
508
|
+
if (csid) capturedSessionId = csid;
|
|
447
509
|
const sid = capturedSessionId || sessionId || "";
|
|
448
|
-
const mapped = mapEvent(evt, sid, stderrLines);
|
|
510
|
+
const mapped = mapEvent(evt, sid, stderrLines, eventSchema, mastraState);
|
|
449
511
|
if (!mapped) continue;
|
|
450
512
|
yield mapped;
|
|
451
513
|
}
|
|
452
514
|
const exitCode = await waitForExit(child);
|
|
453
515
|
if (capturedSessionId) sessionId = capturedSessionId;
|
|
454
516
|
if (exitCode !== 0 && exitCode !== null) {
|
|
517
|
+
const binLabel = eventSchema === "mastra-jsonl" ? "mastracode" : "claude";
|
|
455
518
|
const errEvt = {
|
|
456
519
|
kind: "error",
|
|
457
520
|
error: {
|
|
458
|
-
message:
|
|
521
|
+
message: `${binLabel} exited with code ${exitCode}`,
|
|
459
522
|
...stderrLines.length ? { data: { stderr: stderrLines.join("\n") } } : {}
|
|
460
523
|
}
|
|
461
524
|
};
|
|
@@ -470,6 +533,75 @@ function createPrintSession(opts) {
|
|
|
470
533
|
},
|
|
471
534
|
async close() {
|
|
472
535
|
activeChild?.kill("SIGTERM");
|
|
536
|
+
mcpRestore?.();
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
function setupMcpConfigFile(opts, eventSchema) {
|
|
541
|
+
if (eventSchema !== "mastra-jsonl") return void 0;
|
|
542
|
+
if (!opts.mcpServers || opts.mcpServers.length === 0) return void 0;
|
|
543
|
+
const dir = join(opts.cwd, ".mastracode");
|
|
544
|
+
const file = join(dir, "mcp.json");
|
|
545
|
+
const injected = toFileBasedMcpServers(opts.mcpServers);
|
|
546
|
+
if (!injected) return void 0;
|
|
547
|
+
const fileExisted = existsSync(file);
|
|
548
|
+
let originalContent;
|
|
549
|
+
if (fileExisted) {
|
|
550
|
+
try {
|
|
551
|
+
originalContent = readFileSync(file, "utf8");
|
|
552
|
+
} catch {
|
|
553
|
+
originalContent = void 0;
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
const dirExisted = existsSync(dir);
|
|
557
|
+
if (!dirExisted) {
|
|
558
|
+
mkdirSync(dir, { recursive: true });
|
|
559
|
+
}
|
|
560
|
+
let existingServers = {};
|
|
561
|
+
if (originalContent !== void 0) {
|
|
562
|
+
try {
|
|
563
|
+
const parsed = JSON.parse(originalContent);
|
|
564
|
+
if (parsed && typeof parsed.mcpServers === "object" && parsed.mcpServers !== null) {
|
|
565
|
+
existingServers = parsed.mcpServers;
|
|
566
|
+
}
|
|
567
|
+
} catch {
|
|
568
|
+
existingServers = {};
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
const merged = { ...existingServers, ...injected };
|
|
572
|
+
const output = JSON.stringify({ mcpServers: merged }, null, 2);
|
|
573
|
+
writeFileSync(file, output, "utf8");
|
|
574
|
+
return () => {
|
|
575
|
+
try {
|
|
576
|
+
if (!fileExisted) {
|
|
577
|
+
rmSync(file, { force: true });
|
|
578
|
+
if (!dirExisted) {
|
|
579
|
+
try {
|
|
580
|
+
rmdirSync(dir);
|
|
581
|
+
} catch {
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
} else if (originalContent !== void 0) {
|
|
585
|
+
let current = {};
|
|
586
|
+
try {
|
|
587
|
+
const parsed = JSON.parse(readFileSync(file, "utf8"));
|
|
588
|
+
if (parsed && typeof parsed.mcpServers === "object" && parsed.mcpServers !== null) {
|
|
589
|
+
current = parsed.mcpServers;
|
|
590
|
+
}
|
|
591
|
+
} catch {
|
|
592
|
+
writeFileSync(file, originalContent, "utf8");
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
for (const key of Object.keys(injected)) {
|
|
596
|
+
delete current[key];
|
|
597
|
+
}
|
|
598
|
+
if (Object.keys(current).length === 0) {
|
|
599
|
+
writeFileSync(file, originalContent, "utf8");
|
|
600
|
+
} else {
|
|
601
|
+
writeFileSync(file, JSON.stringify({ mcpServers: current }, null, 2), "utf8");
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
} catch {
|
|
473
605
|
}
|
|
474
606
|
};
|
|
475
607
|
}
|
|
@@ -484,7 +616,33 @@ function extractPromptText(message) {
|
|
|
484
616
|
}
|
|
485
617
|
return JSON.stringify(message);
|
|
486
618
|
}
|
|
487
|
-
function
|
|
619
|
+
function captureSessionId(evt, schema) {
|
|
620
|
+
switch (schema) {
|
|
621
|
+
case "claude-stream-json":
|
|
622
|
+
if (evt.type === "result" && typeof evt.session_id === "string" && evt.session_id)
|
|
623
|
+
return evt.session_id;
|
|
624
|
+
return null;
|
|
625
|
+
case "mastra-jsonl":
|
|
626
|
+
if (evt.type === "result" && typeof evt.threadId === "string" && evt.threadId)
|
|
627
|
+
return evt.threadId;
|
|
628
|
+
return null;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
function mapEvent(evt, sessionId, stderrLines, schema, mastraState) {
|
|
632
|
+
switch (schema) {
|
|
633
|
+
case "claude-stream-json":
|
|
634
|
+
return mapClaudeEvent(evt, sessionId, stderrLines);
|
|
635
|
+
case "mastra-jsonl": {
|
|
636
|
+
if (!mastraState) {
|
|
637
|
+
return mapClaudeEvent(evt, sessionId, stderrLines);
|
|
638
|
+
}
|
|
639
|
+
return mapMastraEvent(evt, sessionId, stderrLines, mastraState);
|
|
640
|
+
}
|
|
641
|
+
default:
|
|
642
|
+
return mapClaudeEvent(evt, sessionId, stderrLines);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
function mapClaudeEvent(evt, sessionId, stderrLines) {
|
|
488
646
|
switch (evt.type) {
|
|
489
647
|
case "text":
|
|
490
648
|
return typeof evt.text === "string" ? { kind: "text-delta", sessionId, text: evt.text } : null;
|
|
@@ -528,6 +686,127 @@ function mapEvent(evt, sessionId, stderrLines) {
|
|
|
528
686
|
return null;
|
|
529
687
|
}
|
|
530
688
|
}
|
|
689
|
+
function createMastraMapperState() {
|
|
690
|
+
return { lastTextLength: 0 };
|
|
691
|
+
}
|
|
692
|
+
function extractTextFromBlocks(content) {
|
|
693
|
+
if (!Array.isArray(content)) return "";
|
|
694
|
+
return content.filter((c) => c.type === "text" && typeof c.text === "string").map((c) => c.text).join("");
|
|
695
|
+
}
|
|
696
|
+
function mapMastraEvent(evt, sessionId, stderrLines, state) {
|
|
697
|
+
switch (evt.type) {
|
|
698
|
+
// ── Text streaming ──────────────────────────────────────────
|
|
699
|
+
case "message_update": {
|
|
700
|
+
const content = evt.message?.content;
|
|
701
|
+
const fullText = extractTextFromBlocks(content);
|
|
702
|
+
if (fullText.length > state.lastTextLength) {
|
|
703
|
+
const delta = fullText.slice(state.lastTextLength);
|
|
704
|
+
state.lastTextLength = fullText.length;
|
|
705
|
+
return delta ? { kind: "text-delta", sessionId, text: delta } : null;
|
|
706
|
+
}
|
|
707
|
+
return null;
|
|
708
|
+
}
|
|
709
|
+
case "message_end": {
|
|
710
|
+
const msg = evt.message;
|
|
711
|
+
if (msg?.role !== "assistant") return null;
|
|
712
|
+
const fullText = extractTextFromBlocks(msg?.content);
|
|
713
|
+
if (fullText.length > state.lastTextLength) {
|
|
714
|
+
const delta = fullText.slice(state.lastTextLength);
|
|
715
|
+
state.lastTextLength = fullText.length;
|
|
716
|
+
return delta ? { kind: "text-delta", sessionId, text: delta } : null;
|
|
717
|
+
}
|
|
718
|
+
return null;
|
|
719
|
+
}
|
|
720
|
+
// ── Tool calls ──────────────────────────────────────────────
|
|
721
|
+
case "tool_start":
|
|
722
|
+
return {
|
|
723
|
+
kind: "tool-call",
|
|
724
|
+
sessionId,
|
|
725
|
+
toolCallId: typeof evt.toolCallId === "string" ? evt.toolCallId : "",
|
|
726
|
+
toolName: typeof evt.toolName === "string" ? evt.toolName : "?",
|
|
727
|
+
// Mastra's controller event carries the tool call payload under
|
|
728
|
+
// `args`, not `input` (that's the Claude Code stream-json field
|
|
729
|
+
// name used by the sibling mapClaudeEvent tool_use case below).
|
|
730
|
+
arguments: evt.args ?? {}
|
|
731
|
+
};
|
|
732
|
+
case "tool_end":
|
|
733
|
+
return {
|
|
734
|
+
kind: "tool-result",
|
|
735
|
+
sessionId,
|
|
736
|
+
toolCallId: typeof evt.toolCallId === "string" ? evt.toolCallId : "",
|
|
737
|
+
result: evt.result ?? null,
|
|
738
|
+
isError: evt.isError === true
|
|
739
|
+
};
|
|
740
|
+
// ── Turn end ────────────────────────────────────────────────
|
|
741
|
+
case "agent_end": {
|
|
742
|
+
const rawReason = typeof evt.reason === "string" ? evt.reason : "complete";
|
|
743
|
+
const reason = mapMastraFinishReason(rawReason);
|
|
744
|
+
return { kind: "turn-end", sessionId, reason };
|
|
745
|
+
}
|
|
746
|
+
// ── Final result line ────────────────────────────────────────
|
|
747
|
+
// Always written last, once, whether or not `agent_end` fired —
|
|
748
|
+
// pre-flight failures (bad model, unresolvable thread, missing API
|
|
749
|
+
// key) call straight into this without ever streaming an
|
|
750
|
+
// `agent_end` or `error` event. `turn-end` already came from
|
|
751
|
+
// `agent_end` on the success path, so this only needs to surface
|
|
752
|
+
// an error for the pre-flight-failure path.
|
|
753
|
+
case "result": {
|
|
754
|
+
const err = evt.error;
|
|
755
|
+
if (!err) return null;
|
|
756
|
+
return {
|
|
757
|
+
kind: "error",
|
|
758
|
+
sessionId,
|
|
759
|
+
error: {
|
|
760
|
+
message: typeof err.message === "string" ? err.message : "Unknown error",
|
|
761
|
+
...stderrLines.length ? { data: { stderr: stderrLines.join("\n") } } : {}
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
// ── Errors ─────────────────────────────────────────────────
|
|
766
|
+
case "error": {
|
|
767
|
+
const err = evt.error;
|
|
768
|
+
return {
|
|
769
|
+
kind: "error",
|
|
770
|
+
sessionId,
|
|
771
|
+
error: {
|
|
772
|
+
message: typeof err?.message === "string" ? err.message : "Unknown error",
|
|
773
|
+
...stderrLines.length ? { data: { stderr: stderrLines.join("\n") } } : {}
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
// ── Shell output (tool-like) ────────────────────────────────
|
|
778
|
+
case "shell_output":
|
|
779
|
+
return typeof evt.output === "string" ? {
|
|
780
|
+
kind: "tool-result",
|
|
781
|
+
sessionId,
|
|
782
|
+
toolCallId: "",
|
|
783
|
+
result: evt.output,
|
|
784
|
+
isError: false
|
|
785
|
+
} : null;
|
|
786
|
+
// ── Skipped events ─────────────────────────────────────────
|
|
787
|
+
case "agent_start":
|
|
788
|
+
case "subagent_start":
|
|
789
|
+
case "subagent_end":
|
|
790
|
+
case "tool_approval_required":
|
|
791
|
+
case "tool_suspended":
|
|
792
|
+
return null;
|
|
793
|
+
default:
|
|
794
|
+
return null;
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
function mapMastraFinishReason(raw) {
|
|
798
|
+
switch (raw) {
|
|
799
|
+
case "complete":
|
|
800
|
+
return "completed";
|
|
801
|
+
case "aborted":
|
|
802
|
+
case "suspended":
|
|
803
|
+
return "cancelled";
|
|
804
|
+
case "error":
|
|
805
|
+
return "error";
|
|
806
|
+
default:
|
|
807
|
+
return "completed";
|
|
808
|
+
}
|
|
809
|
+
}
|
|
531
810
|
function waitForExit(child) {
|
|
532
811
|
return new Promise((resolve) => {
|
|
533
812
|
child.once("exit", (code) => resolve(code));
|
|
@@ -535,6 +814,27 @@ function waitForExit(child) {
|
|
|
535
814
|
});
|
|
536
815
|
}
|
|
537
816
|
|
|
817
|
+
// src/protocol/proprietary.ts
|
|
818
|
+
async function createProprietaryProtocolArm(options) {
|
|
819
|
+
let mod;
|
|
820
|
+
try {
|
|
821
|
+
mod = await import(options.adapter);
|
|
822
|
+
} catch (err) {
|
|
823
|
+
const cause = err instanceof Error ? err.message : String(err);
|
|
824
|
+
throw new Error(
|
|
825
|
+
`createProprietaryProtocolArm: could not load adapter package '${options.adapter}'. Install it with: npm i ${options.adapter}
|
|
826
|
+
cause: ${cause}`
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
const candidate = "createAgentCliClient" in mod ? mod.createAgentCliClient : mod.default;
|
|
830
|
+
if (typeof candidate !== "function") {
|
|
831
|
+
throw new Error(
|
|
832
|
+
`createProprietaryProtocolArm: adapter package '${options.adapter}' does not export a 'createAgentCliClient' factory function (or a default export function). A protocol="proprietary" adapter must export createAgentCliClient(definition: AgentCliHandle): AgentCliClient | Promise<AgentCliClient>.`
|
|
833
|
+
);
|
|
834
|
+
}
|
|
835
|
+
return await candidate(options.definition);
|
|
836
|
+
}
|
|
837
|
+
|
|
538
838
|
// src/manifest/compose.ts
|
|
539
839
|
var RuntimeConfigError = class extends Error {
|
|
540
840
|
code;
|
|
@@ -735,32 +1035,51 @@ function createAgentCliRuntime(definition) {
|
|
|
735
1035
|
...composed.env,
|
|
736
1036
|
...opts?.env ?? {}
|
|
737
1037
|
};
|
|
1038
|
+
const permissionMode = resolveClaudeCodePermissionMode(
|
|
1039
|
+
definition,
|
|
1040
|
+
opts?.config?.mode
|
|
1041
|
+
);
|
|
1042
|
+
if (permissionMode) {
|
|
1043
|
+
const configDir = mkdtempSync(
|
|
1044
|
+
join(tmpdir(), "agentproto-claude-config-")
|
|
1045
|
+
);
|
|
1046
|
+
writeFileSync(
|
|
1047
|
+
join(configDir, "settings.json"),
|
|
1048
|
+
JSON.stringify({ permissions: { defaultMode: permissionMode } })
|
|
1049
|
+
);
|
|
1050
|
+
env.CLAUDE_CONFIG_DIR = configDir;
|
|
1051
|
+
}
|
|
738
1052
|
if (definition.protocol === "print") {
|
|
739
1053
|
return createPrintSession({
|
|
740
1054
|
bin: definition.bin,
|
|
741
1055
|
baseArgs: composed.binArgs,
|
|
742
1056
|
cwd,
|
|
743
1057
|
env,
|
|
744
|
-
...opts?.resumeSessionId ? { resumeSessionId: opts.resumeSessionId } : {}
|
|
1058
|
+
...opts?.resumeSessionId ? { resumeSessionId: opts.resumeSessionId } : {},
|
|
1059
|
+
...opts?.mcpServers ? { mcpServers: opts.mcpServers } : {},
|
|
1060
|
+
printConfig: definition.print
|
|
745
1061
|
});
|
|
746
1062
|
}
|
|
747
|
-
|
|
748
|
-
cwd,
|
|
749
|
-
env,
|
|
750
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
751
|
-
signal: opts?.signal
|
|
752
|
-
});
|
|
1063
|
+
let child;
|
|
753
1064
|
const stderrBuf = [];
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
1065
|
+
if (definition.protocol !== "proprietary") {
|
|
1066
|
+
child = spawn(definition.bin, composed.binArgs, {
|
|
1067
|
+
cwd,
|
|
1068
|
+
env,
|
|
1069
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
1070
|
+
signal: opts?.signal
|
|
1071
|
+
});
|
|
1072
|
+
const STDERR_KEEP_LINES = 80;
|
|
1073
|
+
child.stderr?.setEncoding("utf8");
|
|
1074
|
+
child.stderr?.on("data", (chunk) => {
|
|
1075
|
+
for (const line of chunk.split(/\r?\n/)) {
|
|
1076
|
+
if (!line) continue;
|
|
1077
|
+
stderrBuf.push(line);
|
|
1078
|
+
if (stderrBuf.length > STDERR_KEEP_LINES) stderrBuf.shift();
|
|
1079
|
+
}
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
const arm = await buildProtocolArm(definition, child, cwd, opts?.config?.mode);
|
|
764
1083
|
arm._stderrTail = () => stderrBuf.join("\n");
|
|
765
1084
|
const abortController = new AbortController();
|
|
766
1085
|
if (opts?.signal) {
|
|
@@ -772,6 +1091,7 @@ function createAgentCliRuntime(definition) {
|
|
|
772
1091
|
const optEffort = opts?.config?.options?.effort;
|
|
773
1092
|
const modelApply = definition.models?.apply ?? "config";
|
|
774
1093
|
const configModel = optModel && modelApply === "config" ? String(optModel) : void 0;
|
|
1094
|
+
const turnIdleTimeoutMs = opts?.turnIdleTimeoutMs ?? definition.session?.turn_idle_timeout_ms;
|
|
775
1095
|
await arm.connect({
|
|
776
1096
|
cwd,
|
|
777
1097
|
env,
|
|
@@ -779,7 +1099,9 @@ function createAgentCliRuntime(definition) {
|
|
|
779
1099
|
...opts?.resumeSessionId ? { resumeSessionId: opts.resumeSessionId } : {},
|
|
780
1100
|
...opts?.mcpServers ? { mcpServers: opts.mcpServers } : {},
|
|
781
1101
|
...configModel ? { model: configModel } : {},
|
|
782
|
-
...optEffort ? { effort: String(optEffort) } : {}
|
|
1102
|
+
...optEffort ? { effort: String(optEffort) } : {},
|
|
1103
|
+
...opts?.onActivity ? { onActivity: opts.onActivity } : {},
|
|
1104
|
+
...turnIdleTimeoutMs !== void 0 ? { turnIdleTimeoutMs } : {}
|
|
783
1105
|
});
|
|
784
1106
|
if (optModel && modelApply === "command") {
|
|
785
1107
|
await applyModelCommand(arm, String(optModel));
|
|
@@ -787,6 +1109,7 @@ function createAgentCliRuntime(definition) {
|
|
|
787
1109
|
const sessionId = arm.sessionId ?? randomUUID();
|
|
788
1110
|
return {
|
|
789
1111
|
sessionId,
|
|
1112
|
+
pid: child?.pid,
|
|
790
1113
|
send(message) {
|
|
791
1114
|
const turnId = randomUUID();
|
|
792
1115
|
return promptTurn(arm, turnId, message);
|
|
@@ -796,7 +1119,7 @@ function createAgentCliRuntime(definition) {
|
|
|
796
1119
|
},
|
|
797
1120
|
async close() {
|
|
798
1121
|
await arm.close();
|
|
799
|
-
if (!child.killed) child.kill("SIGTERM");
|
|
1122
|
+
if (child && !child.killed) child.kill("SIGTERM");
|
|
800
1123
|
}
|
|
801
1124
|
};
|
|
802
1125
|
}
|
|
@@ -839,24 +1162,39 @@ async function* promptTurn(arm, turnId, message) {
|
|
|
839
1162
|
yield evt;
|
|
840
1163
|
}
|
|
841
1164
|
}
|
|
842
|
-
function buildProtocolArm(def, child, cwd) {
|
|
1165
|
+
async function buildProtocolArm(def, child, cwd, requestedMode) {
|
|
843
1166
|
switch (def.protocol) {
|
|
844
1167
|
case "acp":
|
|
1168
|
+
if (!child) {
|
|
1169
|
+
throw new Error("createAgentCliRuntime: acp protocol requires a spawned subprocess");
|
|
1170
|
+
}
|
|
845
1171
|
return createAcpProtocolArm({
|
|
846
1172
|
child,
|
|
847
1173
|
cwd,
|
|
848
|
-
clientInfo: { name: def.id, version: def.version }
|
|
1174
|
+
clientInfo: { name: def.id, version: def.version },
|
|
1175
|
+
requestedMode
|
|
849
1176
|
});
|
|
850
1177
|
case "mcp":
|
|
851
1178
|
throw new Error("createAgentCliRuntime: mcp protocol arm not yet implemented");
|
|
852
1179
|
case "proprietary":
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
1180
|
+
if (!def.adapter) {
|
|
1181
|
+
throw new Error(
|
|
1182
|
+
"createAgentCliRuntime: proprietary protocol requires manifest.adapter"
|
|
1183
|
+
);
|
|
1184
|
+
}
|
|
1185
|
+
return createProprietaryProtocolArm({ adapter: def.adapter, definition: def });
|
|
856
1186
|
case "print":
|
|
857
1187
|
throw new Error("createAgentCliRuntime: print arm bypasses buildProtocolArm");
|
|
858
1188
|
}
|
|
859
1189
|
}
|
|
1190
|
+
function resolveClaudeCodePermissionMode(definition, configMode) {
|
|
1191
|
+
if (definition.id !== "claude-code" || !configMode) return void 0;
|
|
1192
|
+
const mode = (definition.modes ?? []).find((m) => m.id === configMode);
|
|
1193
|
+
const args = mode?.bin_args_append ?? [];
|
|
1194
|
+
const flagIndex = args.indexOf("--permission-mode");
|
|
1195
|
+
if (flagIndex === -1 || flagIndex + 1 >= args.length) return void 0;
|
|
1196
|
+
return args[flagIndex + 1];
|
|
1197
|
+
}
|
|
860
1198
|
function filterStringEnv(env) {
|
|
861
1199
|
const out = {};
|
|
862
1200
|
for (const [k, v] of Object.entries(env)) {
|
|
@@ -865,6 +1203,6 @@ function filterStringEnv(env) {
|
|
|
865
1203
|
return out;
|
|
866
1204
|
}
|
|
867
1205
|
|
|
868
|
-
export { RuntimeConfigError, agentCliFrontmatterSchema, autoAllowPermissionHandler, composeSpawn, createAcpProtocolArm, createAgentCliRuntime, createPrintSession, defineAgentCli, resolveContinuationStrategy, runtimeConfigSchema };
|
|
869
|
-
//# sourceMappingURL=chunk-
|
|
870
|
-
//# sourceMappingURL=chunk-
|
|
1206
|
+
export { RuntimeConfigError, agentCliFrontmatterSchema, autoAllowPermissionHandler, composeSpawn, createAcpProtocolArm, createAgentCliRuntime, createMastraMapperState, createPrintSession, createProprietaryProtocolArm, defineAgentCli, mapMastraEvent, planModePermissionHandler, resolveContinuationStrategy, runtimeConfigSchema, toFileBasedMcpServers };
|
|
1207
|
+
//# sourceMappingURL=chunk-KHHRPQ2Q.mjs.map
|
|
1208
|
+
//# sourceMappingURL=chunk-KHHRPQ2Q.mjs.map
|