@cydm/pie 1.0.33 → 1.0.35
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 +145 -24
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -43962,7 +43962,7 @@ import * as path29 from "path";
|
|
|
43962
43962
|
|
|
43963
43963
|
// src/cli-args.ts
|
|
43964
43964
|
var FLAGS_WITH_VALUES = /* @__PURE__ */ new Set(["--session-id", "--extension-path"]);
|
|
43965
|
-
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["--raw-output", "--json-output", "--json-events"]);
|
|
43965
|
+
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set(["--raw-output", "--json-output", "--json-events", "--resume-required"]);
|
|
43966
43966
|
var HELP_FLAGS = /* @__PURE__ */ new Set(["help", "--help", "-h"]);
|
|
43967
43967
|
var COMMANDS = /* @__PURE__ */ new Set(["chat", "help"]);
|
|
43968
43968
|
function parseCliInvocation(args) {
|
|
@@ -44014,6 +44014,16 @@ function parseCliInvocation(args) {
|
|
|
44014
44014
|
initialPrompt: positionals.join(" ").trim() || void 0
|
|
44015
44015
|
};
|
|
44016
44016
|
}
|
|
44017
|
+
function parseRepeatedFlag(args, flag) {
|
|
44018
|
+
const values = [];
|
|
44019
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
44020
|
+
if (args[i] === flag && args[i + 1]) {
|
|
44021
|
+
values.push(args[i + 1]);
|
|
44022
|
+
i += 1;
|
|
44023
|
+
}
|
|
44024
|
+
}
|
|
44025
|
+
return values;
|
|
44026
|
+
}
|
|
44017
44027
|
|
|
44018
44028
|
// src/debug/file-logger.ts
|
|
44019
44029
|
import * as fs from "fs";
|
|
@@ -54844,7 +54854,8 @@ var DEFAULT_APP_KEYBINDINGS = {
|
|
|
54844
54854
|
toggleThinking: "ctrl+t",
|
|
54845
54855
|
toggleSessionNamedFilter: "ctrl+n",
|
|
54846
54856
|
externalEditor: "ctrl+g",
|
|
54847
|
-
|
|
54857
|
+
steer: "alt+enter",
|
|
54858
|
+
followUp: [],
|
|
54848
54859
|
dequeue: ["alt+up", "ctrl+shift+up"],
|
|
54849
54860
|
pasteImage: "ctrl+v",
|
|
54850
54861
|
newSession: [],
|
|
@@ -54869,6 +54880,7 @@ var APP_ACTIONS = [
|
|
|
54869
54880
|
"toggleThinking",
|
|
54870
54881
|
"toggleSessionNamedFilter",
|
|
54871
54882
|
"externalEditor",
|
|
54883
|
+
"steer",
|
|
54872
54884
|
"followUp",
|
|
54873
54885
|
"dequeue",
|
|
54874
54886
|
"pasteImage",
|
|
@@ -63849,7 +63861,7 @@ function handleHotkeysCommand(host) {
|
|
|
63849
63861
|
theme.fg("muted", "Editor shortcuts:"),
|
|
63850
63862
|
" Enter Submit message",
|
|
63851
63863
|
" Shift+Enter New line",
|
|
63852
|
-
` ${theme.fg("dim", kb.getKeys("
|
|
63864
|
+
` ${theme.fg("dim", kb.getKeys("steer").join(" / "))} ${theme.fg("muted", "Queue steering message for the active turn")}`,
|
|
63853
63865
|
` ${theme.fg("dim", kb.getKeys("dequeue").join(" / "))} ${theme.fg("muted", "Restore queued messages")}`,
|
|
63854
63866
|
" / Show slash commands",
|
|
63855
63867
|
" Esc Cancel autocomplete",
|
|
@@ -66772,6 +66784,10 @@ function setupInteractiveKeybindings(host) {
|
|
|
66772
66784
|
host.dequeueMessages();
|
|
66773
66785
|
return { consume: true };
|
|
66774
66786
|
}
|
|
66787
|
+
if (host.keybindings.matches(data, "steer")) {
|
|
66788
|
+
host.handleSteer();
|
|
66789
|
+
return { consume: true };
|
|
66790
|
+
}
|
|
66775
66791
|
if (host.keybindings.matches(data, "followUp")) {
|
|
66776
66792
|
host.handleFollowUp();
|
|
66777
66793
|
return { consume: true };
|
|
@@ -66872,6 +66888,19 @@ function handleFollowUp(host) {
|
|
|
66872
66888
|
void host.editor.onSubmit(text);
|
|
66873
66889
|
}
|
|
66874
66890
|
}
|
|
66891
|
+
function handleSteer(host) {
|
|
66892
|
+
const text = host.editor.getText().trim();
|
|
66893
|
+
if (!text) return;
|
|
66894
|
+
if (isCommandLikeInput(text)) {
|
|
66895
|
+
host.editor.onSubmit?.(text);
|
|
66896
|
+
return;
|
|
66897
|
+
}
|
|
66898
|
+
if (host.submitLock || (host.agentSessionController?.hasQueuedMessages ?? false)) {
|
|
66899
|
+
queueMessage(host, text, "steer");
|
|
66900
|
+
} else if (host.editor.onSubmit) {
|
|
66901
|
+
void host.editor.onSubmit(text);
|
|
66902
|
+
}
|
|
66903
|
+
}
|
|
66875
66904
|
function truncate(text, maxLength) {
|
|
66876
66905
|
if (text.length <= maxLength) return text;
|
|
66877
66906
|
return text.slice(0, maxLength) + "...";
|
|
@@ -69558,6 +69587,9 @@ var InteractiveMode = class {
|
|
|
69558
69587
|
handleFollowUp() {
|
|
69559
69588
|
handleFollowUp(this);
|
|
69560
69589
|
}
|
|
69590
|
+
handleSteer() {
|
|
69591
|
+
handleSteer(this);
|
|
69592
|
+
}
|
|
69561
69593
|
restoreEditor() {
|
|
69562
69594
|
return restoreEditor(this.uiHelperHost);
|
|
69563
69595
|
}
|
|
@@ -69572,6 +69604,17 @@ var CliMissingApiKeyError = class extends Error {
|
|
|
69572
69604
|
this.name = "CliMissingApiKeyError";
|
|
69573
69605
|
}
|
|
69574
69606
|
};
|
|
69607
|
+
var CliSessionResumeError = class extends Error {
|
|
69608
|
+
constructor(sessionId, code, message = code === "session_not_found" ? `Session not found: ${sessionId}` : `Session could not be recovered: ${sessionId}`) {
|
|
69609
|
+
super(message);
|
|
69610
|
+
this.sessionId = sessionId;
|
|
69611
|
+
this.code = code;
|
|
69612
|
+
this.name = "CliSessionResumeError";
|
|
69613
|
+
}
|
|
69614
|
+
sessionId;
|
|
69615
|
+
code;
|
|
69616
|
+
recoverable = true;
|
|
69617
|
+
};
|
|
69575
69618
|
function getCliRuntimePaths() {
|
|
69576
69619
|
const configDir = getConfigDir();
|
|
69577
69620
|
const sessionsDir = getSessionsDir();
|
|
@@ -69644,10 +69687,17 @@ async function composeCliRuntime(params) {
|
|
|
69644
69687
|
const cwd = params.cwd ?? process.cwd();
|
|
69645
69688
|
const sessionManager = createSessionManager({ sessionsDir: paths.sessionsDir });
|
|
69646
69689
|
if (params.explicitSessionId) {
|
|
69690
|
+
const sessionFileExists = params.requireExistingSession ? await sessionManager.hasSession(params.explicitSessionId) : false;
|
|
69647
69691
|
const loaded = await sessionManager.loadSession(params.explicitSessionId, {
|
|
69648
69692
|
warnIfMissing: params.warnIfExplicitSessionMissing
|
|
69649
69693
|
});
|
|
69650
69694
|
if (!loaded) {
|
|
69695
|
+
if (params.requireExistingSession) {
|
|
69696
|
+
throw new CliSessionResumeError(
|
|
69697
|
+
params.explicitSessionId,
|
|
69698
|
+
sessionFileExists ? "session_unrecoverable" : "session_not_found"
|
|
69699
|
+
);
|
|
69700
|
+
}
|
|
69651
69701
|
await sessionManager.createSession(void 0, void 0, params.explicitSessionId);
|
|
69652
69702
|
} else {
|
|
69653
69703
|
const restored = restoreSessionModelState({
|
|
@@ -70174,12 +70224,17 @@ function parseInput(line) {
|
|
|
70174
70224
|
reason: typeof parsed.reason === "string" ? parsed.reason : void 0
|
|
70175
70225
|
};
|
|
70176
70226
|
}
|
|
70177
|
-
if (parsed.type === "turn.request" && typeof parsed.turnId === "string" && typeof parsed.prompt === "string") {
|
|
70227
|
+
if ((parsed.type === "turn.request" || parsed.type === "turn.input") && typeof parsed.turnId === "string" && typeof parsed.prompt === "string") {
|
|
70228
|
+
const streamingBehavior = parsed.streamingBehavior;
|
|
70229
|
+
if (streamingBehavior !== void 0 && streamingBehavior !== "steer" && streamingBehavior !== "followUp") {
|
|
70230
|
+
return null;
|
|
70231
|
+
}
|
|
70178
70232
|
return {
|
|
70179
70233
|
type: "turn.request",
|
|
70180
70234
|
sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : void 0,
|
|
70181
70235
|
turnId: parsed.turnId,
|
|
70182
70236
|
prompt: parsed.prompt,
|
|
70237
|
+
streamingBehavior,
|
|
70183
70238
|
cwd: typeof parsed.cwd === "string" ? parsed.cwd : void 0,
|
|
70184
70239
|
metadata: isRecord4(parsed.metadata) ? parsed.metadata : void 0
|
|
70185
70240
|
};
|
|
@@ -70343,6 +70398,13 @@ async function runJsonEventsMode(params) {
|
|
|
70343
70398
|
function delay(ms) {
|
|
70344
70399
|
return new Promise((resolve5) => setTimeout(resolve5, Math.max(0, ms)));
|
|
70345
70400
|
}
|
|
70401
|
+
async function waitForActiveController(timeoutMs = 1e3) {
|
|
70402
|
+
const deadline = Date.now() + timeoutMs;
|
|
70403
|
+
while (!controller && activeTurn && !activeTurn.finalized && Date.now() < deadline) {
|
|
70404
|
+
await delay(5);
|
|
70405
|
+
}
|
|
70406
|
+
return controller;
|
|
70407
|
+
}
|
|
70346
70408
|
function touch() {
|
|
70347
70409
|
if (activeTurn) {
|
|
70348
70410
|
activeTurn.lastActivityAt = Date.now();
|
|
@@ -70453,6 +70515,25 @@ async function runJsonEventsMode(params) {
|
|
|
70453
70515
|
display(chunk);
|
|
70454
70516
|
}
|
|
70455
70517
|
}
|
|
70518
|
+
function failureDetail(detail) {
|
|
70519
|
+
if (!detail) return { error: "turn failed" };
|
|
70520
|
+
if (typeof detail === "string") return { error: detail };
|
|
70521
|
+
return {
|
|
70522
|
+
error: detail.message,
|
|
70523
|
+
code: detail.code,
|
|
70524
|
+
recoverable: detail.recoverable
|
|
70525
|
+
};
|
|
70526
|
+
}
|
|
70527
|
+
function errorToFailureDetail(error) {
|
|
70528
|
+
if (error instanceof CliSessionResumeError) {
|
|
70529
|
+
return {
|
|
70530
|
+
message: error.message,
|
|
70531
|
+
code: error.code,
|
|
70532
|
+
recoverable: error.recoverable
|
|
70533
|
+
};
|
|
70534
|
+
}
|
|
70535
|
+
return error instanceof Error ? error.message : String(error);
|
|
70536
|
+
}
|
|
70456
70537
|
function finalize(kind, detail) {
|
|
70457
70538
|
const turn = activeTurn;
|
|
70458
70539
|
if (!turn || turn.finalized) return;
|
|
@@ -70466,10 +70547,10 @@ async function runJsonEventsMode(params) {
|
|
|
70466
70547
|
};
|
|
70467
70548
|
switch (kind) {
|
|
70468
70549
|
case "completed":
|
|
70469
|
-
writeEvent({ type: "turn.completed", ...base, summary: (detail
|
|
70550
|
+
writeEvent({ type: "turn.completed", ...base, summary: (typeof detail === "string" ? detail : turn.summary).trim() });
|
|
70470
70551
|
break;
|
|
70471
70552
|
case "failed":
|
|
70472
|
-
writeEvent({ type: "turn.failed", ...base,
|
|
70553
|
+
writeEvent({ type: "turn.failed", ...base, ...failureDetail(detail) });
|
|
70473
70554
|
break;
|
|
70474
70555
|
case "cancelled":
|
|
70475
70556
|
writeEvent({ type: "turn.cancelled", ...base, reason: detail || "interrupted" });
|
|
@@ -70844,12 +70925,7 @@ async function runJsonEventsMode(params) {
|
|
|
70844
70925
|
return;
|
|
70845
70926
|
}
|
|
70846
70927
|
if (activeTurn && !activeTurn.finalized) {
|
|
70847
|
-
|
|
70848
|
-
type: "turn.failed",
|
|
70849
|
-
sessionId,
|
|
70850
|
-
turnId: message.turnId,
|
|
70851
|
-
error: "another turn is already running"
|
|
70852
|
-
});
|
|
70928
|
+
await queueActiveTurnInput(message);
|
|
70853
70929
|
return;
|
|
70854
70930
|
}
|
|
70855
70931
|
activeTurn = {
|
|
@@ -70897,7 +70973,7 @@ async function runJsonEventsMode(params) {
|
|
|
70897
70973
|
try {
|
|
70898
70974
|
await ensureRuntime(message.cwd);
|
|
70899
70975
|
} catch (error) {
|
|
70900
|
-
finalize("failed",
|
|
70976
|
+
finalize("failed", errorToFailureDetail(error));
|
|
70901
70977
|
if (activeTurn === turn) emitSettled(turn);
|
|
70902
70978
|
if (activeTurn === turn) activeTurn = null;
|
|
70903
70979
|
return;
|
|
@@ -70974,6 +71050,55 @@ async function runJsonEventsMode(params) {
|
|
|
70974
71050
|
if (activeTurn === turn) activeTurn = null;
|
|
70975
71051
|
}
|
|
70976
71052
|
}
|
|
71053
|
+
async function queueActiveTurnInput(message) {
|
|
71054
|
+
if (!message.streamingBehavior) {
|
|
71055
|
+
writeEvent({
|
|
71056
|
+
type: "turn.failed",
|
|
71057
|
+
sessionId,
|
|
71058
|
+
turnId: message.turnId,
|
|
71059
|
+
error: "another turn is already running; specify streamingBehavior ('steer' or 'followUp') to queue the message"
|
|
71060
|
+
});
|
|
71061
|
+
return;
|
|
71062
|
+
}
|
|
71063
|
+
const activeController = await waitForActiveController();
|
|
71064
|
+
if (!activeController) {
|
|
71065
|
+
writeEvent({
|
|
71066
|
+
type: "turn.failed",
|
|
71067
|
+
sessionId,
|
|
71068
|
+
turnId: message.turnId,
|
|
71069
|
+
error: "JSON events runtime is not ready to queue a streaming turn"
|
|
71070
|
+
});
|
|
71071
|
+
return;
|
|
71072
|
+
}
|
|
71073
|
+
try {
|
|
71074
|
+
applyRuntimeSelection(message);
|
|
71075
|
+
trace?.notePendingUserText(message.prompt);
|
|
71076
|
+
trace?.noteRuntimeEvent("json_events_turn_queued", {
|
|
71077
|
+
mode: message.streamingBehavior,
|
|
71078
|
+
turnId: message.turnId
|
|
71079
|
+
});
|
|
71080
|
+
await activeController.prompt(message.prompt, {
|
|
71081
|
+
source: "json-events",
|
|
71082
|
+
streamingBehavior: message.streamingBehavior,
|
|
71083
|
+
displayText: message.prompt,
|
|
71084
|
+
deliverWhileStreaming: message.streamingBehavior === "steer"
|
|
71085
|
+
});
|
|
71086
|
+
writeEvent({
|
|
71087
|
+
type: "turn.queued",
|
|
71088
|
+
sessionId,
|
|
71089
|
+
turnId: message.turnId,
|
|
71090
|
+
mode: message.streamingBehavior,
|
|
71091
|
+
activeTurnId: activeTurn?.turnId
|
|
71092
|
+
});
|
|
71093
|
+
} catch (error) {
|
|
71094
|
+
writeEvent({
|
|
71095
|
+
type: "turn.failed",
|
|
71096
|
+
sessionId,
|
|
71097
|
+
turnId: message.turnId,
|
|
71098
|
+
error: error instanceof Error ? error.message : String(error)
|
|
71099
|
+
});
|
|
71100
|
+
}
|
|
71101
|
+
}
|
|
70977
71102
|
async function interrupt(message) {
|
|
70978
71103
|
if (isSessionMismatch(message)) {
|
|
70979
71104
|
writeEvent({
|
|
@@ -71098,6 +71223,7 @@ Commands:
|
|
|
71098
71223
|
Interactive Mode Key Bindings:
|
|
71099
71224
|
Enter Submit message
|
|
71100
71225
|
\\ + Enter New line (fallback)
|
|
71226
|
+
Alt+Enter Queue steering message for the active turn
|
|
71101
71227
|
Ctrl+C Exit
|
|
71102
71228
|
Ctrl+D Exit
|
|
71103
71229
|
Ctrl+O Expand/collapse tool output
|
|
@@ -71115,6 +71241,7 @@ Print Mode Options:
|
|
|
71115
71241
|
--json-output Print structured JSON in non-interactive mode
|
|
71116
71242
|
--json-events Run JSONL protocol mode over stdin/stdout
|
|
71117
71243
|
--session-id Reuse or create a specific session in non-interactive mode
|
|
71244
|
+
--resume-required In JSON-events mode, fail if --session-id cannot be resumed
|
|
71118
71245
|
--extension-path Add an extra extension search directory (repeatable)
|
|
71119
71246
|
--no-builtin-extensions Skip built-in extensions (keep user/project ones)
|
|
71120
71247
|
--no-extensions Skip all discovered extensions (keeps --extension-path)
|
|
@@ -71194,16 +71321,6 @@ async function runModelsCommand(args) {
|
|
|
71194
71321
|
pie models init [--path <path>] [--force] [--stdout]
|
|
71195
71322
|
pie models validate [--path <path>] [--probe web_search] [--json]`);
|
|
71196
71323
|
}
|
|
71197
|
-
function parseRepeatedFlag(args, flag) {
|
|
71198
|
-
const values = [];
|
|
71199
|
-
for (let i = 0; i < args.length; i += 1) {
|
|
71200
|
-
if (args[i] === flag && args[i + 1]) {
|
|
71201
|
-
values.push(args[i + 1]);
|
|
71202
|
-
i += 1;
|
|
71203
|
-
}
|
|
71204
|
-
}
|
|
71205
|
-
return values;
|
|
71206
|
-
}
|
|
71207
71324
|
async function runWithJsonEventsConsoleIsolation(fn) {
|
|
71208
71325
|
const originalLog = console.log;
|
|
71209
71326
|
const originalInfo = console.info;
|
|
@@ -71228,6 +71345,7 @@ async function startChat(initialPrompt, testCommand) {
|
|
|
71228
71345
|
const rawOutput = process.argv.includes("--raw-output");
|
|
71229
71346
|
const jsonOutput = process.argv.includes("--json-output");
|
|
71230
71347
|
const jsonEvents = process.argv.includes("--json-events");
|
|
71348
|
+
const resumeRequired = process.argv.includes("--resume-required");
|
|
71231
71349
|
const sessionIdFlagIndex = process.argv.indexOf("--session-id");
|
|
71232
71350
|
const explicitSessionId = sessionIdFlagIndex >= 0 ? process.argv[sessionIdFlagIndex + 1] : void 0;
|
|
71233
71351
|
const extensionPaths = parseRepeatedFlag(process.argv, "--extension-path");
|
|
@@ -71237,19 +71355,22 @@ async function startChat(initialPrompt, testCommand) {
|
|
|
71237
71355
|
if (process.env.PIE_TEST_MOCK_RESPONSE !== void 0) {
|
|
71238
71356
|
await runJsonEventsMode({
|
|
71239
71357
|
explicitSessionId,
|
|
71358
|
+
resumeRequired,
|
|
71240
71359
|
mockResponse: process.env.PIE_TEST_MOCK_RESPONSE
|
|
71241
71360
|
});
|
|
71242
71361
|
return;
|
|
71243
71362
|
}
|
|
71244
71363
|
await runJsonEventsMode({
|
|
71245
71364
|
explicitSessionId,
|
|
71365
|
+
resumeRequired,
|
|
71246
71366
|
streamFn: await createCliTestStreamFnFromEnv(),
|
|
71247
71367
|
createRuntime: async ({ cwd, sessionId }) => composeCliRuntime({
|
|
71248
71368
|
explicitSessionId: explicitSessionId ?? sessionId,
|
|
71249
71369
|
extensionPaths,
|
|
71250
71370
|
extensionFlags,
|
|
71251
71371
|
cwd,
|
|
71252
|
-
warnIfExplicitSessionMissing: false
|
|
71372
|
+
warnIfExplicitSessionMissing: false,
|
|
71373
|
+
requireExistingSession: resumeRequired && !!explicitSessionId
|
|
71253
71374
|
})
|
|
71254
71375
|
});
|
|
71255
71376
|
});
|