@cydm/pie 1.0.13 → 1.0.15

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/cli.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  getSettingsPath,
15
15
  getThemesDir,
16
16
  migrateConfigFromAgentDir
17
- } from "./chunks/chunk-EFG2MQFD.js";
17
+ } from "./chunks/chunk-55RUSXEA.js";
18
18
  import {
19
19
  AGENTS_CONTEXT_FILE_NAME,
20
20
  AgentSessionController,
@@ -52,7 +52,8 @@ import {
52
52
  selectToolsForRuntimePolicy,
53
53
  shouldPreserveExecutionStateForUserText,
54
54
  supersedeExecutionState
55
- } from "./chunks/chunk-LF5Q7BVU.js";
55
+ } from "./chunks/chunk-R5LYKDKA.js";
56
+ import "./chunks/chunk-VE2HDCNB.js";
56
57
  import {
57
58
  Deref,
58
59
  Errors,
@@ -86,7 +87,7 @@ import {
86
87
  setLogger,
87
88
  sortToolModelCandidatesByCapability,
88
89
  type_exports
89
- } from "./chunks/chunk-D7NAXU7F.js";
90
+ } from "./chunks/chunk-5DA2D3K2.js";
90
91
  import {
91
92
  resolveCliProjectRoot
92
93
  } from "./chunks/chunk-NTYHFBUA.js";
@@ -43943,7 +43944,7 @@ import * as path26 from "path";
43943
43944
 
43944
43945
  // src/cli-args.ts
43945
43946
  var FLAGS_WITH_VALUES = /* @__PURE__ */ new Set(["--session-id", "--extension-path"]);
43946
- var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["--raw-output", "--json-output"]);
43947
+ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["--raw-output", "--json-output", "--json-events"]);
43947
43948
  var HELP_FLAGS = /* @__PURE__ */ new Set(["help", "--help", "-h"]);
43948
43949
  var COMMANDS = /* @__PURE__ */ new Set(["chat", "help"]);
43949
43950
  function parseCliInvocation(args) {
@@ -64043,6 +64044,34 @@ function buildCliSystemPrompt(options) {
64043
64044
  ].filter(Boolean).join("\n\n");
64044
64045
  }
64045
64046
 
64047
+ // src/runtime/retry-policy.ts
64048
+ var TRANSIENT_MODEL_ERROR_PATTERN = /overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated|retry delay|sse stream aborted|sse stream closed before end|sse stream ended before response completed/i;
64049
+ var USER_ABORT_PATTERN = /request was aborted/i;
64050
+ var CLI_RETRY_MAX_RETRIES = 3;
64051
+ var CLI_RETRY_BASE_DELAY_MS = 2e3;
64052
+ function isCliContextOverflowError(errorMessage3) {
64053
+ return /context length exceeded|context_length_exceeded|maximum context length|maximum context size|too many tokens|input.*too long|prompt.*too long|context window|token limit exceeded|exceeds.{0,20}context/i.test(
64054
+ errorMessage3
64055
+ );
64056
+ }
64057
+ function isCliRetryableError(errorMessage3) {
64058
+ if (isCliContextOverflowError(errorMessage3)) {
64059
+ return false;
64060
+ }
64061
+ if (USER_ABORT_PATTERN.test(errorMessage3)) {
64062
+ return false;
64063
+ }
64064
+ return TRANSIENT_MODEL_ERROR_PATTERN.test(errorMessage3);
64065
+ }
64066
+ function getCliRetryBaseDelayMs() {
64067
+ const override = process.env.PIE_TEST_CLI_RETRY_BASE_DELAY_MS;
64068
+ if (!override) {
64069
+ return CLI_RETRY_BASE_DELAY_MS;
64070
+ }
64071
+ const parsed = Number(override);
64072
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : CLI_RETRY_BASE_DELAY_MS;
64073
+ }
64074
+
64046
64075
  // src/runtime/interactive-context-ui.ts
