@cydm/pie 1.0.45 → 1.0.47
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/builtin/extensions/ask-user/index.js +1 -1
- package/dist/builtin/extensions/plan-mode/index.js +1 -1
- package/dist/builtin/extensions/subagent/index.js +2 -2
- package/dist/builtin/extensions/todo/index.js +1 -1
- package/dist/chunks/{chunk-PKR3PO73.js → chunk-IJMP3JTX.js} +195 -34
- package/dist/chunks/{chunk-75JWZPRK.js → chunk-U4B6RJ6Z.js} +1 -1
- package/dist/chunks/{test-stream-XCE2KXJU.js → test-stream-5T7E7C25.js} +9 -2
- package/dist/cli.js +1989 -790
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -19,7 +19,7 @@ import {
|
|
|
19
19
|
getThemesDir,
|
|
20
20
|
migrateConfigFromAgentDir,
|
|
21
21
|
truncateHeadTail
|
|
22
|
-
} from "./chunks/chunk-
|
|
22
|
+
} from "./chunks/chunk-U4B6RJ6Z.js";
|
|
23
23
|
import {
|
|
24
24
|
AGENTS_CONTEXT_FILE_NAME,
|
|
25
25
|
AgentSessionController,
|
|
@@ -66,10 +66,11 @@ import {
|
|
|
66
66
|
resolveExtensionIdentity,
|
|
67
67
|
restoreExecutionState,
|
|
68
68
|
selectToolsForRuntimePolicy,
|
|
69
|
+
setEnablementInMap,
|
|
69
70
|
setExtensionEnabledInSettings,
|
|
70
71
|
shouldPreserveExecutionStateForUserText,
|
|
71
72
|
supersedeExecutionState
|
|
72
|
-
} from "./chunks/chunk-
|
|
73
|
+
} from "./chunks/chunk-IJMP3JTX.js";
|
|
73
74
|
import "./chunks/chunk-FKAO25XH.js";
|
|
74
75
|
import {
|
|
75
76
|
Deref,
|
|
@@ -1236,12 +1237,12 @@ var require_supports_color = __commonJS({
|
|
|
1236
1237
|
"use strict";
|
|
1237
1238
|
var os9 = __require("os");
|
|
1238
1239
|
var tty = __require("tty");
|
|
1239
|
-
var
|
|
1240
|
+
var hasFlag = require_has_flag();
|
|
1240
1241
|
var { env } = process;
|
|
1241
1242
|
var forceColor;
|
|
1242
|
-
if (
|
|
1243
|
+
if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
|
|
1243
1244
|
forceColor = 0;
|
|
1244
|
-
} else if (
|
|
1245
|
+
} else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
|
|
1245
1246
|
forceColor = 1;
|
|
1246
1247
|
}
|
|
1247
1248
|
if ("FORCE_COLOR" in env) {
|
|
@@ -1268,10 +1269,10 @@ var require_supports_color = __commonJS({
|
|
|
1268
1269
|
if (forceColor === 0) {
|
|
1269
1270
|
return 0;
|
|
1270
1271
|
}
|
|
1271
|
-
if (
|
|
1272
|
+
if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
|
|
1272
1273
|
return 3;
|
|
1273
1274
|
}
|
|
1274
|
-
if (
|
|
1275
|
+
if (hasFlag("color=256")) {
|
|
1275
1276
|
return 2;
|
|
1276
1277
|
}
|
|
1277
1278
|
if (haveStream && !streamIsTTY && forceColor === void 0) {
|
|
@@ -46223,6 +46224,13 @@ var ModelRegistry = class {
|
|
|
46223
46224
|
// src/core/settings-manager.ts
|
|
46224
46225
|
import * as fs4 from "fs";
|
|
46225
46226
|
import * as path4 from "path";
|
|
46227
|
+
function getDisabledToolNames(settingsManager) {
|
|
46228
|
+
return new Set(typeof settingsManager?.getDisabledTools === "function" ? settingsManager.getDisabledTools() : []);
|
|
46229
|
+
}
|
|
46230
|
+
function filterEnabledTools(tools, settingsManager) {
|
|
46231
|
+
const disabled = getDisabledToolNames(settingsManager);
|
|
46232
|
+
return disabled.size > 0 ? tools.filter((tool) => !disabled.has(tool.name)) : [...tools];
|
|
46233
|
+
}
|
|
46226
46234
|
var SettingsManager = class {
|
|
46227
46235
|
settingsPath;
|
|
46228
46236
|
legacyConfigPath;
|
|
@@ -46379,6 +46387,44 @@ var SettingsManager = class {
|
|
|
46379
46387
|
this.writeSettingsValue(nextSettings);
|
|
46380
46388
|
this.settings = nextSettings;
|
|
46381
46389
|
}
|
|
46390
|
+
/** Raw skill enablement map. */
|
|
46391
|
+
getSkillSettings() {
|
|
46392
|
+
return this.settings.skills ?? {};
|
|
46393
|
+
}
|
|
46394
|
+
/** Whether a skill is enabled; absent entries mean "enabled". */
|
|
46395
|
+
isSkillEnabled(name) {
|
|
46396
|
+
return isExtensionEnabled(name, this.getSkillSettings());
|
|
46397
|
+
}
|
|
46398
|
+
/** Set or clear (enabled=undefined) a skill enablement override. */
|
|
46399
|
+
setSkillEnabled(name, enabled) {
|
|
46400
|
+
const nextSettings = { ...this.settings };
|
|
46401
|
+
setEnablementInMap(nextSettings, "skills", name, enabled);
|
|
46402
|
+
this.writeSettingsValue(nextSettings);
|
|
46403
|
+
this.settings = nextSettings;
|
|
46404
|
+
}
|
|
46405
|
+
/** Disabled runtime tool names (may contain names no longer installed). */
|
|
46406
|
+
getDisabledTools() {
|
|
46407
|
+
return [...this.settings.tools?.disabledTools ?? []];
|
|
46408
|
+
}
|
|
46409
|
+
/** Whether a runtime tool is enabled; absent means "enabled". */
|
|
46410
|
+
isToolEnabled(name) {
|
|
46411
|
+
return !this.getDisabledTools().includes(name);
|
|
46412
|
+
}
|
|
46413
|
+
/** Enable/disable a runtime tool by name (persisted in settings.json). */
|
|
46414
|
+
setToolEnabled(name, enabled) {
|
|
46415
|
+
const disabled = this.getDisabledTools().filter((tool) => tool !== name);
|
|
46416
|
+
if (!enabled) disabled.push(name);
|
|
46417
|
+
disabled.sort();
|
|
46418
|
+
const nextTools = { ...this.settings.tools ?? {} };
|
|
46419
|
+
delete nextTools.disabledTools;
|
|
46420
|
+
if (disabled.length > 0) nextTools.disabledTools = disabled;
|
|
46421
|
+
const nextSettings = { ...this.settings, tools: nextTools };
|
|
46422
|
+
if (Object.keys(nextTools).length === 0) {
|
|
46423
|
+
delete nextSettings.tools;
|
|
46424
|
+
}
|
|
46425
|
+
this.writeSettingsValue(nextSettings);
|
|
46426
|
+
this.settings = nextSettings;
|
|
46427
|
+
}
|
|
46382
46428
|
};
|
|
46383
46429
|
|
|
46384
46430
|
// src/doctor.ts
|
|
@@ -46772,28 +46818,54 @@ function formatDoctorReport(report) {
|
|
|
46772
46818
|
}
|
|
46773
46819
|
|
|
46774
46820
|
// src/permissions-help.ts
|
|
46821
|
+
var MODE_RULES = {
|
|
46822
|
+
default: [
|
|
46823
|
+
"File tools read and write inside the current workspace.",
|
|
46824
|
+
"~/.pie is allowlisted for Pie configuration and session support.",
|
|
46825
|
+
"Shell commands run from the workspace and return structured output, timeout, and truncation details.",
|
|
46826
|
+
"web_research is read-only, uses provider-native web/search/fetch capabilities, and does not grant bash/curl web scraping permission.",
|
|
46827
|
+
"Protected paths from extensions can block reads/writes even when tools are present."
|
|
46828
|
+
],
|
|
46829
|
+
plan: [
|
|
46830
|
+
"The agent should inspect and plan before making changes.",
|
|
46831
|
+
"Risky write/shell actions should be deferred until the user approves the plan."
|
|
46832
|
+
],
|
|
46833
|
+
yolo: [
|
|
46834
|
+
"/settings/yolo relaxes filesystem sandbox directory restrictions.",
|
|
46835
|
+
"It does not make destructive shell commands safe; use it only in trusted workspaces."
|
|
46836
|
+
],
|
|
46837
|
+
subagents: [
|
|
46838
|
+
"Subagents inherit the parent tool set, then runtime policy removes write and high-risk tools.",
|
|
46839
|
+
"Subagents are expected to return evidence and hand off required writes to the parent agent."
|
|
46840
|
+
]
|
|
46841
|
+
};
|
|
46842
|
+
var MODE_TITLES = {
|
|
46843
|
+
default: "Default mode",
|
|
46844
|
+
plan: "Plan mode",
|
|
46845
|
+
yolo: "YOLO mode",
|
|
46846
|
+
subagents: "Subagents"
|
|
46847
|
+
};
|
|
46848
|
+
function buildPermissionsData() {
|
|
46849
|
+
return {
|
|
46850
|
+
modes: Object.fromEntries(Object.entries(MODE_RULES).map(([key, rules]) => [key, [...rules]])),
|
|
46851
|
+
tools: Object.entries(BUILTIN_TOOL_CAPABILITY_METADATA).map(([name, meta]) => ({
|
|
46852
|
+
name,
|
|
46853
|
+
...meta.riskClass ? { riskClass: meta.riskClass } : {},
|
|
46854
|
+
...meta.permissionScope ? { permissionScope: meta.permissionScope } : {},
|
|
46855
|
+
...meta.availableInPlanMode ? { availableInPlanMode: true } : {},
|
|
46856
|
+
...meta.allowedForSubagentByDefault ? { allowedForSubagentByDefault: true } : {},
|
|
46857
|
+
...meta.highRisk ? { highRisk: true } : {}
|
|
46858
|
+
}))
|
|
46859
|
+
};
|
|
46860
|
+
}
|
|
46775
46861
|
function formatPermissionsHelp() {
|
|
46776
|
-
const
|
|
46862
|
+
const data = buildPermissionsData();
|
|
46863
|
+
const modeSections = Object.entries(data.modes).map(([key, rules]) => `${MODE_TITLES[key]}:
|
|
46864
|
+
${rules.map((rule) => ` - ${rule}`).join("\n")}`).join("\n\n");
|
|
46865
|
+
const toolLines = data.tools.map((tool) => ` - ${tool.name}: ${tool.riskClass ?? "unknown"}${tool.permissionScope ? `, scope=${tool.permissionScope}` : ""}${tool.availableInPlanMode ? ", plan" : ""}${tool.allowedForSubagentByDefault ? ", subagent" : ""}${tool.highRisk ? ", high-risk" : ""}`).join("\n");
|
|
46777
46866
|
return `Pie permissions and safety model
|
|
46778
46867
|
|
|
46779
|
-
|
|
46780
|
-
- File tools read and write inside the current workspace.
|
|
46781
|
-
- ~/.pie is allowlisted for Pie configuration and session support.
|
|
46782
|
-
- Shell commands run from the workspace and return structured output, timeout, and truncation details.
|
|
46783
|
-
- web_research is read-only, uses provider-native web/search/fetch capabilities, and does not grant bash/curl web scraping permission.
|
|
46784
|
-
- Protected paths from extensions can block reads/writes even when tools are present.
|
|
46785
|
-
|
|
46786
|
-
Plan mode:
|
|
46787
|
-
- The agent should inspect and plan before making changes.
|
|
46788
|
-
- Risky write/shell actions should be deferred until the user approves the plan.
|
|
46789
|
-
|
|
46790
|
-
YOLO mode:
|
|
46791
|
-
- /settings/yolo relaxes filesystem sandbox directory restrictions.
|
|
46792
|
-
- It does not make destructive shell commands safe; use it only in trusted workspaces.
|
|
46793
|
-
|
|
46794
|
-
Subagents:
|
|
46795
|
-
- Subagents inherit the parent tool set, then runtime policy removes write and high-risk tools.
|
|
46796
|
-
- Subagents are expected to return evidence and hand off required writes to the parent agent.
|
|
46868
|
+
${modeSections}
|
|
46797
46869
|
|
|
46798
46870
|
Tool policy snapshot:
|
|
46799
46871
|
${toolLines}
|
|
@@ -47042,30 +47114,677 @@ async function probeModelsConfig(options) {
|
|
|
47042
47114
|
message: passed ? `web_search probe passed using ${attempts.find((attempt) => attempt.status === "passed")?.route}.` : "web_search probe failed for all configured candidate routes."
|
|
47043
47115
|
};
|
|
47044
47116
|
}
|
|
47045
|
-
|
|
47046
|
-
|
|
47047
|
-
|
|
47048
|
-
|
|
47049
|
-
|
|
47050
|
-
|
|
47051
|
-
|
|
47052
|
-
|
|
47053
|
-
|
|
47054
|
-
|
|
47055
|
-
|
|
47056
|
-
|
|
47057
|
-
|
|
47058
|
-
|
|
47059
|
-
|
|
47060
|
-
|
|
47061
|
-
|
|
47062
|
-
|
|
47063
|
-
|
|
47064
|
-
|
|
47065
|
-
|
|
47117
|
+
|
|
47118
|
+
// src/command-args.ts
|
|
47119
|
+
var HELP_FLAG_NAMES = /* @__PURE__ */ new Set(["--help", "-h"]);
|
|
47120
|
+
function parseCommandArgs(args, spec) {
|
|
47121
|
+
const flags = /* @__PURE__ */ new Map();
|
|
47122
|
+
const positionals = /* @__PURE__ */ new Map();
|
|
47123
|
+
const flagByName = /* @__PURE__ */ new Map();
|
|
47124
|
+
for (const flag of spec.flags) {
|
|
47125
|
+
flagByName.set(flag.name, flag);
|
|
47126
|
+
for (const alias of flag.aliases ?? []) {
|
|
47127
|
+
flagByName.set(alias, flag);
|
|
47128
|
+
}
|
|
47129
|
+
}
|
|
47130
|
+
let help = false;
|
|
47131
|
+
let positionalIndex = 0;
|
|
47132
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
47133
|
+
const arg = args[index];
|
|
47134
|
+
if (HELP_FLAG_NAMES.has(arg)) {
|
|
47135
|
+
help = true;
|
|
47136
|
+
continue;
|
|
47137
|
+
}
|
|
47138
|
+
if (arg.startsWith("--")) {
|
|
47139
|
+
const equals = arg.indexOf("=");
|
|
47140
|
+
const head = equals >= 0 ? arg.slice(0, equals) : arg;
|
|
47141
|
+
const inlineValue = equals >= 0 ? arg.slice(equals + 1) : void 0;
|
|
47142
|
+
if (HELP_FLAG_NAMES.has(head)) {
|
|
47143
|
+
return {
|
|
47144
|
+
help,
|
|
47145
|
+
flags,
|
|
47146
|
+
positionals,
|
|
47147
|
+
error: {
|
|
47148
|
+
code: "unknown_flag",
|
|
47149
|
+
flag: arg,
|
|
47150
|
+
message: `Unknown flag: ${arg}. Use --help (no value) instead.`
|
|
47151
|
+
}
|
|
47152
|
+
};
|
|
47153
|
+
}
|
|
47154
|
+
const flagSpec = flagByName.get(head);
|
|
47155
|
+
if (!flagSpec) {
|
|
47156
|
+
return {
|
|
47157
|
+
help,
|
|
47158
|
+
flags,
|
|
47159
|
+
positionals,
|
|
47160
|
+
error: {
|
|
47161
|
+
code: "unknown_flag",
|
|
47162
|
+
flag: arg,
|
|
47163
|
+
message: `Unknown flag: ${arg}. Run 'pie ${spec.path} --help' for supported flags.`
|
|
47164
|
+
}
|
|
47165
|
+
};
|
|
47166
|
+
}
|
|
47167
|
+
if (flagSpec.kind === "boolean") {
|
|
47168
|
+
if (inlineValue !== void 0) {
|
|
47169
|
+
return {
|
|
47170
|
+
help,
|
|
47171
|
+
flags,
|
|
47172
|
+
positionals,
|
|
47173
|
+
error: {
|
|
47174
|
+
code: "unknown_flag",
|
|
47175
|
+
flag: arg,
|
|
47176
|
+
message: `Flag ${flagSpec.name} does not take a value.`
|
|
47177
|
+
}
|
|
47178
|
+
};
|
|
47179
|
+
}
|
|
47180
|
+
flags.set(flagSpec.name, true);
|
|
47181
|
+
continue;
|
|
47182
|
+
}
|
|
47183
|
+
let value = inlineValue;
|
|
47184
|
+
if (value === void 0) {
|
|
47185
|
+
const next = args[index + 1];
|
|
47186
|
+
if (next === void 0 || next.startsWith("--")) {
|
|
47187
|
+
return {
|
|
47188
|
+
help,
|
|
47189
|
+
flags,
|
|
47190
|
+
positionals,
|
|
47191
|
+
error: {
|
|
47192
|
+
code: "missing_value",
|
|
47193
|
+
flag: flagSpec.name,
|
|
47194
|
+
message: `Flag ${flagSpec.name} requires a value.`
|
|
47195
|
+
}
|
|
47196
|
+
};
|
|
47197
|
+
}
|
|
47198
|
+
value = next;
|
|
47199
|
+
index += 1;
|
|
47200
|
+
}
|
|
47201
|
+
if (flagSpec.repeatable) {
|
|
47202
|
+
const existing = flags.get(flagSpec.name);
|
|
47203
|
+
const collected = Array.isArray(existing) ? existing : [];
|
|
47204
|
+
collected.push(value);
|
|
47205
|
+
flags.set(flagSpec.name, collected);
|
|
47206
|
+
} else {
|
|
47207
|
+
flags.set(flagSpec.name, value);
|
|
47208
|
+
}
|
|
47209
|
+
continue;
|
|
47210
|
+
}
|
|
47211
|
+
const slot = spec.positional[positionalIndex];
|
|
47212
|
+
if (!slot) {
|
|
47213
|
+
return {
|
|
47214
|
+
help,
|
|
47215
|
+
flags,
|
|
47216
|
+
positionals,
|
|
47217
|
+
error: {
|
|
47218
|
+
code: "unexpected_positional",
|
|
47219
|
+
positional: arg,
|
|
47220
|
+
message: `Unexpected argument: ${arg}. Run 'pie ${spec.usage}' to see expected arguments.`
|
|
47221
|
+
}
|
|
47222
|
+
};
|
|
47223
|
+
}
|
|
47224
|
+
if (slot.variadic) {
|
|
47225
|
+
const collected = getPositionals({ help, flags, positionals }, slot.name);
|
|
47226
|
+
collected.push(arg);
|
|
47227
|
+
positionals.set(slot.name, collected);
|
|
47228
|
+
continue;
|
|
47229
|
+
}
|
|
47230
|
+
positionals.set(slot.name, arg);
|
|
47231
|
+
positionalIndex += 1;
|
|
47232
|
+
}
|
|
47233
|
+
if (help) return { help, flags, positionals };
|
|
47234
|
+
for (const slot of spec.positional) {
|
|
47235
|
+
if (!slot.required) continue;
|
|
47236
|
+
const value = positionals.get(slot.name);
|
|
47237
|
+
if (value === void 0 || Array.isArray(value) && value.length === 0) {
|
|
47238
|
+
return {
|
|
47239
|
+
help,
|
|
47240
|
+
flags,
|
|
47241
|
+
positionals,
|
|
47242
|
+
error: {
|
|
47243
|
+
code: "missing_positional",
|
|
47244
|
+
positional: slot.name,
|
|
47245
|
+
message: `Missing required argument: <${slot.name}>.`
|
|
47246
|
+
}
|
|
47247
|
+
};
|
|
47248
|
+
}
|
|
47249
|
+
}
|
|
47250
|
+
return { help, flags, positionals };
|
|
47251
|
+
}
|
|
47252
|
+
function getFlagString(parsed, name) {
|
|
47253
|
+
const value = parsed.flags.get(name);
|
|
47254
|
+
if (typeof value === "string") return value;
|
|
47255
|
+
return void 0;
|
|
47256
|
+
}
|
|
47257
|
+
function getFlagStrings(parsed, name) {
|
|
47258
|
+
const value = parsed.flags.get(name);
|
|
47259
|
+
return Array.isArray(value) ? value : [];
|
|
47260
|
+
}
|
|
47261
|
+
function getFlagBool(parsed, name) {
|
|
47262
|
+
return parsed.flags.get(name) === true;
|
|
47263
|
+
}
|
|
47264
|
+
function getPositional(parsed, name) {
|
|
47265
|
+
const value = parsed.positionals.get(name);
|
|
47266
|
+
if (typeof value === "string") return value;
|
|
47267
|
+
return void 0;
|
|
47268
|
+
}
|
|
47269
|
+
function getPositionals(parsed, name) {
|
|
47270
|
+
const value = parsed.positionals.get(name);
|
|
47271
|
+
return Array.isArray(value) ? value : [];
|
|
47272
|
+
}
|
|
47273
|
+
function renderCommandUsage(spec) {
|
|
47274
|
+
return `Usage: pie ${spec.usage}`;
|
|
47275
|
+
}
|
|
47276
|
+
function renderCommandHelp(spec) {
|
|
47277
|
+
const lines = [renderCommandUsage(spec), "", spec.summary];
|
|
47278
|
+
if (spec.positional.length > 0) {
|
|
47279
|
+
lines.push("", "Arguments:");
|
|
47280
|
+
for (const slot of spec.positional) {
|
|
47281
|
+
const marker = slot.required ? `<${slot.name}>` : `[${slot.name}]`;
|
|
47282
|
+
lines.push(
|
|
47283
|
+
` ${marker}${slot.variadic ? "..." : ""} ${slot.description}`
|
|
47284
|
+
);
|
|
47285
|
+
}
|
|
47286
|
+
}
|
|
47287
|
+
if (spec.flags.length > 0) {
|
|
47288
|
+
lines.push("", "Options:");
|
|
47289
|
+
for (const flag of spec.flags) {
|
|
47290
|
+
const names = [flag.name, ...flag.aliases ?? []].join(", ");
|
|
47291
|
+
const valueHint = flag.kind === "string" ? " <value>" : "";
|
|
47292
|
+
lines.push(` ${names}${valueHint} ${flag.description}`);
|
|
47293
|
+
}
|
|
47294
|
+
}
|
|
47295
|
+
lines.push("", " --help, -h Show this help");
|
|
47296
|
+
return lines.join("\n");
|
|
47297
|
+
}
|
|
47298
|
+
|
|
47299
|
+
// src/command-specs.ts
|
|
47300
|
+
var SESSIONS_LIST_SPEC = {
|
|
47301
|
+
path: "sessions list",
|
|
47302
|
+
summary: "List sessions, most recently updated first.",
|
|
47303
|
+
usage: "sessions list [--json] [--limit <n>] [--cursor <cursor>] [--cwd <path> | --all] [--fields <list>] [--full]",
|
|
47304
|
+
flags: [
|
|
47305
|
+
{ name: "--json", kind: "boolean", description: "Emit the machine envelope (compact JSON)." },
|
|
47306
|
+
{ name: "--limit", kind: "string", description: "Page size, 1-1000 (default 50)." },
|
|
47307
|
+
{ name: "--cursor", kind: "string", description: "Resume from meta.nextCursor of a previous page." },
|
|
47308
|
+
{ name: "--cwd", kind: "string", description: "Only sessions whose cwd matches this path." },
|
|
47309
|
+
{ name: "--all", kind: "boolean", description: "Ignore cwd scoping (JSON mode defaults to the current directory)." },
|
|
47310
|
+
{ name: "--fields", kind: "string", description: "Extra row fields (comma list): createdAt, cwd, activeEntryId, rootEntryId, sourceSessionId, sourceEntryId, sourceActiveEntryId, forkBaseEntryId, or all." },
|
|
47311
|
+
{ name: "--full", kind: "boolean", description: "Disable name truncation." }
|
|
47312
|
+
],
|
|
47313
|
+
positional: []
|
|
47314
|
+
};
|
|
47315
|
+
var SESSIONS_READ_SPEC = {
|
|
47316
|
+
path: "sessions read",
|
|
47317
|
+
summary: "Read a session's active transcript path.",
|
|
47318
|
+
usage: "sessions read <sessionId> [--json] [--limit <n>] [--before <cursor>] [--fields <list>] [--full]",
|
|
47319
|
+
flags: [
|
|
47320
|
+
{ name: "--json", kind: "boolean", description: "Emit the machine envelope (compact JSON)." },
|
|
47321
|
+
{ name: "--limit", kind: "string", description: "Max events per page, 1-1000 (default 200)." },
|
|
47322
|
+
{ name: "--before", kind: "string", description: "Event entryId or sequence number to read up to (exclusive)." },
|
|
47323
|
+
{ name: "--fields", kind: "string", description: "Extra event fields (comma list): timestamp, turnId, message, or all." },
|
|
47324
|
+
{ name: "--full", kind: "boolean", description: "Disable content truncation." }
|
|
47325
|
+
],
|
|
47326
|
+
positional: [
|
|
47327
|
+
{ name: "sessionId", required: true, description: "Session identifier." }
|
|
47328
|
+
]
|
|
47329
|
+
};
|
|
47330
|
+
var SESSIONS_RENAME_SPEC = {
|
|
47331
|
+
path: "sessions rename",
|
|
47332
|
+
summary: "Rename a session.",
|
|
47333
|
+
usage: "sessions rename <sessionId> <name...> [--json] [--cwd <path>]",
|
|
47334
|
+
flags: [
|
|
47335
|
+
{ name: "--json", kind: "boolean", description: "Emit the machine envelope (compact JSON)." },
|
|
47336
|
+
{ name: "--cwd", kind: "string", description: "Also update the session's cwd." }
|
|
47337
|
+
],
|
|
47338
|
+
positional: [
|
|
47339
|
+
{ name: "sessionId", required: true, description: "Session identifier." },
|
|
47340
|
+
{ name: "name", required: true, variadic: true, description: "New session name." }
|
|
47341
|
+
]
|
|
47342
|
+
};
|
|
47343
|
+
var SESSIONS_REWIND_SPEC = {
|
|
47344
|
+
path: "sessions rewind",
|
|
47345
|
+
summary: "Move a session's active head back to an earlier entry.",
|
|
47346
|
+
usage: "sessions rewind <sessionId> --to <entryId> [--json]",
|
|
47347
|
+
flags: [
|
|
47348
|
+
{ name: "--json", kind: "boolean", description: "Emit the machine envelope (compact JSON)." },
|
|
47349
|
+
{ name: "--to", kind: "string", description: "Target entryId on the active path." }
|
|
47350
|
+
],
|
|
47351
|
+
positional: [
|
|
47352
|
+
{ name: "sessionId", required: true, description: "Session identifier." }
|
|
47353
|
+
]
|
|
47354
|
+
};
|
|
47355
|
+
var SESSIONS_FORK_SPEC = {
|
|
47356
|
+
path: "sessions fork",
|
|
47357
|
+
summary: "Fork a session at an entry into a new session.",
|
|
47358
|
+
usage: "sessions fork <sessionId> --from <entryId> --target <newSessionId> --name <name> [--cwd <path>] [--force] [--json]",
|
|
47359
|
+
flags: [
|
|
47360
|
+
{ name: "--json", kind: "boolean", description: "Emit the machine envelope (compact JSON)." },
|
|
47361
|
+
{ name: "--from", kind: "string", description: "EntryId to fork at." },
|
|
47362
|
+
{ name: "--target", kind: "string", description: "Identifier for the new session." },
|
|
47363
|
+
{ name: "--name", kind: "string", description: "Name for the new session." },
|
|
47364
|
+
{ name: "--cwd", kind: "string", description: "cwd recorded on the new session." },
|
|
47365
|
+
{ name: "--force", kind: "boolean", description: "Overwrite the target session if it already exists." }
|
|
47366
|
+
],
|
|
47367
|
+
positional: [
|
|
47368
|
+
{ name: "sessionId", required: true, description: "Source session identifier." }
|
|
47369
|
+
]
|
|
47370
|
+
};
|
|
47371
|
+
var DOCTOR_SPEC = {
|
|
47372
|
+
path: "doctor",
|
|
47373
|
+
summary: "Diagnose local Pie configuration and runtime dependencies.",
|
|
47374
|
+
usage: "doctor [--json]",
|
|
47375
|
+
flags: [
|
|
47376
|
+
{ name: "--json", kind: "boolean", description: "Emit the machine envelope (compact JSON)." }
|
|
47377
|
+
],
|
|
47378
|
+
positional: []
|
|
47379
|
+
};
|
|
47380
|
+
var MODELS_INIT_SPEC = {
|
|
47381
|
+
path: "models init",
|
|
47382
|
+
summary: "Create a starter models.json template.",
|
|
47383
|
+
usage: "models init [--path <path>] [--force] [--stdout] [--json]",
|
|
47384
|
+
flags: [
|
|
47385
|
+
{ name: "--json", kind: "boolean", description: "Emit the machine envelope (compact JSON)." },
|
|
47386
|
+
{ name: "--path", kind: "string", description: "Target models.json path (default ~/.pie/models.json)." },
|
|
47387
|
+
{ name: "--force", kind: "boolean", description: "Overwrite an existing file." },
|
|
47388
|
+
{ name: "--stdout", kind: "boolean", description: "Print the template instead of writing a file." }
|
|
47389
|
+
],
|
|
47390
|
+
positional: []
|
|
47391
|
+
};
|
|
47392
|
+
var MODELS_VALIDATE_SPEC = {
|
|
47393
|
+
path: "models validate",
|
|
47394
|
+
summary: "Validate models.json configuration.",
|
|
47395
|
+
usage: "models validate [--path <path>] [--probe web_search] [--json]",
|
|
47396
|
+
flags: [
|
|
47397
|
+
{ name: "--json", kind: "boolean", description: "Emit the machine envelope (compact JSON)." },
|
|
47398
|
+
{ name: "--path", kind: "string", description: "models.json path to validate (default ~/.pie/models.json)." },
|
|
47399
|
+
{ name: "--probe", kind: "string", description: "Run a live capability probe (web_search)." }
|
|
47400
|
+
],
|
|
47401
|
+
positional: []
|
|
47402
|
+
};
|
|
47403
|
+
var EXTENSIONS_LIST_SPEC = {
|
|
47404
|
+
path: "extensions list",
|
|
47405
|
+
summary: "List discovered extensions.",
|
|
47406
|
+
usage: "extensions list [--json] [--extension-path <dir>] [--fields <list>]",
|
|
47407
|
+
flags: [
|
|
47408
|
+
{ name: "--json", kind: "boolean", description: "Emit the machine envelope (compact JSON)." },
|
|
47409
|
+
{ name: "--extension-path", kind: "string", repeatable: true, description: "Extra extension search directory (repeatable)." },
|
|
47410
|
+
{ name: "--no-builtin-extensions", kind: "boolean", description: "Skip built-in extensions." },
|
|
47411
|
+
{ name: "--no-extensions", kind: "boolean", description: "Skip all discovered extensions." },
|
|
47412
|
+
{ name: "--fields", kind: "string", description: "Extra row fields (comma list): entryPath, description, or all." }
|
|
47413
|
+
],
|
|
47414
|
+
positional: []
|
|
47415
|
+
};
|
|
47416
|
+
var EXTENSIONS_TOGGLE_SPEC = {
|
|
47417
|
+
path: "extensions enable/disable",
|
|
47418
|
+
summary: "Toggle extension enablement in user or project settings.",
|
|
47419
|
+
usage: "extensions <enable|disable> <name> [--project | --user] [--json]",
|
|
47420
|
+
flags: [
|
|
47421
|
+
{ name: "--json", kind: "boolean", description: "Emit the machine envelope (compact JSON)." },
|
|
47422
|
+
{ name: "--project", kind: "boolean", description: "Write ./.pie/settings.json (default is user scope)." },
|
|
47423
|
+
{ name: "--user", kind: "boolean", description: "Write ~/.pie/settings.json (default)." }
|
|
47424
|
+
],
|
|
47425
|
+
positional: [
|
|
47426
|
+
{ name: "name", required: true, description: "Extension identity." }
|
|
47427
|
+
]
|
|
47428
|
+
};
|
|
47429
|
+
var PERMISSIONS_SPEC = {
|
|
47430
|
+
path: "permissions",
|
|
47431
|
+
summary: "Explain Pie tool and shell safety defaults.",
|
|
47432
|
+
usage: "permissions [--json]",
|
|
47433
|
+
flags: [
|
|
47434
|
+
{ name: "--json", kind: "boolean", description: "Emit the machine envelope (compact JSON)." }
|
|
47435
|
+
],
|
|
47436
|
+
positional: []
|
|
47437
|
+
};
|
|
47438
|
+
var CAPABILITIES_SPEC = {
|
|
47439
|
+
path: "capabilities",
|
|
47440
|
+
summary: "Report command surface, flags, and output schema generation for agents.",
|
|
47441
|
+
usage: "capabilities [--json]",
|
|
47442
|
+
flags: [
|
|
47443
|
+
{ name: "--json", kind: "boolean", description: "Emit the machine envelope (compact JSON)." }
|
|
47444
|
+
],
|
|
47445
|
+
positional: []
|
|
47446
|
+
};
|
|
47447
|
+
var CHAT_SPEC = {
|
|
47448
|
+
path: "chat",
|
|
47449
|
+
summary: "Interactive chat (default), print mode, or JSONL protocol mode.",
|
|
47450
|
+
usage: "chat [prompt] [--raw-output | --json-output | --json-events] [--session-id <id>] ...",
|
|
47451
|
+
flags: [
|
|
47452
|
+
{ name: "--raw-output", kind: "boolean", description: "Print assistant text only in non-interactive mode." },
|
|
47453
|
+
{ name: "--json-output", kind: "boolean", description: "Print structured JSON in non-interactive mode." },
|
|
47454
|
+
{ name: "--json-events", kind: "boolean", description: "Run JSONL protocol mode over stdin/stdout." },
|
|
47455
|
+
{ name: "--event-detail", kind: "string", description: "JSON-events payload detail: compact (default) caps tool results and summaries; full keeps historical caps." },
|
|
47456
|
+
{ name: "--session-id", kind: "string", description: "Reuse or create a specific session." },
|
|
47457
|
+
{ name: "--resume-required", kind: "boolean", description: "Fail if --session-id cannot be resumed." },
|
|
47458
|
+
{ name: "--developer-instructions", kind: "string", description: "Append stable host/developer instructions." },
|
|
47459
|
+
{ name: "--developer-instructions-file", kind: "string", description: "Read developer instructions from a file." },
|
|
47460
|
+
{ name: "--extension-path", kind: "string", repeatable: true, description: "Extra extension search directory (repeatable)." },
|
|
47461
|
+
{ name: "--no-builtin-extensions", kind: "boolean", description: "Skip built-in extensions." },
|
|
47462
|
+
{ name: "--no-extensions", kind: "boolean", description: "Skip all discovered extensions." }
|
|
47463
|
+
],
|
|
47464
|
+
positional: [
|
|
47465
|
+
{ name: "prompt", required: false, description: "Initial prompt (starts print mode instead of the TUI)." }
|
|
47466
|
+
]
|
|
47467
|
+
};
|
|
47468
|
+
var MANAGEMENT_COMMAND_SPECS = [
|
|
47469
|
+
CHAT_SPEC,
|
|
47470
|
+
DOCTOR_SPEC,
|
|
47471
|
+
MODELS_INIT_SPEC,
|
|
47472
|
+
MODELS_VALIDATE_SPEC,
|
|
47473
|
+
SESSIONS_LIST_SPEC,
|
|
47474
|
+
SESSIONS_READ_SPEC,
|
|
47475
|
+
SESSIONS_RENAME_SPEC,
|
|
47476
|
+
SESSIONS_REWIND_SPEC,
|
|
47477
|
+
SESSIONS_FORK_SPEC,
|
|
47478
|
+
EXTENSIONS_LIST_SPEC,
|
|
47479
|
+
EXTENSIONS_TOGGLE_SPEC,
|
|
47480
|
+
PERMISSIONS_SPEC,
|
|
47481
|
+
CAPABILITIES_SPEC
|
|
47482
|
+
];
|
|
47483
|
+
|
|
47484
|
+
// src/output/envelope.ts
|
|
47485
|
+
var OUTPUT_SCHEMA_VERSION = 1;
|
|
47486
|
+
var EXIT_BUSINESS_FAILURE = 1;
|
|
47487
|
+
var EXIT_USAGE_ERROR = 2;
|
|
47488
|
+
function buildEnvelope(kind, options) {
|
|
47489
|
+
const envelope = {
|
|
47490
|
+
v: OUTPUT_SCHEMA_VERSION,
|
|
47491
|
+
ok: options.ok !== false,
|
|
47492
|
+
kind
|
|
47493
|
+
};
|
|
47494
|
+
if (options.data !== void 0) envelope.data = options.data;
|
|
47495
|
+
if (options.meta && Object.keys(options.meta).length > 0) envelope.meta = options.meta;
|
|
47496
|
+
if (options.help && options.help.length > 0) envelope.help = options.help;
|
|
47497
|
+
if (options.error) envelope.error = options.error;
|
|
47498
|
+
return JSON.stringify(envelope);
|
|
47499
|
+
}
|
|
47500
|
+
function successEnvelope(kind, data, meta, help) {
|
|
47501
|
+
const envelope = {
|
|
47502
|
+
v: OUTPUT_SCHEMA_VERSION,
|
|
47503
|
+
ok: true,
|
|
47504
|
+
kind
|
|
47505
|
+
};
|
|
47506
|
+
if (data !== void 0) envelope.data = data;
|
|
47507
|
+
if (meta && Object.keys(meta).length > 0) envelope.meta = meta;
|
|
47508
|
+
if (help && help.length > 0) envelope.help = help;
|
|
47509
|
+
return JSON.stringify(envelope);
|
|
47510
|
+
}
|
|
47511
|
+
function errorEnvelope(kind, code, message, hint) {
|
|
47512
|
+
const envelope = {
|
|
47513
|
+
v: OUTPUT_SCHEMA_VERSION,
|
|
47514
|
+
ok: false,
|
|
47515
|
+
kind,
|
|
47516
|
+
error: {
|
|
47517
|
+
code,
|
|
47518
|
+
message,
|
|
47519
|
+
...hint ? { hint } : {}
|
|
47520
|
+
}
|
|
47521
|
+
};
|
|
47522
|
+
return JSON.stringify(envelope);
|
|
47523
|
+
}
|
|
47524
|
+
function printSuccessEnvelope(kind, data, meta, help) {
|
|
47525
|
+
process.stdout.write(`${successEnvelope(kind, data, meta, help)}
|
|
47526
|
+
`);
|
|
47527
|
+
}
|
|
47528
|
+
var CommandError = class extends Error {
|
|
47529
|
+
kind;
|
|
47530
|
+
code;
|
|
47531
|
+
usage;
|
|
47532
|
+
hint;
|
|
47533
|
+
constructor(kind, code, message, options = {}) {
|
|
47534
|
+
super(message);
|
|
47535
|
+
this.name = "CommandError";
|
|
47536
|
+
this.kind = kind;
|
|
47537
|
+
this.code = code;
|
|
47538
|
+
this.usage = options.usage === true;
|
|
47539
|
+
this.hint = options.hint;
|
|
47540
|
+
}
|
|
47541
|
+
};
|
|
47542
|
+
function isCommandError(value) {
|
|
47543
|
+
return value instanceof CommandError;
|
|
47544
|
+
}
|
|
47545
|
+
function emitCommandError(error, options) {
|
|
47546
|
+
const commandError = isCommandError(error) ? error : new CommandError(options.fallbackKind, "internal_error", error instanceof Error ? error.message : String(error));
|
|
47547
|
+
if (options.json) {
|
|
47548
|
+
process.stdout.write(`${errorEnvelope(commandError.kind, commandError.code, commandError.message, commandError.hint)}
|
|
47549
|
+
`);
|
|
47550
|
+
} else {
|
|
47551
|
+
console.error(commandError.message);
|
|
47552
|
+
if (commandError.hint) {
|
|
47553
|
+
console.error(`Hint: ${commandError.hint}`);
|
|
47554
|
+
}
|
|
47555
|
+
}
|
|
47556
|
+
process.exitCode = commandError.usage ? EXIT_USAGE_ERROR : EXIT_BUSINESS_FAILURE;
|
|
47557
|
+
}
|
|
47558
|
+
function truncateText(text, maxChars) {
|
|
47559
|
+
const chars = Array.from(text);
|
|
47560
|
+
if (chars.length <= maxChars) {
|
|
47561
|
+
return { text, truncated: false, fullLength: chars.length };
|
|
47562
|
+
}
|
|
47563
|
+
return { text: chars.slice(0, maxChars).join(""), truncated: true, fullLength: chars.length };
|
|
47564
|
+
}
|
|
47565
|
+
|
|
47566
|
+
// src/capabilities.ts
|
|
47567
|
+
function buildCapabilitiesReport() {
|
|
47568
|
+
return {
|
|
47569
|
+
name: "pie",
|
|
47570
|
+
version: VERSION,
|
|
47571
|
+
outputSchemaVersion: OUTPUT_SCHEMA_VERSION,
|
|
47572
|
+
outputFormats: ["human", "json"],
|
|
47573
|
+
exitCodes: { success: 0, businessFailure: 1, usageError: 2 },
|
|
47574
|
+
commands: MANAGEMENT_COMMAND_SPECS.map((spec) => ({
|
|
47575
|
+
path: spec.path,
|
|
47576
|
+
summary: spec.summary,
|
|
47577
|
+
flags: spec.flags.map((flag) => ({
|
|
47578
|
+
name: flag.name,
|
|
47579
|
+
kind: flag.kind,
|
|
47580
|
+
description: flag.description
|
|
47581
|
+
})),
|
|
47582
|
+
positional: spec.positional.map((slot) => ({
|
|
47583
|
+
name: slot.name,
|
|
47584
|
+
required: slot.required,
|
|
47585
|
+
...slot.variadic ? { variadic: true } : {},
|
|
47586
|
+
description: slot.description
|
|
47587
|
+
}))
|
|
47588
|
+
}))
|
|
47589
|
+
};
|
|
47590
|
+
}
|
|
47591
|
+
function formatCapabilitiesHelp(report) {
|
|
47592
|
+
const lines = [
|
|
47593
|
+
`pie ${report.version} capabilities`,
|
|
47594
|
+
`output schema: v${report.outputSchemaVersion} (formats: ${report.outputFormats.join(", ")})`,
|
|
47595
|
+
`exit codes: ${report.exitCodes.success} success, ${report.exitCodes.businessFailure} business failure, ${report.exitCodes.usageError} usage error`,
|
|
47596
|
+
"",
|
|
47597
|
+
"Commands:"
|
|
47598
|
+
];
|
|
47599
|
+
for (const command of report.commands) {
|
|
47600
|
+
lines.push(` pie ${command.path} ${command.summary}`);
|
|
47601
|
+
}
|
|
47602
|
+
lines.push("", "Per-command flags: pie <command> --help");
|
|
47603
|
+
return lines.join("\n");
|
|
47604
|
+
}
|
|
47605
|
+
|
|
47606
|
+
// src/commands/management.ts
|
|
47607
|
+
function emitTopLevelUsageError(kind, code, message, args) {
|
|
47608
|
+
emitCommandError(new CommandError(kind, code, message, { usage: true }), {
|
|
47609
|
+
json: args.includes("--json"),
|
|
47610
|
+
fallbackKind: kind
|
|
47611
|
+
});
|
|
47612
|
+
}
|
|
47613
|
+
async function runDoctorCommand(args) {
|
|
47614
|
+
const parsed = parseCommandArgs(args, DOCTOR_SPEC);
|
|
47615
|
+
if (parsed.error) {
|
|
47616
|
+
emitTopLevelUsageError("doctor", parsed.error.code, parsed.error.message, args);
|
|
47617
|
+
return;
|
|
47618
|
+
}
|
|
47619
|
+
if (parsed.help) {
|
|
47620
|
+
console.log(renderCommandHelp(DOCTOR_SPEC));
|
|
47621
|
+
return;
|
|
47622
|
+
}
|
|
47623
|
+
const json = getFlagBool(parsed, "--json");
|
|
47624
|
+
const report = await runDoctor();
|
|
47625
|
+
if (json) {
|
|
47626
|
+
process.stdout.write(`${buildEnvelope("doctor", {
|
|
47627
|
+
ok: report.ok,
|
|
47628
|
+
data: { summary: report.summary, checks: report.checks },
|
|
47629
|
+
...report.ok ? {} : { error: { code: "doctor_failed", message: `${report.summary.fail} check(s) failed. Run pie doctor for details.` } }
|
|
47630
|
+
})}
|
|
47631
|
+
`);
|
|
47632
|
+
} else {
|
|
47633
|
+
console.log(formatDoctorReport(report));
|
|
47634
|
+
}
|
|
47635
|
+
if (!report.ok) {
|
|
47636
|
+
process.exitCode = EXIT_BUSINESS_FAILURE;
|
|
47637
|
+
}
|
|
47638
|
+
}
|
|
47639
|
+
function printModelsUsage() {
|
|
47640
|
+
console.log(`Usage:
|
|
47641
|
+
pie models init [--path <path>] [--force] [--stdout] [--json]
|
|
47642
|
+
pie models validate [--path <path>] [--probe web_search] [--json]`);
|
|
47643
|
+
}
|
|
47644
|
+
async function runModelsCommand(args) {
|
|
47645
|
+
const subcommand = args[0];
|
|
47646
|
+
if (!subcommand || subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
|
|
47647
|
+
printModelsUsage();
|
|
47648
|
+
return;
|
|
47649
|
+
}
|
|
47650
|
+
const rest = args.slice(1);
|
|
47651
|
+
if (subcommand === "init") {
|
|
47652
|
+
await runModelsInit(rest, args);
|
|
47653
|
+
return;
|
|
47654
|
+
}
|
|
47655
|
+
if (subcommand === "validate") {
|
|
47656
|
+
await runModelsValidate(rest, args);
|
|
47657
|
+
return;
|
|
47658
|
+
}
|
|
47659
|
+
emitTopLevelUsageError("models", "unknown_command", `Unknown models command: ${subcommand}`, args);
|
|
47660
|
+
}
|
|
47661
|
+
async function runModelsInit(rest, allArgs) {
|
|
47662
|
+
const parsed = parseCommandArgs(rest, MODELS_INIT_SPEC);
|
|
47663
|
+
if (parsed.error) {
|
|
47664
|
+
emitTopLevelUsageError("models.init", parsed.error.code, `${parsed.error.message}
|
|
47665
|
+
${renderCommandUsage(MODELS_INIT_SPEC)}`, allArgs);
|
|
47666
|
+
return;
|
|
47667
|
+
}
|
|
47668
|
+
if (parsed.help) {
|
|
47669
|
+
console.log(renderCommandHelp(MODELS_INIT_SPEC));
|
|
47670
|
+
return;
|
|
47671
|
+
}
|
|
47672
|
+
const json = getFlagBool(parsed, "--json");
|
|
47673
|
+
try {
|
|
47674
|
+
const result = initModelsConfig({
|
|
47675
|
+
path: getFlagString(parsed, "--path"),
|
|
47676
|
+
force: getFlagBool(parsed, "--force"),
|
|
47677
|
+
stdout: getFlagBool(parsed, "--stdout")
|
|
47678
|
+
});
|
|
47679
|
+
if (getFlagBool(parsed, "--stdout")) {
|
|
47680
|
+
process.stdout.write(result.content);
|
|
47681
|
+
return;
|
|
47682
|
+
}
|
|
47683
|
+
if (json) {
|
|
47684
|
+
printSuccessEnvelope("models.init", { path: result.path, wrote: result.wrote });
|
|
47685
|
+
} else {
|
|
47686
|
+
console.log(`Wrote models.json template: ${result.path}`);
|
|
47687
|
+
}
|
|
47688
|
+
} catch (error) {
|
|
47689
|
+
emitCommandError(error, { json, fallbackKind: "models.init" });
|
|
47690
|
+
}
|
|
47691
|
+
}
|
|
47692
|
+
async function runModelsValidate(rest, allArgs) {
|
|
47693
|
+
const parsed = parseCommandArgs(rest, MODELS_VALIDATE_SPEC);
|
|
47694
|
+
if (parsed.error) {
|
|
47695
|
+
emitTopLevelUsageError("models.validate", parsed.error.code, `${parsed.error.message}
|
|
47696
|
+
${renderCommandUsage(MODELS_VALIDATE_SPEC)}`, allArgs);
|
|
47697
|
+
return;
|
|
47698
|
+
}
|
|
47699
|
+
if (parsed.help) {
|
|
47700
|
+
console.log(renderCommandHelp(MODELS_VALIDATE_SPEC));
|
|
47701
|
+
return;
|
|
47702
|
+
}
|
|
47703
|
+
const json = getFlagBool(parsed, "--json");
|
|
47704
|
+
const probePurpose = getFlagString(parsed, "--probe");
|
|
47705
|
+
const result = validateModelsConfig({ path: getFlagString(parsed, "--path") });
|
|
47706
|
+
const probe = result.ok && probePurpose ? await probeModelsConfig({ path: getFlagString(parsed, "--path"), probe: probePurpose }) : void 0;
|
|
47707
|
+
if (json) {
|
|
47708
|
+
const { ok: _ok, ...fields } = result;
|
|
47709
|
+
process.stdout.write(`${buildEnvelope("models.validate", {
|
|
47710
|
+
ok: result.ok && probe?.status !== "failed",
|
|
47711
|
+
data: { ...fields, ...probe ? { probe } : {} },
|
|
47712
|
+
...result.ok ? {} : { error: { code: "models_invalid", message: result.message } },
|
|
47713
|
+
...probe?.status === "failed" ? { error: { code: "probe_failed", message: probe.message } } : {}
|
|
47714
|
+
})}
|
|
47715
|
+
`);
|
|
47716
|
+
if (!result.ok || probe?.status === "failed") process.exitCode = EXIT_BUSINESS_FAILURE;
|
|
47717
|
+
return;
|
|
47718
|
+
}
|
|
47719
|
+
if (!result.ok) {
|
|
47720
|
+
console.error(result.message);
|
|
47721
|
+
process.exitCode = EXIT_BUSINESS_FAILURE;
|
|
47722
|
+
return;
|
|
47723
|
+
}
|
|
47724
|
+
console.log(result.message);
|
|
47725
|
+
if (result.profiles.length > 0) {
|
|
47726
|
+
console.log(`Profiles: ${result.profiles.join(", ")}`);
|
|
47727
|
+
console.log(`Models: ${result.modelCount}`);
|
|
47728
|
+
}
|
|
47729
|
+
if (result.defaultModel) {
|
|
47730
|
+
console.log(`Default: ${result.defaultModel}`);
|
|
47731
|
+
}
|
|
47732
|
+
if (result.modelClasses && result.modelClasses.length > 0) {
|
|
47733
|
+
console.log(`Model classes: ${result.modelClasses.join(", ")}`);
|
|
47734
|
+
}
|
|
47735
|
+
if (result.webSearchModels && result.webSearchModels.length > 0) {
|
|
47736
|
+
console.log(`Web search: ${result.webSearchModels.join(", ")}`);
|
|
47737
|
+
}
|
|
47738
|
+
if (result.webSearchRouteCandidates && result.webSearchRouteCandidates.length > 0) {
|
|
47739
|
+
console.log(`Web search routes: ${result.webSearchRouteCandidates.join(", ")}`);
|
|
47740
|
+
}
|
|
47741
|
+
if (result.fileCapabilityModels && result.fileCapabilityModels.length > 0) {
|
|
47742
|
+
console.log(`File capabilities: ${result.fileCapabilityModels.join(", ")}`);
|
|
47743
|
+
}
|
|
47744
|
+
if (result.toolModelRoutes && result.toolModelRoutes.length > 0) {
|
|
47745
|
+
console.log(`Tool model routes: ${result.toolModelRoutes.join(", ")}`);
|
|
47746
|
+
}
|
|
47747
|
+
if (probePurpose) {
|
|
47748
|
+
const probeReport = probe ?? await probeModelsConfig({ path: getFlagString(parsed, "--path"), probe: probePurpose });
|
|
47749
|
+
console.log(`Probe ${probeReport.purpose}: ${probeReport.message}`);
|
|
47750
|
+
for (const attempt of probeReport.attempts) {
|
|
47751
|
+
console.log(`- ${attempt.status} ${attempt.route} sources=${attempt.sourceCount}${attempt.failureCategory ? ` failure=${attempt.failureCategory}` : ""}`);
|
|
47066
47752
|
}
|
|
47753
|
+
if (probeReport.status === "failed") process.exitCode = EXIT_BUSINESS_FAILURE;
|
|
47754
|
+
}
|
|
47755
|
+
}
|
|
47756
|
+
function runPermissionsCommand(args) {
|
|
47757
|
+
const parsed = parseCommandArgs(args, PERMISSIONS_SPEC);
|
|
47758
|
+
if (parsed.error) {
|
|
47759
|
+
emitTopLevelUsageError("permissions", parsed.error.code, parsed.error.message, args);
|
|
47760
|
+
return;
|
|
47761
|
+
}
|
|
47762
|
+
if (parsed.help) {
|
|
47763
|
+
console.log(renderCommandHelp(PERMISSIONS_SPEC));
|
|
47764
|
+
return;
|
|
47765
|
+
}
|
|
47766
|
+
if (getFlagBool(parsed, "--json")) {
|
|
47767
|
+
printSuccessEnvelope("permissions", buildPermissionsData());
|
|
47768
|
+
return;
|
|
47067
47769
|
}
|
|
47068
|
-
|
|
47770
|
+
console.log(formatPermissionsHelp());
|
|
47771
|
+
}
|
|
47772
|
+
function runCapabilitiesCommand(args) {
|
|
47773
|
+
const parsed = parseCommandArgs(args, CAPABILITIES_SPEC);
|
|
47774
|
+
if (parsed.error) {
|
|
47775
|
+
emitTopLevelUsageError("capabilities", parsed.error.code, parsed.error.message, args);
|
|
47776
|
+
return;
|
|
47777
|
+
}
|
|
47778
|
+
if (parsed.help) {
|
|
47779
|
+
console.log(renderCommandHelp(CAPABILITIES_SPEC));
|
|
47780
|
+
return;
|
|
47781
|
+
}
|
|
47782
|
+
const report = buildCapabilitiesReport();
|
|
47783
|
+
if (getFlagBool(parsed, "--json")) {
|
|
47784
|
+
printSuccessEnvelope("capabilities", report, void 0, ["try: pie sessions list --json"]);
|
|
47785
|
+
return;
|
|
47786
|
+
}
|
|
47787
|
+
console.log(formatCapabilitiesHelp(report));
|
|
47069
47788
|
}
|
|
47070
47789
|
|
|
47071
47790
|
// src/commands/sessions.ts
|
|
@@ -47097,7 +47816,7 @@ async function loadRequiredSession(store, sessionId) {
|
|
|
47097
47816
|
async function rewindStoredSession(params) {
|
|
47098
47817
|
const data = await loadRequiredSession(params.store, params.sessionId);
|
|
47099
47818
|
if (!data.entries.some((entry) => entry.id === params.entryId)) {
|
|
47100
|
-
throw new SessionControlError("
|
|
47819
|
+
throw new SessionControlError("entry_not_found", `Entry not found: ${params.entryId}`);
|
|
47101
47820
|
}
|
|
47102
47821
|
try {
|
|
47103
47822
|
await params.store.save(params.sessionId, data.entries, {
|
|
@@ -47112,9 +47831,7 @@ async function rewindStoredSession(params) {
|
|
|
47112
47831
|
return {
|
|
47113
47832
|
sessionId: params.sessionId,
|
|
47114
47833
|
entryId: params.entryId,
|
|
47115
|
-
checkpointId: params.entryId,
|
|
47116
47834
|
activeEntryId: params.entryId,
|
|
47117
|
-
headEntryId: params.entryId,
|
|
47118
47835
|
metadata
|
|
47119
47836
|
};
|
|
47120
47837
|
} catch (error) {
|
|
@@ -47124,12 +47841,14 @@ async function rewindStoredSession(params) {
|
|
|
47124
47841
|
}
|
|
47125
47842
|
async function forkStoredSession(params) {
|
|
47126
47843
|
try {
|
|
47127
|
-
|
|
47128
|
-
|
|
47844
|
+
if (!params.force) {
|
|
47845
|
+
const existingTarget = await maybeLoadExistingForkTarget(params);
|
|
47846
|
+
if (existingTarget) return existingTarget;
|
|
47847
|
+
}
|
|
47129
47848
|
const source = await loadRequiredSession(params.store, params.sourceSessionId);
|
|
47130
47849
|
const pathEntries = pathToEntry(source, params.sourceEntryId);
|
|
47131
47850
|
if (pathEntries.length === 0 || pathEntries[pathEntries.length - 1]?.id !== params.sourceEntryId) {
|
|
47132
|
-
throw new SessionControlError("
|
|
47851
|
+
throw new SessionControlError("entry_not_found", `Entry not found: ${params.sourceEntryId}`);
|
|
47133
47852
|
}
|
|
47134
47853
|
const now = params.now ?? Date.now();
|
|
47135
47854
|
const idMap = /* @__PURE__ */ new Map();
|
|
@@ -47202,11 +47921,8 @@ function buildForkResult(params) {
|
|
|
47202
47921
|
return {
|
|
47203
47922
|
sourceSessionId: params.sourceSessionId,
|
|
47204
47923
|
sourceEntryId: params.sourceEntryId,
|
|
47205
|
-
sourceCheckpointId: params.sourceEntryId,
|
|
47206
47924
|
targetSessionId: params.metadata.id,
|
|
47207
47925
|
targetActiveEntryId,
|
|
47208
|
-
targetHeadEntryId: targetActiveEntryId,
|
|
47209
|
-
headEntryId: targetActiveEntryId,
|
|
47210
47926
|
sourceActiveEntryId: params.sourceActiveEntryId,
|
|
47211
47927
|
forkBaseEntryId,
|
|
47212
47928
|
metadata: params.metadata
|
|
@@ -47229,238 +47945,312 @@ function cloneJson(value) {
|
|
|
47229
47945
|
}
|
|
47230
47946
|
|
|
47231
47947
|
// src/commands/sessions.ts
|
|
47948
|
+
var NAME_MAX_CHARS = 24;
|
|
47949
|
+
var CONTENT_MAX_CHARS = 80;
|
|
47950
|
+
var LIST_ROW_EXTRA_FIELDS = [
|
|
47951
|
+
"createdAt",
|
|
47952
|
+
"cwd",
|
|
47953
|
+
"activeEntryId",
|
|
47954
|
+
"rootEntryId",
|
|
47955
|
+
"sourceSessionId",
|
|
47956
|
+
"sourceEntryId",
|
|
47957
|
+
"sourceActiveEntryId",
|
|
47958
|
+
"forkBaseEntryId"
|
|
47959
|
+
];
|
|
47960
|
+
var READ_EVENT_EXTRA_FIELDS = ["timestamp", "turnId", "message"];
|
|
47961
|
+
var SUBCOMMANDS = {
|
|
47962
|
+
list: { spec: SESSIONS_LIST_SPEC, kind: "sessions.list", run: listSessions },
|
|
47963
|
+
read: { spec: SESSIONS_READ_SPEC, kind: "sessions.read", run: readSession },
|
|
47964
|
+
rename: { spec: SESSIONS_RENAME_SPEC, kind: "sessions.rename", run: renameSession },
|
|
47965
|
+
rewind: { spec: SESSIONS_REWIND_SPEC, kind: "sessions.rewind", run: rewindSession },
|
|
47966
|
+
fork: { spec: SESSIONS_FORK_SPEC, kind: "sessions.fork", run: forkSession }
|
|
47967
|
+
};
|
|
47232
47968
|
async function runSessionsCommand(args) {
|
|
47233
|
-
const
|
|
47234
|
-
|
|
47969
|
+
const first = args[0];
|
|
47970
|
+
if (!first || first === "help" || first === "--help" || first === "-h") {
|
|
47971
|
+
printSessionsUsage();
|
|
47972
|
+
return;
|
|
47973
|
+
}
|
|
47974
|
+
const entry = SUBCOMMANDS[first];
|
|
47235
47975
|
try {
|
|
47236
|
-
if (
|
|
47237
|
-
|
|
47238
|
-
|
|
47239
|
-
|
|
47240
|
-
|
|
47241
|
-
await readSession(rest);
|
|
47242
|
-
return;
|
|
47243
|
-
}
|
|
47244
|
-
if (command === "rename") {
|
|
47245
|
-
await renameSession(rest);
|
|
47246
|
-
return;
|
|
47247
|
-
}
|
|
47248
|
-
if (command === "rewind") {
|
|
47249
|
-
await rewindSession(rest);
|
|
47250
|
-
return;
|
|
47976
|
+
if (!entry) {
|
|
47977
|
+
throw new CommandError("sessions", "unknown_command", `Unknown sessions command: ${first}`, {
|
|
47978
|
+
usage: true,
|
|
47979
|
+
hint: "subcommands: list, read, rename, rewind, fork"
|
|
47980
|
+
});
|
|
47251
47981
|
}
|
|
47252
|
-
|
|
47253
|
-
|
|
47254
|
-
|
|
47982
|
+
const parsed = parseCommandArgs(args.slice(1), entry.spec);
|
|
47983
|
+
if (parsed.error) {
|
|
47984
|
+
throw new CommandError(entry.kind, parsed.error.code, `${parsed.error.message}
|
|
47985
|
+
${renderCommandUsage(entry.spec)}`, { usage: true });
|
|
47255
47986
|
}
|
|
47256
|
-
if (
|
|
47257
|
-
|
|
47987
|
+
if (parsed.help) {
|
|
47988
|
+
console.log(renderCommandHelp(entry.spec));
|
|
47258
47989
|
return;
|
|
47259
47990
|
}
|
|
47260
|
-
|
|
47991
|
+
await entry.run(parsed);
|
|
47261
47992
|
} catch (error) {
|
|
47262
|
-
|
|
47263
|
-
|
|
47264
|
-
} else {
|
|
47265
|
-
console.error(error instanceof Error ? error.message : String(error));
|
|
47266
|
-
}
|
|
47267
|
-
process.exitCode = 1;
|
|
47993
|
+
const mapped = toSessionCommandError(error, entry?.kind ?? "sessions");
|
|
47994
|
+
emitCommandError(mapped, { json: args.includes("--json"), fallbackKind: entry?.kind ?? "sessions" });
|
|
47268
47995
|
}
|
|
47269
47996
|
}
|
|
47270
|
-
|
|
47271
|
-
|
|
47272
|
-
|
|
47273
|
-
|
|
47274
|
-
|
|
47997
|
+
function toSessionCommandError(error, kind) {
|
|
47998
|
+
if (error instanceof SessionControlError) {
|
|
47999
|
+
const hints = {
|
|
48000
|
+
session_not_found: "list sessions: pie sessions list --json",
|
|
48001
|
+
target_exists: "choose a new --target, or add --force to overwrite"
|
|
48002
|
+
};
|
|
48003
|
+
return new CommandError(kind, error.code, error.message, { hint: hints[error.code] });
|
|
48004
|
+
}
|
|
48005
|
+
return error;
|
|
48006
|
+
}
|
|
48007
|
+
async function listSessions(parsed) {
|
|
48008
|
+
const json = getFlagBool(parsed, "--json");
|
|
48009
|
+
const all = getFlagBool(parsed, "--all");
|
|
48010
|
+
const cwdFlag = getFlagString(parsed, "--cwd");
|
|
48011
|
+
const limit = parseLimitFlag(parsed, "sessions.list", 50);
|
|
48012
|
+
const cursor = getFlagString(parsed, "--cursor");
|
|
48013
|
+
const fields = parseExtraFields(getFlagString(parsed, "--fields"), LIST_ROW_EXTRA_FIELDS, "sessions.list");
|
|
48014
|
+
const full = getFlagBool(parsed, "--full");
|
|
48015
|
+
const cwdFilter = cwdFlag ?? (json && !all ? process.cwd() : void 0);
|
|
47275
48016
|
const store = new FileSessionStore(getSessionsDir());
|
|
47276
48017
|
const cursorState = decodeListCursor(cursor);
|
|
47277
|
-
const queryKey = listCursorQueryKey({ cwd });
|
|
48018
|
+
const queryKey = listCursorQueryKey({ cwd: cwdFilter });
|
|
47278
48019
|
const after = cursorState.q === queryKey ? cursorState.after : void 0;
|
|
47279
|
-
const
|
|
47280
|
-
|
|
47281
|
-
|
|
47282
|
-
|
|
47283
|
-
|
|
47284
|
-
|
|
47285
|
-
|
|
47286
|
-
|
|
47287
|
-
|
|
47288
|
-
|
|
47289
|
-
console.log(JSON.stringify({ ok: true, sessions, hasMore, nextCursor }, null, 2));
|
|
47290
|
-
return;
|
|
47291
|
-
}
|
|
47292
|
-
if (sessions.length === 0) {
|
|
47293
|
-
console.log("No sessions.");
|
|
48020
|
+
const matchesCwd = cwdFilter ? (metadata) => cwdMatches(typeof metadata.cwd === "string" ? metadata.cwd : void 0, cwdFilter) : void 0;
|
|
48021
|
+
const page = await store.listMetadataPage({ limit, after, filter: matchesCwd });
|
|
48022
|
+
if (!json) {
|
|
48023
|
+
if (page.metadata.length === 0) {
|
|
48024
|
+
console.log("No sessions.");
|
|
48025
|
+
return;
|
|
48026
|
+
}
|
|
48027
|
+
for (const session of page.metadata) {
|
|
48028
|
+
console.log(`${session.id} ${session.name} ${new Date(session.updatedAt).toISOString()}${session.cwd ? ` ${session.cwd}` : ""}`);
|
|
48029
|
+
}
|
|
47294
48030
|
return;
|
|
47295
48031
|
}
|
|
47296
|
-
|
|
47297
|
-
|
|
48032
|
+
const rows = page.metadata.map((metadata) => listRow(metadata, fields, full));
|
|
48033
|
+
const hasMore = page.hasMore;
|
|
48034
|
+
const lastSession = page.metadata.at(-1);
|
|
48035
|
+
const nextCursor = hasMore && lastSession ? encodeListCursor({ v: 2, q: queryKey, after: { updatedAt: lastSession.updatedAt, id: lastSession.id } }) : void 0;
|
|
48036
|
+
const total = matchesCwd ? (await store.listMetadata()).filter(matchesCwd).length : (await store.listMetadata()).length;
|
|
48037
|
+
const meta = {
|
|
48038
|
+
count: rows.length,
|
|
48039
|
+
total,
|
|
48040
|
+
hasMore,
|
|
48041
|
+
scope: cwdFilter ? "cwd" : "all",
|
|
48042
|
+
...cwdFilter ? { cwd: cwdFilter } : {},
|
|
48043
|
+
...nextCursor ? { nextCursor } : {}
|
|
48044
|
+
};
|
|
48045
|
+
const help = [];
|
|
48046
|
+
if (nextCursor) help.push("next page: pass meta.nextCursor to --cursor");
|
|
48047
|
+
if (rows.some((row) => row.truncated === true)) help.push("full names: add --full");
|
|
48048
|
+
if (cwdFilter) help.push("all projects: add --all");
|
|
48049
|
+
if (rows.length === 0) help.push("sessions are created by running pie chat in a project directory");
|
|
48050
|
+
else if (!nextCursor) help.push("open a session: pie sessions read <id> --json");
|
|
48051
|
+
printSuccessEnvelope("sessions.list", rows, meta, help.slice(0, 3));
|
|
48052
|
+
}
|
|
48053
|
+
function listRow(metadata, fields, full) {
|
|
48054
|
+
const name = full ? { text: metadata.name, truncated: false } : truncateText(metadata.name, NAME_MAX_CHARS);
|
|
48055
|
+
const row = {
|
|
48056
|
+
id: metadata.id,
|
|
48057
|
+
name: name.text,
|
|
48058
|
+
updatedAt: metadata.updatedAt,
|
|
48059
|
+
count: metadata.entryCount
|
|
48060
|
+
};
|
|
48061
|
+
if (name.truncated) row.truncated = true;
|
|
48062
|
+
const optional = {
|
|
48063
|
+
createdAt: metadata.createdAt,
|
|
48064
|
+
cwd: typeof metadata.cwd === "string" ? metadata.cwd : void 0,
|
|
48065
|
+
activeEntryId: metadata.activeEntryId ?? void 0,
|
|
48066
|
+
rootEntryId: metadata.rootEntryId ?? void 0,
|
|
48067
|
+
sourceSessionId: typeof metadata.sourceSessionId === "string" ? metadata.sourceSessionId : void 0,
|
|
48068
|
+
sourceEntryId: typeof metadata.sourceEntryId === "string" ? metadata.sourceEntryId : void 0,
|
|
48069
|
+
sourceActiveEntryId: typeof metadata.sourceActiveEntryId === "string" ? metadata.sourceActiveEntryId : void 0,
|
|
48070
|
+
forkBaseEntryId: typeof metadata.forkBaseEntryId === "string" ? metadata.forkBaseEntryId : void 0
|
|
48071
|
+
};
|
|
48072
|
+
for (const field of fields) {
|
|
48073
|
+
const value = optional[field];
|
|
48074
|
+
if (value !== void 0) row[field] = value;
|
|
48075
|
+
}
|
|
48076
|
+
return row;
|
|
48077
|
+
}
|
|
48078
|
+
async function readSession(parsed) {
|
|
48079
|
+
const json = getFlagBool(parsed, "--json");
|
|
48080
|
+
const limit = parseLimitFlag(parsed, "sessions.read", 200);
|
|
48081
|
+
const before = getFlagString(parsed, "--before");
|
|
48082
|
+
const fields = parseExtraFields(getFlagString(parsed, "--fields"), READ_EVENT_EXTRA_FIELDS, "sessions.read");
|
|
48083
|
+
const full = getFlagBool(parsed, "--full");
|
|
48084
|
+
const sessionId = getPositional(parsed, "sessionId");
|
|
48085
|
+
if (!sessionId) {
|
|
48086
|
+
throw new CommandError("sessions.read", "missing_positional", renderCommandUsage(SESSIONS_READ_SPEC), { usage: true });
|
|
47298
48087
|
}
|
|
47299
|
-
}
|
|
47300
|
-
async function readSession(args) {
|
|
47301
|
-
const json = hasFlag(args, "--json");
|
|
47302
|
-
const includeMessage = hasFlag(args, "--raw") || hasFlag(args, "--include-message");
|
|
47303
|
-
const sessionId = positionalArgs(args, /* @__PURE__ */ new Set(["--limit", "--before"]))[0];
|
|
47304
|
-
if (!sessionId) throw new Error("Usage: pie sessions read <sessionId> [--json] [--raw|--include-message] [--limit <n>] [--before <cursor>]");
|
|
47305
|
-
const limit = numericFlag(args, "--limit", 200);
|
|
47306
|
-
const before = stringFlag(args, "--before");
|
|
47307
48088
|
const store = new FileSessionStore(getSessionsDir());
|
|
47308
|
-
const data = await store.
|
|
47309
|
-
if (!data) throw new Error(`Session not found: ${sessionId}`);
|
|
48089
|
+
const data = await loadSession(store, sessionId, "sessions.read");
|
|
47310
48090
|
const events = activeTranscriptEvents(activePathEntries(data));
|
|
47311
48091
|
const end = resolveBeforeCursor(events, before);
|
|
47312
48092
|
const start = Math.max(0, end - limit);
|
|
47313
48093
|
const page = events.slice(start, end);
|
|
47314
|
-
|
|
47315
|
-
|
|
47316
|
-
|
|
47317
|
-
|
|
48094
|
+
if (!json) {
|
|
48095
|
+
console.log(`${data.metadata.id}: ${data.metadata.name}`);
|
|
48096
|
+
for (const entry of page) {
|
|
48097
|
+
console.log(`${entry.logicalSeq} ${entry.type}${entry.role ? `:${entry.role}` : ""} ${entry.content ?? ""}`);
|
|
48098
|
+
}
|
|
48099
|
+
return;
|
|
48100
|
+
}
|
|
48101
|
+
const rows = page.map((event) => readEventRow(event, fields, full));
|
|
48102
|
+
const meta = {
|
|
48103
|
+
count: rows.length,
|
|
47318
48104
|
activeEntryId: data.metadata.activeEntryId,
|
|
47319
|
-
events: json && !includeMessage ? page.map(stableTranscriptEvent) : page,
|
|
47320
48105
|
hasMoreBefore: start > 0,
|
|
47321
|
-
|
|
48106
|
+
...start > 0 ? { nextBefore: String(start) } : {}
|
|
47322
48107
|
};
|
|
47323
|
-
|
|
47324
|
-
|
|
47325
|
-
|
|
47326
|
-
}
|
|
47327
|
-
|
|
47328
|
-
|
|
47329
|
-
|
|
48108
|
+
const help = [];
|
|
48109
|
+
if (start > 0) help.push("earlier events: pass meta.nextBefore to --before");
|
|
48110
|
+
if (rows.some((row) => row.truncated === true)) help.push("full content: add --full or --fields message");
|
|
48111
|
+
printSuccessEnvelope("sessions.read", { session: fullSessionRow(data.metadata), events: rows }, meta, help);
|
|
48112
|
+
}
|
|
48113
|
+
function readEventRow(event, fields, full) {
|
|
48114
|
+
const row = {
|
|
48115
|
+
seq: event.logicalSeq,
|
|
48116
|
+
entryId: event.entryId,
|
|
48117
|
+
type: event.type
|
|
48118
|
+
};
|
|
48119
|
+
if (event.role) row.role = event.role;
|
|
48120
|
+
if (event.content !== void 0) {
|
|
48121
|
+
if (full) {
|
|
48122
|
+
row.content = event.content;
|
|
48123
|
+
} else {
|
|
48124
|
+
const content = truncateText(event.content, CONTENT_MAX_CHARS);
|
|
48125
|
+
row.content = content.text;
|
|
48126
|
+
if (content.truncated) row.truncated = true;
|
|
48127
|
+
}
|
|
47330
48128
|
}
|
|
48129
|
+
if (fields.includes("timestamp")) row.timestamp = event.timestamp;
|
|
48130
|
+
if (fields.includes("turnId") && event.turnId) row.turnId = event.turnId;
|
|
48131
|
+
if (fields.includes("message") && event.message !== void 0) row.message = event.message;
|
|
48132
|
+
return row;
|
|
47331
48133
|
}
|
|
47332
|
-
async function renameSession(
|
|
47333
|
-
const json =
|
|
47334
|
-
const cwd =
|
|
47335
|
-
const
|
|
47336
|
-
const
|
|
47337
|
-
|
|
47338
|
-
|
|
48134
|
+
async function renameSession(parsed) {
|
|
48135
|
+
const json = getFlagBool(parsed, "--json");
|
|
48136
|
+
const cwd = getFlagString(parsed, "--cwd");
|
|
48137
|
+
const sessionId = getPositional(parsed, "sessionId");
|
|
48138
|
+
const name = getPositionals(parsed, "name").join(" ").trim();
|
|
48139
|
+
if (!sessionId || !name) {
|
|
48140
|
+
throw new CommandError("sessions.rename", "missing_positional", renderCommandUsage(SESSIONS_RENAME_SPEC), { usage: true });
|
|
48141
|
+
}
|
|
47339
48142
|
const store = new FileSessionStore(getSessionsDir());
|
|
47340
|
-
const data = await store.
|
|
47341
|
-
if (!data) throw new Error(`Session not found: ${sessionId}`);
|
|
48143
|
+
const data = await loadSession(store, sessionId, "sessions.rename");
|
|
47342
48144
|
await store.save(sessionId, data.entries, { ...data.metadata, name, nameSource: "manual", ...cwd ? { cwd } : {}, updatedAt: Date.now() });
|
|
47343
48145
|
const updated = await store.getMetadata(sessionId);
|
|
47344
|
-
if (!updated) throw new
|
|
47345
|
-
const response = { ok: true, session: sessionSummary(updated) };
|
|
48146
|
+
if (!updated) throw new CommandError("sessions.rename", "session_not_found", `Session not found after rename: ${sessionId}`);
|
|
47346
48147
|
if (json) {
|
|
47347
|
-
|
|
48148
|
+
printSuccessEnvelope("sessions.rename", { session: fullSessionRow(updated) });
|
|
47348
48149
|
return;
|
|
47349
48150
|
}
|
|
47350
48151
|
console.log(`Renamed ${sessionId} to "${name}".`);
|
|
47351
48152
|
}
|
|
47352
|
-
async function rewindSession(
|
|
47353
|
-
const json =
|
|
47354
|
-
const sessionId =
|
|
47355
|
-
const entryId =
|
|
47356
|
-
if (!sessionId || !entryId)
|
|
48153
|
+
async function rewindSession(parsed) {
|
|
48154
|
+
const json = getFlagBool(parsed, "--json");
|
|
48155
|
+
const sessionId = getPositional(parsed, "sessionId");
|
|
48156
|
+
const entryId = getFlagString(parsed, "--to");
|
|
48157
|
+
if (!sessionId || !entryId) {
|
|
48158
|
+
throw new CommandError("sessions.rewind", "missing_positional", renderCommandUsage(SESSIONS_REWIND_SPEC), { usage: true });
|
|
48159
|
+
}
|
|
47357
48160
|
const store = new FileSessionStore(getSessionsDir());
|
|
47358
48161
|
const result = await rewindStoredSession({ store, sessionId, entryId });
|
|
47359
|
-
const response = {
|
|
47360
|
-
ok: true,
|
|
47361
|
-
session: sessionSummary(result.metadata),
|
|
47362
|
-
activeEntryId: result.activeEntryId,
|
|
47363
|
-
currentHead: result.headEntryId
|
|
47364
|
-
};
|
|
47365
48162
|
if (json) {
|
|
47366
|
-
|
|
48163
|
+
printSuccessEnvelope("sessions.rewind", {
|
|
48164
|
+
session: fullSessionRow(result.metadata),
|
|
48165
|
+
activeEntryId: result.activeEntryId
|
|
48166
|
+
});
|
|
47367
48167
|
return;
|
|
47368
48168
|
}
|
|
47369
48169
|
console.log(`Rewound ${sessionId} to ${entryId}.`);
|
|
47370
48170
|
}
|
|
47371
|
-
async function forkSession(
|
|
47372
|
-
const json =
|
|
47373
|
-
const
|
|
47374
|
-
const sourceEntryId =
|
|
47375
|
-
const targetSessionId =
|
|
47376
|
-
const name =
|
|
47377
|
-
const cwd =
|
|
47378
|
-
|
|
47379
|
-
|
|
48171
|
+
async function forkSession(parsed) {
|
|
48172
|
+
const json = getFlagBool(parsed, "--json");
|
|
48173
|
+
const sessionId = getPositional(parsed, "sessionId");
|
|
48174
|
+
const sourceEntryId = getFlagString(parsed, "--from");
|
|
48175
|
+
const targetSessionId = getFlagString(parsed, "--target");
|
|
48176
|
+
const name = getFlagString(parsed, "--name");
|
|
48177
|
+
const cwd = getFlagString(parsed, "--cwd");
|
|
48178
|
+
const force = getFlagBool(parsed, "--force");
|
|
48179
|
+
if (!sessionId || !sourceEntryId || !targetSessionId || !name) {
|
|
48180
|
+
throw new CommandError("sessions.fork", "missing_positional", renderCommandUsage(SESSIONS_FORK_SPEC), { usage: true });
|
|
47380
48181
|
}
|
|
47381
48182
|
const store = new FileSessionStore(getSessionsDir());
|
|
47382
48183
|
const result = await forkStoredSession({
|
|
47383
48184
|
store,
|
|
47384
|
-
sourceSessionId,
|
|
48185
|
+
sourceSessionId: sessionId,
|
|
47385
48186
|
sourceEntryId,
|
|
47386
48187
|
targetSessionId,
|
|
47387
48188
|
name,
|
|
47388
|
-
cwd
|
|
48189
|
+
cwd,
|
|
48190
|
+
force
|
|
47389
48191
|
});
|
|
47390
|
-
const response = {
|
|
47391
|
-
ok: true,
|
|
47392
|
-
session: sessionSummary(result.metadata),
|
|
47393
|
-
sourceSessionId,
|
|
47394
|
-
sourceEntryId,
|
|
47395
|
-
sourceActiveEntryId: result.sourceActiveEntryId,
|
|
47396
|
-
forkBaseEntryId: result.forkBaseEntryId,
|
|
47397
|
-
activeEntryId: result.targetActiveEntryId,
|
|
47398
|
-
currentHead: result.targetHeadEntryId
|
|
47399
|
-
};
|
|
47400
48192
|
if (json) {
|
|
47401
|
-
|
|
48193
|
+
printSuccessEnvelope("sessions.fork", {
|
|
48194
|
+
session: fullSessionRow(result.metadata),
|
|
48195
|
+
sourceSessionId: result.sourceSessionId,
|
|
48196
|
+
sourceEntryId: result.sourceEntryId,
|
|
48197
|
+
activeEntryId: result.targetActiveEntryId,
|
|
48198
|
+
forkBaseEntryId: result.forkBaseEntryId
|
|
48199
|
+
});
|
|
47402
48200
|
return;
|
|
47403
48201
|
}
|
|
47404
|
-
console.log(`Forked ${
|
|
47405
|
-
}
|
|
47406
|
-
function printSessionsUsage() {
|
|
47407
|
-
console.log(`Usage:
|
|
47408
|
-
pie sessions list [--json] [--limit <n>] [--cursor <cursor>] [--cwd <path>]
|
|
47409
|
-
pie sessions read <sessionId> [--json] [--raw|--include-message] [--limit <n>] [--before <cursor>]
|
|
47410
|
-
pie sessions rename <sessionId> <name> [--json] [--cwd <path>]
|
|
47411
|
-
pie sessions rewind <sessionId> --to <entryId> [--json]
|
|
47412
|
-
pie sessions fork <sessionId> --from <entryId> --target <newSessionId> --name <name> [--cwd <path>] [--json]`);
|
|
47413
|
-
}
|
|
47414
|
-
function hasFlag(args, flag) {
|
|
47415
|
-
return args.includes(flag);
|
|
47416
|
-
}
|
|
47417
|
-
function stringFlag(args, flag) {
|
|
47418
|
-
const index = args.indexOf(flag);
|
|
47419
|
-
if (index < 0) return void 0;
|
|
47420
|
-
const value = args[index + 1];
|
|
47421
|
-
return value && !value.startsWith("-") ? value : void 0;
|
|
47422
|
-
}
|
|
47423
|
-
function numericFlag(args, flag, fallback) {
|
|
47424
|
-
const index = args.indexOf(flag);
|
|
47425
|
-
if (index < 0) return fallback;
|
|
47426
|
-
const value = args[index + 1];
|
|
47427
|
-
if (!value) throw new Error(`${flag} requires a value.`);
|
|
47428
|
-
const parsed = Number(value);
|
|
47429
|
-
const max = 1e3;
|
|
47430
|
-
if (!Number.isInteger(parsed) || parsed <= 0 || parsed > max) {
|
|
47431
|
-
throw new Error(`${flag} must be a positive integer no greater than ${max}.`);
|
|
47432
|
-
}
|
|
47433
|
-
return parsed;
|
|
48202
|
+
console.log(`Forked ${sessionId} at ${sourceEntryId} into ${targetSessionId}.`);
|
|
47434
48203
|
}
|
|
47435
|
-
function
|
|
47436
|
-
const
|
|
47437
|
-
|
|
47438
|
-
|
|
47439
|
-
if (arg.startsWith("--")) {
|
|
47440
|
-
if (valueFlags.has(arg)) index += 1;
|
|
47441
|
-
continue;
|
|
47442
|
-
}
|
|
47443
|
-
result.push(arg);
|
|
47444
|
-
}
|
|
47445
|
-
return result;
|
|
48204
|
+
async function loadSession(store, sessionId, kind) {
|
|
48205
|
+
const data = await store.load(sessionId);
|
|
48206
|
+
if (!data) throw new CommandError(kind, "session_not_found", `Session not found: ${sessionId}`, { hint: "list sessions: pie sessions list --json" });
|
|
48207
|
+
return data;
|
|
47446
48208
|
}
|
|
47447
|
-
function
|
|
48209
|
+
function fullSessionRow(metadata) {
|
|
47448
48210
|
return {
|
|
47449
48211
|
id: metadata.id,
|
|
47450
48212
|
name: metadata.name,
|
|
47451
48213
|
createdAt: metadata.createdAt,
|
|
47452
48214
|
updatedAt: metadata.updatedAt,
|
|
47453
|
-
|
|
48215
|
+
...typeof metadata.cwd === "string" ? { cwd: metadata.cwd } : {},
|
|
47454
48216
|
entryCount: metadata.entryCount,
|
|
47455
|
-
messageCount: metadata.messageCount,
|
|
47456
48217
|
activeEntryId: metadata.activeEntryId,
|
|
47457
|
-
rootEntryId: metadata.rootEntryId,
|
|
47458
|
-
|
|
47459
|
-
|
|
47460
|
-
|
|
47461
|
-
|
|
48218
|
+
...typeof metadata.rootEntryId === "string" ? { rootEntryId: metadata.rootEntryId } : {},
|
|
48219
|
+
...typeof metadata.sourceSessionId === "string" ? { sourceSessionId: metadata.sourceSessionId } : {},
|
|
48220
|
+
...typeof metadata.sourceEntryId === "string" ? { sourceEntryId: metadata.sourceEntryId } : {},
|
|
48221
|
+
...typeof metadata.sourceActiveEntryId === "string" ? { sourceActiveEntryId: metadata.sourceActiveEntryId } : {},
|
|
48222
|
+
...typeof metadata.forkBaseEntryId === "string" ? { forkBaseEntryId: metadata.forkBaseEntryId } : {}
|
|
47462
48223
|
};
|
|
47463
48224
|
}
|
|
48225
|
+
function parseLimitFlag(parsed, kind, fallback) {
|
|
48226
|
+
const raw = getFlagString(parsed, "--limit");
|
|
48227
|
+
if (raw === void 0) return fallback;
|
|
48228
|
+
const value = Number(raw);
|
|
48229
|
+
const max = 1e3;
|
|
48230
|
+
if (!Number.isInteger(value) || value <= 0 || value > max) {
|
|
48231
|
+
throw new CommandError(kind, "invalid_argument", `--limit must be a positive integer no greater than ${max}.`, { usage: true });
|
|
48232
|
+
}
|
|
48233
|
+
return value;
|
|
48234
|
+
}
|
|
48235
|
+
function parseExtraFields(raw, allowed, kind) {
|
|
48236
|
+
if (!raw) return [];
|
|
48237
|
+
if (raw === "all") return [...allowed];
|
|
48238
|
+
const requested = raw.split(",").map((value) => value.trim()).filter(Boolean);
|
|
48239
|
+
for (const field of requested) {
|
|
48240
|
+
if (!allowed.includes(field)) {
|
|
48241
|
+
throw new CommandError(kind, "invalid_argument", `Unknown --fields entry: ${field}. Allowed: ${allowed.join(", ")}, all.`, { usage: true });
|
|
48242
|
+
}
|
|
48243
|
+
}
|
|
48244
|
+
return [...new Set(requested)];
|
|
48245
|
+
}
|
|
48246
|
+
function printSessionsUsage() {
|
|
48247
|
+
console.log(`Usage:
|
|
48248
|
+
pie sessions list [--json] [--limit <n>] [--cursor <cursor>] [--cwd <path> | --all] [--fields <list>] [--full]
|
|
48249
|
+
pie sessions read <sessionId> [--json] [--limit <n>] [--before <cursor>] [--fields <list>] [--full]
|
|
48250
|
+
pie sessions rename <sessionId> <name> [--json] [--cwd <path>]
|
|
48251
|
+
pie sessions rewind <sessionId> --to <entryId> [--json]
|
|
48252
|
+
pie sessions fork <sessionId> --from <entryId> --target <newSessionId> --name <name> [--cwd <path>] [--force] [--json]`);
|
|
48253
|
+
}
|
|
47464
48254
|
function cwdMatches(sessionCwd, requestedCwd) {
|
|
47465
48255
|
if (!sessionCwd) return false;
|
|
47466
48256
|
if (sessionCwd === requestedCwd) return true;
|
|
@@ -47479,12 +48269,9 @@ function activeTranscriptEvents(entries) {
|
|
|
47479
48269
|
const turnId = isRecord2(entry.message) && typeof entry.message.turnId === "string" ? entry.message.turnId : void 0;
|
|
47480
48270
|
return {
|
|
47481
48271
|
logicalSeq: index + 1,
|
|
47482
|
-
checkpointId: entry.id,
|
|
47483
48272
|
entryId: entry.id,
|
|
47484
|
-
id: entry.id,
|
|
47485
48273
|
type: entry.type,
|
|
47486
48274
|
timestamp: entry.timestamp,
|
|
47487
|
-
occurredAt: entry.timestamp,
|
|
47488
48275
|
role,
|
|
47489
48276
|
turnId,
|
|
47490
48277
|
content: textFromMessage(entry.message),
|
|
@@ -47492,20 +48279,6 @@ function activeTranscriptEvents(entries) {
|
|
|
47492
48279
|
};
|
|
47493
48280
|
});
|
|
47494
48281
|
}
|
|
47495
|
-
function stableTranscriptEvent(event) {
|
|
47496
|
-
return {
|
|
47497
|
-
logicalSeq: event.logicalSeq,
|
|
47498
|
-
checkpointId: event.checkpointId,
|
|
47499
|
-
entryId: event.entryId,
|
|
47500
|
-
id: event.id,
|
|
47501
|
-
type: event.type,
|
|
47502
|
-
timestamp: event.timestamp,
|
|
47503
|
-
occurredAt: event.occurredAt,
|
|
47504
|
-
...event.role ? { role: event.role } : {},
|
|
47505
|
-
...event.turnId ? { turnId: event.turnId } : {},
|
|
47506
|
-
...event.content ? { content: event.content } : {}
|
|
47507
|
-
};
|
|
47508
|
-
}
|
|
47509
48282
|
function activePathEntries(data) {
|
|
47510
48283
|
const activeEntryId = data.metadata.activeEntryId;
|
|
47511
48284
|
if (!activeEntryId) return [];
|
|
@@ -47517,7 +48290,7 @@ function resolveBeforeCursor(events, cursor) {
|
|
|
47517
48290
|
if (Number.isInteger(numeric) && numeric >= 0) {
|
|
47518
48291
|
return Math.max(0, Math.min(events.length, numeric));
|
|
47519
48292
|
}
|
|
47520
|
-
const index = events.findIndex((event) => event.entryId === cursor
|
|
48293
|
+
const index = events.findIndex((event) => event.entryId === cursor);
|
|
47521
48294
|
return index >= 0 ? index : events.length;
|
|
47522
48295
|
}
|
|
47523
48296
|
function cloneJson2(value) {
|
|
@@ -48249,31 +49022,7 @@ function parseExtensionFlags(argv) {
|
|
|
48249
49022
|
}
|
|
48250
49023
|
|
|
48251
49024
|
// src/commands/extensions.ts
|
|
48252
|
-
|
|
48253
|
-
const extensionPaths = [];
|
|
48254
|
-
let json = false;
|
|
48255
|
-
let scope = "user";
|
|
48256
|
-
let name;
|
|
48257
|
-
const rest = [];
|
|
48258
|
-
for (let i = 0; i < args.length; i += 1) {
|
|
48259
|
-
const arg = args[i];
|
|
48260
|
-
if (arg === "--json") {
|
|
48261
|
-
json = true;
|
|
48262
|
-
} else if (arg === "--project") {
|
|
48263
|
-
scope = "project";
|
|
48264
|
-
} else if (arg === "--user") {
|
|
48265
|
-
scope = "user";
|
|
48266
|
-
} else if (arg === "--extension-path" && args[i + 1]) {
|
|
48267
|
-
extensionPaths.push(args[i + 1]);
|
|
48268
|
-
i += 1;
|
|
48269
|
-
} else if (!name && !arg.startsWith("-")) {
|
|
48270
|
-
name = arg;
|
|
48271
|
-
} else {
|
|
48272
|
-
rest.push(arg);
|
|
48273
|
-
}
|
|
48274
|
-
}
|
|
48275
|
-
return { json, scope, name, extensionPaths, rest };
|
|
48276
|
-
}
|
|
49025
|
+
var EXTENSION_ROW_EXTRA_FIELDS = ["entryPath", "description"];
|
|
48277
49026
|
function listExtensions(settingsManager, extensionPaths) {
|
|
48278
49027
|
const cwd = process.cwd();
|
|
48279
49028
|
return discoverAllExtensions(
|
|
@@ -48294,40 +49043,112 @@ function formatExtensionList(infos) {
|
|
|
48294
49043
|
});
|
|
48295
49044
|
return lines.join("\n");
|
|
48296
49045
|
}
|
|
49046
|
+
function printExtensionsUsage() {
|
|
49047
|
+
console.log(`Usage:
|
|
49048
|
+
pie extensions list [--json] [--extension-path <dir>] [--fields <list>]
|
|
49049
|
+
pie extensions enable <name> [--project|--user] [--json]
|
|
49050
|
+
pie extensions disable <name> [--project|--user] [--json]
|
|
49051
|
+
|
|
49052
|
+
Enablement overrides are stored sparsely; absent entries default to enabled.
|
|
49053
|
+
Project scope writes ./.pie/settings.json and overrides user scope.`);
|
|
49054
|
+
}
|
|
48297
49055
|
async function runExtensionsCommand(args) {
|
|
48298
49056
|
const subcommand = args[0] || "list";
|
|
48299
|
-
|
|
48300
|
-
|
|
48301
|
-
|
|
48302
|
-
|
|
48303
|
-
|
|
48304
|
-
|
|
49057
|
+
if (subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
|
|
49058
|
+
printExtensionsUsage();
|
|
49059
|
+
return;
|
|
49060
|
+
}
|
|
49061
|
+
const rest = args.slice(1);
|
|
49062
|
+
try {
|
|
49063
|
+
if (subcommand === "list") {
|
|
49064
|
+
await runExtensionsList(rest);
|
|
48305
49065
|
return;
|
|
48306
49066
|
}
|
|
49067
|
+
if (subcommand === "enable" || subcommand === "disable") {
|
|
49068
|
+
await runExtensionsToggle(subcommand, rest);
|
|
49069
|
+
return;
|
|
49070
|
+
}
|
|
49071
|
+
throw new CommandError("extensions", "unknown_command", `Unknown extensions command: ${subcommand}`, {
|
|
49072
|
+
usage: true,
|
|
49073
|
+
hint: "subcommands: list, enable, disable"
|
|
49074
|
+
});
|
|
49075
|
+
} catch (error) {
|
|
49076
|
+
emitCommandError(error, { json: args.includes("--json"), fallbackKind: "extensions" });
|
|
49077
|
+
}
|
|
49078
|
+
}
|
|
49079
|
+
async function runExtensionsList(rest) {
|
|
49080
|
+
const parsed = parseCommandArgs(rest, EXTENSIONS_LIST_SPEC);
|
|
49081
|
+
if (parsed.error) {
|
|
49082
|
+
throw new CommandError("extensions.list", parsed.error.code, parsed.error.message, { usage: true });
|
|
49083
|
+
}
|
|
49084
|
+
if (parsed.help) {
|
|
49085
|
+
console.log(renderCommandHelp(EXTENSIONS_LIST_SPEC));
|
|
49086
|
+
return;
|
|
49087
|
+
}
|
|
49088
|
+
const json = getFlagBool(parsed, "--json");
|
|
49089
|
+
const settingsManager = new SettingsManager();
|
|
49090
|
+
const infos = listExtensions(settingsManager, getFlagStrings(parsed, "--extension-path"));
|
|
49091
|
+
if (!json) {
|
|
48307
49092
|
console.log(formatExtensionList(infos));
|
|
48308
49093
|
return;
|
|
48309
49094
|
}
|
|
48310
|
-
|
|
48311
|
-
|
|
48312
|
-
|
|
48313
|
-
|
|
48314
|
-
|
|
48315
|
-
|
|
48316
|
-
|
|
48317
|
-
|
|
48318
|
-
|
|
48319
|
-
|
|
48320
|
-
|
|
48321
|
-
|
|
49095
|
+
const fields = parseExtensionFields(getFlagString(parsed, "--fields"));
|
|
49096
|
+
const rows = infos.map((info) => {
|
|
49097
|
+
const row = {
|
|
49098
|
+
identity: info.identity ?? null,
|
|
49099
|
+
source: info.source,
|
|
49100
|
+
enabled: info.enabled
|
|
49101
|
+
};
|
|
49102
|
+
if (fields.includes("entryPath")) row.entryPath = info.entryPath;
|
|
49103
|
+
if (fields.includes("description") && info.description) row.description = info.description;
|
|
49104
|
+
return row;
|
|
49105
|
+
});
|
|
49106
|
+
printSuccessEnvelope("extensions.list", rows, { count: rows.length, total: rows.length }, [
|
|
49107
|
+
"toggle: pie extensions enable|disable <name>"
|
|
49108
|
+
]);
|
|
49109
|
+
}
|
|
49110
|
+
async function runExtensionsToggle(subcommand, rest) {
|
|
49111
|
+
const parsed = parseCommandArgs(rest, EXTENSIONS_TOGGLE_SPEC);
|
|
49112
|
+
if (parsed.error) {
|
|
49113
|
+
throw new CommandError(`extensions.${subcommand}`, parsed.error.code, parsed.error.message, { usage: true });
|
|
49114
|
+
}
|
|
49115
|
+
if (parsed.help) {
|
|
49116
|
+
console.log(renderCommandHelp(EXTENSIONS_TOGGLE_SPEC));
|
|
48322
49117
|
return;
|
|
48323
49118
|
}
|
|
48324
|
-
|
|
48325
|
-
|
|
48326
|
-
|
|
48327
|
-
|
|
48328
|
-
|
|
48329
|
-
|
|
48330
|
-
|
|
49119
|
+
const json = getFlagBool(parsed, "--json");
|
|
49120
|
+
const name = getPositional(parsed, "name");
|
|
49121
|
+
if (!name) {
|
|
49122
|
+
throw new CommandError(`extensions.${subcommand}`, "missing_positional", `Usage: pie extensions ${subcommand} <name> [--project|--user]`, { usage: true });
|
|
49123
|
+
}
|
|
49124
|
+
const project = getFlagBool(parsed, "--project");
|
|
49125
|
+
const user = getFlagBool(parsed, "--user");
|
|
49126
|
+
if (project && user) {
|
|
49127
|
+
throw new CommandError(`extensions.${subcommand}`, "invalid_argument", "Choose one scope: --project or --user.", { usage: true });
|
|
49128
|
+
}
|
|
49129
|
+
const scope = project ? "project" : "user";
|
|
49130
|
+
const enabled = subcommand === "enable";
|
|
49131
|
+
const settingsManager = new SettingsManager();
|
|
49132
|
+
settingsManager.setExtensionEnabled(name, enabled, scope);
|
|
49133
|
+
if (json) {
|
|
49134
|
+
printSuccessEnvelope(`extensions.${subcommand}`, { identity: name, enabled, scope });
|
|
49135
|
+
return;
|
|
49136
|
+
}
|
|
49137
|
+
const scopeLabel = scope === "project" ? "./.pie/settings.json" : "~/.pie/settings.json";
|
|
49138
|
+
console.log(
|
|
49139
|
+
`Extension "${name}" ${enabled ? "enabled" : "disabled"} in ${scopeLabel}. Takes effect on next start.`
|
|
49140
|
+
);
|
|
49141
|
+
}
|
|
49142
|
+
function parseExtensionFields(raw) {
|
|
49143
|
+
if (!raw) return [];
|
|
49144
|
+
if (raw === "all") return [...EXTENSION_ROW_EXTRA_FIELDS];
|
|
49145
|
+
const requested = raw.split(",").map((value) => value.trim()).filter(Boolean);
|
|
49146
|
+
for (const field of requested) {
|
|
49147
|
+
if (!EXTENSION_ROW_EXTRA_FIELDS.includes(field)) {
|
|
49148
|
+
throw new CommandError("extensions.list", "invalid_argument", `Unknown --fields entry: ${field}. Allowed: ${EXTENSION_ROW_EXTRA_FIELDS.join(", ")}, all.`, { usage: true });
|
|
49149
|
+
}
|
|
49150
|
+
}
|
|
49151
|
+
return requested;
|
|
48331
49152
|
}
|
|
48332
49153
|
|
|
48333
49154
|
// src/interactive-mode.ts
|
|
@@ -55703,6 +56524,267 @@ function wrapToolsWithExtensions(tools, runner) {
|
|
|
55703
56524
|
return tools.map((tool) => wrapToolWithExtensions(tool, runner));
|
|
55704
56525
|
}
|
|
55705
56526
|
|
|
56527
|
+
// src/core/defaults.ts
|
|
56528
|
+
var DEFAULT_THINKING_LEVEL = "medium";
|
|
56529
|
+
|
|
56530
|
+
// src/core/model-resolver.ts
|
|
56531
|
+
function normalizeProviderName(provider) {
|
|
56532
|
+
return provider.toLowerCase().replace(/[^a-z]/g, "");
|
|
56533
|
+
}
|
|
56534
|
+
function selectFallbackModel(registry, preferred) {
|
|
56535
|
+
const availableModels = registry.getAvailable();
|
|
56536
|
+
if (preferred?.provider && preferred?.modelId) {
|
|
56537
|
+
const exact = availableModels.find(
|
|
56538
|
+
(model) => model.provider === preferred.provider && model.id === preferred.modelId
|
|
56539
|
+
);
|
|
56540
|
+
if (exact) return exact;
|
|
56541
|
+
}
|
|
56542
|
+
if (preferred?.provider) {
|
|
56543
|
+
const sameProvider = availableModels.find((model) => model.provider === preferred.provider);
|
|
56544
|
+
if (sameProvider) return sameProvider;
|
|
56545
|
+
}
|
|
56546
|
+
return availableModels[0] || registry.getAll()[0];
|
|
56547
|
+
}
|
|
56548
|
+
function resolveConfiguredModel(registry, provider, modelId) {
|
|
56549
|
+
const exact = registry.find(provider, modelId);
|
|
56550
|
+
if (exact) {
|
|
56551
|
+
return { model: exact, provider, modelId, corrected: false };
|
|
56552
|
+
}
|
|
56553
|
+
const allModels = registry.getAll();
|
|
56554
|
+
if (allModels.length === 0) {
|
|
56555
|
+
throw new Error("No registered models are available.");
|
|
56556
|
+
}
|
|
56557
|
+
const sameIdMatches = allModels.filter((model) => model.id === modelId);
|
|
56558
|
+
const normalizedProviderMatches = sameIdMatches.filter(
|
|
56559
|
+
(model) => normalizeProviderName(model.provider) === normalizeProviderName(provider)
|
|
56560
|
+
);
|
|
56561
|
+
if (normalizedProviderMatches.length === 1) {
|
|
56562
|
+
const matched = normalizedProviderMatches[0];
|
|
56563
|
+
return {
|
|
56564
|
+
model: matched,
|
|
56565
|
+
provider: matched.provider,
|
|
56566
|
+
modelId: matched.id,
|
|
56567
|
+
corrected: true,
|
|
56568
|
+
warning: `Configured model "${provider}/${modelId}" was not found. Using "${matched.provider}/${matched.id}" instead.`
|
|
56569
|
+
};
|
|
56570
|
+
}
|
|
56571
|
+
if (sameIdMatches.length === 1) {
|
|
56572
|
+
const matched = sameIdMatches[0];
|
|
56573
|
+
return {
|
|
56574
|
+
model: matched,
|
|
56575
|
+
provider: matched.provider,
|
|
56576
|
+
modelId: matched.id,
|
|
56577
|
+
corrected: true,
|
|
56578
|
+
warning: `Configured model "${provider}/${modelId}" was not found. Reusing the available model "${matched.provider}/${matched.id}".`
|
|
56579
|
+
};
|
|
56580
|
+
}
|
|
56581
|
+
const providerModels = registry.getByProvider(provider);
|
|
56582
|
+
if (providerModels.length > 0) {
|
|
56583
|
+
const fallback2 = providerModels[0];
|
|
56584
|
+
return {
|
|
56585
|
+
model: fallback2,
|
|
56586
|
+
provider: fallback2.provider,
|
|
56587
|
+
modelId: fallback2.id,
|
|
56588
|
+
corrected: true,
|
|
56589
|
+
warning: `Configured model "${provider}/${modelId}" was not found. Falling back to "${fallback2.provider}/${fallback2.id}".`
|
|
56590
|
+
};
|
|
56591
|
+
}
|
|
56592
|
+
const fallback = selectFallbackModel(registry);
|
|
56593
|
+
if (!fallback) {
|
|
56594
|
+
throw new Error("No registered models are available.");
|
|
56595
|
+
}
|
|
56596
|
+
return {
|
|
56597
|
+
model: fallback,
|
|
56598
|
+
provider: fallback.provider,
|
|
56599
|
+
modelId: fallback.id,
|
|
56600
|
+
corrected: true,
|
|
56601
|
+
warning: `Configured model "${provider}/${modelId}" was not found. Falling back to "${fallback.provider}/${fallback.id}".`
|
|
56602
|
+
};
|
|
56603
|
+
}
|
|
56604
|
+
function findInitialModel(options) {
|
|
56605
|
+
const configDefaults = options.registry.getConfigDefaults();
|
|
56606
|
+
const configuredProvider = options.configuredProvider || configDefaults?.provider;
|
|
56607
|
+
const configuredModelId = options.configuredModelId || configDefaults?.modelId;
|
|
56608
|
+
const resolved = configuredProvider && configuredModelId ? resolveConfiguredModel(options.registry, configuredProvider, configuredModelId) : void 0;
|
|
56609
|
+
const apiKey = resolved ? options.registry.getApiKey(resolved.model) : void 0;
|
|
56610
|
+
if (!resolved || !apiKey) {
|
|
56611
|
+
const fallback = selectFallbackModel(options.registry, {
|
|
56612
|
+
provider: configuredProvider,
|
|
56613
|
+
modelId: configuredModelId
|
|
56614
|
+
});
|
|
56615
|
+
if (!fallback) {
|
|
56616
|
+
return {
|
|
56617
|
+
model: void 0,
|
|
56618
|
+
apiKey: void 0,
|
|
56619
|
+
provider: void 0,
|
|
56620
|
+
modelId: void 0,
|
|
56621
|
+
unconfigured: true,
|
|
56622
|
+
warning: "No models are configured. Add one in ~/.pie/models.json before sending messages."
|
|
56623
|
+
};
|
|
56624
|
+
}
|
|
56625
|
+
const fallbackKey = options.registry.getApiKey(fallback);
|
|
56626
|
+
if (!fallbackKey) {
|
|
56627
|
+
throw new Error(`No API key found for provider "${resolved?.provider || fallback.provider}".`);
|
|
56628
|
+
}
|
|
56629
|
+
return {
|
|
56630
|
+
model: fallback,
|
|
56631
|
+
apiKey: fallbackKey,
|
|
56632
|
+
provider: fallback.provider,
|
|
56633
|
+
modelId: fallback.id,
|
|
56634
|
+
warning: resolved ? resolved.warning || `No API key found for "${resolved.provider}". Using "${fallback.provider}/${fallback.id}" instead.` : configuredProvider && configuredModelId ? `Configured model "${configuredProvider}/${configuredModelId}" was not found. Using "${fallback.provider}/${fallback.id}" instead.` : void 0
|
|
56635
|
+
};
|
|
56636
|
+
}
|
|
56637
|
+
return {
|
|
56638
|
+
model: resolved.model,
|
|
56639
|
+
apiKey,
|
|
56640
|
+
provider: resolved.provider,
|
|
56641
|
+
modelId: resolved.modelId,
|
|
56642
|
+
warning: resolved.warning
|
|
56643
|
+
};
|
|
56644
|
+
}
|
|
56645
|
+
function restoreModelFromSession(options) {
|
|
56646
|
+
const savedProvider = options.savedProvider;
|
|
56647
|
+
const restored = options.registry.find(savedProvider, options.savedModelId);
|
|
56648
|
+
if (restored && options.registry.getApiKey(restored)) {
|
|
56649
|
+
return { model: restored };
|
|
56650
|
+
}
|
|
56651
|
+
if (options.currentModel) {
|
|
56652
|
+
return {
|
|
56653
|
+
model: options.currentModel,
|
|
56654
|
+
fallbackMessage: `Could not restore model ${savedProvider}/${options.savedModelId}. Using ${options.currentModel.provider}/${options.currentModel.id}.`
|
|
56655
|
+
};
|
|
56656
|
+
}
|
|
56657
|
+
const fallback = selectFallbackModel(options.registry, {
|
|
56658
|
+
provider: savedProvider,
|
|
56659
|
+
modelId: options.savedModelId
|
|
56660
|
+
});
|
|
56661
|
+
return fallback ? {
|
|
56662
|
+
model: fallback,
|
|
56663
|
+
fallbackMessage: `Could not restore model ${savedProvider}/${options.savedModelId}. Using ${fallback.provider}/${fallback.id}.`
|
|
56664
|
+
} : { model: void 0 };
|
|
56665
|
+
}
|
|
56666
|
+
|
|
56667
|
+
// src/core/session-model-metadata.ts
|
|
56668
|
+
function getSavedSessionModelSelection(activeSession) {
|
|
56669
|
+
if (!activeSession) return {};
|
|
56670
|
+
const provider = typeof activeSession.metadata.provider === "string" ? activeSession.metadata.provider : typeof activeSession.metadata.defaultProvider === "string" ? activeSession.metadata.defaultProvider : void 0;
|
|
56671
|
+
const modelId = typeof activeSession.metadata.modelId === "string" ? activeSession.metadata.modelId : typeof activeSession.metadata.defaultModel === "string" ? activeSession.metadata.defaultModel : void 0;
|
|
56672
|
+
const thinkingLevel = typeof activeSession.metadata.thinkingLevel === "string" ? activeSession.metadata.thinkingLevel : void 0;
|
|
56673
|
+
return { provider, modelId, thinkingLevel };
|
|
56674
|
+
}
|
|
56675
|
+
function syncSessionModelMetadata(sessionManager, model, thinkingLevel) {
|
|
56676
|
+
const activeSession = sessionManager.getActiveSession();
|
|
56677
|
+
if (!activeSession || !model) return;
|
|
56678
|
+
activeSession.metadata.provider = model.provider;
|
|
56679
|
+
activeSession.metadata.modelId = model.id;
|
|
56680
|
+
activeSession.metadata.defaultProvider = model.provider;
|
|
56681
|
+
activeSession.metadata.defaultModel = model.id;
|
|
56682
|
+
activeSession.metadata.thinkingLevel = thinkingLevel;
|
|
56683
|
+
activeSession.isDirty = true;
|
|
56684
|
+
}
|
|
56685
|
+
function restoreSessionModelState(options) {
|
|
56686
|
+
const { provider, modelId, thinkingLevel } = getSavedSessionModelSelection(options.activeSession);
|
|
56687
|
+
if (!provider || !modelId) {
|
|
56688
|
+
return {
|
|
56689
|
+
model: options.currentModel,
|
|
56690
|
+
thinkingLevel
|
|
56691
|
+
};
|
|
56692
|
+
}
|
|
56693
|
+
const restored = restoreModelFromSession({
|
|
56694
|
+
registry: options.registry,
|
|
56695
|
+
savedProvider: provider,
|
|
56696
|
+
savedModelId: modelId,
|
|
56697
|
+
currentModel: options.currentModel
|
|
56698
|
+
});
|
|
56699
|
+
return {
|
|
56700
|
+
model: restored.model,
|
|
56701
|
+
thinkingLevel,
|
|
56702
|
+
fallbackMessage: restored.fallbackMessage
|
|
56703
|
+
};
|
|
56704
|
+
}
|
|
56705
|
+
|
|
56706
|
+
// src/core/interactive-model-state.ts
|
|
56707
|
+
var THINKING_LEVELS = [
|
|
56708
|
+
"off",
|
|
56709
|
+
"minimal",
|
|
56710
|
+
"low",
|
|
56711
|
+
"medium",
|
|
56712
|
+
"high",
|
|
56713
|
+
"xhigh"
|
|
56714
|
+
];
|
|
56715
|
+
var THINKING_LEVEL_DESCRIPTIONS = {
|
|
56716
|
+
off: "No reasoning",
|
|
56717
|
+
minimal: "Very brief reasoning (~1k tokens)",
|
|
56718
|
+
low: "Light reasoning (~2k tokens)",
|
|
56719
|
+
medium: "Moderate reasoning (~8k tokens)",
|
|
56720
|
+
high: "Deep reasoning (~16k tokens)",
|
|
56721
|
+
xhigh: "Maximum reasoning (~32k tokens)"
|
|
56722
|
+
};
|
|
56723
|
+
function isThinkingLevel(value) {
|
|
56724
|
+
return THINKING_LEVELS.includes(value);
|
|
56725
|
+
}
|
|
56726
|
+
function resolveInitialThinkingLevel(options) {
|
|
56727
|
+
const sessionLevel = options.session?.metadata.thinkingLevel;
|
|
56728
|
+
if (typeof sessionLevel === "string" && isThinkingLevel(sessionLevel)) {
|
|
56729
|
+
return sessionLevel;
|
|
56730
|
+
}
|
|
56731
|
+
return options.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;
|
|
56732
|
+
}
|
|
56733
|
+
function maskApiKey(key) {
|
|
56734
|
+
if (key.length <= 6) return "***";
|
|
56735
|
+
return key.slice(0, 6) + "***";
|
|
56736
|
+
}
|
|
56737
|
+
function applyThinkingLevel(options) {
|
|
56738
|
+
options.agent.setThinkingLevel(options.level);
|
|
56739
|
+
options.settingsManager.setDefaultThinkingLevel(options.level);
|
|
56740
|
+
syncSessionModelMetadata(options.sessionManager, options.model, options.level);
|
|
56741
|
+
}
|
|
56742
|
+
function switchInteractiveModel(options) {
|
|
56743
|
+
const [provider, modelId] = options.fullModelId.split("/");
|
|
56744
|
+
const model = options.registry.find(provider, modelId);
|
|
56745
|
+
if (!model) {
|
|
56746
|
+
throw new Error(`Model "${options.fullModelId}" not found`);
|
|
56747
|
+
}
|
|
56748
|
+
const apiKey = options.registry.getApiKey(model);
|
|
56749
|
+
options.agent.setModel(model);
|
|
56750
|
+
if (apiKey) {
|
|
56751
|
+
options.agent.apiKey = apiKey;
|
|
56752
|
+
fileLogger.log("cli", `Switched model to ${options.fullModelId}, updated API key`, {
|
|
56753
|
+
keyPrefix: maskApiKey(apiKey)
|
|
56754
|
+
});
|
|
56755
|
+
} else {
|
|
56756
|
+
fileLogger.log("cli", `Switched model to ${options.fullModelId}, no API key found`);
|
|
56757
|
+
}
|
|
56758
|
+
options.settingsManager.setDefaultModelAndProvider(provider, modelId);
|
|
56759
|
+
syncSessionModelMetadata(options.sessionManager, model, options.thinkingLevel);
|
|
56760
|
+
return { model, apiKey };
|
|
56761
|
+
}
|
|
56762
|
+
function restoreInteractiveSessionState(options) {
|
|
56763
|
+
const restored = restoreSessionModelState({
|
|
56764
|
+
activeSession: options.activeSession,
|
|
56765
|
+
registry: options.registry,
|
|
56766
|
+
currentModel: options.currentModel
|
|
56767
|
+
});
|
|
56768
|
+
const thinkingLevel = restored.thinkingLevel && isThinkingLevel(restored.thinkingLevel) ? restored.thinkingLevel : void 0;
|
|
56769
|
+
if (thinkingLevel) {
|
|
56770
|
+
options.agent.setThinkingLevel(thinkingLevel);
|
|
56771
|
+
}
|
|
56772
|
+
let apiKey;
|
|
56773
|
+
if (restored.model) {
|
|
56774
|
+
options.agent.setModel(restored.model);
|
|
56775
|
+
apiKey = options.registry.getApiKey(restored.model);
|
|
56776
|
+
if (apiKey) {
|
|
56777
|
+
options.agent.apiKey = apiKey;
|
|
56778
|
+
}
|
|
56779
|
+
}
|
|
56780
|
+
return {
|
|
56781
|
+
model: restored.model,
|
|
56782
|
+
apiKey,
|
|
56783
|
+
thinkingLevel,
|
|
56784
|
+
fallbackMessage: restored.fallbackMessage
|
|
56785
|
+
};
|
|
56786
|
+
}
|
|
56787
|
+
|
|
55706
56788
|
// src/keybindings.ts
|
|
55707
56789
|
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
|
|
55708
56790
|
import { join as join7 } from "path";
|
|
@@ -56829,23 +57911,23 @@ function parseThemeJson(label, json) {
|
|
|
56829
57911
|
otherErrors.push(` - ${e.path}: ${e.message}`);
|
|
56830
57912
|
}
|
|
56831
57913
|
}
|
|
56832
|
-
let
|
|
57914
|
+
let errorMessage4 = `Invalid theme "${label}":
|
|
56833
57915
|
`;
|
|
56834
57916
|
if (missingColors.length > 0) {
|
|
56835
|
-
|
|
56836
|
-
|
|
56837
|
-
|
|
57917
|
+
errorMessage4 += "\nMissing required color tokens:\n";
|
|
57918
|
+
errorMessage4 += missingColors.map((c) => ` - ${c}`).join("\n");
|
|
57919
|
+
errorMessage4 += `
|
|
56838
57920
|
|
|
56839
57921
|
Please add these colors to your theme's "colors" object.`;
|
|
56840
|
-
|
|
57922
|
+
errorMessage4 += "\nSee the built-in themes (dark.json, light.json) for reference values.";
|
|
56841
57923
|
}
|
|
56842
57924
|
if (otherErrors.length > 0) {
|
|
56843
|
-
|
|
57925
|
+
errorMessage4 += `
|
|
56844
57926
|
|
|
56845
57927
|
Other errors:
|
|
56846
57928
|
${otherErrors.join("\n")}`;
|
|
56847
57929
|
}
|
|
56848
|
-
throw new Error(
|
|
57930
|
+
throw new Error(errorMessage4);
|
|
56849
57931
|
}
|
|
56850
57932
|
return json;
|
|
56851
57933
|
}
|
|
@@ -61265,257 +62347,6 @@ var SettingsSelectorComponent = class extends Container {
|
|
|
61265
62347
|
}
|
|
61266
62348
|
};
|
|
61267
62349
|
|
|
61268
|
-
// src/core/model-resolver.ts
|
|
61269
|
-
function normalizeProviderName(provider) {
|
|
61270
|
-
return provider.toLowerCase().replace(/[^a-z]/g, "");
|
|
61271
|
-
}
|
|
61272
|
-
function selectFallbackModel(registry, preferred) {
|
|
61273
|
-
const availableModels = registry.getAvailable();
|
|
61274
|
-
if (preferred?.provider && preferred?.modelId) {
|
|
61275
|
-
const exact = availableModels.find(
|
|
61276
|
-
(model) => model.provider === preferred.provider && model.id === preferred.modelId
|
|
61277
|
-
);
|
|
61278
|
-
if (exact) return exact;
|
|
61279
|
-
}
|
|
61280
|
-
if (preferred?.provider) {
|
|
61281
|
-
const sameProvider = availableModels.find((model) => model.provider === preferred.provider);
|
|
61282
|
-
if (sameProvider) return sameProvider;
|
|
61283
|
-
}
|
|
61284
|
-
return availableModels[0] || registry.getAll()[0];
|
|
61285
|
-
}
|
|
61286
|
-
function resolveConfiguredModel(registry, provider, modelId) {
|
|
61287
|
-
const exact = registry.find(provider, modelId);
|
|
61288
|
-
if (exact) {
|
|
61289
|
-
return { model: exact, provider, modelId, corrected: false };
|
|
61290
|
-
}
|
|
61291
|
-
const allModels = registry.getAll();
|
|
61292
|
-
if (allModels.length === 0) {
|
|
61293
|
-
throw new Error("No registered models are available.");
|
|
61294
|
-
}
|
|
61295
|
-
const sameIdMatches = allModels.filter((model) => model.id === modelId);
|
|
61296
|
-
const normalizedProviderMatches = sameIdMatches.filter(
|
|
61297
|
-
(model) => normalizeProviderName(model.provider) === normalizeProviderName(provider)
|
|
61298
|
-
);
|
|
61299
|
-
if (normalizedProviderMatches.length === 1) {
|
|
61300
|
-
const matched = normalizedProviderMatches[0];
|
|
61301
|
-
return {
|
|
61302
|
-
model: matched,
|
|
61303
|
-
provider: matched.provider,
|
|
61304
|
-
modelId: matched.id,
|
|
61305
|
-
corrected: true,
|
|
61306
|
-
warning: `Configured model "${provider}/${modelId}" was not found. Using "${matched.provider}/${matched.id}" instead.`
|
|
61307
|
-
};
|
|
61308
|
-
}
|
|
61309
|
-
if (sameIdMatches.length === 1) {
|
|
61310
|
-
const matched = sameIdMatches[0];
|
|
61311
|
-
return {
|
|
61312
|
-
model: matched,
|
|
61313
|
-
provider: matched.provider,
|
|
61314
|
-
modelId: matched.id,
|
|
61315
|
-
corrected: true,
|
|
61316
|
-
warning: `Configured model "${provider}/${modelId}" was not found. Reusing the available model "${matched.provider}/${matched.id}".`
|
|
61317
|
-
};
|
|
61318
|
-
}
|
|
61319
|
-
const providerModels = registry.getByProvider(provider);
|
|
61320
|
-
if (providerModels.length > 0) {
|
|
61321
|
-
const fallback2 = providerModels[0];
|
|
61322
|
-
return {
|
|
61323
|
-
model: fallback2,
|
|
61324
|
-
provider: fallback2.provider,
|
|
61325
|
-
modelId: fallback2.id,
|
|
61326
|
-
corrected: true,
|
|
61327
|
-
warning: `Configured model "${provider}/${modelId}" was not found. Falling back to "${fallback2.provider}/${fallback2.id}".`
|
|
61328
|
-
};
|
|
61329
|
-
}
|
|
61330
|
-
const fallback = selectFallbackModel(registry);
|
|
61331
|
-
if (!fallback) {
|
|
61332
|
-
throw new Error("No registered models are available.");
|
|
61333
|
-
}
|
|
61334
|
-
return {
|
|
61335
|
-
model: fallback,
|
|
61336
|
-
provider: fallback.provider,
|
|
61337
|
-
modelId: fallback.id,
|
|
61338
|
-
corrected: true,
|
|
61339
|
-
warning: `Configured model "${provider}/${modelId}" was not found. Falling back to "${fallback.provider}/${fallback.id}".`
|
|
61340
|
-
};
|
|
61341
|
-
}
|
|
61342
|
-
function findInitialModel(options) {
|
|
61343
|
-
const configDefaults = options.registry.getConfigDefaults();
|
|
61344
|
-
const configuredProvider = options.configuredProvider || configDefaults?.provider;
|
|
61345
|
-
const configuredModelId = options.configuredModelId || configDefaults?.modelId;
|
|
61346
|
-
const resolved = configuredProvider && configuredModelId ? resolveConfiguredModel(options.registry, configuredProvider, configuredModelId) : void 0;
|
|
61347
|
-
const apiKey = resolved ? options.registry.getApiKey(resolved.model) : void 0;
|
|
61348
|
-
if (!resolved || !apiKey) {
|
|
61349
|
-
const fallback = selectFallbackModel(options.registry, {
|
|
61350
|
-
provider: configuredProvider,
|
|
61351
|
-
modelId: configuredModelId
|
|
61352
|
-
});
|
|
61353
|
-
if (!fallback) {
|
|
61354
|
-
return {
|
|
61355
|
-
model: void 0,
|
|
61356
|
-
apiKey: void 0,
|
|
61357
|
-
provider: void 0,
|
|
61358
|
-
modelId: void 0,
|
|
61359
|
-
unconfigured: true,
|
|
61360
|
-
warning: "No models are configured. Add one in ~/.pie/models.json before sending messages."
|
|
61361
|
-
};
|
|
61362
|
-
}
|
|
61363
|
-
const fallbackKey = options.registry.getApiKey(fallback);
|
|
61364
|
-
if (!fallbackKey) {
|
|
61365
|
-
throw new Error(`No API key found for provider "${resolved?.provider || fallback.provider}".`);
|
|
61366
|
-
}
|
|
61367
|
-
return {
|
|
61368
|
-
model: fallback,
|
|
61369
|
-
apiKey: fallbackKey,
|
|
61370
|
-
provider: fallback.provider,
|
|
61371
|
-
modelId: fallback.id,
|
|
61372
|
-
warning: resolved ? resolved.warning || `No API key found for "${resolved.provider}". Using "${fallback.provider}/${fallback.id}" instead.` : configuredProvider && configuredModelId ? `Configured model "${configuredProvider}/${configuredModelId}" was not found. Using "${fallback.provider}/${fallback.id}" instead.` : void 0
|
|
61373
|
-
};
|
|
61374
|
-
}
|
|
61375
|
-
return {
|
|
61376
|
-
model: resolved.model,
|
|
61377
|
-
apiKey,
|
|
61378
|
-
provider: resolved.provider,
|
|
61379
|
-
modelId: resolved.modelId,
|
|
61380
|
-
warning: resolved.warning
|
|
61381
|
-
};
|
|
61382
|
-
}
|
|
61383
|
-
function restoreModelFromSession(options) {
|
|
61384
|
-
const savedProvider = options.savedProvider;
|
|
61385
|
-
const restored = options.registry.find(savedProvider, options.savedModelId);
|
|
61386
|
-
if (restored && options.registry.getApiKey(restored)) {
|
|
61387
|
-
return { model: restored };
|
|
61388
|
-
}
|
|
61389
|
-
if (options.currentModel) {
|
|
61390
|
-
return {
|
|
61391
|
-
model: options.currentModel,
|
|
61392
|
-
fallbackMessage: `Could not restore model ${savedProvider}/${options.savedModelId}. Using ${options.currentModel.provider}/${options.currentModel.id}.`
|
|
61393
|
-
};
|
|
61394
|
-
}
|
|
61395
|
-
const fallback = selectFallbackModel(options.registry, {
|
|
61396
|
-
provider: savedProvider,
|
|
61397
|
-
modelId: options.savedModelId
|
|
61398
|
-
});
|
|
61399
|
-
return fallback ? {
|
|
61400
|
-
model: fallback,
|
|
61401
|
-
fallbackMessage: `Could not restore model ${savedProvider}/${options.savedModelId}. Using ${fallback.provider}/${fallback.id}.`
|
|
61402
|
-
} : { model: void 0 };
|
|
61403
|
-
}
|
|
61404
|
-
|
|
61405
|
-
// src/core/session-model-metadata.ts
|
|
61406
|
-
function getSavedSessionModelSelection(activeSession) {
|
|
61407
|
-
if (!activeSession) return {};
|
|
61408
|
-
const provider = typeof activeSession.metadata.provider === "string" ? activeSession.metadata.provider : typeof activeSession.metadata.defaultProvider === "string" ? activeSession.metadata.defaultProvider : void 0;
|
|
61409
|
-
const modelId = typeof activeSession.metadata.modelId === "string" ? activeSession.metadata.modelId : typeof activeSession.metadata.defaultModel === "string" ? activeSession.metadata.defaultModel : void 0;
|
|
61410
|
-
const thinkingLevel = typeof activeSession.metadata.thinkingLevel === "string" ? activeSession.metadata.thinkingLevel : void 0;
|
|
61411
|
-
return { provider, modelId, thinkingLevel };
|
|
61412
|
-
}
|
|
61413
|
-
function syncSessionModelMetadata(sessionManager, model, thinkingLevel) {
|
|
61414
|
-
const activeSession = sessionManager.getActiveSession();
|
|
61415
|
-
if (!activeSession || !model) return;
|
|
61416
|
-
activeSession.metadata.provider = model.provider;
|
|
61417
|
-
activeSession.metadata.modelId = model.id;
|
|
61418
|
-
activeSession.metadata.defaultProvider = model.provider;
|
|
61419
|
-
activeSession.metadata.defaultModel = model.id;
|
|
61420
|
-
activeSession.metadata.thinkingLevel = thinkingLevel;
|
|
61421
|
-
activeSession.isDirty = true;
|
|
61422
|
-
}
|
|
61423
|
-
function restoreSessionModelState(options) {
|
|
61424
|
-
const { provider, modelId, thinkingLevel } = getSavedSessionModelSelection(options.activeSession);
|
|
61425
|
-
if (!provider || !modelId) {
|
|
61426
|
-
return {
|
|
61427
|
-
model: options.currentModel,
|
|
61428
|
-
thinkingLevel
|
|
61429
|
-
};
|
|
61430
|
-
}
|
|
61431
|
-
const restored = restoreModelFromSession({
|
|
61432
|
-
registry: options.registry,
|
|
61433
|
-
savedProvider: provider,
|
|
61434
|
-
savedModelId: modelId,
|
|
61435
|
-
currentModel: options.currentModel
|
|
61436
|
-
});
|
|
61437
|
-
return {
|
|
61438
|
-
model: restored.model,
|
|
61439
|
-
thinkingLevel,
|
|
61440
|
-
fallbackMessage: restored.fallbackMessage
|
|
61441
|
-
};
|
|
61442
|
-
}
|
|
61443
|
-
|
|
61444
|
-
// src/core/interactive-model-state.ts
|
|
61445
|
-
var THINKING_LEVELS = [
|
|
61446
|
-
"off",
|
|
61447
|
-
"minimal",
|
|
61448
|
-
"low",
|
|
61449
|
-
"medium",
|
|
61450
|
-
"high",
|
|
61451
|
-
"xhigh"
|
|
61452
|
-
];
|
|
61453
|
-
var THINKING_LEVEL_DESCRIPTIONS = {
|
|
61454
|
-
off: "No reasoning",
|
|
61455
|
-
minimal: "Very brief reasoning (~1k tokens)",
|
|
61456
|
-
low: "Light reasoning (~2k tokens)",
|
|
61457
|
-
medium: "Moderate reasoning (~8k tokens)",
|
|
61458
|
-
high: "Deep reasoning (~16k tokens)",
|
|
61459
|
-
xhigh: "Maximum reasoning (~32k tokens)"
|
|
61460
|
-
};
|
|
61461
|
-
function isThinkingLevel(value) {
|
|
61462
|
-
return THINKING_LEVELS.includes(value);
|
|
61463
|
-
}
|
|
61464
|
-
function maskApiKey(key) {
|
|
61465
|
-
if (key.length <= 6) return "***";
|
|
61466
|
-
return key.slice(0, 6) + "***";
|
|
61467
|
-
}
|
|
61468
|
-
function applyThinkingLevel(options) {
|
|
61469
|
-
options.agent.setThinkingLevel(options.level);
|
|
61470
|
-
options.settingsManager.setDefaultThinkingLevel(options.level);
|
|
61471
|
-
syncSessionModelMetadata(options.sessionManager, options.model, options.level);
|
|
61472
|
-
}
|
|
61473
|
-
function switchInteractiveModel(options) {
|
|
61474
|
-
const [provider, modelId] = options.fullModelId.split("/");
|
|
61475
|
-
const model = options.registry.find(provider, modelId);
|
|
61476
|
-
if (!model) {
|
|
61477
|
-
throw new Error(`Model "${options.fullModelId}" not found`);
|
|
61478
|
-
}
|
|
61479
|
-
const apiKey = options.registry.getApiKey(model);
|
|
61480
|
-
options.agent.setModel(model);
|
|
61481
|
-
if (apiKey) {
|
|
61482
|
-
options.agent.apiKey = apiKey;
|
|
61483
|
-
fileLogger.log("cli", `Switched model to ${options.fullModelId}, updated API key`, {
|
|
61484
|
-
keyPrefix: maskApiKey(apiKey)
|
|
61485
|
-
});
|
|
61486
|
-
} else {
|
|
61487
|
-
fileLogger.log("cli", `Switched model to ${options.fullModelId}, no API key found`);
|
|
61488
|
-
}
|
|
61489
|
-
options.settingsManager.setDefaultModelAndProvider(provider, modelId);
|
|
61490
|
-
syncSessionModelMetadata(options.sessionManager, model, options.thinkingLevel);
|
|
61491
|
-
return { model, apiKey };
|
|
61492
|
-
}
|
|
61493
|
-
function restoreInteractiveSessionState(options) {
|
|
61494
|
-
const restored = restoreSessionModelState({
|
|
61495
|
-
activeSession: options.activeSession,
|
|
61496
|
-
registry: options.registry,
|
|
61497
|
-
currentModel: options.currentModel
|
|
61498
|
-
});
|
|
61499
|
-
const thinkingLevel = restored.thinkingLevel && isThinkingLevel(restored.thinkingLevel) ? restored.thinkingLevel : void 0;
|
|
61500
|
-
if (thinkingLevel) {
|
|
61501
|
-
options.agent.setThinkingLevel(thinkingLevel);
|
|
61502
|
-
}
|
|
61503
|
-
let apiKey;
|
|
61504
|
-
if (restored.model) {
|
|
61505
|
-
options.agent.setModel(restored.model);
|
|
61506
|
-
apiKey = options.registry.getApiKey(restored.model);
|
|
61507
|
-
if (apiKey) {
|
|
61508
|
-
options.agent.apiKey = apiKey;
|
|
61509
|
-
}
|
|
61510
|
-
}
|
|
61511
|
-
return {
|
|
61512
|
-
model: restored.model,
|
|
61513
|
-
apiKey,
|
|
61514
|
-
thinkingLevel,
|
|
61515
|
-
fallbackMessage: restored.fallbackMessage
|
|
61516
|
-
};
|
|
61517
|
-
}
|
|
61518
|
-
|
|
61519
62350
|
// src/core/session-display.ts
|
|
61520
62351
|
function deriveSessionTitle(options) {
|
|
61521
62352
|
const { activeSession, messages } = options;
|
|
@@ -61833,23 +62664,30 @@ var BUILTIN_SLASH_COMMANDS = [
|
|
|
61833
62664
|
{ name: "sessions/info", description: "Show session info" },
|
|
61834
62665
|
{ name: "sessions/fork", description: "Fork from a message" },
|
|
61835
62666
|
{ name: "settings", description: "Open settings menu" },
|
|
61836
|
-
{ name: "
|
|
62667
|
+
{ name: "extensions", description: "Manage extensions (list/enable/disable)" },
|
|
62668
|
+
{ name: "extensions/list", description: "List discovered extensions (including disabled)" },
|
|
62669
|
+
{ name: "extensions/enable", description: "Enable an extension by identity (writes settings)" },
|
|
62670
|
+
{ name: "extensions/disable", description: "Disable an extension by identity (writes settings)" },
|
|
61837
62671
|
{ name: "settings/help", description: "Show help information (keyboard shortcuts and commands)" },
|
|
61838
62672
|
{ name: "settings/hotkeys", description: "Show keyboard shortcuts" },
|
|
61839
62673
|
{ name: "settings/model", description: "Select AI model" },
|
|
61840
62674
|
{ name: "settings/theme", description: "Change theme" },
|
|
61841
62675
|
{ name: "settings/thinking", description: "Set thinking level" },
|
|
61842
62676
|
{ name: "settings/calm", description: "Toggle calm mode: show only questions and answers" },
|
|
61843
|
-
{ name: "calm", description: "Alias for /settings/calm" },
|
|
61844
62677
|
{ name: "settings/yolo", description: "Toggle or set YOLO mode" },
|
|
61845
|
-
{ name: "
|
|
61846
|
-
{ name: "
|
|
61847
|
-
{ name: "
|
|
62678
|
+
{ name: "debugs/cache-test", description: "Run provider cache diagnostics with a dedicated 2-request probe" },
|
|
62679
|
+
{ name: "debugs/context", description: "Append a context summary to ~/.pie/logs/pie-cli.log" },
|
|
62680
|
+
{ name: "debugs/package", description: "Append a package summary to ~/.pie/logs/pie-cli.log" },
|
|
61848
62681
|
{ name: "settings/quit", description: "Exit Pie" },
|
|
61849
62682
|
{ name: "skills", description: "Open skills menu" },
|
|
61850
62683
|
{ name: "skills/list", description: "List available skills" },
|
|
62684
|
+
{ name: "skills/enable", description: "Enable a skill by name" },
|
|
62685
|
+
{ name: "skills/disable", description: "Disable a skill by name" },
|
|
61851
62686
|
{ name: "skills/reload", description: "Reload skills from disk" },
|
|
61852
62687
|
{ name: "skills/use", description: "Use a skill" },
|
|
62688
|
+
{ name: "tools", description: "List tools and manage enable/disable toggles" },
|
|
62689
|
+
{ name: "tools/enable", description: "Enable a tool by name" },
|
|
62690
|
+
{ name: "tools/disable", description: "Disable a tool by name" },
|
|
61853
62691
|
{ name: "tools/subagent", description: "Spawn subagents in parallel to handle tasks" }
|
|
61854
62692
|
];
|
|
61855
62693
|
|
|
@@ -63959,7 +64797,7 @@ async function handleResumeCommand(host) {
|
|
|
63959
64797
|
return { component: selector, focus: selector.getSelectList() };
|
|
63960
64798
|
});
|
|
63961
64799
|
}
|
|
63962
|
-
async function
|
|
64800
|
+
async function loadSession2(host, sessionId) {
|
|
63963
64801
|
const beforeSwitch = await host.extensionRunner?.emitSessionBeforeSwitch({
|
|
63964
64802
|
type: "session:before_switch",
|
|
63965
64803
|
reason: "resume",
|
|
@@ -64432,6 +65270,14 @@ function handleSkillsCommand(host) {
|
|
|
64432
65270
|
host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${skill.name}: ${skill.description}`), 1, 0));
|
|
64433
65271
|
}
|
|
64434
65272
|
}
|
|
65273
|
+
const disabledNames = Object.entries(host.options.settingsManager.getSkillSettings()).filter(([, entry]) => entry === false || entry && typeof entry === "object" && entry.enabled === false).map(([name]) => name).filter((name) => !host.skills.some((skill) => skill.name === name));
|
|
65274
|
+
if (disabledNames.length > 0) {
|
|
65275
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
65276
|
+
host.chatContainer.addChild(new Text(theme.fg("dim", "Disabled skills:"), 1, 0));
|
|
65277
|
+
for (const name of disabledNames) {
|
|
65278
|
+
host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${name} (disabled; /skills/enable ${name})`), 1, 0));
|
|
65279
|
+
}
|
|
65280
|
+
}
|
|
64435
65281
|
host.chatContainer.addChild(new Spacer(1));
|
|
64436
65282
|
host.chatContainer.addChild(new Text(theme.fg("dim", "Usage: /skills/skill:<name> <your request>"), 1, 0));
|
|
64437
65283
|
host.chatContainer.addChild(new Text(theme.fg("dim", "Example: /skills/skill:browser-tools navigate to google.com"), 1, 0));
|
|
@@ -64458,7 +65304,11 @@ function handleSkillCommand(host, name) {
|
|
|
64458
65304
|
async function handleSkillInvoke(host, skillName, args) {
|
|
64459
65305
|
const skill = host.skills.find((s) => s.name === skillName);
|
|
64460
65306
|
if (!skill) {
|
|
64461
|
-
host.
|
|
65307
|
+
if (!host.options.settingsManager.isSkillEnabled(skillName)) {
|
|
65308
|
+
host.showError(`Skill disabled: ${skillName}. Use /skills/enable ${skillName} to restore it.`);
|
|
65309
|
+
} else {
|
|
65310
|
+
host.showError(`Skill not found: ${skillName}`);
|
|
65311
|
+
}
|
|
64462
65312
|
return;
|
|
64463
65313
|
}
|
|
64464
65314
|
const skillText = `skill:${skillName} ${args}`.trim();
|
|
@@ -64542,6 +65392,30 @@ function stripFrontmatter(host, content) {
|
|
|
64542
65392
|
}
|
|
64543
65393
|
return content;
|
|
64544
65394
|
}
|
|
65395
|
+
async function handleSkillToggleCommand(host, args, enabled) {
|
|
65396
|
+
const name = args.trim();
|
|
65397
|
+
if (!name) {
|
|
65398
|
+
host.showError(`Usage: /skills/${enabled ? "enable" : "disable"} <name>`);
|
|
65399
|
+
return;
|
|
65400
|
+
}
|
|
65401
|
+
const builtinDir = path25.join(getBuiltinDir(), "skills");
|
|
65402
|
+
const userDir = path25.join(os7.homedir(), ".pie", "skills");
|
|
65403
|
+
const projectDir = path25.join(process.cwd(), ".pie", "skills");
|
|
65404
|
+
const discovered = loadSkills({ dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: process.cwd() }) }).skills;
|
|
65405
|
+
if (!discovered.some((skill) => skill.name === name)) {
|
|
65406
|
+
host.showError(`Skill not found: ${name}`);
|
|
65407
|
+
return;
|
|
65408
|
+
}
|
|
65409
|
+
try {
|
|
65410
|
+
host.options.settingsManager.setSkillEnabled(name, enabled);
|
|
65411
|
+
} catch (error) {
|
|
65412
|
+
host.showError(`Failed to update skill "${name}": ${errorMessage2(error)}`);
|
|
65413
|
+
return;
|
|
65414
|
+
}
|
|
65415
|
+
await handleSkillsReload(host);
|
|
65416
|
+
host.chatContainer.addChild(new Text(theme.fg("accent", `Skill "${name}" ${enabled ? "enabled" : "disabled"} in ~/.pie/settings.json`), 1, 0));
|
|
65417
|
+
host.ui.requestRender();
|
|
65418
|
+
}
|
|
64545
65419
|
async function handleSkillsCreate(host, args) {
|
|
64546
65420
|
console.error(`[SkillsCreate] Called with args: "${args}"`);
|
|
64547
65421
|
try {
|
|
@@ -64637,7 +65511,7 @@ async function handleSkillsReload(host) {
|
|
|
64637
65511
|
const userDir = path25.join(os7.homedir(), ".pie", "skills");
|
|
64638
65512
|
const projectDir = path25.join(process.cwd(), ".pie", "skills");
|
|
64639
65513
|
const result = loadSkills({ dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: process.cwd() }) });
|
|
64640
|
-
host.skills = result.skills;
|
|
65514
|
+
host.skills = result.skills.filter((skill) => host.options.settingsManager.isSkillEnabled(skill.name));
|
|
64641
65515
|
host.skillsSection = formatSkillsForPrompt(host.skills);
|
|
64642
65516
|
host.applyRuntimeToolMode(host.allTools.length > 0 ? host.allTools : host.agent.state.tools);
|
|
64643
65517
|
host.updateSystemPromptTools();
|
|
@@ -64672,6 +65546,67 @@ async function handleSkillsReload(host) {
|
|
|
64672
65546
|
}
|
|
64673
65547
|
}
|
|
64674
65548
|
|
|
65549
|
+
// src/commands/interactive-tools-command.ts
|
|
65550
|
+
function errorMessage3(error) {
|
|
65551
|
+
return error instanceof Error ? error.message : String(error);
|
|
65552
|
+
}
|
|
65553
|
+
function collectKnownToolNames(host) {
|
|
65554
|
+
const liveNames = (host.allTools.length > 0 ? host.allTools : host.agent?.state.tools ?? []).map((tool) => tool.name);
|
|
65555
|
+
const disabledNames = host.options.settingsManager.getDisabledTools();
|
|
65556
|
+
const disabled = disabledNames.filter((name) => !liveNames.includes(name));
|
|
65557
|
+
return { active: [...liveNames].sort(), disabled: [...disabled].sort() };
|
|
65558
|
+
}
|
|
65559
|
+
function handleToolsCommand(host, args) {
|
|
65560
|
+
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
65561
|
+
const subcommand = parts[0];
|
|
65562
|
+
if (subcommand === "enable" || subcommand === "disable") {
|
|
65563
|
+
const name = parts.slice(1).join(" ").trim();
|
|
65564
|
+
if (!name) {
|
|
65565
|
+
host.showError(`Usage: /tools ${subcommand} <tool-name>`);
|
|
65566
|
+
return;
|
|
65567
|
+
}
|
|
65568
|
+
const { active: active2, disabled: disabled2 } = collectKnownToolNames(host);
|
|
65569
|
+
if (!active2.includes(name) && !disabled2.includes(name)) {
|
|
65570
|
+
host.showError(`Tool not found: ${name}. Use /tools to list tool names.`);
|
|
65571
|
+
return;
|
|
65572
|
+
}
|
|
65573
|
+
const enabled = subcommand === "enable";
|
|
65574
|
+
try {
|
|
65575
|
+
host.options.settingsManager.setToolEnabled(name, enabled);
|
|
65576
|
+
} catch (error) {
|
|
65577
|
+
host.showError(`Failed to update tool "${name}": ${errorMessage3(error)}`);
|
|
65578
|
+
return;
|
|
65579
|
+
}
|
|
65580
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
65581
|
+
host.chatContainer.addChild(new Text(
|
|
65582
|
+
theme.fg("accent", `Tool "${name}" ${enabled ? "enabled" : "disabled"} in ~/.pie/settings.json. Takes effect on next start.`),
|
|
65583
|
+
1,
|
|
65584
|
+
0
|
|
65585
|
+
));
|
|
65586
|
+
host.ui.requestRender();
|
|
65587
|
+
return;
|
|
65588
|
+
}
|
|
65589
|
+
if (subcommand) {
|
|
65590
|
+
host.showError("Usage: /tools [enable|disable <tool-name>]");
|
|
65591
|
+
return;
|
|
65592
|
+
}
|
|
65593
|
+
const { active, disabled } = collectKnownToolNames(host);
|
|
65594
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
65595
|
+
host.chatContainer.addChild(new Text(theme.bold("Tools"), 1, 0));
|
|
65596
|
+
if (active.length === 0 && disabled.length === 0) {
|
|
65597
|
+
host.chatContainer.addChild(new Text(theme.fg("dim", " No tools available."), 1, 0));
|
|
65598
|
+
}
|
|
65599
|
+
for (const name of active) {
|
|
65600
|
+
host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${name}: enabled`), 1, 0));
|
|
65601
|
+
}
|
|
65602
|
+
for (const name of disabled) {
|
|
65603
|
+
host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${name}: disabled (/tools/enable ${name})`), 1, 0));
|
|
65604
|
+
}
|
|
65605
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
65606
|
+
host.chatContainer.addChild(new Text(theme.fg("dim", "Usage: /tools/enable <name> | /tools/disable <name> (takes effect on next start)"), 1, 0));
|
|
65607
|
+
host.ui.requestRender();
|
|
65608
|
+
}
|
|
65609
|
+
|
|
64675
65610
|
// src/commands/interactive-command-handlers.ts
|
|
64676
65611
|
function showSettingsSelector(host) {
|
|
64677
65612
|
host.showSelector((done) => {
|
|
@@ -65272,23 +66207,19 @@ function registerBuiltinCommands(host) {
|
|
|
65272
66207
|
description: "Toggle calm mode: show only questions and answers (on/off/status)",
|
|
65273
66208
|
handler: (_2, args) => host.handleCalmCommand(args)
|
|
65274
66209
|
});
|
|
65275
|
-
commandTree.register(["
|
|
65276
|
-
description: "Alias for /settings/calm (questions and answers only)",
|
|
65277
|
-
handler: (_2, args) => host.handleCalmCommand(args)
|
|
65278
|
-
});
|
|
65279
|
-
commandTree.register(["settings", "extensions"], {
|
|
66210
|
+
commandTree.register(["extensions"], {
|
|
65280
66211
|
description: "List extensions and manage enable/disable toggles",
|
|
65281
66212
|
handler: (_2, args) => host.handleExtensionsCommand(args)
|
|
65282
66213
|
});
|
|
65283
|
-
commandTree.register(["
|
|
66214
|
+
commandTree.register(["extensions", "list"], {
|
|
65284
66215
|
description: "List discovered extensions (including disabled)",
|
|
65285
66216
|
handler: (_2, args) => host.handleExtensionsCommand(args ? `list ${args}` : "list")
|
|
65286
66217
|
});
|
|
65287
|
-
commandTree.register(["
|
|
66218
|
+
commandTree.register(["extensions", "enable"], {
|
|
65288
66219
|
description: "Enable an extension by identity (writes settings)",
|
|
65289
66220
|
handler: (_2, args) => host.handleExtensionsCommand(`enable ${args || ""}`)
|
|
65290
66221
|
});
|
|
65291
|
-
commandTree.register(["
|
|
66222
|
+
commandTree.register(["extensions", "disable"], {
|
|
65292
66223
|
description: "Disable an extension by identity (writes settings)",
|
|
65293
66224
|
handler: (_2, args) => host.handleExtensionsCommand(`disable ${args || ""}`)
|
|
65294
66225
|
});
|
|
@@ -65306,6 +66237,14 @@ function registerBuiltinCommands(host) {
|
|
|
65306
66237
|
await host.handleSkillsReload();
|
|
65307
66238
|
}
|
|
65308
66239
|
});
|
|
66240
|
+
commandTree.register(["skills", "enable"], {
|
|
66241
|
+
description: "Enable a skill by name (writes settings, reloads immediately)",
|
|
66242
|
+
handler: (_2, args) => host.handleSkillToggleCommand(args || "", true)
|
|
66243
|
+
});
|
|
66244
|
+
commandTree.register(["skills", "disable"], {
|
|
66245
|
+
description: "Disable a skill by name (writes settings, reloads immediately)",
|
|
66246
|
+
handler: (_2, args) => host.handleSkillToggleCommand(args || "", false)
|
|
66247
|
+
});
|
|
65309
66248
|
for (const skill of host.skills) {
|
|
65310
66249
|
commandTree.register(["skills", `skill:${skill.name}`], {
|
|
65311
66250
|
description: skill.description,
|
|
@@ -65316,15 +66255,27 @@ function registerBuiltinCommands(host) {
|
|
|
65316
66255
|
description: "Spawn subagents in parallel to handle tasks",
|
|
65317
66256
|
handler: (_2, args) => host.handleSubagentCommand(args || "")
|
|
65318
66257
|
});
|
|
65319
|
-
commandTree.register(["
|
|
66258
|
+
commandTree.register(["tools"], {
|
|
66259
|
+
description: "List runtime tools and manage enable/disable toggles",
|
|
66260
|
+
handler: (_2, args) => host.handleToolsCommand(args || "")
|
|
66261
|
+
});
|
|
66262
|
+
commandTree.register(["tools", "enable"], {
|
|
66263
|
+
description: "Enable a tool by name (writes settings; next start)",
|
|
66264
|
+
handler: (_2, args) => host.handleToolsCommand(`enable ${args || ""}`)
|
|
66265
|
+
});
|
|
66266
|
+
commandTree.register(["tools", "disable"], {
|
|
66267
|
+
description: "Disable a tool by name (writes settings; next start)",
|
|
66268
|
+
handler: (_2, args) => host.handleToolsCommand(`disable ${args || ""}`)
|
|
66269
|
+
});
|
|
66270
|
+
commandTree.register(["debugs", "cache-test"], {
|
|
65320
66271
|
description: "Run provider cache diagnostics with a dedicated 2-request probe",
|
|
65321
66272
|
handler: () => host.handleCacheTest()
|
|
65322
66273
|
});
|
|
65323
|
-
commandTree.register(["
|
|
66274
|
+
commandTree.register(["debugs", "context"], {
|
|
65324
66275
|
description: "Append a context summary to ~/.pie/logs/pie-cli.log",
|
|
65325
66276
|
handler: () => host.handleDebugContextCommand()
|
|
65326
66277
|
});
|
|
65327
|
-
commandTree.register(["
|
|
66278
|
+
commandTree.register(["debugs", "package"], {
|
|
65328
66279
|
description: "Append a package summary to ~/.pie/logs/pie-cli.log",
|
|
65329
66280
|
handler: () => host.handleDebugPackageCommand()
|
|
65330
66281
|
});
|
|
@@ -66243,7 +67194,7 @@ function setupInteractiveEditorSubmitHandler(host) {
|
|
|
66243
67194
|
host.ui.requestRender();
|
|
66244
67195
|
await new Promise((resolve7) => setImmediate(resolve7));
|
|
66245
67196
|
let finalContent = messageContent;
|
|
66246
|
-
const reminderPrefix = host.executionReminder;
|
|
67197
|
+
const reminderPrefix = host.executionState.getReminder() ?? host.executionReminder;
|
|
66247
67198
|
const combinedPrefix = [reminderPrefix].filter((value) => Boolean(value)).join("");
|
|
66248
67199
|
if (combinedPrefix) {
|
|
66249
67200
|
if (typeof messageContent === "string") {
|
|
@@ -67207,17 +68158,17 @@ var MentionHandler = class {
|
|
|
67207
68158
|
} catch (err) {
|
|
67208
68159
|
this.onInsertMention("", pendingMention);
|
|
67209
68160
|
this.clearPendingStatus(pendingStatusKey);
|
|
67210
|
-
const
|
|
67211
|
-
if (
|
|
68161
|
+
const errorMessage4 = err instanceof Error ? err.message : String(err);
|
|
68162
|
+
if (errorMessage4.includes("PLATFORM_NOT_SUPPORTED")) {
|
|
67212
68163
|
this.onError?.("The current AI model does not support file uploads.");
|
|
67213
|
-
} else if (
|
|
68164
|
+
} else if (errorMessage4.includes("ENOENT")) {
|
|
67214
68165
|
this.onError?.("File does not exist or cannot be accessed.");
|
|
67215
|
-
} else if (
|
|
68166
|
+
} else if (errorMessage4.includes("EACCES") || errorMessage4.includes("PERMISSION")) {
|
|
67216
68167
|
this.onError?.("Permission denied while accessing the file.");
|
|
67217
|
-
} else if (
|
|
68168
|
+
} else if (errorMessage4.includes("network") || errorMessage4.includes("ETIMEDOUT") || errorMessage4.includes("ECONNREFUSED")) {
|
|
67218
68169
|
this.onError?.("Network error. Check the connection and try again.");
|
|
67219
68170
|
} else {
|
|
67220
|
-
this.onError?.(`Upload failed: ${
|
|
68171
|
+
this.onError?.(`Upload failed: ${errorMessage4}`);
|
|
67221
68172
|
}
|
|
67222
68173
|
} finally {
|
|
67223
68174
|
this.clearPendingStatus(pendingStatusKey);
|
|
@@ -68417,8 +69368,8 @@ function calculateCliContextUsage(params) {
|
|
|
68417
69368
|
};
|
|
68418
69369
|
}
|
|
68419
69370
|
function createCliAutoCompactDecision(params) {
|
|
68420
|
-
const
|
|
68421
|
-
if (
|
|
69371
|
+
const errorMessage4 = params.message?.role === "assistant" ? params.message.errorMessage : void 0;
|
|
69372
|
+
if (errorMessage4 && params.isContextOverflowError(errorMessage4)) {
|
|
68422
69373
|
return { reason: "overflow", willRetry: true };
|
|
68423
69374
|
}
|
|
68424
69375
|
if (!params.autoCompactEnabled || params.contextWindow <= 0) {
|
|
@@ -68504,9 +69455,9 @@ var INVALID_FILE_REFERENCE_PATTERN = /not the owner of this file|owner of this f
|
|
|
68504
69455
|
var INVALID_REQUEST_PATTERN = /bad request|\b400\b|invalid request|invalid schema|schema validation|invalid parameter|unsupported parameter|malformed/i;
|
|
68505
69456
|
var CLI_RETRY_MAX_RETRIES = 3;
|
|
68506
69457
|
var CLI_RETRY_BASE_DELAY_MS = 2e3;
|
|
68507
|
-
function isCliContextOverflowError(
|
|
69458
|
+
function isCliContextOverflowError(errorMessage4) {
|
|
68508
69459
|
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(
|
|
68509
|
-
|
|
69460
|
+
errorMessage4
|
|
68510
69461
|
);
|
|
68511
69462
|
}
|
|
68512
69463
|
function createClassification(kind, message, overrides) {
|
|
@@ -68521,56 +69472,56 @@ function createClassification(kind, message, overrides) {
|
|
|
68521
69472
|
};
|
|
68522
69473
|
}
|
|
68523
69474
|
function classifyCliFailure(context) {
|
|
68524
|
-
const
|
|
68525
|
-
if (isCliContextOverflowError(
|
|
68526
|
-
return createClassification("context_overflow",
|
|
69475
|
+
const errorMessage4 = typeof context === "string" ? context : context.errorMessage;
|
|
69476
|
+
if (isCliContextOverflowError(errorMessage4)) {
|
|
69477
|
+
return createClassification("context_overflow", errorMessage4, {
|
|
68527
69478
|
compactable: true,
|
|
68528
69479
|
terminal: false
|
|
68529
69480
|
});
|
|
68530
69481
|
}
|
|
68531
|
-
if (USER_ABORT_PATTERN.test(
|
|
68532
|
-
return createClassification("user_abort",
|
|
69482
|
+
if (USER_ABORT_PATTERN.test(errorMessage4)) {
|
|
69483
|
+
return createClassification("user_abort", errorMessage4, {
|
|
68533
69484
|
userAbort: true,
|
|
68534
69485
|
terminal: false
|
|
68535
69486
|
});
|
|
68536
69487
|
}
|
|
68537
|
-
if (INVALID_FILE_REFERENCE_PATTERN.test(
|
|
68538
|
-
return createClassification("invalid_file_reference",
|
|
69488
|
+
if (INVALID_FILE_REFERENCE_PATTERN.test(errorMessage4)) {
|
|
69489
|
+
return createClassification("invalid_file_reference", errorMessage4);
|
|
68539
69490
|
}
|
|
68540
|
-
if (AUTH_CONFIG_PATTERN.test(
|
|
68541
|
-
return createClassification("auth_config",
|
|
69491
|
+
if (AUTH_CONFIG_PATTERN.test(errorMessage4)) {
|
|
69492
|
+
return createClassification("auth_config", errorMessage4);
|
|
68542
69493
|
}
|
|
68543
|
-
if (TRANSIENT_NETWORK_ERROR_PATTERN.test(
|
|
68544
|
-
return createClassification("transient_network",
|
|
69494
|
+
if (TRANSIENT_NETWORK_ERROR_PATTERN.test(errorMessage4)) {
|
|
69495
|
+
return createClassification("transient_network", errorMessage4, {
|
|
68545
69496
|
retryable: true,
|
|
68546
69497
|
terminal: false
|
|
68547
69498
|
});
|
|
68548
69499
|
}
|
|
68549
|
-
if (
|
|
68550
|
-
return createClassification("provider_transient",
|
|
69500
|
+
if (errorMessage4.includes(EMPTY_ASSISTANT_CONTENT_ERROR)) {
|
|
69501
|
+
return createClassification("provider_transient", errorMessage4, {
|
|
68551
69502
|
retryable: true,
|
|
68552
69503
|
terminal: false
|
|
68553
69504
|
});
|
|
68554
69505
|
}
|
|
68555
|
-
if (
|
|
68556
|
-
return createClassification("provider_transient",
|
|
69506
|
+
if (errorMessage4.includes(OPENAI_COMPAT_PROTOCOL_ERROR_CODE)) {
|
|
69507
|
+
return createClassification("provider_transient", errorMessage4, {
|
|
68557
69508
|
retryable: true,
|
|
68558
69509
|
terminal: false
|
|
68559
69510
|
});
|
|
68560
69511
|
}
|
|
68561
|
-
if (PROVIDER_TRANSIENT_ERROR_PATTERN.test(
|
|
68562
|
-
return createClassification("provider_transient",
|
|
69512
|
+
if (PROVIDER_TRANSIENT_ERROR_PATTERN.test(errorMessage4)) {
|
|
69513
|
+
return createClassification("provider_transient", errorMessage4, {
|
|
68563
69514
|
retryable: true,
|
|
68564
69515
|
terminal: false
|
|
68565
69516
|
});
|
|
68566
69517
|
}
|
|
68567
|
-
if (INVALID_REQUEST_PATTERN.test(
|
|
68568
|
-
return createClassification("invalid_request",
|
|
69518
|
+
if (INVALID_REQUEST_PATTERN.test(errorMessage4)) {
|
|
69519
|
+
return createClassification("invalid_request", errorMessage4);
|
|
68569
69520
|
}
|
|
68570
|
-
return createClassification("unknown",
|
|
69521
|
+
return createClassification("unknown", errorMessage4);
|
|
68571
69522
|
}
|
|
68572
|
-
function isCliRetryableError(
|
|
68573
|
-
return classifyCliFailure(
|
|
69523
|
+
function isCliRetryableError(errorMessage4) {
|
|
69524
|
+
return classifyCliFailure(errorMessage4).retryable;
|
|
68574
69525
|
}
|
|
68575
69526
|
function getCliRetryBaseDelayMs() {
|
|
68576
69527
|
const override = process.env.PIE_TEST_CLI_RETRY_BASE_DELAY_MS;
|
|
@@ -68743,23 +69694,23 @@ function setupAutocomplete(host) {
|
|
|
68743
69694
|
};
|
|
68744
69695
|
host.editor.setAutocompleteProvider(provider);
|
|
68745
69696
|
}
|
|
68746
|
-
function isContextOverflowError(
|
|
68747
|
-
return isCliContextOverflowError(
|
|
69697
|
+
function isContextOverflowError(errorMessage4) {
|
|
69698
|
+
return isCliContextOverflowError(errorMessage4);
|
|
68748
69699
|
}
|
|
68749
69700
|
function shouldAutoCompact(host, contextTokens, contextWindow) {
|
|
68750
69701
|
if (!host.options.settingsManager.getAutoCompactEnabled()) return false;
|
|
68751
69702
|
const reserveTokens = host.options.settingsManager.getAutoCompactReserveTokens();
|
|
68752
69703
|
return shouldCliAutoCompactTokens({ tokens: contextTokens, contextWindow, reserveTokens });
|
|
68753
69704
|
}
|
|
68754
|
-
function isRetryableError(
|
|
68755
|
-
return isCliRetryableError(
|
|
69705
|
+
function isRetryableError(errorMessage4) {
|
|
69706
|
+
return isCliRetryableError(errorMessage4);
|
|
68756
69707
|
}
|
|
68757
|
-
function isInvalidFileReferenceError(
|
|
69708
|
+
function isInvalidFileReferenceError(errorMessage4) {
|
|
68758
69709
|
return /not the owner of this file|owner of this file|invalid_authentication_error/i.test(
|
|
68759
|
-
|
|
69710
|
+
errorMessage4
|
|
68760
69711
|
);
|
|
68761
69712
|
}
|
|
68762
|
-
function recoverFromInvalidFileReferenceError(host,
|
|
69713
|
+
function recoverFromInvalidFileReferenceError(host, errorMessage4) {
|
|
68763
69714
|
if (!host.fileManager || !host.agent) return;
|
|
68764
69715
|
const messages = host.agent.state.messages.slice();
|
|
68765
69716
|
const invalidFileIds = /* @__PURE__ */ new Set();
|
|
@@ -68777,7 +69728,7 @@ function recoverFromInvalidFileReferenceError(host, errorMessage3) {
|
|
|
68777
69728
|
}
|
|
68778
69729
|
if (invalidFileIds.size === 0) return;
|
|
68779
69730
|
for (const fileId of invalidFileIds) {
|
|
68780
|
-
host.fileManager.markFileReferenceError(fileId,
|
|
69731
|
+
host.fileManager.markFileReferenceError(fileId, errorMessage4);
|
|
68781
69732
|
}
|
|
68782
69733
|
let changed = false;
|
|
68783
69734
|
const sanitizedMessages = messages.map((message) => {
|
|
@@ -69055,9 +70006,9 @@ function showStatus(host, message) {
|
|
|
69055
70006
|
host.lastStatusText = text;
|
|
69056
70007
|
host.ui.requestRender();
|
|
69057
70008
|
}
|
|
69058
|
-
function showError(host,
|
|
70009
|
+
function showError(host, errorMessage4) {
|
|
69059
70010
|
host.chatContainer.addChild(new Spacer(1));
|
|
69060
|
-
host.chatContainer.addChild(new Text(theme.fg("error", `Error: ${
|
|
70011
|
+
host.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage4}`), 1, 0));
|
|
69061
70012
|
host.ui.requestRender();
|
|
69062
70013
|
}
|
|
69063
70014
|
async function executeCommand(host, command) {
|
|
@@ -69284,7 +70235,7 @@ function createInteractiveAgentSessionController(host) {
|
|
|
69284
70235
|
getAutoContinueMessage: () => host.getTodoAutoContinueMessage(),
|
|
69285
70236
|
classifyFailure: (context) => classifyCliFailure(context),
|
|
69286
70237
|
retry: {
|
|
69287
|
-
isRetryableError: (
|
|
70238
|
+
isRetryableError: (errorMessage4) => !host._isContextOverflowError(errorMessage4) && isCliRetryableError(errorMessage4),
|
|
69288
70239
|
maxRetries: CLI_RETRY_MAX_RETRIES,
|
|
69289
70240
|
baseDelayMs: getCliRetryBaseDelayMs()
|
|
69290
70241
|
},
|
|
@@ -69436,6 +70387,13 @@ function createInteractiveAgentSessionController(host) {
|
|
|
69436
70387
|
host.appendWarningSummary(outcome.terminalSummary);
|
|
69437
70388
|
}
|
|
69438
70389
|
host.setControllerBusy(false);
|
|
70390
|
+
} else if (event.type === "runtime_guard_advisory") {
|
|
70391
|
+
host.noteRuntimeGuardAdvisory(event);
|
|
70392
|
+
host.sessionTrace.noteRuntimeEvent("runtime_guard_advisory", {
|
|
70393
|
+
toolName: event.toolName,
|
|
70394
|
+
repeatCount: event.repeatCount,
|
|
70395
|
+
reason: event.reason
|
|
70396
|
+
});
|
|
69439
70397
|
} else if (event.type === "runtime_guard_triggered") {
|
|
69440
70398
|
host.sessionTrace.noteStalled("runtime_guard_triggered", {
|
|
69441
70399
|
toolName: event.toolName,
|
|
@@ -69636,6 +70594,43 @@ function createRuntimeModeTransformContext(options) {
|
|
|
69636
70594
|
};
|
|
69637
70595
|
}
|
|
69638
70596
|
|
|
70597
|
+
// src/runtime/guard-advisory-context.ts
|
|
70598
|
+
var GUARD_ADVISORY_MARKER = "<runtime-guard-advisory>";
|
|
70599
|
+
var GUARD_ADVISORY_END_MARKER = "</runtime-guard-advisory>";
|
|
70600
|
+
function isMarkerOnlyUserMessage(message) {
|
|
70601
|
+
if (message.role !== "user") return false;
|
|
70602
|
+
const content = message.content;
|
|
70603
|
+
const text = typeof content === "string" ? content : Array.isArray(content) && content.length === 1 && content[0]?.type === "text" ? content[0].text : "";
|
|
70604
|
+
return text.trim().startsWith(GUARD_ADVISORY_MARKER) && text.trim().endsWith(GUARD_ADVISORY_END_MARKER);
|
|
70605
|
+
}
|
|
70606
|
+
function stripGuardAdvisories(messages) {
|
|
70607
|
+
return messages.filter((message) => !isMarkerOnlyUserMessage(message));
|
|
70608
|
+
}
|
|
70609
|
+
function findLatestUserIndex2(messages) {
|
|
70610
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
70611
|
+
if (messages[index].role === "user") return index;
|
|
70612
|
+
}
|
|
70613
|
+
return -1;
|
|
70614
|
+
}
|
|
70615
|
+
function injectGuardAdvisory(messages, guidance) {
|
|
70616
|
+
const advisoryMessage = {
|
|
70617
|
+
role: "user",
|
|
70618
|
+
content: `${GUARD_ADVISORY_MARKER}
|
|
70619
|
+
${guidance}
|
|
70620
|
+
${GUARD_ADVISORY_END_MARKER}`,
|
|
70621
|
+
timestamp: Date.now()
|
|
70622
|
+
};
|
|
70623
|
+
const latestUserIndex = findLatestUserIndex2(messages);
|
|
70624
|
+
if (latestUserIndex < 0) {
|
|
70625
|
+
return [...messages, advisoryMessage];
|
|
70626
|
+
}
|
|
70627
|
+
return [
|
|
70628
|
+
...messages.slice(0, latestUserIndex),
|
|
70629
|
+
advisoryMessage,
|
|
70630
|
+
...messages.slice(latestUserIndex)
|
|
70631
|
+
];
|
|
70632
|
+
}
|
|
70633
|
+
|
|
69639
70634
|
// src/runtime/tool-policy.ts
|
|
69640
70635
|
function selectToolsForRuntimeMode(tools, mode) {
|
|
69641
70636
|
return selectToolsForRuntimePolicy(tools, mode);
|
|
@@ -70326,7 +71321,7 @@ async function loadInteractiveExtensions(host) {
|
|
|
70326
71321
|
console.error(`[Extension] Failed to load ${path33}: ${error}`);
|
|
70327
71322
|
}
|
|
70328
71323
|
}
|
|
70329
|
-
const extensionTools = convertExtensionTools(extensions);
|
|
71324
|
+
const extensionTools = filterEnabledTools(convertExtensionTools(extensions), host.options.settingsManager);
|
|
70330
71325
|
const activeTools = [...host.agent.state.tools, ...extensionTools];
|
|
70331
71326
|
host.agent.state.tools = wrapToolsWithExtensions(activeTools, host.extensionRunner);
|
|
70332
71327
|
const availableTools = [
|
|
@@ -70395,12 +71390,13 @@ var InteractiveMode = class {
|
|
|
70395
71390
|
isProcessing = false;
|
|
70396
71391
|
_turnIndex = 0;
|
|
70397
71392
|
_semanticTurnIndex = 0;
|
|
70398
|
-
thinkingLevel =
|
|
71393
|
+
thinkingLevel = DEFAULT_THINKING_LEVEL;
|
|
70399
71394
|
toolOutputExpanded = false;
|
|
70400
71395
|
planModeEnabled = false;
|
|
70401
71396
|
pendingPlanModeTransition = null;
|
|
70402
71397
|
pendingYoloModeTransition = null;
|
|
70403
71398
|
executionReminder = null;
|
|
71399
|
+
pendingRuntimeGuardAdvisory = null;
|
|
70404
71400
|
fileManager;
|
|
70405
71401
|
mentionHandler;
|
|
70406
71402
|
mentionPickerComponent;
|
|
@@ -70710,12 +71706,9 @@ var InteractiveMode = class {
|
|
|
70710
71706
|
});
|
|
70711
71707
|
}
|
|
70712
71708
|
async init() {
|
|
70713
|
-
const savedLevel = this.options.settingsManager.getDefaultThinkingLevel();
|
|
70714
|
-
if (savedLevel) {
|
|
70715
|
-
this.thinkingLevel = savedLevel;
|
|
70716
|
-
}
|
|
70717
|
-
const { Agent } = await import("./chunks/src-HYZFAW4V.js");
|
|
70718
71709
|
const activeSession = this.sessionManager.getActiveSession();
|
|
71710
|
+
this.thinkingLevel = resolveInitialThinkingLevel({ session: activeSession, settingsManager: this.options.settingsManager });
|
|
71711
|
+
const { Agent } = await import("./chunks/src-HYZFAW4V.js");
|
|
70719
71712
|
this.agent = new Agent({
|
|
70720
71713
|
initialState: {
|
|
70721
71714
|
systemPrompt: this.buildSystemPrompt(),
|
|
@@ -70726,20 +71719,27 @@ var InteractiveMode = class {
|
|
|
70726
71719
|
apiKey: this.options.apiKey,
|
|
70727
71720
|
sessionId: activeSession?.id,
|
|
70728
71721
|
streamFn: this.options.streamFn,
|
|
70729
|
-
transformContext:
|
|
70730
|
-
|
|
70731
|
-
|
|
70732
|
-
|
|
70733
|
-
|
|
70734
|
-
|
|
70735
|
-
|
|
70736
|
-
|
|
70737
|
-
|
|
70738
|
-
|
|
70739
|
-
|
|
70740
|
-
|
|
70741
|
-
|
|
70742
|
-
|
|
71722
|
+
transformContext: async (messages) => {
|
|
71723
|
+
const runtimeModeTransform = createRuntimeModeTransformContext({
|
|
71724
|
+
getState: () => this.getRuntimeModeState(),
|
|
71725
|
+
consumeTransition: () => this.consumeRuntimeModeTransition(),
|
|
71726
|
+
onInjected: (state) => this.sessionTrace.noteRuntimeEvent("runtime_context_injected", {
|
|
71727
|
+
yoloMode: state.yoloMode,
|
|
71728
|
+
planMode: state.planMode,
|
|
71729
|
+
filesystemScope: state.filesystemScope,
|
|
71730
|
+
pendingTransition: state.pendingTransition,
|
|
71731
|
+
currentDate: state.currentDate,
|
|
71732
|
+
timeZone: state.timeZone,
|
|
71733
|
+
activeToolCount: state.activeToolNames.length
|
|
71734
|
+
}),
|
|
71735
|
+
onStripped: (count) => this.sessionTrace.noteRuntimeEvent("stale_runtime_context_stripped", { count })
|
|
71736
|
+
});
|
|
71737
|
+
let transformed = await runtimeModeTransform(messages);
|
|
71738
|
+
const advisory = this.pendingRuntimeGuardAdvisory;
|
|
71739
|
+
this.pendingRuntimeGuardAdvisory = null;
|
|
71740
|
+
transformed = advisory ? injectGuardAdvisory(transformed, advisory) : stripGuardAdvisories(transformed);
|
|
71741
|
+
return transformed;
|
|
71742
|
+
}
|
|
70743
71743
|
});
|
|
70744
71744
|
this.agentSessionController = createInteractiveAgentSessionController(this.controllerSetupHost);
|
|
70745
71745
|
this.updateTerminalTitle();
|
|
@@ -70842,6 +71842,10 @@ var InteractiveMode = class {
|
|
|
70842
71842
|
calculateContextUsage() {
|
|
70843
71843
|
return calculateContextUsage(this.contextUiHost);
|
|
70844
71844
|
}
|
|
71845
|
+
noteRuntimeGuardAdvisory(event) {
|
|
71846
|
+
this.pendingRuntimeGuardAdvisory = event.guidance;
|
|
71847
|
+
this.showStatus(`Runtime guard: ${event.toolName} failed ${event.repeatCount}x identically; advisory queued for next request.`);
|
|
71848
|
+
}
|
|
70845
71849
|
persistExecutionState() {
|
|
70846
71850
|
const activeSession = this.sessionManager.getActiveSession();
|
|
70847
71851
|
if (!activeSession) return;
|
|
@@ -70870,20 +71874,20 @@ var InteractiveMode = class {
|
|
|
70870
71874
|
setupAgentSubscription() {
|
|
70871
71875
|
bindInteractiveRuntimeEvents(this.runtimeEventHost);
|
|
70872
71876
|
}
|
|
70873
|
-
_isContextOverflowError(
|
|
70874
|
-
return isContextOverflowError(
|
|
71877
|
+
_isContextOverflowError(errorMessage4) {
|
|
71878
|
+
return isContextOverflowError(errorMessage4);
|
|
70875
71879
|
}
|
|
70876
71880
|
_shouldAutoCompact(contextTokens, contextWindow) {
|
|
70877
71881
|
return shouldAutoCompact(this.contextUiHost, contextTokens, contextWindow);
|
|
70878
71882
|
}
|
|
70879
|
-
_isRetryableError(
|
|
70880
|
-
return isRetryableError(
|
|
71883
|
+
_isRetryableError(errorMessage4) {
|
|
71884
|
+
return isRetryableError(errorMessage4);
|
|
70881
71885
|
}
|
|
70882
|
-
_isInvalidFileReferenceError(
|
|
70883
|
-
return isInvalidFileReferenceError(
|
|
71886
|
+
_isInvalidFileReferenceError(errorMessage4) {
|
|
71887
|
+
return isInvalidFileReferenceError(errorMessage4);
|
|
70884
71888
|
}
|
|
70885
|
-
_recoverFromInvalidFileReferenceError(
|
|
70886
|
-
return recoverFromInvalidFileReferenceError(this.contextUiHost,
|
|
71889
|
+
_recoverFromInvalidFileReferenceError(errorMessage4) {
|
|
71890
|
+
return recoverFromInvalidFileReferenceError(this.contextUiHost, errorMessage4);
|
|
70887
71891
|
}
|
|
70888
71892
|
async handleCompactCommand() {
|
|
70889
71893
|
return handleCompactCommand(this.compactCommandHost);
|
|
@@ -70932,7 +71936,7 @@ var InteractiveMode = class {
|
|
|
70932
71936
|
this.todoWidget.setCalmMode(enabled);
|
|
70933
71937
|
this.extensionWidgets.setCalmMode(enabled);
|
|
70934
71938
|
this.showStatus(`Calm mode ${enabled ? "on \u2014 showing questions and answers only" : "off"}`);
|
|
70935
|
-
this.safeRequestRender();
|
|
71939
|
+
this.safeRequestRender(true);
|
|
70936
71940
|
}
|
|
70937
71941
|
async handleCalmCommand(args) {
|
|
70938
71942
|
return handleCalmCommand(this, args);
|
|
@@ -70974,7 +71978,7 @@ var InteractiveMode = class {
|
|
|
70974
71978
|
return handleResumeCommand(this);
|
|
70975
71979
|
}
|
|
70976
71980
|
async loadSession(sessionId) {
|
|
70977
|
-
return
|
|
71981
|
+
return loadSession2(this, sessionId);
|
|
70978
71982
|
}
|
|
70979
71983
|
updateTerminalTitle() {
|
|
70980
71984
|
return updateTerminalTitle(this);
|
|
@@ -71036,6 +72040,12 @@ var InteractiveMode = class {
|
|
|
71036
72040
|
async handleSkillsReload() {
|
|
71037
72041
|
return handleSkillsReload(this);
|
|
71038
72042
|
}
|
|
72043
|
+
async handleSkillToggleCommand(args, enabled) {
|
|
72044
|
+
return handleSkillToggleCommand(this, args, enabled);
|
|
72045
|
+
}
|
|
72046
|
+
handleToolsCommand(args) {
|
|
72047
|
+
return handleToolsCommand(this, args);
|
|
72048
|
+
}
|
|
71039
72049
|
isInteractiveCommand(commandPath) {
|
|
71040
72050
|
const interactiveCommands = [
|
|
71041
72051
|
"/skills/create",
|
|
@@ -71054,8 +72064,8 @@ var InteractiveMode = class {
|
|
|
71054
72064
|
showStatus(message) {
|
|
71055
72065
|
return showStatus(this.uiHelperHost, message);
|
|
71056
72066
|
}
|
|
71057
|
-
showError(
|
|
71058
|
-
return showError(this.uiHelperHost,
|
|
72067
|
+
showError(errorMessage4) {
|
|
72068
|
+
return showError(this.uiHelperHost, errorMessage4);
|
|
71059
72069
|
}
|
|
71060
72070
|
async handleDirectBash(command) {
|
|
71061
72071
|
return handleDirectBash(this.directBashHost, command);
|
|
@@ -71229,8 +72239,8 @@ async function composeCliRuntime(params) {
|
|
|
71229
72239
|
} else {
|
|
71230
72240
|
await sessionManager.createSession();
|
|
71231
72241
|
}
|
|
71232
|
-
syncSessionModelMetadata(sessionManager, model, settingsManager.getDefaultThinkingLevel() || "off");
|
|
71233
72242
|
const activeSession = sessionManager.getActiveSession();
|
|
72243
|
+
syncSessionModelMetadata(sessionManager, model, resolveInitialThinkingLevel({ session: activeSession, settingsManager }));
|
|
71234
72244
|
if (activeSession && activeSession.metadata.cwd !== cwd) {
|
|
71235
72245
|
activeSession.metadata.cwd = cwd;
|
|
71236
72246
|
await sessionManager.save();
|
|
@@ -71247,7 +72257,7 @@ async function composeCliRuntime(params) {
|
|
|
71247
72257
|
keyPrefix: apiKey ? maskApiKey2(apiKey) : "none"
|
|
71248
72258
|
});
|
|
71249
72259
|
const projectSkillsDir = path30.join(cwd, ".pie", "skills");
|
|
71250
|
-
const { skills, diagnostics } = loadSkills({
|
|
72260
|
+
const { skills: discoveredSkills, diagnostics } = loadSkills({
|
|
71251
72261
|
dirs: buildSkillDirs({
|
|
71252
72262
|
builtinDir: paths.builtinSkillsDir,
|
|
71253
72263
|
userDir: paths.skillsDir,
|
|
@@ -71255,6 +72265,7 @@ async function composeCliRuntime(params) {
|
|
|
71255
72265
|
cwd
|
|
71256
72266
|
})
|
|
71257
72267
|
});
|
|
72268
|
+
const skills = discoveredSkills.filter((skill) => settingsManager.isSkillEnabled(skill.name));
|
|
71258
72269
|
let interactiveOptions;
|
|
71259
72270
|
const getCurrentModel = () => interactiveOptions?.model ?? model;
|
|
71260
72271
|
const cliHostCapabilities = createCliHostCapabilities(cwd, {
|
|
@@ -71278,22 +72289,23 @@ async function composeCliRuntime(params) {
|
|
|
71278
72289
|
...createCliFileSystemTools(cwd, fileSystemToolOptions),
|
|
71279
72290
|
...cliHostCapabilities.tools
|
|
71280
72291
|
];
|
|
72292
|
+
const enabledRawTools = filterEnabledTools(rawTools, settingsManager);
|
|
71281
72293
|
recordCliCompositionStep(compositionTrace, {
|
|
71282
72294
|
id: "host_shared_capabilities",
|
|
71283
72295
|
inputSummary: `cwd=${cwd}`,
|
|
71284
|
-
outputSummary: summarizeToolNames(
|
|
71285
|
-
toolCount:
|
|
72296
|
+
outputSummary: summarizeToolNames(enabledRawTools),
|
|
72297
|
+
toolCount: enabledRawTools.length
|
|
71286
72298
|
});
|
|
71287
|
-
const allTools = createPolicyEnforcedTools(
|
|
72299
|
+
const allTools = createPolicyEnforcedTools(enabledRawTools, {
|
|
71288
72300
|
getContext: () => ({ mode: "normal", confirmationPolicy: "allow" })
|
|
71289
72301
|
});
|
|
71290
72302
|
const tools = [...allTools];
|
|
71291
72303
|
recordCliCompositionStep(compositionTrace, {
|
|
71292
72304
|
id: "policy_filtering",
|
|
71293
|
-
inputSummary: `tools=${
|
|
72305
|
+
inputSummary: `tools=${enabledRawTools.length}`,
|
|
71294
72306
|
outputSummary: summarizeToolNames(tools),
|
|
71295
72307
|
toolCount: tools.length,
|
|
71296
|
-
policyDecisions:
|
|
72308
|
+
policyDecisions: enabledRawTools.length === allTools.length ? ["allow:default"] : [`filtered:${enabledRawTools.length - allTools.length}`]
|
|
71297
72309
|
});
|
|
71298
72310
|
for (const diag of diagnostics.filter((d) => d.type === "collision")) {
|
|
71299
72311
|
console.log(`[CLI] ${diag.message}`);
|
|
@@ -71478,7 +72490,7 @@ async function loadPrintModeExtensions(params) {
|
|
|
71478
72490
|
);
|
|
71479
72491
|
runner.setUIContext(uiContext);
|
|
71480
72492
|
await restoreExtensionProviderCredentials(params.modelRegistry);
|
|
71481
|
-
const extensionTools = convertExtensionTools(extensions);
|
|
72493
|
+
const extensionTools = filterEnabledTools(convertExtensionTools(extensions), params.settingsManager);
|
|
71482
72494
|
availableTools = [...availableTools, ...extensionTools];
|
|
71483
72495
|
return {
|
|
71484
72496
|
extensions,
|
|
@@ -71538,12 +72550,13 @@ async function runPrintMode(params) {
|
|
|
71538
72550
|
knowledgeSection: runtime.knowledgeSection,
|
|
71539
72551
|
tools: printModeTools.map((tool) => ({ name: tool.name, description: tool.description }))
|
|
71540
72552
|
});
|
|
72553
|
+
const printThinkingLevel = resolveInitialThinkingLevel({ session: runtime.sessionManager.getActiveSession(), settingsManager: runtime.settingsManager });
|
|
71541
72554
|
agent = new AgentClass({
|
|
71542
72555
|
initialState: {
|
|
71543
72556
|
systemPrompt: baseSystemPrompt,
|
|
71544
72557
|
model: runtime.model,
|
|
71545
72558
|
tools: printModeTools,
|
|
71546
|
-
thinkingLevel:
|
|
72559
|
+
thinkingLevel: printThinkingLevel
|
|
71547
72560
|
},
|
|
71548
72561
|
apiKey: runtime.apiKey,
|
|
71549
72562
|
streamFn: params.streamFn
|
|
@@ -71678,21 +72691,21 @@ async function runPrintMode(params) {
|
|
|
71678
72691
|
console.log(assistantText);
|
|
71679
72692
|
}
|
|
71680
72693
|
} catch (err) {
|
|
71681
|
-
const
|
|
71682
|
-
sessionTrace.noteStalled(
|
|
72694
|
+
const errorMessage4 = err instanceof Error ? err.message : String(err);
|
|
72695
|
+
sessionTrace.noteStalled(errorMessage4, { mode: "print" });
|
|
71683
72696
|
process.exitCode = 1;
|
|
71684
72697
|
if (params.jsonOutput) {
|
|
71685
72698
|
console.log(
|
|
71686
72699
|
JSON.stringify({
|
|
71687
72700
|
ok: false,
|
|
71688
|
-
error:
|
|
72701
|
+
error: errorMessage4,
|
|
71689
72702
|
sessionId: runtime.sessionManager.getActiveSession()?.id,
|
|
71690
72703
|
provider: runtime.provider,
|
|
71691
72704
|
modelId: runtime.modelId
|
|
71692
72705
|
})
|
|
71693
72706
|
);
|
|
71694
72707
|
}
|
|
71695
|
-
console.error("Error:",
|
|
72708
|
+
console.error("Error:", errorMessage4);
|
|
71696
72709
|
}
|
|
71697
72710
|
if (!params.rawOutput && !params.jsonOutput) {
|
|
71698
72711
|
console.log("");
|
|
@@ -71709,6 +72722,9 @@ var MAX_EVENT_OBJECT_KEYS = 50;
|
|
|
71709
72722
|
var MAX_EVENT_ARRAY_ITEMS = 50;
|
|
71710
72723
|
var MAX_EVENT_VALUE_DEPTH = 4;
|
|
71711
72724
|
var MAX_EVENT_STRING_LENGTH = 4e3;
|
|
72725
|
+
var COMPACT_EVENT_STRING_LENGTH = 800;
|
|
72726
|
+
var FULL_DETAIL = "full";
|
|
72727
|
+
var COMPACT_DETAIL = "compact";
|
|
71712
72728
|
function createNoOpExtensionUIContext2() {
|
|
71713
72729
|
return {
|
|
71714
72730
|
notify: () => {
|
|
@@ -71724,10 +72740,10 @@ function writeEvent(event) {
|
|
|
71724
72740
|
process.stdout.write(`${JSON.stringify(event)}
|
|
71725
72741
|
`);
|
|
71726
72742
|
}
|
|
71727
|
-
function toJsonValue(value, depth = 0) {
|
|
72743
|
+
function toJsonValue(value, depth = 0, cap = MAX_EVENT_STRING_LENGTH) {
|
|
71728
72744
|
if (value === null) return null;
|
|
71729
72745
|
if (typeof value === "string") {
|
|
71730
|
-
return value.length >
|
|
72746
|
+
return value.length > cap ? value.slice(0, cap) : value;
|
|
71731
72747
|
}
|
|
71732
72748
|
if (typeof value === "number") return Number.isFinite(value) ? value : String(value);
|
|
71733
72749
|
if (typeof value === "boolean") return value;
|
|
@@ -71735,17 +72751,33 @@ function toJsonValue(value, depth = 0) {
|
|
|
71735
72751
|
if (typeof value !== "object") return void 0;
|
|
71736
72752
|
if (depth >= MAX_EVENT_VALUE_DEPTH) return "[truncated]";
|
|
71737
72753
|
if (Array.isArray(value)) {
|
|
71738
|
-
return value.slice(0, MAX_EVENT_ARRAY_ITEMS).map((item) => toJsonValue(item, depth + 1) ?? null);
|
|
72754
|
+
return value.slice(0, MAX_EVENT_ARRAY_ITEMS).map((item) => toJsonValue(item, depth + 1, cap) ?? null);
|
|
71739
72755
|
}
|
|
71740
72756
|
const result = {};
|
|
71741
72757
|
for (const [key, item] of Object.entries(value).slice(0, MAX_EVENT_OBJECT_KEYS)) {
|
|
71742
|
-
result[key] = toJsonValue(item, depth + 1);
|
|
72758
|
+
result[key] = toJsonValue(item, depth + 1, cap);
|
|
71743
72759
|
}
|
|
71744
72760
|
return result;
|
|
71745
72761
|
}
|
|
71746
72762
|
function isRecord4(value) {
|
|
71747
72763
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
71748
72764
|
}
|
|
72765
|
+
function truncateForEvent(text, cap) {
|
|
72766
|
+
if (text.length <= cap) {
|
|
72767
|
+
return { value: text, truncated: false, fullLength: text.length };
|
|
72768
|
+
}
|
|
72769
|
+
return { value: text.slice(0, cap), truncated: true, fullLength: text.length };
|
|
72770
|
+
}
|
|
72771
|
+
function hasOversizedValue(value, cap, depth = 0) {
|
|
72772
|
+
if (typeof value === "string") return value.length > cap;
|
|
72773
|
+
if (!value || typeof value !== "object") return false;
|
|
72774
|
+
if (depth >= MAX_EVENT_VALUE_DEPTH) return true;
|
|
72775
|
+
if (Array.isArray(value)) {
|
|
72776
|
+
return value.length > MAX_EVENT_ARRAY_ITEMS || value.some((item) => hasOversizedValue(item, cap, depth + 1));
|
|
72777
|
+
}
|
|
72778
|
+
const entries = Object.entries(value);
|
|
72779
|
+
return entries.length > MAX_EVENT_OBJECT_KEYS || entries.some(([, item]) => hasOversizedValue(item, cap, depth + 1));
|
|
72780
|
+
}
|
|
71749
72781
|
function parseInput(line) {
|
|
71750
72782
|
let parsed;
|
|
71751
72783
|
try {
|
|
@@ -71770,8 +72802,7 @@ function parseInput(line) {
|
|
|
71770
72802
|
type: "session.rewind",
|
|
71771
72803
|
sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : void 0,
|
|
71772
72804
|
requestId: typeof parsed.requestId === "string" ? parsed.requestId : void 0,
|
|
71773
|
-
entryId: typeof parsed.entryId === "string" ? parsed.entryId : void 0
|
|
71774
|
-
checkpointId: typeof parsed.checkpointId === "string" ? parsed.checkpointId : void 0
|
|
72805
|
+
entryId: typeof parsed.entryId === "string" ? parsed.entryId : void 0
|
|
71775
72806
|
};
|
|
71776
72807
|
}
|
|
71777
72808
|
if (parsed.type === "session.fork") {
|
|
@@ -71785,6 +72816,14 @@ function parseInput(line) {
|
|
|
71785
72816
|
cwd: typeof parsed.cwd === "string" ? parsed.cwd : void 0
|
|
71786
72817
|
};
|
|
71787
72818
|
}
|
|
72819
|
+
if (parsed.type === "sidechat.request" && typeof parsed.requestId === "string" && typeof parsed.prompt === "string") {
|
|
72820
|
+
return {
|
|
72821
|
+
type: "sidechat.request",
|
|
72822
|
+
sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : void 0,
|
|
72823
|
+
requestId: parsed.requestId,
|
|
72824
|
+
prompt: parsed.prompt
|
|
72825
|
+
};
|
|
72826
|
+
}
|
|
71788
72827
|
if ((parsed.type === "turn.request" || parsed.type === "turn.input") && typeof parsed.turnId === "string" && typeof parsed.prompt === "string") {
|
|
71789
72828
|
const streamingBehavior = parsed.streamingBehavior;
|
|
71790
72829
|
if (streamingBehavior !== void 0 && streamingBehavior !== "steer" && streamingBehavior !== "followUp") {
|
|
@@ -71818,6 +72857,12 @@ function assistantTextFromMessage(message) {
|
|
|
71818
72857
|
}
|
|
71819
72858
|
return text;
|
|
71820
72859
|
}
|
|
72860
|
+
function assistantUsageFromAgent(agent) {
|
|
72861
|
+
const messages = agent?.state.messages ?? [];
|
|
72862
|
+
const lastMessage = messages[messages.length - 1];
|
|
72863
|
+
if (lastMessage?.role !== "assistant") return void 0;
|
|
72864
|
+
return toJsonValue(lastMessage.usage);
|
|
72865
|
+
}
|
|
71821
72866
|
function assistantErrorFromAgent(agent) {
|
|
71822
72867
|
const messages = agent?.state.messages ?? [];
|
|
71823
72868
|
const lastMessage = messages[messages.length - 1];
|
|
@@ -71926,7 +72971,7 @@ async function loadJsonModeExtensions(params) {
|
|
|
71926
72971
|
);
|
|
71927
72972
|
runner.setUIContext(uiContext);
|
|
71928
72973
|
await restoreExtensionProviderCredentials(params.runtime.modelRegistry);
|
|
71929
|
-
const extensionTools = convertExtensionTools(extensions);
|
|
72974
|
+
const extensionTools = filterEnabledTools(convertExtensionTools(extensions), params.runtime.settingsManager);
|
|
71930
72975
|
availableTools = [...availableTools, ...extensionTools];
|
|
71931
72976
|
return {
|
|
71932
72977
|
runner,
|
|
@@ -71935,6 +72980,8 @@ async function loadJsonModeExtensions(params) {
|
|
|
71935
72980
|
};
|
|
71936
72981
|
}
|
|
71937
72982
|
async function runJsonEventsMode(params) {
|
|
72983
|
+
const eventDetail = params.eventDetail === FULL_DETAIL ? FULL_DETAIL : COMPACT_DETAIL;
|
|
72984
|
+
const eventStringCap = eventDetail === FULL_DETAIL ? MAX_EVENT_STRING_LENGTH : COMPACT_EVENT_STRING_LENGTH;
|
|
71938
72985
|
const sessionId = params.explicitSessionId || params.runtime?.sessionManager.getActiveSession()?.id || `pie-json-${Date.now()}`;
|
|
71939
72986
|
let activeTurn = null;
|
|
71940
72987
|
let runtime = params.runtime;
|
|
@@ -71945,13 +72992,28 @@ async function runJsonEventsMode(params) {
|
|
|
71945
72992
|
let trace;
|
|
71946
72993
|
let lastRetryEvent;
|
|
71947
72994
|
let mockActiveEntryId;
|
|
71948
|
-
let thinkingLevel =
|
|
72995
|
+
let thinkingLevel = DEFAULT_THINKING_LEVEL;
|
|
72996
|
+
let thinkingLevelInitialized = false;
|
|
71949
72997
|
let defaultRuntime;
|
|
71950
72998
|
let defaultModelState;
|
|
71951
72999
|
const completedSessionControlRequests = /* @__PURE__ */ new Map();
|
|
73000
|
+
const completedSidechatRequests = /* @__PURE__ */ new Map();
|
|
73001
|
+
const ensureRuntimeInFlight = /* @__PURE__ */ new Map();
|
|
73002
|
+
let activeSidechat = null;
|
|
73003
|
+
let activeSidechatPromise = null;
|
|
73004
|
+
let sidechatChainStopped = false;
|
|
71952
73005
|
const noProgressTimeoutMs = Number(process.env.PIE_JSON_EVENTS_NO_PROGRESS_MS || 6e5);
|
|
71953
73006
|
const mockResponseDelayMs = Number(process.env.PIE_TEST_MOCK_RESPONSE_DELAY_MS || 0);
|
|
73007
|
+
const prewarmTimeoutMs = Number(process.env.PIE_JSON_EVENTS_PREWARM_TIMEOUT_MS || 1e4);
|
|
73008
|
+
const sidechatTimeoutMs = Number(process.env.PIE_JSON_EVENTS_SIDECHAT_TIMEOUT_MS || 3e5);
|
|
73009
|
+
await prewarmRuntime();
|
|
71954
73010
|
writeEvent({ type: "agent.ready", sessionId });
|
|
73011
|
+
function trackSidechatPromise(promise) {
|
|
73012
|
+
activeSidechatPromise = promise;
|
|
73013
|
+
void promise.finally(() => {
|
|
73014
|
+
if (activeSidechatPromise === promise) activeSidechatPromise = null;
|
|
73015
|
+
});
|
|
73016
|
+
}
|
|
71955
73017
|
function sessionMismatchError(requestedSessionId) {
|
|
71956
73018
|
return `session mismatch: JSON events process is bound to ${sessionId}, received ${requestedSessionId}`;
|
|
71957
73019
|
}
|
|
@@ -72123,15 +73185,10 @@ async function runJsonEventsMode(params) {
|
|
|
72123
73185
|
}
|
|
72124
73186
|
function resolveRewindEntryId(message) {
|
|
72125
73187
|
const entryId = message.entryId?.trim();
|
|
72126
|
-
|
|
72127
|
-
|
|
72128
|
-
throw invalidSessionControl("entryId and checkpointId must match when both are provided");
|
|
72129
|
-
}
|
|
72130
|
-
const resolved = entryId || checkpointId;
|
|
72131
|
-
if (!resolved) {
|
|
72132
|
-
throw invalidSessionControl("entryId or checkpointId is required");
|
|
73188
|
+
if (!entryId) {
|
|
73189
|
+
throw invalidSessionControl("entryId is required");
|
|
72133
73190
|
}
|
|
72134
|
-
return
|
|
73191
|
+
return entryId;
|
|
72135
73192
|
}
|
|
72136
73193
|
function writeSessionControlFailure(message, operation, error) {
|
|
72137
73194
|
const detail = error instanceof SessionControlError ? error : new SessionControlError("session_io_error", error instanceof Error ? error.message : String(error));
|
|
@@ -72183,14 +73240,12 @@ async function runJsonEventsMode(params) {
|
|
|
72183
73240
|
entryId
|
|
72184
73241
|
});
|
|
72185
73242
|
await syncRuntimeAfterRewind(controlSessionId);
|
|
72186
|
-
mockActiveEntryId = result.
|
|
73243
|
+
mockActiveEntryId = result.activeEntryId;
|
|
72187
73244
|
const event = {
|
|
72188
73245
|
type: "session.rewound",
|
|
72189
73246
|
sessionId: controlSessionId,
|
|
72190
73247
|
requestId,
|
|
72191
73248
|
entryId: result.entryId,
|
|
72192
|
-
checkpointId: result.checkpointId,
|
|
72193
|
-
headEntryId: result.headEntryId,
|
|
72194
73249
|
activeEntryId: result.activeEntryId
|
|
72195
73250
|
};
|
|
72196
73251
|
completedSessionControlRequests.set(requestId, event);
|
|
@@ -72227,11 +73282,8 @@ async function runJsonEventsMode(params) {
|
|
|
72227
73282
|
requestId,
|
|
72228
73283
|
sourceSessionId: result.sourceSessionId,
|
|
72229
73284
|
sourceEntryId: result.sourceEntryId,
|
|
72230
|
-
sourceCheckpointId: result.sourceCheckpointId,
|
|
72231
73285
|
targetSessionId: result.targetSessionId,
|
|
72232
|
-
|
|
72233
|
-
targetActiveEntryId: result.targetActiveEntryId,
|
|
72234
|
-
headEntryId: result.headEntryId
|
|
73286
|
+
targetActiveEntryId: result.targetActiveEntryId
|
|
72235
73287
|
};
|
|
72236
73288
|
completedSessionControlRequests.set(requestId, event);
|
|
72237
73289
|
writeEvent(event);
|
|
@@ -72239,21 +73291,150 @@ async function runJsonEventsMode(params) {
|
|
|
72239
73291
|
writeSessionControlFailure(message, "fork", error);
|
|
72240
73292
|
}
|
|
72241
73293
|
}
|
|
73294
|
+
function writeSidechatFailure(message, error, code) {
|
|
73295
|
+
writeEvent({
|
|
73296
|
+
type: "sidechat.failed",
|
|
73297
|
+
sessionId,
|
|
73298
|
+
requestId: message.requestId.trim(),
|
|
73299
|
+
error,
|
|
73300
|
+
code
|
|
73301
|
+
});
|
|
73302
|
+
}
|
|
73303
|
+
async function handleSidechat(message) {
|
|
73304
|
+
if (isSessionMismatch(message)) {
|
|
73305
|
+
writeSidechatFailure(message, sessionMismatchError(message.sessionId), "session_mismatch");
|
|
73306
|
+
return;
|
|
73307
|
+
}
|
|
73308
|
+
const requestId = message.requestId.trim();
|
|
73309
|
+
if (!requestId) {
|
|
73310
|
+
writeSidechatFailure(message, "requestId is required", "invalid_request");
|
|
73311
|
+
return;
|
|
73312
|
+
}
|
|
73313
|
+
const cached = completedSidechatRequests.get(requestId);
|
|
73314
|
+
if (cached) {
|
|
73315
|
+
writeEvent(cached);
|
|
73316
|
+
return;
|
|
73317
|
+
}
|
|
73318
|
+
if (activeTurn && !activeTurn.finalized) {
|
|
73319
|
+
writeSidechatFailure(message, "Cannot run sidechat while a turn is active", "session_busy");
|
|
73320
|
+
return;
|
|
73321
|
+
}
|
|
73322
|
+
const startedAt = Date.now();
|
|
73323
|
+
if (params.mockResponse !== void 0) {
|
|
73324
|
+
writeEvent({ type: "sidechat.started", sessionId, requestId });
|
|
73325
|
+
const event = {
|
|
73326
|
+
type: "sidechat.completed",
|
|
73327
|
+
sessionId,
|
|
73328
|
+
requestId,
|
|
73329
|
+
text: params.mockResponse,
|
|
73330
|
+
durationMs: Date.now() - startedAt
|
|
73331
|
+
};
|
|
73332
|
+
completedSidechatRequests.set(requestId, event);
|
|
73333
|
+
writeEvent(event);
|
|
73334
|
+
return;
|
|
73335
|
+
}
|
|
73336
|
+
writeEvent({ type: "sidechat.started", sessionId, requestId });
|
|
73337
|
+
const sidechatController = new AbortController();
|
|
73338
|
+
let abortKind;
|
|
73339
|
+
activeSidechat = {
|
|
73340
|
+
abort: () => {
|
|
73341
|
+
if (!abortKind) abortKind = "interrupted";
|
|
73342
|
+
sidechatController.abort();
|
|
73343
|
+
}
|
|
73344
|
+
};
|
|
73345
|
+
try {
|
|
73346
|
+
await ensureRuntime();
|
|
73347
|
+
if (!agent || !runtime) {
|
|
73348
|
+
throw new Error("JSON events runtime was not initialized");
|
|
73349
|
+
}
|
|
73350
|
+
if (runtime.initialModel.unconfigured) {
|
|
73351
|
+
writeSidechatFailure(message, runtime.initialModel.warning || "No models are configured.");
|
|
73352
|
+
return;
|
|
73353
|
+
}
|
|
73354
|
+
if (sidechatController.signal.aborted) {
|
|
73355
|
+
writeSidechatFailure(message, "sidechat aborted before dispatch", "sidechat_interrupted");
|
|
73356
|
+
return;
|
|
73357
|
+
}
|
|
73358
|
+
const parent = agent;
|
|
73359
|
+
const { Agent: AgentClass } = await import("./chunks/src-HYZFAW4V.js");
|
|
73360
|
+
const sideAgent = new AgentClass({
|
|
73361
|
+
initialState: {
|
|
73362
|
+
systemPrompt: parent.state.systemPrompt,
|
|
73363
|
+
model: parent.state.model,
|
|
73364
|
+
thinkingLevel: parent.state.thinkingLevel,
|
|
73365
|
+
tools: [],
|
|
73366
|
+
messages: structuredClone(parent.state.messages)
|
|
73367
|
+
},
|
|
73368
|
+
apiKey: runtime.apiKey,
|
|
73369
|
+
streamFn: params.streamFn
|
|
73370
|
+
});
|
|
73371
|
+
sidechatController.signal.addEventListener("abort", () => sideAgent.abort(), { once: true });
|
|
73372
|
+
const timer = setTimeout(() => {
|
|
73373
|
+
if (!abortKind) abortKind = "timeout";
|
|
73374
|
+
sidechatController.abort();
|
|
73375
|
+
}, sidechatTimeoutMs);
|
|
73376
|
+
timer.unref?.();
|
|
73377
|
+
try {
|
|
73378
|
+
await sideAgent.prompt(message.prompt);
|
|
73379
|
+
} finally {
|
|
73380
|
+
clearTimeout(timer);
|
|
73381
|
+
}
|
|
73382
|
+
if (abortKind) {
|
|
73383
|
+
const code = abortKind === "timeout" ? "sidechat_timeout" : "sidechat_interrupted";
|
|
73384
|
+
writeSidechatFailure(message, sideAgent.state.error || "sidechat aborted", code);
|
|
73385
|
+
return;
|
|
73386
|
+
}
|
|
73387
|
+
const failure = sideAgent.state.error;
|
|
73388
|
+
if (failure) {
|
|
73389
|
+
writeSidechatFailure(message, failure);
|
|
73390
|
+
return;
|
|
73391
|
+
}
|
|
73392
|
+
const sidechatText = assistantTextFromAgent(sideAgent);
|
|
73393
|
+
const capped = sidechatText === void 0 ? void 0 : truncateForEvent(sidechatText, eventStringCap);
|
|
73394
|
+
const event = {
|
|
73395
|
+
type: "sidechat.completed",
|
|
73396
|
+
sessionId,
|
|
73397
|
+
requestId,
|
|
73398
|
+
text: capped?.value,
|
|
73399
|
+
...capped?.truncated ? { truncated: true, fullLength: capped.fullLength } : {},
|
|
73400
|
+
usage: assistantUsageFromAgent(sideAgent),
|
|
73401
|
+
durationMs: Date.now() - startedAt
|
|
73402
|
+
};
|
|
73403
|
+
completedSidechatRequests.set(requestId, event);
|
|
73404
|
+
writeEvent(event);
|
|
73405
|
+
} catch (error) {
|
|
73406
|
+
const detail = errorToFailureDetail(error);
|
|
73407
|
+
writeSidechatFailure(
|
|
73408
|
+
message,
|
|
73409
|
+
typeof detail === "string" ? detail : detail.message,
|
|
73410
|
+
typeof detail === "string" ? void 0 : detail.code
|
|
73411
|
+
);
|
|
73412
|
+
} finally {
|
|
73413
|
+
activeSidechat = null;
|
|
73414
|
+
}
|
|
73415
|
+
}
|
|
72242
73416
|
function finalize(kind, detail) {
|
|
72243
73417
|
const turn = activeTurn;
|
|
72244
73418
|
if (!turn || turn.finalized) return;
|
|
72245
73419
|
turn.finalized = true;
|
|
72246
|
-
const
|
|
73420
|
+
const activeEntryId = activeHeadEntryId();
|
|
72247
73421
|
const base = {
|
|
72248
73422
|
sessionId: turn.sessionId,
|
|
72249
73423
|
turnId: turn.turnId,
|
|
72250
|
-
|
|
72251
|
-
activeEntryId: headEntryId
|
|
73424
|
+
activeEntryId
|
|
72252
73425
|
};
|
|
72253
73426
|
switch (kind) {
|
|
72254
|
-
case "completed":
|
|
72255
|
-
|
|
73427
|
+
case "completed": {
|
|
73428
|
+
const summaryText = (typeof detail === "string" ? detail : turn.summary).trim();
|
|
73429
|
+
const capped = truncateForEvent(summaryText, eventStringCap);
|
|
73430
|
+
writeEvent({
|
|
73431
|
+
type: "turn.completed",
|
|
73432
|
+
...base,
|
|
73433
|
+
summary: capped.value,
|
|
73434
|
+
...capped.truncated ? { truncated: true, fullLength: capped.fullLength } : {}
|
|
73435
|
+
});
|
|
72256
73436
|
break;
|
|
73437
|
+
}
|
|
72257
73438
|
case "failed":
|
|
72258
73439
|
writeEvent({ type: "turn.failed", ...base, ...failureDetail(detail) });
|
|
72259
73440
|
break;
|
|
@@ -72266,13 +73447,12 @@ async function runJsonEventsMode(params) {
|
|
|
72266
73447
|
}
|
|
72267
73448
|
}
|
|
72268
73449
|
function emitSettled(turn) {
|
|
72269
|
-
const
|
|
73450
|
+
const activeEntryId = activeHeadEntryId();
|
|
72270
73451
|
writeEvent({
|
|
72271
73452
|
type: "turn.settled",
|
|
72272
73453
|
sessionId: turn.sessionId,
|
|
72273
73454
|
turnId: turn.turnId,
|
|
72274
|
-
|
|
72275
|
-
activeEntryId: headEntryId
|
|
73455
|
+
activeEntryId
|
|
72276
73456
|
});
|
|
72277
73457
|
}
|
|
72278
73458
|
function rememberTerminal(kind, detail, options) {
|
|
@@ -72295,14 +73475,20 @@ async function runJsonEventsMode(params) {
|
|
|
72295
73475
|
break;
|
|
72296
73476
|
case "tool_started":
|
|
72297
73477
|
touch();
|
|
72298
|
-
|
|
72299
|
-
|
|
72300
|
-
|
|
72301
|
-
|
|
72302
|
-
|
|
72303
|
-
|
|
72304
|
-
|
|
72305
|
-
|
|
73478
|
+
{
|
|
73479
|
+
const argsOversized = eventDetail === COMPACT_DETAIL && hasOversizedValue(event.args, eventStringCap);
|
|
73480
|
+
writeEvent({
|
|
73481
|
+
type: "tool.started",
|
|
73482
|
+
sessionId: activeTurn.sessionId,
|
|
73483
|
+
turnId: activeTurn.turnId,
|
|
73484
|
+
toolCallId: event.toolCallId,
|
|
73485
|
+
name: event.toolName,
|
|
73486
|
+
data: toJsonValue({
|
|
73487
|
+
args: event.args,
|
|
73488
|
+
...argsOversized ? { truncated: true } : {}
|
|
73489
|
+
}, 0, eventStringCap)
|
|
73490
|
+
});
|
|
73491
|
+
}
|
|
72306
73492
|
break;
|
|
72307
73493
|
case "tool_progressed":
|
|
72308
73494
|
touch();
|
|
@@ -72316,18 +73502,23 @@ async function runJsonEventsMode(params) {
|
|
|
72316
73502
|
break;
|
|
72317
73503
|
case "tool_finished":
|
|
72318
73504
|
touch();
|
|
72319
|
-
|
|
72320
|
-
|
|
72321
|
-
|
|
72322
|
-
|
|
72323
|
-
|
|
72324
|
-
|
|
72325
|
-
|
|
72326
|
-
|
|
72327
|
-
|
|
72328
|
-
|
|
72329
|
-
|
|
72330
|
-
|
|
73505
|
+
{
|
|
73506
|
+
const resultText = extractJsonEventsToolProgressText(event.result);
|
|
73507
|
+
const capped = resultText === void 0 || resultText === null ? void 0 : truncateForEvent(resultText, eventStringCap);
|
|
73508
|
+
writeEvent({
|
|
73509
|
+
type: "tool.completed",
|
|
73510
|
+
sessionId: activeTurn.sessionId,
|
|
73511
|
+
turnId: activeTurn.turnId,
|
|
73512
|
+
toolCallId: event.toolCallId,
|
|
73513
|
+
name: event.toolName,
|
|
73514
|
+
status: event.isError ? "error" : "ok",
|
|
73515
|
+
data: toJsonValue({
|
|
73516
|
+
resultText: capped?.value,
|
|
73517
|
+
isError: event.isError,
|
|
73518
|
+
...capped?.truncated ? { truncated: true, fullLength: capped.fullLength } : {}
|
|
73519
|
+
}, 0, eventStringCap)
|
|
73520
|
+
});
|
|
73521
|
+
}
|
|
72331
73522
|
break;
|
|
72332
73523
|
}
|
|
72333
73524
|
}
|
|
@@ -72453,9 +73644,30 @@ async function runJsonEventsMode(params) {
|
|
|
72453
73644
|
trace = void 0;
|
|
72454
73645
|
cleanupBashOutputArtifacts();
|
|
72455
73646
|
}
|
|
73647
|
+
async function prewarmRuntime() {
|
|
73648
|
+
if (params.mockResponse !== void 0) return;
|
|
73649
|
+
if (!params.createRuntime && !params.runtime) return;
|
|
73650
|
+
try {
|
|
73651
|
+
await new Promise((resolve7, reject) => {
|
|
73652
|
+
const timer = setTimeout(() => reject(new Error("prewarm timeout")), prewarmTimeoutMs);
|
|
73653
|
+
timer.unref?.();
|
|
73654
|
+
void ensureRuntime().then(resolve7, reject).finally(() => clearTimeout(timer));
|
|
73655
|
+
});
|
|
73656
|
+
} catch {
|
|
73657
|
+
}
|
|
73658
|
+
}
|
|
72456
73659
|
async function ensureRuntime(requestedCwd) {
|
|
72457
73660
|
if (params.mockResponse !== void 0) return;
|
|
72458
73661
|
const effectiveCwd = requestedCwd ?? process.cwd();
|
|
73662
|
+
const inFlight = ensureRuntimeInFlight.get(effectiveCwd);
|
|
73663
|
+
if (inFlight) return inFlight;
|
|
73664
|
+
const composed = composeRuntime(effectiveCwd);
|
|
73665
|
+
ensureRuntimeInFlight.set(effectiveCwd, composed);
|
|
73666
|
+
void composed.finally(() => ensureRuntimeInFlight.delete(effectiveCwd)).catch(() => {
|
|
73667
|
+
});
|
|
73668
|
+
return composed;
|
|
73669
|
+
}
|
|
73670
|
+
async function composeRuntime(effectiveCwd) {
|
|
72459
73671
|
if (params.createRuntime && (!runtime || runtime.cwd !== effectiveCwd)) {
|
|
72460
73672
|
await disposeRuntime();
|
|
72461
73673
|
runtime = await params.createRuntime({ cwd: effectiveCwd, sessionId });
|
|
@@ -72550,6 +73762,11 @@ async function runJsonEventsMode(params) {
|
|
|
72550
73762
|
agent.setTools(wrapToolsWithExtensions(agent.state.tools, jsonModeExtensions.runner));
|
|
72551
73763
|
controller.updateRuntimeContext({ tools: agent.state.tools });
|
|
72552
73764
|
disposeSemanticSubscription = agent.subscribeSemantic(handleSemanticEvent);
|
|
73765
|
+
if (!thinkingLevelInitialized) {
|
|
73766
|
+
thinkingLevelInitialized = true;
|
|
73767
|
+
thinkingLevel = resolveInitialThinkingLevel({ session: runtime.sessionManager.getActiveSession(), settingsManager: runtime.settingsManager });
|
|
73768
|
+
agent.setThinkingLevel(thinkingLevel);
|
|
73769
|
+
}
|
|
72553
73770
|
}
|
|
72554
73771
|
function metadataSelection(metadata, key) {
|
|
72555
73772
|
if (!metadata || !(key in metadata)) return void 0;
|
|
@@ -72611,6 +73828,7 @@ async function runJsonEventsMode(params) {
|
|
|
72611
73828
|
const nextLevel = requestedThinkingLevel === null ? "off" : requestedThinkingLevel;
|
|
72612
73829
|
if (!isThinkingLevel(nextLevel)) throw new Error(`Unsupported thinkingLevel: ${nextLevel}`);
|
|
72613
73830
|
thinkingLevel = nextLevel;
|
|
73831
|
+
thinkingLevelInitialized = true;
|
|
72614
73832
|
applyThinkingLevel({
|
|
72615
73833
|
level: thinkingLevel,
|
|
72616
73834
|
agent,
|
|
@@ -72870,6 +74088,8 @@ async function runJsonEventsMode(params) {
|
|
|
72870
74088
|
}
|
|
72871
74089
|
if (message.type === "shutdown") {
|
|
72872
74090
|
shutdownActiveTurn(message.reason);
|
|
74091
|
+
sidechatChainStopped = true;
|
|
74092
|
+
activeSidechat?.abort();
|
|
72873
74093
|
break;
|
|
72874
74094
|
}
|
|
72875
74095
|
if (message.type === "turn.interrupt") {
|
|
@@ -72884,6 +74104,24 @@ async function runJsonEventsMode(params) {
|
|
|
72884
74104
|
await handleSessionFork(message);
|
|
72885
74105
|
continue;
|
|
72886
74106
|
}
|
|
74107
|
+
if (message.type === "sidechat.request") {
|
|
74108
|
+
const prior = activeSidechatPromise ?? Promise.resolve();
|
|
74109
|
+
trackSidechatPromise(prior.then(async () => {
|
|
74110
|
+
if (sidechatChainStopped) {
|
|
74111
|
+
const cached = completedSidechatRequests.get(message.requestId.trim());
|
|
74112
|
+
if (cached) {
|
|
74113
|
+
writeEvent(cached);
|
|
74114
|
+
} else {
|
|
74115
|
+
writeSidechatFailure(message, "sidechat discarded on shutdown", "sidechat_interrupted");
|
|
74116
|
+
}
|
|
74117
|
+
return;
|
|
74118
|
+
}
|
|
74119
|
+
await handleSidechat(message).catch((error) => {
|
|
74120
|
+
writeSidechatFailure(message, error instanceof Error ? error.message : String(error));
|
|
74121
|
+
});
|
|
74122
|
+
}));
|
|
74123
|
+
continue;
|
|
74124
|
+
}
|
|
72887
74125
|
const shouldTrackTurn = !activeTurn || activeTurn.finalized;
|
|
72888
74126
|
const turnPromise = runTurn(message).catch((error) => {
|
|
72889
74127
|
writeEvent({
|
|
@@ -72902,6 +74140,7 @@ async function runJsonEventsMode(params) {
|
|
|
72902
74140
|
}
|
|
72903
74141
|
}
|
|
72904
74142
|
await activeTurnPromise;
|
|
74143
|
+
await activeSidechatPromise;
|
|
72905
74144
|
await disposeRuntime();
|
|
72906
74145
|
}
|
|
72907
74146
|
|
|
@@ -72958,6 +74197,7 @@ Commands:
|
|
|
72958
74197
|
sessions List, read, rename, rewind, and fork Pie sessions
|
|
72959
74198
|
extensions List and enable/disable extensions (list/enable/disable)
|
|
72960
74199
|
permissions Explain Pie tool and shell safety defaults
|
|
74200
|
+
capabilities Report command surface and flags for agents (add --json)
|
|
72961
74201
|
help Show this help message
|
|
72962
74202
|
|
|
72963
74203
|
Interactive Mode Key Bindings:
|
|
@@ -73006,86 +74246,13 @@ setupGlobalErrorHandlers(logError);
|
|
|
73006
74246
|
migrateConfigFromAgentDir();
|
|
73007
74247
|
var STABLE_CLI_COMMANDS = {
|
|
73008
74248
|
chat: "chat",
|
|
74249
|
+
capabilities: "capabilities",
|
|
73009
74250
|
doctor: "doctor",
|
|
73010
74251
|
models: "models",
|
|
73011
74252
|
sessions: "sessions",
|
|
73012
74253
|
extensions: "extensions",
|
|
73013
74254
|
permissions: "permissions"
|
|
73014
74255
|
};
|
|
73015
|
-
async function runDoctorCommand(args) {
|
|
73016
|
-
const json = args.includes("--json");
|
|
73017
|
-
const report = await runDoctor();
|
|
73018
|
-
if (json) {
|
|
73019
|
-
console.log(JSON.stringify(report, null, 2));
|
|
73020
|
-
} else {
|
|
73021
|
-
console.log(formatDoctorReport(report));
|
|
73022
|
-
}
|
|
73023
|
-
if (!report.ok) {
|
|
73024
|
-
process.exitCode = 1;
|
|
73025
|
-
}
|
|
73026
|
-
}
|
|
73027
|
-
async function runModelsCommand(args) {
|
|
73028
|
-
const subcommand = args[0] || "help";
|
|
73029
|
-
const parsed = parseModelsCommandArgs(args.slice(1));
|
|
73030
|
-
if (subcommand === "init") {
|
|
73031
|
-
const result = initModelsConfig(parsed);
|
|
73032
|
-
if (parsed.stdout) {
|
|
73033
|
-
process.stdout.write(result.content);
|
|
73034
|
-
} else {
|
|
73035
|
-
console.log(`Wrote models.json template: ${result.path}`);
|
|
73036
|
-
}
|
|
73037
|
-
return;
|
|
73038
|
-
}
|
|
73039
|
-
if (subcommand === "validate") {
|
|
73040
|
-
const result = validateModelsConfig({ path: parsed.path });
|
|
73041
|
-
if (parsed.json) {
|
|
73042
|
-
const probe = result.ok && parsed.probe ? await probeModelsConfig({ path: parsed.path, probe: parsed.probe }) : void 0;
|
|
73043
|
-
console.log(JSON.stringify({ ...result, ...probe ? { probe } : {} }, null, 2));
|
|
73044
|
-
if (!result.ok || probe?.status === "failed") process.exitCode = 1;
|
|
73045
|
-
return;
|
|
73046
|
-
}
|
|
73047
|
-
if (!result.ok) {
|
|
73048
|
-
console.error(result.message);
|
|
73049
|
-
process.exitCode = 1;
|
|
73050
|
-
return;
|
|
73051
|
-
}
|
|
73052
|
-
console.log(result.message);
|
|
73053
|
-
if (result.profiles.length > 0) {
|
|
73054
|
-
console.log(`Profiles: ${result.profiles.join(", ")}`);
|
|
73055
|
-
console.log(`Models: ${result.modelCount}`);
|
|
73056
|
-
}
|
|
73057
|
-
if (result.defaultModel) {
|
|
73058
|
-
console.log(`Default: ${result.defaultModel}`);
|
|
73059
|
-
}
|
|
73060
|
-
if (result.modelClasses && result.modelClasses.length > 0) {
|
|
73061
|
-
console.log(`Model classes: ${result.modelClasses.join(", ")}`);
|
|
73062
|
-
}
|
|
73063
|
-
if (result.webSearchModels && result.webSearchModels.length > 0) {
|
|
73064
|
-
console.log(`Web search: ${result.webSearchModels.join(", ")}`);
|
|
73065
|
-
}
|
|
73066
|
-
if (result.webSearchRouteCandidates && result.webSearchRouteCandidates.length > 0) {
|
|
73067
|
-
console.log(`Web search routes: ${result.webSearchRouteCandidates.join(", ")}`);
|
|
73068
|
-
}
|
|
73069
|
-
if (result.fileCapabilityModels && result.fileCapabilityModels.length > 0) {
|
|
73070
|
-
console.log(`File capabilities: ${result.fileCapabilityModels.join(", ")}`);
|
|
73071
|
-
}
|
|
73072
|
-
if (result.toolModelRoutes && result.toolModelRoutes.length > 0) {
|
|
73073
|
-
console.log(`Tool model routes: ${result.toolModelRoutes.join(", ")}`);
|
|
73074
|
-
}
|
|
73075
|
-
if (parsed.probe) {
|
|
73076
|
-
const probe = await probeModelsConfig({ path: parsed.path, probe: parsed.probe });
|
|
73077
|
-
console.log(`Probe ${probe.purpose}: ${probe.message}`);
|
|
73078
|
-
for (const attempt of probe.attempts) {
|
|
73079
|
-
console.log(`- ${attempt.status} ${attempt.route} sources=${attempt.sourceCount}${attempt.failureCategory ? ` failure=${attempt.failureCategory}` : ""}`);
|
|
73080
|
-
}
|
|
73081
|
-
if (probe.status === "failed") process.exitCode = 1;
|
|
73082
|
-
}
|
|
73083
|
-
return;
|
|
73084
|
-
}
|
|
73085
|
-
console.log(`Usage:
|
|
73086
|
-
pie models init [--path <path>] [--force] [--stdout]
|
|
73087
|
-
pie models validate [--path <path>] [--probe web_search] [--json]`);
|
|
73088
|
-
}
|
|
73089
74256
|
async function runWithJsonEventsConsoleIsolation(fn) {
|
|
73090
74257
|
const originalLog = console.log;
|
|
73091
74258
|
const originalInfo = console.info;
|
|
@@ -73104,7 +74271,21 @@ async function runWithJsonEventsConsoleIsolation(fn) {
|
|
|
73104
74271
|
}
|
|
73105
74272
|
async function createCliTestStreamFnFromEnv() {
|
|
73106
74273
|
if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) return void 0;
|
|
73107
|
-
return (await import("./chunks/test-stream-
|
|
74274
|
+
return (await import("./chunks/test-stream-5T7E7C25.js")).createTestStreamFnFromSequenceEnv();
|
|
74275
|
+
}
|
|
74276
|
+
function resolveJsonEventsDetailFlag() {
|
|
74277
|
+
for (let index = 0; index < process.argv.length; index += 1) {
|
|
74278
|
+
const arg = process.argv[index];
|
|
74279
|
+
if (arg === "--event-detail") {
|
|
74280
|
+
const raw = process.argv[index + 1] ?? "";
|
|
74281
|
+
return raw === "compact" || raw === "full" ? { value: raw } : { error: raw || "(missing)" };
|
|
74282
|
+
}
|
|
74283
|
+
if (arg.startsWith("--event-detail=")) {
|
|
74284
|
+
const raw = arg.slice("--event-detail=".length);
|
|
74285
|
+
return raw === "compact" || raw === "full" ? { value: raw } : { error: raw };
|
|
74286
|
+
}
|
|
74287
|
+
}
|
|
74288
|
+
return { value: "compact" };
|
|
73108
74289
|
}
|
|
73109
74290
|
async function startChat(initialPrompt, testCommand) {
|
|
73110
74291
|
const rawOutput = process.argv.includes("--raw-output");
|
|
@@ -73116,6 +74297,12 @@ async function startChat(initialPrompt, testCommand) {
|
|
|
73116
74297
|
const extensionPaths = parseRepeatedFlag(process.argv, "--extension-path");
|
|
73117
74298
|
const extensionFlags = parseExtensionFlags(process.argv);
|
|
73118
74299
|
if (jsonEvents) {
|
|
74300
|
+
const detailFlag = resolveJsonEventsDetailFlag();
|
|
74301
|
+
if ("error" in detailFlag) {
|
|
74302
|
+
console.error(`Invalid --event-detail value: ${detailFlag.error}. Use compact or full.`);
|
|
74303
|
+
process.exit(2);
|
|
74304
|
+
}
|
|
74305
|
+
const eventDetail = detailFlag.value;
|
|
73119
74306
|
let developerInstructions;
|
|
73120
74307
|
try {
|
|
73121
74308
|
developerInstructions = resolveDeveloperInstructionsFromArgs(process.argv);
|
|
@@ -73129,7 +74316,8 @@ async function startChat(initialPrompt, testCommand) {
|
|
|
73129
74316
|
explicitSessionId,
|
|
73130
74317
|
resumeRequired,
|
|
73131
74318
|
developerInstructions,
|
|
73132
|
-
mockResponse: process.env.PIE_TEST_MOCK_RESPONSE
|
|
74319
|
+
mockResponse: process.env.PIE_TEST_MOCK_RESPONSE,
|
|
74320
|
+
eventDetail
|
|
73133
74321
|
});
|
|
73134
74322
|
return;
|
|
73135
74323
|
}
|
|
@@ -73137,6 +74325,7 @@ async function startChat(initialPrompt, testCommand) {
|
|
|
73137
74325
|
explicitSessionId,
|
|
73138
74326
|
resumeRequired,
|
|
73139
74327
|
developerInstructions,
|
|
74328
|
+
eventDetail,
|
|
73140
74329
|
streamFn: await createCliTestStreamFnFromEnv(),
|
|
73141
74330
|
createRuntime: async ({ cwd, sessionId }) => composeCliRuntime({
|
|
73142
74331
|
explicitSessionId: explicitSessionId ?? sessionId,
|
|
@@ -73223,6 +74412,16 @@ async function main() {
|
|
|
73223
74412
|
console.log(VERSION);
|
|
73224
74413
|
return;
|
|
73225
74414
|
}
|
|
74415
|
+
if (args.length === 0 && !process.stdin.isTTY) {
|
|
74416
|
+
console.error("pie: no arguments and stdin is not a terminal; refusing to start interactive mode.");
|
|
74417
|
+
showHelp();
|
|
74418
|
+
process.exitCode = 1;
|
|
74419
|
+
return;
|
|
74420
|
+
}
|
|
74421
|
+
if (args[0] === STABLE_CLI_COMMANDS.capabilities) {
|
|
74422
|
+
runCapabilitiesCommand(args.slice(1));
|
|
74423
|
+
return;
|
|
74424
|
+
}
|
|
73226
74425
|
if (args[0] === STABLE_CLI_COMMANDS.doctor) {
|
|
73227
74426
|
await runDoctorCommand(args.slice(1));
|
|
73228
74427
|
return;
|
|
@@ -73245,7 +74444,7 @@ async function main() {
|
|
|
73245
74444
|
return;
|
|
73246
74445
|
}
|
|
73247
74446
|
if (args[0] === STABLE_CLI_COMMANDS.permissions) {
|
|
73248
|
-
|
|
74447
|
+
runPermissionsCommand(args.slice(1));
|
|
73249
74448
|
return;
|
|
73250
74449
|
}
|
|
73251
74450
|
const parsed = parseCliInvocation(args);
|