@cydm/pie 1.0.13 → 1.0.14
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 +577 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -43943,7 +43943,7 @@ import * as path26 from "path";
|
|
|
43943
43943
|
|
|
43944
43944
|
// src/cli-args.ts
|
|
43945
43945
|
var FLAGS_WITH_VALUES = /* @__PURE__ */ new Set(["--session-id", "--extension-path"]);
|
|
43946
|
-
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["--raw-output", "--json-output"]);
|
|
43946
|
+
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["--raw-output", "--json-output", "--json-events"]);
|
|
43947
43947
|
var HELP_FLAGS = /* @__PURE__ */ new Set(["help", "--help", "-h"]);
|
|
43948
43948
|
var COMMANDS = /* @__PURE__ */ new Set(["chat", "help"]);
|
|
43949
43949
|
function parseCliInvocation(args) {
|
|
@@ -67520,6 +67520,538 @@ async function runPrintMode(params) {
|
|
|
67520
67520
|
sessionTrace.flush();
|
|
67521
67521
|
}
|
|
67522
67522
|
|
|
67523
|
+
// src/app/json-events-mode.ts
|
|
67524
|
+
import readline from "node:readline";
|
|
67525
|
+
var MAX_EVENT_OBJECT_KEYS = 50;
|
|
67526
|
+
var MAX_EVENT_ARRAY_ITEMS = 50;
|
|
67527
|
+
var MAX_EVENT_VALUE_DEPTH = 4;
|
|
67528
|
+
var MAX_EVENT_STRING_LENGTH = 4e3;
|
|
67529
|
+
function createNoOpExtensionUIContext2() {
|
|
67530
|
+
return {
|
|
67531
|
+
notify: () => {
|
|
67532
|
+
},
|
|
67533
|
+
select: async () => void 0,
|
|
67534
|
+
confirm: async () => false,
|
|
67535
|
+
input: async () => void 0,
|
|
67536
|
+
editor: async () => void 0,
|
|
67537
|
+
custom: async () => void 0
|
|
67538
|
+
};
|
|
67539
|
+
}
|
|
67540
|
+
function writeEvent(event) {
|
|
67541
|
+
process.stdout.write(`${JSON.stringify(event)}
|
|
67542
|
+
`);
|
|
67543
|
+
}
|
|
67544
|
+
function toJsonValue(value, depth = 0) {
|
|
67545
|
+
if (value === null) return null;
|
|
67546
|
+
if (typeof value === "string") {
|
|
67547
|
+
return value.length > MAX_EVENT_STRING_LENGTH ? `${value.slice(0, MAX_EVENT_STRING_LENGTH)}...` : value;
|
|
67548
|
+
}
|
|
67549
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : String(value);
|
|
67550
|
+
if (typeof value === "boolean") return value;
|
|
67551
|
+
if (typeof value === "bigint") return value.toString();
|
|
67552
|
+
if (typeof value !== "object") return void 0;
|
|
67553
|
+
if (depth >= MAX_EVENT_VALUE_DEPTH) return "[truncated]";
|
|
67554
|
+
if (Array.isArray(value)) {
|
|
67555
|
+
return value.slice(0, MAX_EVENT_ARRAY_ITEMS).map((item) => toJsonValue(item, depth + 1) ?? null);
|
|
67556
|
+
}
|
|
67557
|
+
const result = {};
|
|
67558
|
+
for (const [key, item] of Object.entries(value).slice(0, MAX_EVENT_OBJECT_KEYS)) {
|
|
67559
|
+
result[key] = toJsonValue(item, depth + 1);
|
|
67560
|
+
}
|
|
67561
|
+
return result;
|
|
67562
|
+
}
|
|
67563
|
+
function isRecord3(value) {
|
|
67564
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
67565
|
+
}
|
|
67566
|
+
function parseInput(line) {
|
|
67567
|
+
let parsed;
|
|
67568
|
+
try {
|
|
67569
|
+
parsed = JSON.parse(line);
|
|
67570
|
+
} catch {
|
|
67571
|
+
return null;
|
|
67572
|
+
}
|
|
67573
|
+
if (!isRecord3(parsed) || typeof parsed.type !== "string") return null;
|
|
67574
|
+
if (parsed.type === "shutdown") {
|
|
67575
|
+
return { type: "shutdown", reason: typeof parsed.reason === "string" ? parsed.reason : void 0 };
|
|
67576
|
+
}
|
|
67577
|
+
if (parsed.type === "turn.interrupt") {
|
|
67578
|
+
return {
|
|
67579
|
+
type: "turn.interrupt",
|
|
67580
|
+
sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : void 0,
|
|
67581
|
+
turnId: typeof parsed.turnId === "string" ? parsed.turnId : void 0,
|
|
67582
|
+
reason: typeof parsed.reason === "string" ? parsed.reason : void 0
|
|
67583
|
+
};
|
|
67584
|
+
}
|
|
67585
|
+
if (parsed.type === "turn.request" && typeof parsed.turnId === "string" && typeof parsed.prompt === "string") {
|
|
67586
|
+
return {
|
|
67587
|
+
type: "turn.request",
|
|
67588
|
+
sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : void 0,
|
|
67589
|
+
turnId: parsed.turnId,
|
|
67590
|
+
prompt: parsed.prompt,
|
|
67591
|
+
cwd: typeof parsed.cwd === "string" ? parsed.cwd : void 0,
|
|
67592
|
+
metadata: isRecord3(parsed.metadata) ? parsed.metadata : void 0
|
|
67593
|
+
};
|
|
67594
|
+
}
|
|
67595
|
+
return null;
|
|
67596
|
+
}
|
|
67597
|
+
function assistantTextFromAgent(agent) {
|
|
67598
|
+
const messages = agent?.state.messages ?? [];
|
|
67599
|
+
const lastMessage = messages[messages.length - 1];
|
|
67600
|
+
if (lastMessage?.role !== "assistant") return "";
|
|
67601
|
+
let text = "";
|
|
67602
|
+
for (const content of lastMessage.content) {
|
|
67603
|
+
if (content.type === "text") {
|
|
67604
|
+
text += content.text;
|
|
67605
|
+
}
|
|
67606
|
+
}
|
|
67607
|
+
return text;
|
|
67608
|
+
}
|
|
67609
|
+
function readProgressText(value) {
|
|
67610
|
+
return typeof value === "string" ? value : "";
|
|
67611
|
+
}
|
|
67612
|
+
function extractJsonEventsToolProgressText(partialResult) {
|
|
67613
|
+
const plainText = readProgressText(partialResult).trim();
|
|
67614
|
+
if (plainText) return plainText;
|
|
67615
|
+
if (!isRecord3(partialResult)) return "";
|
|
67616
|
+
const content = partialResult.content;
|
|
67617
|
+
if (Array.isArray(content)) {
|
|
67618
|
+
return content.map((block) => isRecord3(block) && block.type === "text" ? readProgressText(block.text) : "").filter(Boolean).join("\n").trim();
|
|
67619
|
+
}
|
|
67620
|
+
const directText = readProgressText(partialResult.text) || readProgressText(partialResult.message);
|
|
67621
|
+
if (directText) return directText.trim();
|
|
67622
|
+
const details = partialResult.details;
|
|
67623
|
+
if (isRecord3(details)) {
|
|
67624
|
+
return (readProgressText(details.text) || readProgressText(details.message)).trim();
|
|
67625
|
+
}
|
|
67626
|
+
return "";
|
|
67627
|
+
}
|
|
67628
|
+
async function loadJsonModeExtensions(params) {
|
|
67629
|
+
const uiContext = createNoOpExtensionUIContext2();
|
|
67630
|
+
const executionState = new ExecutionStateManager();
|
|
67631
|
+
const activeSession = params.runtime.sessionManager.getActiveSession();
|
|
67632
|
+
executionState.restoreFromMetadata(activeSession?.metadata?.executionState);
|
|
67633
|
+
const actions = {
|
|
67634
|
+
setActiveTools: (toolNames) => {
|
|
67635
|
+
const agent = params.getAgent();
|
|
67636
|
+
if (!agent) return;
|
|
67637
|
+
agent.state.tools = agent.state.tools.filter((tool) => toolNames.includes(tool.name));
|
|
67638
|
+
},
|
|
67639
|
+
getActiveTools: () => params.getAgent()?.state.tools.map((tool) => tool.name) ?? [],
|
|
67640
|
+
sendUserMessage: () => {
|
|
67641
|
+
},
|
|
67642
|
+
setPlanMode: () => {
|
|
67643
|
+
},
|
|
67644
|
+
setExecutionReminder: (text) => {
|
|
67645
|
+
const session = params.runtime.sessionManager.getActiveSession();
|
|
67646
|
+
if (!session) return;
|
|
67647
|
+
if (text) {
|
|
67648
|
+
session.metadata.executionReminder = text;
|
|
67649
|
+
} else {
|
|
67650
|
+
delete session.metadata.executionReminder;
|
|
67651
|
+
}
|
|
67652
|
+
},
|
|
67653
|
+
getExecutionState: () => executionState.read(),
|
|
67654
|
+
setExecutionState: (state) => {
|
|
67655
|
+
const nextState = executionState.replace(state);
|
|
67656
|
+
const session = params.runtime.sessionManager.getActiveSession();
|
|
67657
|
+
if (session) {
|
|
67658
|
+
session.metadata.executionState = executionState.createMetadata();
|
|
67659
|
+
}
|
|
67660
|
+
return nextState;
|
|
67661
|
+
},
|
|
67662
|
+
cwd: params.runtime.cwd,
|
|
67663
|
+
apiKey: params.runtime.apiKey,
|
|
67664
|
+
model: params.runtime.model,
|
|
67665
|
+
skills: params.runtime.skills,
|
|
67666
|
+
getAllTools: () => params.getAgent()?.state.tools.map((tool) => ({
|
|
67667
|
+
name: tool.name,
|
|
67668
|
+
description: tool.description,
|
|
67669
|
+
parameters: tool.parameters
|
|
67670
|
+
})) ?? [],
|
|
67671
|
+
getRuntimeTools: () => params.getAgent()?.state.tools ?? [],
|
|
67672
|
+
resolveModelClass: (modelClass) => params.runtime.modelRegistry.resolveModelClass(modelClass),
|
|
67673
|
+
getMessages: () => params.getAgent()?.state.messages ?? [],
|
|
67674
|
+
getSessionMetadata: () => ({ ...params.runtime.sessionManager.getActiveSession()?.metadata ?? {} }),
|
|
67675
|
+
setSessionMetadata: (key, value) => {
|
|
67676
|
+
const session = params.runtime.sessionManager.getActiveSession();
|
|
67677
|
+
if (!session) return;
|
|
67678
|
+
session.metadata[key] = value;
|
|
67679
|
+
},
|
|
67680
|
+
yoloMode: false
|
|
67681
|
+
};
|
|
67682
|
+
const { extensions } = await loadExtensions(
|
|
67683
|
+
params.runtime.extensionPaths,
|
|
67684
|
+
params.runtime.cwd,
|
|
67685
|
+
uiContext,
|
|
67686
|
+
() => params.getAgent()?.abort(),
|
|
67687
|
+
() => true,
|
|
67688
|
+
false,
|
|
67689
|
+
actions
|
|
67690
|
+
);
|
|
67691
|
+
const runner = new ExtensionRunner(
|
|
67692
|
+
extensions,
|
|
67693
|
+
actions,
|
|
67694
|
+
{
|
|
67695
|
+
isIdle: () => true,
|
|
67696
|
+
abort: () => params.getAgent()?.abort()
|
|
67697
|
+
},
|
|
67698
|
+
false
|
|
67699
|
+
);
|
|
67700
|
+
runner.setUIContext(uiContext);
|
|
67701
|
+
return {
|
|
67702
|
+
runner,
|
|
67703
|
+
extensionTools: convertExtensionTools(extensions),
|
|
67704
|
+
extensionCount: extensions.length
|
|
67705
|
+
};
|
|
67706
|
+
}
|
|
67707
|
+
async function runJsonEventsMode(params) {
|
|
67708
|
+
const sessionId = params.explicitSessionId || params.runtime?.sessionManager.getActiveSession()?.id || `pie-json-${Date.now()}`;
|
|
67709
|
+
let activeTurn = null;
|
|
67710
|
+
let agent;
|
|
67711
|
+
let controller;
|
|
67712
|
+
let disposeAgentSubscription;
|
|
67713
|
+
let disposeSemanticSubscription;
|
|
67714
|
+
let trace;
|
|
67715
|
+
const noProgressTimeoutMs = Number(process.env.PIE_JSON_EVENTS_NO_PROGRESS_MS || 6e5);
|
|
67716
|
+
const mockResponseDelayMs = Number(process.env.PIE_TEST_MOCK_RESPONSE_DELAY_MS || 0);
|
|
67717
|
+
writeEvent({ type: "agent.ready", sessionId });
|
|
67718
|
+
function sessionMismatchError(requestedSessionId) {
|
|
67719
|
+
return `session mismatch: JSON events process is bound to ${sessionId}, received ${requestedSessionId}`;
|
|
67720
|
+
}
|
|
67721
|
+
function isSessionMismatch(message) {
|
|
67722
|
+
return typeof message.sessionId === "string" && message.sessionId !== sessionId;
|
|
67723
|
+
}
|
|
67724
|
+
function delay(ms) {
|
|
67725
|
+
return new Promise((resolve4) => setTimeout(resolve4, Math.max(0, ms)));
|
|
67726
|
+
}
|
|
67727
|
+
function touch() {
|
|
67728
|
+
if (activeTurn) {
|
|
67729
|
+
activeTurn.lastActivityAt = Date.now();
|
|
67730
|
+
}
|
|
67731
|
+
}
|
|
67732
|
+
function display(chunk) {
|
|
67733
|
+
if (!activeTurn || !chunk) return;
|
|
67734
|
+
activeTurn.summary += chunk;
|
|
67735
|
+
touch();
|
|
67736
|
+
writeEvent({
|
|
67737
|
+
type: "display.output",
|
|
67738
|
+
sessionId: activeTurn.sessionId,
|
|
67739
|
+
turnId: activeTurn.turnId,
|
|
67740
|
+
stream: "terminal",
|
|
67741
|
+
chunk
|
|
67742
|
+
});
|
|
67743
|
+
}
|
|
67744
|
+
function finalize(kind, detail) {
|
|
67745
|
+
const turn = activeTurn;
|
|
67746
|
+
if (!turn || turn.finalized) return;
|
|
67747
|
+
turn.finalized = true;
|
|
67748
|
+
switch (kind) {
|
|
67749
|
+
case "completed":
|
|
67750
|
+
writeEvent({ type: "turn.completed", sessionId: turn.sessionId, turnId: turn.turnId, summary: turn.summary.trim() });
|
|
67751
|
+
break;
|
|
67752
|
+
case "failed":
|
|
67753
|
+
writeEvent({ type: "turn.failed", sessionId: turn.sessionId, turnId: turn.turnId, error: detail || "turn failed" });
|
|
67754
|
+
break;
|
|
67755
|
+
case "cancelled":
|
|
67756
|
+
writeEvent({ type: "turn.cancelled", sessionId: turn.sessionId, turnId: turn.turnId, reason: detail || "interrupted" });
|
|
67757
|
+
break;
|
|
67758
|
+
case "stalled":
|
|
67759
|
+
writeEvent({ type: "turn.stalled", sessionId: turn.sessionId, turnId: turn.turnId, reason: detail || "no_progress_timeout" });
|
|
67760
|
+
break;
|
|
67761
|
+
}
|
|
67762
|
+
}
|
|
67763
|
+
function handleSemanticEvent(event) {
|
|
67764
|
+
if (!activeTurn || activeTurn.finalized) return;
|
|
67765
|
+
switch (event.type) {
|
|
67766
|
+
case "assistant_response_delta":
|
|
67767
|
+
display(event.delta);
|
|
67768
|
+
break;
|
|
67769
|
+
case "tool_started":
|
|
67770
|
+
touch();
|
|
67771
|
+
writeEvent({
|
|
67772
|
+
type: "tool.started",
|
|
67773
|
+
sessionId: activeTurn.sessionId,
|
|
67774
|
+
turnId: activeTurn.turnId,
|
|
67775
|
+
toolCallId: event.toolCallId,
|
|
67776
|
+
name: event.toolName,
|
|
67777
|
+
data: toJsonValue({ args: event.args })
|
|
67778
|
+
});
|
|
67779
|
+
break;
|
|
67780
|
+
case "tool_progressed":
|
|
67781
|
+
touch();
|
|
67782
|
+
{
|
|
67783
|
+
const progressText = extractJsonEventsToolProgressText(event.partialResult);
|
|
67784
|
+
if (progressText) {
|
|
67785
|
+
display(progressText.endsWith("\n") ? progressText : `${progressText}
|
|
67786
|
+
`);
|
|
67787
|
+
}
|
|
67788
|
+
}
|
|
67789
|
+
break;
|
|
67790
|
+
case "tool_finished":
|
|
67791
|
+
touch();
|
|
67792
|
+
writeEvent({
|
|
67793
|
+
type: "tool.completed",
|
|
67794
|
+
sessionId: activeTurn.sessionId,
|
|
67795
|
+
turnId: activeTurn.turnId,
|
|
67796
|
+
toolCallId: event.toolCallId,
|
|
67797
|
+
name: event.toolName,
|
|
67798
|
+
status: event.isError ? "error" : "ok",
|
|
67799
|
+
data: toJsonValue({
|
|
67800
|
+
resultText: extractJsonEventsToolProgressText(event.result),
|
|
67801
|
+
isError: event.isError
|
|
67802
|
+
})
|
|
67803
|
+
});
|
|
67804
|
+
break;
|
|
67805
|
+
}
|
|
67806
|
+
}
|
|
67807
|
+
async function ensureRuntime() {
|
|
67808
|
+
if (params.mockResponse !== void 0 || controller) return;
|
|
67809
|
+
const runtime = params.runtime;
|
|
67810
|
+
if (!runtime) {
|
|
67811
|
+
throw new Error("JSON events mode requires a CLI runtime");
|
|
67812
|
+
}
|
|
67813
|
+
if (runtime.initialModel.unconfigured) {
|
|
67814
|
+
return;
|
|
67815
|
+
}
|
|
67816
|
+
const { Agent: AgentClass } = await import("./chunks/src-LZC56DRG.js");
|
|
67817
|
+
const jsonModeExtensions = await loadJsonModeExtensions({ runtime, getAgent: () => agent });
|
|
67818
|
+
const tools = [...runtime.tools, ...jsonModeExtensions.extensionTools];
|
|
67819
|
+
recordCliCompositionStep(runtime.compositionTrace, {
|
|
67820
|
+
id: "extensions_tool_wrapping",
|
|
67821
|
+
inputSummary: `baseTools=${runtime.tools.length} extensionPaths=${runtime.extensionPaths.length}`,
|
|
67822
|
+
outputSummary: `extensions=${jsonModeExtensions.extensionCount}`,
|
|
67823
|
+
toolCount: tools.length,
|
|
67824
|
+
extensionWrapping: {
|
|
67825
|
+
extensionCount: jsonModeExtensions.extensionCount,
|
|
67826
|
+
extensionToolCount: jsonModeExtensions.extensionTools.length,
|
|
67827
|
+
wrappedToolCount: tools.length
|
|
67828
|
+
}
|
|
67829
|
+
});
|
|
67830
|
+
const baseSystemPrompt = buildCliSystemPrompt({
|
|
67831
|
+
cwd: runtime.cwd,
|
|
67832
|
+
skillsSection: runtime.skillsSection,
|
|
67833
|
+
knowledgeSection: runtime.knowledgeSection,
|
|
67834
|
+
tools: tools.map((tool) => ({ name: tool.name, description: tool.description }))
|
|
67835
|
+
});
|
|
67836
|
+
agent = new AgentClass({
|
|
67837
|
+
initialState: {
|
|
67838
|
+
systemPrompt: baseSystemPrompt,
|
|
67839
|
+
model: runtime.model,
|
|
67840
|
+
tools,
|
|
67841
|
+
thinkingLevel: "off"
|
|
67842
|
+
},
|
|
67843
|
+
apiKey: runtime.apiKey
|
|
67844
|
+
});
|
|
67845
|
+
controller = new AgentSessionController({
|
|
67846
|
+
agent,
|
|
67847
|
+
sessionManager: runtime.sessionManager,
|
|
67848
|
+
cwd: runtime.cwd,
|
|
67849
|
+
baseSystemPrompt,
|
|
67850
|
+
prepareTurn: async (context) => {
|
|
67851
|
+
const result = await jsonModeExtensions.runner.emitBeforeAgentStart({
|
|
67852
|
+
type: "before_agent_start",
|
|
67853
|
+
messages: context.messages,
|
|
67854
|
+
baseSystemPrompt: context.baseSystemPrompt ?? baseSystemPrompt,
|
|
67855
|
+
source: context.source
|
|
67856
|
+
});
|
|
67857
|
+
return {
|
|
67858
|
+
systemPrompt: result?.systemPrompt ?? context.baseSystemPrompt ?? baseSystemPrompt,
|
|
67859
|
+
messages: result?.messages?.length ? [...context.messages, ...result.messages] : context.messages
|
|
67860
|
+
};
|
|
67861
|
+
}
|
|
67862
|
+
});
|
|
67863
|
+
trace = new SessionTraceWriter(runtime.paths.sessionsDir, runtime.sessionManager);
|
|
67864
|
+
attachAgentEventsToSessionTrace({ agent, trace });
|
|
67865
|
+
agent.setTools(wrapToolsWithExtensions(agent.state.tools, jsonModeExtensions.runner));
|
|
67866
|
+
controller.updateRuntimeContext({ tools: agent.state.tools });
|
|
67867
|
+
disposeSemanticSubscription = agent.subscribeSemantic(handleSemanticEvent);
|
|
67868
|
+
}
|
|
67869
|
+
async function runTurn(message) {
|
|
67870
|
+
if (isSessionMismatch(message)) {
|
|
67871
|
+
writeEvent({
|
|
67872
|
+
type: "turn.failed",
|
|
67873
|
+
sessionId,
|
|
67874
|
+
turnId: message.turnId,
|
|
67875
|
+
error: sessionMismatchError(message.sessionId)
|
|
67876
|
+
});
|
|
67877
|
+
return;
|
|
67878
|
+
}
|
|
67879
|
+
if (activeTurn && !activeTurn.finalized) {
|
|
67880
|
+
writeEvent({
|
|
67881
|
+
type: "turn.failed",
|
|
67882
|
+
sessionId,
|
|
67883
|
+
turnId: message.turnId,
|
|
67884
|
+
error: "another turn is already running"
|
|
67885
|
+
});
|
|
67886
|
+
return;
|
|
67887
|
+
}
|
|
67888
|
+
activeTurn = {
|
|
67889
|
+
sessionId,
|
|
67890
|
+
turnId: message.turnId,
|
|
67891
|
+
prompt: message.prompt,
|
|
67892
|
+
startedAt: Date.now(),
|
|
67893
|
+
lastActivityAt: Date.now(),
|
|
67894
|
+
interrupted: false,
|
|
67895
|
+
stalled: false,
|
|
67896
|
+
finalized: false,
|
|
67897
|
+
summary: ""
|
|
67898
|
+
};
|
|
67899
|
+
const turn = activeTurn;
|
|
67900
|
+
writeEvent({ type: "turn.started", sessionId: activeTurn.sessionId, turnId: activeTurn.turnId });
|
|
67901
|
+
if (params.mockResponse !== void 0) {
|
|
67902
|
+
if (mockResponseDelayMs > 0) {
|
|
67903
|
+
await delay(mockResponseDelayMs);
|
|
67904
|
+
}
|
|
67905
|
+
if (activeTurn !== turn || turn.finalized) {
|
|
67906
|
+
return;
|
|
67907
|
+
}
|
|
67908
|
+
display(params.mockResponse);
|
|
67909
|
+
finalize("completed");
|
|
67910
|
+
if (activeTurn === turn) activeTurn = null;
|
|
67911
|
+
return;
|
|
67912
|
+
}
|
|
67913
|
+
if (params.startupError) {
|
|
67914
|
+
finalize("failed", params.startupError);
|
|
67915
|
+
if (activeTurn === turn) activeTurn = null;
|
|
67916
|
+
return;
|
|
67917
|
+
}
|
|
67918
|
+
try {
|
|
67919
|
+
await ensureRuntime();
|
|
67920
|
+
} catch (error) {
|
|
67921
|
+
finalize("failed", error instanceof Error ? error.message : String(error));
|
|
67922
|
+
if (activeTurn === turn) activeTurn = null;
|
|
67923
|
+
return;
|
|
67924
|
+
}
|
|
67925
|
+
const runtime = params.runtime;
|
|
67926
|
+
if (runtime?.initialModel.unconfigured) {
|
|
67927
|
+
finalize("failed", runtime.initialModel.warning || "No models are configured.");
|
|
67928
|
+
if (activeTurn === turn) activeTurn = null;
|
|
67929
|
+
return;
|
|
67930
|
+
}
|
|
67931
|
+
if (!controller || !agent) {
|
|
67932
|
+
finalize("failed", "JSON events runtime was not initialized");
|
|
67933
|
+
if (activeTurn === turn) activeTurn = null;
|
|
67934
|
+
return;
|
|
67935
|
+
}
|
|
67936
|
+
const progressTimer = setInterval(() => {
|
|
67937
|
+
const turn2 = activeTurn;
|
|
67938
|
+
if (!turn2 || turn2.finalized) return;
|
|
67939
|
+
if (Date.now() - turn2.lastActivityAt >= noProgressTimeoutMs) {
|
|
67940
|
+
turn2.stalled = true;
|
|
67941
|
+
agent?.abort();
|
|
67942
|
+
finalize("stalled", "no_progress_timeout");
|
|
67943
|
+
}
|
|
67944
|
+
}, Math.max(1e3, Math.min(noProgressTimeoutMs, 1e4)));
|
|
67945
|
+
progressTimer.unref?.();
|
|
67946
|
+
try {
|
|
67947
|
+
trace?.notePendingUserText(message.prompt);
|
|
67948
|
+
trace?.noteDispatchStart({ mode: "json-events" });
|
|
67949
|
+
await controller.prompt(message.prompt, { source: "json-events" });
|
|
67950
|
+
trace?.noteDispatchSettled({ mode: "json-events" });
|
|
67951
|
+
trace?.noteWaitForIdleStart({ mode: "json-events" });
|
|
67952
|
+
await controller.waitForIdle();
|
|
67953
|
+
trace?.noteWaitForIdleSettled({ mode: "json-events" });
|
|
67954
|
+
if (!activeTurn?.finalized) {
|
|
67955
|
+
const text = activeTurn?.summary.trim() || assistantTextFromAgent(agent);
|
|
67956
|
+
if (!activeTurn?.summary && text) {
|
|
67957
|
+
display(text);
|
|
67958
|
+
}
|
|
67959
|
+
finalize(activeTurn?.interrupted ? "cancelled" : "completed", activeTurn?.interrupted ? "user_interrupt" : void 0);
|
|
67960
|
+
}
|
|
67961
|
+
} catch (error) {
|
|
67962
|
+
const messageText = error instanceof Error ? error.message : String(error);
|
|
67963
|
+
trace?.noteStalled(messageText, { mode: "json-events" });
|
|
67964
|
+
if (!activeTurn?.finalized) {
|
|
67965
|
+
finalize(activeTurn?.interrupted ? "cancelled" : "failed", activeTurn?.interrupted ? "user_interrupt" : messageText);
|
|
67966
|
+
}
|
|
67967
|
+
} finally {
|
|
67968
|
+
clearInterval(progressTimer);
|
|
67969
|
+
trace?.flush();
|
|
67970
|
+
await runtime?.sessionManager.save();
|
|
67971
|
+
if (activeTurn === turn) activeTurn = null;
|
|
67972
|
+
}
|
|
67973
|
+
}
|
|
67974
|
+
async function interrupt(message) {
|
|
67975
|
+
if (isSessionMismatch(message)) {
|
|
67976
|
+
writeEvent({
|
|
67977
|
+
type: "turn.cancelled",
|
|
67978
|
+
sessionId,
|
|
67979
|
+
turnId: message.turnId || "no-active-turn",
|
|
67980
|
+
reason: sessionMismatchError(message.sessionId)
|
|
67981
|
+
});
|
|
67982
|
+
return;
|
|
67983
|
+
}
|
|
67984
|
+
if (!activeTurn || activeTurn.finalized) {
|
|
67985
|
+
writeEvent({
|
|
67986
|
+
type: "turn.cancelled",
|
|
67987
|
+
sessionId,
|
|
67988
|
+
turnId: message.turnId || "no-active-turn",
|
|
67989
|
+
reason: message.reason || "no_active_turn"
|
|
67990
|
+
});
|
|
67991
|
+
return;
|
|
67992
|
+
}
|
|
67993
|
+
if (message.turnId && message.turnId !== activeTurn.turnId) {
|
|
67994
|
+
writeEvent({
|
|
67995
|
+
type: "turn.cancelled",
|
|
67996
|
+
sessionId,
|
|
67997
|
+
turnId: message.turnId,
|
|
67998
|
+
reason: `turn mismatch: active turn is ${activeTurn.turnId}`
|
|
67999
|
+
});
|
|
68000
|
+
return;
|
|
68001
|
+
}
|
|
68002
|
+
activeTurn.interrupted = true;
|
|
68003
|
+
agent?.abort();
|
|
68004
|
+
if (params.mockResponse !== void 0) {
|
|
68005
|
+
finalize("cancelled", message.reason || "user_interrupt");
|
|
68006
|
+
activeTurn = null;
|
|
68007
|
+
}
|
|
68008
|
+
}
|
|
68009
|
+
const input = readline.createInterface({ input: process.stdin });
|
|
68010
|
+
let activeTurnPromise = null;
|
|
68011
|
+
for await (const line of input) {
|
|
68012
|
+
if (!line.trim()) continue;
|
|
68013
|
+
const message = parseInput(line);
|
|
68014
|
+
if (!message) {
|
|
68015
|
+
writeEvent({ type: "turn.failed", sessionId, turnId: `invalid-${Date.now()}`, error: "invalid JSON events input" });
|
|
68016
|
+
continue;
|
|
68017
|
+
}
|
|
68018
|
+
if (message.type === "shutdown") {
|
|
68019
|
+
if (activeTurn && !activeTurn.finalized) {
|
|
68020
|
+
activeTurn.interrupted = true;
|
|
68021
|
+
agent?.abort();
|
|
68022
|
+
finalize("cancelled", message.reason || "shutdown");
|
|
68023
|
+
}
|
|
68024
|
+
break;
|
|
68025
|
+
}
|
|
68026
|
+
if (message.type === "turn.interrupt") {
|
|
68027
|
+
await interrupt(message);
|
|
68028
|
+
continue;
|
|
68029
|
+
}
|
|
68030
|
+
const shouldTrackTurn = !activeTurn || activeTurn.finalized;
|
|
68031
|
+
const turnPromise = runTurn(message).catch((error) => {
|
|
68032
|
+
writeEvent({
|
|
68033
|
+
type: "turn.failed",
|
|
68034
|
+
sessionId,
|
|
68035
|
+
turnId: message.turnId,
|
|
68036
|
+
error: error instanceof Error ? error.message : String(error)
|
|
68037
|
+
});
|
|
68038
|
+
}).finally(() => {
|
|
68039
|
+
if (activeTurnPromise === turnPromise) {
|
|
68040
|
+
activeTurnPromise = null;
|
|
68041
|
+
}
|
|
68042
|
+
});
|
|
68043
|
+
if (shouldTrackTurn) {
|
|
68044
|
+
activeTurnPromise = turnPromise;
|
|
68045
|
+
}
|
|
68046
|
+
}
|
|
68047
|
+
await activeTurnPromise;
|
|
68048
|
+
disposeAgentSubscription?.();
|
|
68049
|
+
disposeSemanticSubscription?.();
|
|
68050
|
+
controller?.dispose();
|
|
68051
|
+
await params.runtime?.sessionManager.save();
|
|
68052
|
+
trace?.flush();
|
|
68053
|
+
}
|
|
68054
|
+
|
|
67523
68055
|
// src/cli.ts
|
|
67524
68056
|
enableEarlyLogBuffer();
|
|
67525
68057
|
var logError = (msg, err) => {
|
|
@@ -67567,6 +68099,7 @@ Config Files:
|
|
|
67567
68099
|
Print Mode Options:
|
|
67568
68100
|
--raw-output Print assistant text only in non-interactive mode
|
|
67569
68101
|
--json-output Print structured JSON in non-interactive mode
|
|
68102
|
+
--json-events Run JSONL protocol mode over stdin/stdout
|
|
67570
68103
|
--session-id Reuse or create a specific session in non-interactive mode
|
|
67571
68104
|
--extension-path Add an extra extension search directory (repeatable)
|
|
67572
68105
|
`);
|
|
@@ -67649,12 +68182,55 @@ function parseRepeatedFlag(args, flag) {
|
|
|
67649
68182
|
}
|
|
67650
68183
|
return values;
|
|
67651
68184
|
}
|
|
68185
|
+
async function runWithJsonEventsConsoleIsolation(fn) {
|
|
68186
|
+
const originalLog = console.log;
|
|
68187
|
+
const originalInfo = console.info;
|
|
68188
|
+
const originalDebug = console.debug;
|
|
68189
|
+
const redirectToStderr = (...args) => console.error(...args);
|
|
68190
|
+
console.log = redirectToStderr;
|
|
68191
|
+
console.info = redirectToStderr;
|
|
68192
|
+
console.debug = redirectToStderr;
|
|
68193
|
+
try {
|
|
68194
|
+
await fn();
|
|
68195
|
+
} finally {
|
|
68196
|
+
console.log = originalLog;
|
|
68197
|
+
console.info = originalInfo;
|
|
68198
|
+
console.debug = originalDebug;
|
|
68199
|
+
}
|
|
68200
|
+
}
|
|
67652
68201
|
async function startChat(initialPrompt, testCommand) {
|
|
67653
68202
|
const rawOutput = process.argv.includes("--raw-output");
|
|
67654
68203
|
const jsonOutput = process.argv.includes("--json-output");
|
|
68204
|
+
const jsonEvents = process.argv.includes("--json-events");
|
|
67655
68205
|
const sessionIdFlagIndex = process.argv.indexOf("--session-id");
|
|
67656
68206
|
const explicitSessionId = sessionIdFlagIndex >= 0 ? process.argv[sessionIdFlagIndex + 1] : void 0;
|
|
67657
68207
|
const extensionPaths = parseRepeatedFlag(process.argv, "--extension-path");
|
|
68208
|
+
if (jsonEvents) {
|
|
68209
|
+
await runWithJsonEventsConsoleIsolation(async () => {
|
|
68210
|
+
if (process.env.PIE_TEST_MOCK_RESPONSE !== void 0) {
|
|
68211
|
+
await runJsonEventsMode({
|
|
68212
|
+
explicitSessionId,
|
|
68213
|
+
mockResponse: process.env.PIE_TEST_MOCK_RESPONSE
|
|
68214
|
+
});
|
|
68215
|
+
return;
|
|
68216
|
+
}
|
|
68217
|
+
let runtime2;
|
|
68218
|
+
try {
|
|
68219
|
+
runtime2 = await composeCliRuntime({ explicitSessionId, extensionPaths });
|
|
68220
|
+
} catch (error) {
|
|
68221
|
+
if (error instanceof CliMissingApiKeyError) {
|
|
68222
|
+
await runJsonEventsMode({
|
|
68223
|
+
explicitSessionId,
|
|
68224
|
+
startupError: error.message
|
|
68225
|
+
});
|
|
68226
|
+
return;
|
|
68227
|
+
}
|
|
68228
|
+
throw error;
|
|
68229
|
+
}
|
|
68230
|
+
await runJsonEventsMode({ runtime: runtime2, explicitSessionId });
|
|
68231
|
+
});
|
|
68232
|
+
return;
|
|
68233
|
+
}
|
|
67658
68234
|
if (initialPrompt && process.env.PIE_TEST_MOCK_RESPONSE !== void 0) {
|
|
67659
68235
|
const text = process.env.PIE_TEST_MOCK_RESPONSE;
|
|
67660
68236
|
if (jsonOutput) {
|