64047
64076
  function calculateContextUsage(host) {
64048
64077
  const messages = host.agent?.state.messages ?? [];
@@ -64266,9 +64295,7 @@ function setupAutocomplete(host) {
64266
64295
  host.editor.setAutocompleteProvider(provider);
64267
64296
  }
64268
64297
  function isContextOverflowError(errorMessage3) {
64269
- return /context length exceeded|context_length_exceeded|maximum context length|maximum context size|too many tokens|input.*too long|prompt.*too long|context window|token limit exceeded|exceeds.{0,20}context/i.test(
64270
- errorMessage3
64271
- );
64298
+ return isCliContextOverflowError(errorMessage3);
64272
64299
  }
64273
64300
  function shouldAutoCompact(host, contextTokens, contextWindow) {
64274
64301
  if (!host.options.settingsManager.getAutoCompactEnabled()) return false;
@@ -64277,9 +64304,7 @@ function shouldAutoCompact(host, contextTokens, contextWindow) {
64277
64304
  return contextTokens > contextWindow - reserveTokens;
64278
64305
  }
64279
64306
  function isRetryableError(errorMessage3) {
64280
- return /overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated|retry delay/i.test(
64281
- errorMessage3
64282
- );
64307
+ return isCliRetryableError(errorMessage3);
64283
64308
  }
64284
64309
  function isInvalidFileReferenceError(errorMessage3) {
64285
64310
  return /not the owner of this file|owner of this file|invalid_authentication_error/i.test(
@@ -64778,9 +64803,9 @@ function createInteractiveAgentSessionController(host) {
64778
64803
  },
64779
64804
  getAutoContinueMessage: () => host.getTodoAutoContinueMessage(),
64780
64805
  retry: {
64781
- isRetryableError: (errorMessage3) => !host._isContextOverflowError(errorMessage3) && host._isRetryableError(errorMessage3),
64782
- maxRetries: 3,
64783
- baseDelayMs: 2e3
64806
+ isRetryableError: (errorMessage3) => !host._isContextOverflowError(errorMessage3) && isCliRetryableError(errorMessage3),
64807
+ maxRetries: CLI_RETRY_MAX_RETRIES,
64808
+ baseDelayMs: getCliRetryBaseDelayMs()
64784
64809
  },
64785
64810
  compaction: {
64786
64811
  compact: async ({ messages }) => createAutoCompactionResult(host, messages)
@@ -66739,7 +66764,7 @@ var InteractiveMode = class {
66739
66764
  if (savedLevel) {
66740
66765
  this.thinkingLevel = savedLevel;
66741
66766
  }
66742
- const { Agent } = await import("./chunks/src-LZC56DRG.js");
66767
+ const { Agent } = await import("./chunks/src-6WPNVGT2.js");
66743
66768
  const activeSession = this.sessionManager.getActiveSession();
66744
66769
  this.agent = new Agent({
66745
66770
  initialState: {
@@ -67303,6 +67328,12 @@ function createNoOpExtensionUIContext() {
67303
67328
  custom: async () => void 0
67304
67329
  };
67305
67330
  }
67331
+ function readAssistantError(message) {
67332
+ if (message.role !== "assistant") {
67333
+ return "";
67334
+ }
67335
+ return message.errorMessage || "assistant response failed";
67336
+ }
67306
67337
  async function loadPrintModeExtensions(params) {
67307
67338
  const uiContext = createNoOpExtensionUIContext();
67308
67339
  const executionState = new ExecutionStateManager();
@@ -67400,7 +67431,7 @@ async function runPrintMode(params) {
67400
67431
  `);
67401
67432
  console.log("Assistant: ");
67402
67433
  }
67403
- const { Agent: AgentClass } = await import("./chunks/src-LZC56DRG.js");
67434
+ const { Agent: AgentClass } = await import("./chunks/src-6WPNVGT2.js");
67404
67435
  let agent;
67405
67436
  const printModeExtensions = await loadPrintModeExtensions({
67406
67437
  cwd: runtime.cwd,
@@ -67437,8 +67468,10 @@ async function runPrintMode(params) {
67437
67468
  tools: printModeTools,
67438
67469
  thinkingLevel: "off"
67439
67470
  },
67440
- apiKey: runtime.apiKey
67471
+ apiKey: runtime.apiKey,
67472
+ streamFn: params.streamFn
67441
67473
  });
67474
+ const sessionTrace = new SessionTraceWriter(runtime.paths.sessionsDir, runtime.sessionManager);
67442
67475
  const agentSessionController = new AgentSessionController({
67443
67476
  agent,
67444
67477
  sessionManager: runtime.sessionManager,
@@ -67458,9 +67491,25 @@ async function runPrintMode(params) {
67458
67491
  systemPrompt: result.systemPrompt ?? context.baseSystemPrompt ?? baseSystemPrompt,
67459
67492
  messages: result.messages?.length ? [...context.messages, ...result.messages] : context.messages
67460
67493
  };
67494
+ },
67495
+ retry: {
67496
+ isRetryableError: isCliRetryableError,
67497
+ maxRetries: CLI_RETRY_MAX_RETRIES,
67498
+ baseDelayMs: getCliRetryBaseDelayMs()
67499
+ },
67500
+ onEvent: (event) => {
67501
+ sessionTrace.noteRuntimeEvent(event.type, event);
67502
+ if (event.type === "retry_scheduled") {
67503
+ console.error(`Transient request error: ${event.errorMessage}. Retrying in ${event.delayMs / 1e3}s (${event.attempt}/${event.maxRetries}).`);
67504
+ } else if (event.type === "retry_start") {
67505
+ console.error(`Retrying request (${event.attempt}/${event.maxRetries})...`);
67506
+ } else if (event.type === "retry_succeeded") {
67507
+ console.error(`Retry succeeded after ${event.attempts} attempt${event.attempts === 1 ? "" : "s"}.`);
67508
+ } else if (event.type === "retry_exhausted") {
67509
+ console.error(`Request failed after ${event.maxRetries} retries: ${event.errorMessage}`);
67510
+ }
67461
67511
  }
67462
67512
  });
67463
- const sessionTrace = new SessionTraceWriter(runtime.paths.sessionsDir, runtime.sessionManager);
67464
67513
  sessionTrace.notePendingUserText(params.initialPrompt);
67465
67514
  attachAgentEventsToSessionTrace({ agent, trace: sessionTrace });
67466
67515
  agent.setTools(wrapToolsWithExtensions(agent.state.tools, printModeExtensions.runner));
@@ -67470,19 +67519,37 @@ async function runPrintMode(params) {
67470
67519
  await agentSessionController.prompt(params.initialPrompt, { source: "print" });
67471
67520
  sessionTrace.noteDispatchSettled({ mode: "print" });
67472
67521
  sessionTrace.noteWaitForIdleStart({ mode: "print" });
67473
- await agentSessionController.waitForIdle();
67522
+ await agentSessionController.waitForSettled();
67474
67523
  sessionTrace.noteWaitForIdleSettled({ mode: "print" });
67475
67524
  const messages = agent.state.messages;
67476
67525
  const lastMessage = messages[messages.length - 1];
67477
67526
  let assistantText = "";
67527
+ let assistantError = "";
67478
67528
  if (lastMessage?.role === "assistant") {
67479
67529
  for (const content of lastMessage.content) {
67480
67530
  if (typeof content === "object" && "type" in content && content.type === "text" && "text" in content) {
67481
67531
  assistantText += content.text;
67482
67532
  }
67483
67533
  }
67534
+ if (lastMessage.stopReason === "error" || lastMessage.stopReason === "aborted") {
67535
+ assistantError = readAssistantError(lastMessage);
67536
+ }
67484
67537
  }
67485
- if (params.jsonOutput) {
67538
+ if (assistantError) {
67539
+ process.exitCode = 1;
67540
+ if (params.jsonOutput) {
67541
+ console.log(
67542
+ JSON.stringify({
67543
+ ok: false,
67544
+ error: assistantError,
67545
+ sessionId: runtime.sessionManager.getActiveSession()?.id,
67546
+ provider: runtime.provider,
67547
+ modelId: runtime.modelId
67548
+ })
67549
+ );
67550
+ }
67551
+ console.error("Error:", assistantError);
67552
+ } else if (params.jsonOutput) {
67486
67553
  console.log(
67487
67554
  JSON.stringify({
67488
67555
  ok: true,
@@ -67520,6 +67587,628 @@ async function runPrintMode(params) {
67520
67587
  sessionTrace.flush();
67521
67588
  }
67522
67589
 
67590
+ // src/app/json-events-mode.ts
67591
+ import readline from "node:readline";
67592
+ var MAX_EVENT_OBJECT_KEYS = 50;
67593
+ var MAX_EVENT_ARRAY_ITEMS = 50;
67594
+ var MAX_EVENT_VALUE_DEPTH = 4;
67595
+ var MAX_EVENT_STRING_LENGTH = 4e3;
67596
+ function createNoOpExtensionUIContext2() {
67597
+ return {
67598
+ notify: () => {
67599
+ },
67600
+ select: async () => void 0,
67601
+ confirm: async () => false,
67602
+ input: async () => void 0,
67603
+ editor: async () => void 0,
67604
+ custom: async () => void 0
67605
+ };
67606
+ }
67607
+ function writeEvent(event) {
67608
+ process.stdout.write(`${JSON.stringify(event)}
67609
+ `);
67610
+ }
67611
+ function toJsonValue(value, depth = 0) {
67612
+ if (value === null) return null;
67613
+ if (typeof value === "string") {
67614
+ return value.length > MAX_EVENT_STRING_LENGTH ? `${value.slice(0, MAX_EVENT_STRING_LENGTH)}...` : value;
67615
+ }
67616
+ if (typeof value === "number") return Number.isFinite(value) ? value : String(value);
67617
+ if (typeof value === "boolean") return value;
67618
+ if (typeof value === "bigint") return value.toString();
67619
+ if (typeof value !== "object") return void 0;
67620
+ if (depth >= MAX_EVENT_VALUE_DEPTH) return "[truncated]";
67621
+ if (Array.isArray(value)) {
67622
+ return value.slice(0, MAX_EVENT_ARRAY_ITEMS).map((item) => toJsonValue(item, depth + 1) ?? null);
67623
+ }
67624
+ const result = {};
67625
+ for (const [key, item] of Object.entries(value).slice(0, MAX_EVENT_OBJECT_KEYS)) {
67626
+ result[key] = toJsonValue(item, depth + 1);
67627
+ }
67628
+ return result;
67629
+ }
67630
+ function isRecord3(value) {
67631
+ return !!value && typeof value === "object" && !Array.isArray(value);
67632
+ }
67633
+ function parseInput(line) {
67634
+ let parsed;
67635
+ try {
67636
+ parsed = JSON.parse(line);
67637
+ } catch {
67638
+ return null;
67639
+ }
67640
+ if (!isRecord3(parsed) || typeof parsed.type !== "string") return null;
67641
+ if (parsed.type === "shutdown") {
67642
+ return { type: "shutdown", reason: typeof parsed.reason === "string" ? parsed.reason : void 0 };
67643
+ }
67644
+ if (parsed.type === "turn.interrupt") {
67645
+ return {
67646
+ type: "turn.interrupt",
67647
+ sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : void 0,
67648
+ turnId: typeof parsed.turnId === "string" ? parsed.turnId : void 0,
67649
+ reason: typeof parsed.reason === "string" ? parsed.reason : void 0
67650
+ };
67651
+ }
67652
+ if (parsed.type === "turn.request" && typeof parsed.turnId === "string" && typeof parsed.prompt === "string") {
67653
+ return {
67654
+ type: "turn.request",
67655
+ sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : void 0,
67656
+ turnId: parsed.turnId,
67657
+ prompt: parsed.prompt,
67658
+ cwd: typeof parsed.cwd === "string" ? parsed.cwd : void 0,
67659
+ metadata: isRecord3(parsed.metadata) ? parsed.metadata : void 0
67660
+ };
67661
+ }
67662
+ return null;
67663
+ }
67664
+ function assistantTextFromAgent(agent) {
67665
+ const messages = agent?.state.messages ?? [];
67666
+ const lastMessage = messages[messages.length - 1];
67667
+ if (lastMessage?.role !== "assistant") return "";
67668
+ let text = "";
67669
+ for (const content of lastMessage.content) {
67670
+ if (content.type === "text") {
67671
+ text += content.text;
67672
+ }
67673
+ }
67674
+ return text;
67675
+ }
67676
+ function assistantErrorFromAgent(agent) {
67677
+ const messages = agent?.state.messages ?? [];
67678
+ const lastMessage = messages[messages.length - 1];
67679
+ if (lastMessage?.role !== "assistant") return "";
67680
+ if (lastMessage.stopReason !== "error" && lastMessage.stopReason !== "aborted") return "";
67681
+ return lastMessage.errorMessage || "assistant response failed";
67682
+ }
67683
+ function readProgressText(value) {
67684
+ return typeof value === "string" ? value : "";
67685
+ }
67686
+ function extractJsonEventsToolProgressText(partialResult) {
67687
+ const plainText = readProgressText(partialResult).trim();
67688
+ if (plainText) return plainText;
67689
+ if (!isRecord3(partialResult)) return "";
67690
+ const content = partialResult.content;
67691
+ if (Array.isArray(content)) {
67692
+ return content.map((block) => isRecord3(block) && block.type === "text" ? readProgressText(block.text) : "").filter(Boolean).join("\n").trim();
67693
+ }
67694
+ const directText = readProgressText(partialResult.text) || readProgressText(partialResult.message);
67695
+ if (directText) return directText.trim();
67696
+ const details = partialResult.details;
67697
+ if (isRecord3(details)) {
67698
+ return (readProgressText(details.text) || readProgressText(details.message)).trim();
67699
+ }
67700
+ return "";
67701
+ }
67702
+ async function loadJsonModeExtensions(params) {
67703
+ const uiContext = createNoOpExtensionUIContext2();
67704
+ const executionState = new ExecutionStateManager();
67705
+ const activeSession = params.runtime.sessionManager.getActiveSession();
67706
+ executionState.restoreFromMetadata(activeSession?.metadata?.executionState);
67707
+ const actions = {
67708
+ setActiveTools: (toolNames) => {
67709
+ const agent = params.getAgent();
67710
+ if (!agent) return;
67711
+ agent.state.tools = agent.state.tools.filter((tool) => toolNames.includes(tool.name));
67712
+ },
67713
+ getActiveTools: () => params.getAgent()?.state.tools.map((tool) => tool.name) ?? [],
67714
+ sendUserMessage: () => {
67715
+ },
67716
+ setPlanMode: () => {
67717
+ },
67718
+ setExecutionReminder: (text) => {
67719
+ const session = params.runtime.sessionManager.getActiveSession();
67720
+ if (!session) return;
67721
+ if (text) {
67722
+ session.metadata.executionReminder = text;
67723
+ } else {
67724
+ delete session.metadata.executionReminder;
67725
+ }
67726
+ },
67727
+ getExecutionState: () => executionState.read(),
67728
+ setExecutionState: (state) => {
67729
+ const nextState = executionState.replace(state);
67730
+ const session = params.runtime.sessionManager.getActiveSession();
67731
+ if (session) {
67732
+ session.metadata.executionState = executionState.createMetadata();
67733
+ }
67734
+ return nextState;
67735
+ },
67736
+ cwd: params.runtime.cwd,
67737
+ apiKey: params.runtime.apiKey,
67738
+ model: params.runtime.model,
67739
+ skills: params.runtime.skills,
67740
+ getAllTools: () => params.getAgent()?.state.tools.map((tool) => ({
67741
+ name: tool.name,
67742
+ description: tool.description,
67743
+ parameters: tool.parameters
67744
+ })) ?? [],
67745
+ getRuntimeTools: () => params.getAgent()?.state.tools ?? [],
67746
+ resolveModelClass: (modelClass) => params.runtime.modelRegistry.resolveModelClass(modelClass),
67747
+ getMessages: () => params.getAgent()?.state.messages ?? [],
67748
+ getSessionMetadata: () => ({ ...params.runtime.sessionManager.getActiveSession()?.metadata ?? {} }),
67749
+ setSessionMetadata: (key, value) => {
67750
+ const session = params.runtime.sessionManager.getActiveSession();
67751
+ if (!session) return;
67752
+ session.metadata[key] = value;
67753
+ },
67754
+ yoloMode: false
67755
+ };
67756
+ const { extensions } = await loadExtensions(
67757
+ params.runtime.extensionPaths,
67758
+ params.runtime.cwd,
67759
+ uiContext,
67760
+ () => params.getAgent()?.abort(),
67761
+ () => true,
67762
+ false,
67763
+ actions
67764
+ );
67765
+ const runner = new ExtensionRunner(
67766
+ extensions,
67767
+ actions,
67768
+ {
67769
+ isIdle: () => true,
67770
+ abort: () => params.getAgent()?.abort()
67771
+ },
67772
+ false
67773
+ );
67774
+ runner.setUIContext(uiContext);
67775
+ return {
67776
+ runner,
67777
+ extensionTools: convertExtensionTools(extensions),
67778
+ extensionCount: extensions.length
67779
+ };
67780
+ }
67781
+ async function runJsonEventsMode(params) {
67782
+ const sessionId = params.explicitSessionId || params.runtime?.sessionManager.getActiveSession()?.id || `pie-json-${Date.now()}`;
67783
+ let activeTurn = null;
67784
+ let agent;
67785
+ let controller;
67786
+ let disposeAgentSubscription;
67787
+ let disposeSemanticSubscription;
67788
+ let trace;
67789
+ let lastRetryEvent;
67790
+ const noProgressTimeoutMs = Number(process.env.PIE_JSON_EVENTS_NO_PROGRESS_MS || 6e5);
67791
+ const mockResponseDelayMs = Number(process.env.PIE_TEST_MOCK_RESPONSE_DELAY_MS || 0);
67792
+ writeEvent({ type: "agent.ready", sessionId });
67793
+ function sessionMismatchError(requestedSessionId) {
67794
+ return `session mismatch: JSON events process is bound to ${sessionId}, received ${requestedSessionId}`;
67795
+ }
67796
+ function isSessionMismatch(message) {
67797
+ return typeof message.sessionId === "string" && message.sessionId !== sessionId;
67798
+ }
67799
+ function delay(ms) {
67800
+ return new Promise((resolve4) => setTimeout(resolve4, Math.max(0, ms)));
67801
+ }
67802
+ function touch() {
67803
+ if (activeTurn) {
67804
+ activeTurn.lastActivityAt = Date.now();
67805
+ }
67806
+ }
67807
+ function display(chunk, options) {
67808
+ if (!activeTurn || !chunk) return;
67809
+ if (options?.appendToSummary !== false) {
67810
+ activeTurn.summary += chunk;
67811
+ }
67812
+ touch();
67813
+ writeEvent({
67814
+ type: "display.output",
67815
+ sessionId: activeTurn.sessionId,
67816
+ turnId: activeTurn.turnId,
67817
+ stream: "terminal",
67818
+ chunk
67819
+ });
67820
+ }
67821
+ function finalize(kind, detail) {
67822
+ const turn = activeTurn;
67823
+ if (!turn || turn.finalized) return;
67824
+ turn.finalized = true;
67825
+ switch (kind) {
67826
+ case "completed":
67827
+ writeEvent({ type: "turn.completed", sessionId: turn.sessionId, turnId: turn.turnId, summary: (detail ?? turn.summary).trim() });
67828
+ break;
67829
+ case "failed":
67830
+ writeEvent({ type: "turn.failed", sessionId: turn.sessionId, turnId: turn.turnId, error: detail || "turn failed" });
67831
+ break;
67832
+ case "cancelled":
67833
+ writeEvent({ type: "turn.cancelled", sessionId: turn.sessionId, turnId: turn.turnId, reason: detail || "interrupted" });
67834
+ break;
67835
+ case "stalled":
67836
+ writeEvent({ type: "turn.stalled", sessionId: turn.sessionId, turnId: turn.turnId, reason: detail || "no_progress_timeout" });
67837
+ break;
67838
+ }
67839
+ }
67840
+ function handleSemanticEvent(event) {
67841
+ if (!activeTurn || activeTurn.finalized) return;
67842
+ switch (event.type) {
67843
+ case "assistant_response_delta":
67844
+ display(event.delta);
67845
+ break;
67846
+ case "tool_started":
67847
+ touch();
67848
+ writeEvent({
67849
+ type: "tool.started",
67850
+ sessionId: activeTurn.sessionId,
67851
+ turnId: activeTurn.turnId,
67852
+ toolCallId: event.toolCallId,
67853
+ name: event.toolName,
67854
+ data: toJsonValue({ args: event.args })
67855
+ });
67856
+ break;
67857
+ case "tool_progressed":
67858
+ touch();
67859
+ {
67860
+ const progressText = extractJsonEventsToolProgressText(event.partialResult);
67861
+ if (progressText) {
67862
+ display(progressText.endsWith("\n") ? progressText : `${progressText}
67863
+ `, { appendToSummary: false });
67864
+ }
67865
+ }
67866
+ break;
67867
+ case "tool_finished":
67868
+ touch();
67869
+ writeEvent({
67870
+ type: "tool.completed",
67871
+ sessionId: activeTurn.sessionId,
67872
+ turnId: activeTurn.turnId,
67873
+ toolCallId: event.toolCallId,
67874
+ name: event.toolName,
67875
+ status: event.isError ? "error" : "ok",
67876
+ data: toJsonValue({
67877
+ resultText: extractJsonEventsToolProgressText(event.result),
67878
+ isError: event.isError
67879
+ })
67880
+ });
67881
+ break;
67882
+ }
67883
+ }
67884
+ function handleControllerEvent(event) {
67885
+ trace?.noteRuntimeEvent(event.type, event);
67886
+ if (!activeTurn || activeTurn.finalized) return;
67887
+ if (event.type === "retry_scheduled") {
67888
+ lastRetryEvent = {
67889
+ attempt: event.attempt,
67890
+ maxRetries: event.maxRetries,
67891
+ delayMs: event.delayMs,
67892
+ error: event.errorMessage
67893
+ };
67894
+ touch();
67895
+ writeEvent({
67896
+ type: "turn.retry.scheduled",
67897
+ sessionId: activeTurn.sessionId,
67898
+ turnId: activeTurn.turnId,
67899
+ attempt: event.attempt,
67900
+ maxRetries: event.maxRetries,
67901
+ delayMs: event.delayMs,
67902
+ error: event.errorMessage
67903
+ });
67904
+ } else if (event.type === "retry_start") {
67905
+ activeTurn.summary = "";
67906
+ lastRetryEvent = {
67907
+ attempt: event.attempt,
67908
+ maxRetries: event.maxRetries,
67909
+ delayMs: lastRetryEvent?.delayMs,
67910
+ error: lastRetryEvent?.error
67911
+ };
67912
+ touch();
67913
+ writeEvent({
67914
+ type: "turn.retry.started",
67915
+ sessionId: activeTurn.sessionId,
67916
+ turnId: activeTurn.turnId,
67917
+ attempt: event.attempt,
67918
+ maxRetries: event.maxRetries,
67919
+ delayMs: lastRetryEvent.delayMs,
67920
+ error: lastRetryEvent.error
67921
+ });
67922
+ } else if (event.type === "retry_succeeded") {
67923
+ touch();
67924
+ writeEvent({
67925
+ type: "turn.retry.succeeded",
67926
+ sessionId: activeTurn.sessionId,
67927
+ turnId: activeTurn.turnId,
67928
+ attempt: event.attempts,
67929
+ maxRetries: lastRetryEvent?.maxRetries ?? CLI_RETRY_MAX_RETRIES,
67930
+ delayMs: lastRetryEvent?.delayMs,
67931
+ error: lastRetryEvent?.error
67932
+ });
67933
+ lastRetryEvent = void 0;
67934
+ } else if (event.type === "retry_exhausted") {
67935
+ touch();
67936
+ writeEvent({
67937
+ type: "turn.retry.exhausted",
67938
+ sessionId: activeTurn.sessionId,
67939
+ turnId: activeTurn.turnId,
67940
+ attempt: lastRetryEvent?.attempt ?? event.maxRetries,
67941
+ maxRetries: event.maxRetries,
67942
+ delayMs: lastRetryEvent?.delayMs,
67943
+ error: event.errorMessage
67944
+ });
67945
+ lastRetryEvent = void 0;
67946
+ }
67947
+ }
67948
+ async function ensureRuntime() {
67949
+ if (params.mockResponse !== void 0 || controller) return;
67950
+ const runtime = params.runtime;
67951
+ if (!runtime) {
67952
+ throw new Error("JSON events mode requires a CLI runtime");
67953
+ }
67954
+ if (runtime.initialModel.unconfigured) {
67955
+ return;
67956
+ }
67957
+ const { Agent: AgentClass } = await import("./chunks/src-6WPNVGT2.js");
67958
+ const jsonModeExtensions = await loadJsonModeExtensions({ runtime, getAgent: () => agent });
67959
+ const tools = [...runtime.tools, ...jsonModeExtensions.extensionTools];
67960
+ recordCliCompositionStep(runtime.compositionTrace, {
67961
+ id: "extensions_tool_wrapping",
67962
+ inputSummary: `baseTools=${runtime.tools.length} extensionPaths=${runtime.extensionPaths.length}`,
67963
+ outputSummary: `extensions=${jsonModeExtensions.extensionCount}`,
67964
+ toolCount: tools.length,
67965
+ extensionWrapping: {
67966
+ extensionCount: jsonModeExtensions.extensionCount,
67967
+ extensionToolCount: jsonModeExtensions.extensionTools.length,
67968
+ wrappedToolCount: tools.length
67969
+ }
67970
+ });
67971
+ const baseSystemPrompt = buildCliSystemPrompt({
67972
+ cwd: runtime.cwd,
67973
+ skillsSection: runtime.skillsSection,
67974
+ knowledgeSection: runtime.knowledgeSection,
67975
+ tools: tools.map((tool) => ({ name: tool.name, description: tool.description }))
67976
+ });
67977
+ agent = new AgentClass({
67978
+ initialState: {
67979
+ systemPrompt: baseSystemPrompt,
67980
+ model: runtime.model,
67981
+ tools,
67982
+ thinkingLevel: "off"
67983
+ },
67984
+ apiKey: runtime.apiKey,
67985
+ streamFn: params.streamFn
67986
+ });
67987
+ controller = new AgentSessionController({
67988
+ agent,
67989
+ sessionManager: runtime.sessionManager,
67990
+ cwd: runtime.cwd,
67991
+ baseSystemPrompt,
67992
+ prepareTurn: async (context) => {
67993
+ const result = await jsonModeExtensions.runner.emitBeforeAgentStart({
67994
+ type: "before_agent_start",
67995
+ messages: context.messages,
67996
+ baseSystemPrompt: context.baseSystemPrompt ?? baseSystemPrompt,
67997
+ source: context.source
67998
+ });
67999
+ return {
68000
+ systemPrompt: result?.systemPrompt ?? context.baseSystemPrompt ?? baseSystemPrompt,
68001
+ messages: result?.messages?.length ? [...context.messages, ...result.messages] : context.messages
68002
+ };
68003
+ },
68004
+ retry: {
68005
+ isRetryableError: isCliRetryableError,
68006
+ maxRetries: CLI_RETRY_MAX_RETRIES,
68007
+ baseDelayMs: getCliRetryBaseDelayMs()
68008
+ },
68009
+ onEvent: handleControllerEvent
68010
+ });
68011
+ trace = new SessionTraceWriter(runtime.paths.sessionsDir, runtime.sessionManager);
68012
+ attachAgentEventsToSessionTrace({ agent, trace });
68013
+ agent.setTools(wrapToolsWithExtensions(agent.state.tools, jsonModeExtensions.runner));
68014
+ controller.updateRuntimeContext({ tools: agent.state.tools });
68015
+ disposeSemanticSubscription = agent.subscribeSemantic(handleSemanticEvent);
68016
+ }
68017
+ async function runTurn(message) {
68018
+ if (isSessionMismatch(message)) {
68019
+ writeEvent({
68020
+ type: "turn.failed",
68021
+ sessionId,
68022
+ turnId: message.turnId,
68023
+ error: sessionMismatchError(message.sessionId)
68024
+ });
68025
+ return;
68026
+ }
68027
+ if (activeTurn && !activeTurn.finalized) {
68028
+ writeEvent({
68029
+ type: "turn.failed",
68030
+ sessionId,
68031
+ turnId: message.turnId,
68032
+ error: "another turn is already running"
68033
+ });
68034
+ return;
68035
+ }
68036
+ activeTurn = {
68037
+ sessionId,
68038
+ turnId: message.turnId,
68039
+ prompt: message.prompt,
68040
+ startedAt: Date.now(),
68041
+ lastActivityAt: Date.now(),
68042
+ interrupted: false,
68043
+ stalled: false,
68044
+ finalized: false,
68045
+ summary: ""
68046
+ };
68047
+ const turn = activeTurn;
68048
+ writeEvent({ type: "turn.started", sessionId: activeTurn.sessionId, turnId: activeTurn.turnId });
68049
+ if (params.mockResponse !== void 0) {
68050
+ if (mockResponseDelayMs > 0) {
68051
+ await delay(mockResponseDelayMs);
68052
+ }
68053
+ if (activeTurn !== turn || turn.finalized) {
68054
+ return;
68055
+ }
68056
+ display(params.mockResponse);
68057
+ finalize("completed");
68058
+ if (activeTurn === turn) activeTurn = null;
68059
+ return;
68060
+ }
68061
+ if (params.startupError) {
68062
+ finalize("failed", params.startupError);
68063
+ if (activeTurn === turn) activeTurn = null;
68064
+ return;
68065
+ }
68066
+ try {
68067
+ await ensureRuntime();
68068
+ } catch (error) {
68069
+ finalize("failed", error instanceof Error ? error.message : String(error));
68070
+ if (activeTurn === turn) activeTurn = null;
68071
+ return;
68072
+ }
68073
+ const runtime = params.runtime;
68074
+ if (runtime?.initialModel.unconfigured) {
68075
+ finalize("failed", runtime.initialModel.warning || "No models are configured.");
68076
+ if (activeTurn === turn) activeTurn = null;
68077
+ return;
68078
+ }
68079
+ if (!controller || !agent) {
68080
+ finalize("failed", "JSON events runtime was not initialized");
68081
+ if (activeTurn === turn) activeTurn = null;
68082
+ return;
68083
+ }
68084
+ const progressTimer = setInterval(() => {
68085
+ const turn2 = activeTurn;
68086
+ if (!turn2 || turn2.finalized) return;
68087
+ if (Date.now() - turn2.lastActivityAt >= noProgressTimeoutMs) {
68088
+ turn2.stalled = true;
68089
+ controller?.abort();
68090
+ finalize("stalled", "no_progress_timeout");
68091
+ }
68092
+ }, Math.max(1e3, Math.min(noProgressTimeoutMs, 1e4)));
68093
+ progressTimer.unref?.();
68094
+ try {
68095
+ trace?.notePendingUserText(message.prompt);
68096
+ trace?.noteDispatchStart({ mode: "json-events" });
68097
+ await controller.prompt(message.prompt, { source: "json-events" });
68098
+ trace?.noteDispatchSettled({ mode: "json-events" });
68099
+ trace?.noteWaitForIdleStart({ mode: "json-events" });
68100
+ await controller.waitForSettled();
68101
+ trace?.noteWaitForIdleSettled({ mode: "json-events" });
68102
+ if (!activeTurn?.finalized) {
68103
+ const finalError = assistantErrorFromAgent(agent);
68104
+ if (activeTurn?.interrupted) {
68105
+ finalize("cancelled", "user_interrupt");
68106
+ return;
68107
+ }
68108
+ if (finalError) {
68109
+ finalize("failed", finalError);
68110
+ return;
68111
+ }
68112
+ const text = assistantTextFromAgent(agent);
68113
+ if (!activeTurn?.summary && text) {
68114
+ display(text);
68115
+ }
68116
+ finalize("completed", text || activeTurn?.summary.trim());
68117
+ }
68118
+ } catch (error) {
68119
+ const messageText = error instanceof Error ? error.message : String(error);
68120
+ trace?.noteStalled(messageText, { mode: "json-events" });
68121
+ if (!activeTurn?.finalized) {
68122
+ finalize(activeTurn?.interrupted ? "cancelled" : "failed", activeTurn?.interrupted ? "user_interrupt" : messageText);
68123
+ }
68124
+ } finally {
68125
+ clearInterval(progressTimer);
68126
+ trace?.flush();
68127
+ await runtime?.sessionManager.save();
68128
+ if (activeTurn === turn) activeTurn = null;
68129
+ }
68130
+ }
68131
+ async function interrupt(message) {
68132
+ if (isSessionMismatch(message)) {
68133
+ writeEvent({
68134
+ type: "turn.cancelled",
68135
+ sessionId,
68136
+ turnId: message.turnId || "no-active-turn",
68137
+ reason: sessionMismatchError(message.sessionId)
68138
+ });
68139
+ return;
68140
+ }
68141
+ if (!activeTurn || activeTurn.finalized) {
68142
+ writeEvent({
68143
+ type: "turn.cancelled",
68144
+ sessionId,
68145
+ turnId: message.turnId || "no-active-turn",
68146
+ reason: message.reason || "no_active_turn"
68147
+ });
68148
+ return;
68149
+ }
68150
+ if (message.turnId && message.turnId !== activeTurn.turnId) {
68151
+ writeEvent({
68152
+ type: "turn.cancelled",
68153
+ sessionId,
68154
+ turnId: message.turnId,
68155
+ reason: `turn mismatch: active turn is ${activeTurn.turnId}`
68156
+ });
68157
+ return;
68158
+ }
68159
+ activeTurn.interrupted = true;
68160
+ controller?.abort();
68161
+ if (params.mockResponse !== void 0) {
68162
+ finalize("cancelled", message.reason || "user_interrupt");
68163
+ activeTurn = null;
68164
+ }
68165
+ }
68166
+ const input = readline.createInterface({ input: process.stdin });
68167
+ let activeTurnPromise = null;
68168
+ for await (const line of input) {
68169
+ if (!line.trim()) continue;
68170
+ const message = parseInput(line);
68171
+ if (!message) {
68172
+ writeEvent({ type: "turn.failed", sessionId, turnId: `invalid-${Date.now()}`, error: "invalid JSON events input" });
68173
+ continue;
68174
+ }
68175
+ if (message.type === "shutdown") {
68176
+ if (activeTurn && !activeTurn.finalized) {
68177
+ activeTurn.interrupted = true;
68178
+ controller?.abort();
68179
+ finalize("cancelled", message.reason || "shutdown");
68180
+ }
68181
+ break;
68182
+ }
68183
+ if (message.type === "turn.interrupt") {
68184
+ await interrupt(message);
68185
+ continue;
68186
+ }
68187
+ const shouldTrackTurn = !activeTurn || activeTurn.finalized;
68188
+ const turnPromise = runTurn(message).catch((error) => {
68189
+ writeEvent({
68190
+ type: "turn.failed",
68191
+ sessionId,
68192
+ turnId: message.turnId,
68193
+ error: error instanceof Error ? error.message : String(error)
68194
+ });
68195
+ }).finally(() => {
68196
+ if (activeTurnPromise === turnPromise) {
68197
+ activeTurnPromise = null;
68198
+ }
68199
+ });
68200
+ if (shouldTrackTurn) {
68201
+ activeTurnPromise = turnPromise;
68202
+ }
68203
+ }
68204
+ await activeTurnPromise;
68205
+ disposeAgentSubscription?.();
68206
+ disposeSemanticSubscription?.();
68207
+ controller?.dispose();
68208
+ await params.runtime?.sessionManager.save();
68209
+ trace?.flush();
68210
+ }
68211
+
67523
68212
  // src/cli.ts
67524
68213
  enableEarlyLogBuffer();
67525
68214
  var logError = (msg, err) => {
@@ -67567,6 +68256,7 @@ Config Files:
67567
68256
  Print Mode Options:
67568
68257
  --raw-output Print assistant text only in non-interactive mode
67569
68258
  --json-output Print structured JSON in non-interactive mode
68259
+ --json-events Run JSONL protocol mode over stdin/stdout
67570
68260
  --session-id Reuse or create a specific session in non-interactive mode
67571
68261
  --extension-path Add an extra extension search directory (repeatable)
67572
68262
  `);
@@ -67649,12 +68339,66 @@ function parseRepeatedFlag(args, flag) {
67649
68339
  }
67650
68340
  return values;
67651
68341
  }
68342
+ async function runWithJsonEventsConsoleIsolation(fn) {
68343
+ const originalLog = console.log;
68344
+ const originalInfo = console.info;
68345
+ const originalDebug = console.debug;
68346
+ const redirectToStderr = (...args) => console.error(...args);
68347
+ console.log = redirectToStderr;
68348
+ console.info = redirectToStderr;
68349
+ console.debug = redirectToStderr;
68350
+ try {
68351
+ await fn();
68352
+ } finally {
68353
+ console.log = originalLog;
68354
+ console.info = originalInfo;
68355
+ console.debug = originalDebug;
68356
+ }
68357
+ }
68358
+ async function createCliTestStreamFnFromEnv() {
68359
+ if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) {
68360
+ return void 0;
68361
+ }
68362
+ const { createTestStreamFnFromSequenceEnv } = await import("./chunks/test-stream-ZSKNLUEJ.js");
68363
+ return createTestStreamFnFromSequenceEnv();
68364
+ }
67652
68365
  async function startChat(initialPrompt, testCommand) {
67653
68366
  const rawOutput = process.argv.includes("--raw-output");
67654
68367
  const jsonOutput = process.argv.includes("--json-output");
68368
+ const jsonEvents = process.argv.includes("--json-events");
67655
68369
  const sessionIdFlagIndex = process.argv.indexOf("--session-id");
67656
68370
  const explicitSessionId = sessionIdFlagIndex >= 0 ? process.argv[sessionIdFlagIndex + 1] : void 0;
67657
68371
  const extensionPaths = parseRepeatedFlag(process.argv, "--extension-path");
68372
+ if (jsonEvents) {
68373
+ await runWithJsonEventsConsoleIsolation(async () => {
68374
+ if (process.env.PIE_TEST_MOCK_RESPONSE !== void 0) {
68375
+ await runJsonEventsMode({
68376
+ explicitSessionId,
68377
+ mockResponse: process.env.PIE_TEST_MOCK_RESPONSE
68378
+ });
68379
+ return;
68380
+ }
68381
+ let runtime2;
68382
+ try {
68383
+ runtime2 = await composeCliRuntime({ explicitSessionId, extensionPaths });
68384
+ } catch (error) {
68385
+ if (error instanceof CliMissingApiKeyError) {
68386
+ await runJsonEventsMode({
68387
+ explicitSessionId,
68388
+ startupError: error.message
68389
+ });
68390
+ return;
68391
+ }
68392
+ throw error;
68393
+ }
68394
+ await runJsonEventsMode({
68395
+ runtime: runtime2,
68396
+ explicitSessionId,
68397
+ streamFn: await createCliTestStreamFnFromEnv()
68398
+ });
68399
+ });
68400
+ return;
68401
+ }
67658
68402
  if (initialPrompt && process.env.PIE_TEST_MOCK_RESPONSE !== void 0) {
67659
68403
  const text = process.env.PIE_TEST_MOCK_RESPONSE;
67660
68404
  if (jsonOutput) {
@@ -67680,7 +68424,13 @@ async function startChat(initialPrompt, testCommand) {
67680
68424
  throw error;
67681
68425
  }
67682
68426
  if (initialPrompt) {
67683
- await runPrintMode({ initialPrompt, rawOutput, jsonOutput, runtime });
68427
+ await runPrintMode({
68428
+ initialPrompt,
68429
+ rawOutput,
68430
+ jsonOutput,
68431
+ runtime,
68432
+ streamFn: await createCliTestStreamFnFromEnv()
68433
+ });
67684
68434
  process.exit(process.exitCode ?? 0);
67685
68435
  return;
67686
68436
  }