@cydm/pie 1.0.46 → 1.0.48
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/README.md +21 -1
- 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 +2316 -894
- 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
|
|
@@ -50833,6 +51654,33 @@ var SelectList = class {
|
|
|
50833
51654
|
}
|
|
50834
51655
|
invalidate() {
|
|
50835
51656
|
}
|
|
51657
|
+
/**
|
|
51658
|
+
* Lay out one item row: label (left column) + description (right column).
|
|
51659
|
+
*
|
|
51660
|
+
* The label column is sized from the actual labels and the available
|
|
51661
|
+
* width. The previous fixed 30-column cap truncated long commands (e.g.
|
|
51662
|
+
* /skills/skill:terminal-pty-testing) even on wide terminals.
|
|
51663
|
+
*/
|
|
51664
|
+
renderLabelParts(prefix, displayValue, descriptionSingleLine, useDescriptionColumn, labelColumnWidth, width) {
|
|
51665
|
+
const prefixWidth = visibleWidth(prefix);
|
|
51666
|
+
if (useDescriptionColumn && descriptionSingleLine) {
|
|
51667
|
+
const truncatedValue = truncateToWidth(displayValue, labelColumnWidth, "");
|
|
51668
|
+
const valueWidth = visibleWidth(truncatedValue);
|
|
51669
|
+
const spacing = " ".repeat(Math.max(1, labelColumnWidth - valueWidth + 2));
|
|
51670
|
+
const descriptionStart = prefixWidth + valueWidth + spacing.length;
|
|
51671
|
+
const remainingWidth = width - descriptionStart - 2;
|
|
51672
|
+
if (remainingWidth > 10) {
|
|
51673
|
+
return {
|
|
51674
|
+
value: truncatedValue,
|
|
51675
|
+
spacing,
|
|
51676
|
+
desc: truncateToWidth(descriptionSingleLine, remainingWidth, "")
|
|
51677
|
+
};
|
|
51678
|
+
}
|
|
51679
|
+
return { value: truncateToWidth(displayValue, width - prefixWidth - 2, ""), spacing: "", desc: "" };
|
|
51680
|
+
}
|
|
51681
|
+
const maxWidth = width - prefixWidth - 2;
|
|
51682
|
+
return { value: truncateToWidth(displayValue, maxWidth, ""), spacing: "", desc: "" };
|
|
51683
|
+
}
|
|
50836
51684
|
render(width) {
|
|
50837
51685
|
const lines = [];
|
|
50838
51686
|
if (this.filteredItems.length === 0) {
|
|
@@ -50840,54 +51688,35 @@ var SelectList = class {
|
|
|
50840
51688
|
return lines;
|
|
50841
51689
|
}
|
|
50842
51690
|
const { startIndex, endIndex } = this.getVisibleRange();
|
|
51691
|
+
const useDescriptionColumn = this.filteredItems.some((item) => item.description) && width > 40;
|
|
51692
|
+
let labelColumnWidth = 0;
|
|
51693
|
+
if (useDescriptionColumn) {
|
|
51694
|
+
const maxLabelWidth = Math.max(
|
|
51695
|
+
...this.filteredItems.map((item) => visibleWidth(item.label || item.value))
|
|
51696
|
+
);
|
|
51697
|
+
labelColumnWidth = Math.max(8, Math.min(maxLabelWidth, Math.floor(width * 0.45)));
|
|
51698
|
+
}
|
|
50843
51699
|
for (let i = startIndex; i < endIndex; i++) {
|
|
50844
51700
|
const item = this.filteredItems[i];
|
|
50845
51701
|
if (!item) continue;
|
|
50846
51702
|
const isSelected = i === this.selectedIndex;
|
|
50847
51703
|
const descriptionSingleLine = item.description ? normalizeToSingleLine(item.description) : void 0;
|
|
51704
|
+
const displayValue = item.label || item.value;
|
|
50848
51705
|
let line = "";
|
|
50849
51706
|
if (isSelected) {
|
|
50850
|
-
const
|
|
50851
|
-
|
|
50852
|
-
|
|
50853
|
-
|
|
50854
|
-
|
|
50855
|
-
|
|
50856
|
-
const spacing = " ".repeat(Math.max(1, 32 - valueWidth));
|
|
50857
|
-
const descriptionStart = prefixWidth + valueWidth + spacing.length;
|
|
50858
|
-
const remainingWidth = width - descriptionStart - 2;
|
|
50859
|
-
if (remainingWidth > 10) {
|
|
50860
|
-
const truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, "");
|
|
50861
|
-
line = truncateToWidth(this.theme.selectedText(`\u2192 ${truncatedValue}${spacing}${truncatedDesc}`), width, "");
|
|
50862
|
-
} else {
|
|
50863
|
-
const maxWidth = width - prefixWidth - 2;
|
|
50864
|
-
line = truncateToWidth(this.theme.selectedText(`\u2192 ${truncateToWidth(displayValue, maxWidth, "")}`), width, "");
|
|
50865
|
-
}
|
|
50866
|
-
} else {
|
|
50867
|
-
const maxWidth = width - prefixWidth - 2;
|
|
50868
|
-
line = truncateToWidth(this.theme.selectedText(`\u2192 ${truncateToWidth(displayValue, maxWidth, "")}`), width, "");
|
|
50869
|
-
}
|
|
51707
|
+
const parts = this.renderLabelParts("\u2192 ", displayValue, descriptionSingleLine, useDescriptionColumn, labelColumnWidth, width);
|
|
51708
|
+
line = truncateToWidth(
|
|
51709
|
+
this.theme.selectedText(`\u2192 ${parts.value}${parts.spacing}${parts.desc}`),
|
|
51710
|
+
width,
|
|
51711
|
+
""
|
|
51712
|
+
);
|
|
50870
51713
|
} else {
|
|
50871
|
-
const
|
|
50872
|
-
|
|
50873
|
-
|
|
50874
|
-
|
|
50875
|
-
const truncatedValue = truncateToWidth(displayValue, maxValueWidth, "");
|
|
50876
|
-
const valueWidth = visibleWidth(truncatedValue);
|
|
50877
|
-
const spacing = " ".repeat(Math.max(1, 32 - valueWidth));
|
|
50878
|
-
const descriptionStart = prefix.length + valueWidth + spacing.length;
|
|
50879
|
-
const remainingWidth = width - descriptionStart - 2;
|
|
50880
|
-
if (remainingWidth > 10) {
|
|
50881
|
-
const truncatedDesc = truncateToWidth(descriptionSingleLine, remainingWidth, "");
|
|
50882
|
-
const descText = this.theme.description(spacing + truncatedDesc);
|
|
50883
|
-
line = truncateToWidth(prefix + truncatedValue + descText, width, "");
|
|
50884
|
-
} else {
|
|
50885
|
-
const maxWidth = width - prefix.length - 2;
|
|
50886
|
-
line = truncateToWidth(prefix + truncateToWidth(displayValue, maxWidth, ""), width, "");
|
|
50887
|
-
}
|
|
51714
|
+
const parts = this.renderLabelParts(" ", displayValue, descriptionSingleLine, useDescriptionColumn, labelColumnWidth, width);
|
|
51715
|
+
if (parts.desc) {
|
|
51716
|
+
const descText = this.theme.description(parts.spacing + parts.desc);
|
|
51717
|
+
line = truncateToWidth(" " + parts.value + descText, width, "");
|
|
50888
51718
|
} else {
|
|
50889
|
-
|
|
50890
|
-
line = truncateToWidth(prefix + truncateToWidth(displayValue, maxWidth, ""), width, "");
|
|
51719
|
+
line = truncateToWidth(" " + parts.value, width, "");
|
|
50891
51720
|
}
|
|
50892
51721
|
}
|
|
50893
51722
|
lines.push(truncateToWidth(line, width, ""));
|
|
@@ -51026,6 +51855,13 @@ var Editor = class {
|
|
|
51026
51855
|
autocompleteState = null;
|
|
51027
51856
|
autocompletePrefix = "";
|
|
51028
51857
|
autocompleteMaxVisible = 5;
|
|
51858
|
+
/**
|
|
51859
|
+
* Whether the user moved the autocomplete selection (arrows/paging).
|
|
51860
|
+
* A bare "/" + Enter still submits the slash itself (root command menu),
|
|
51861
|
+
* but once the user has actively highlighted an item, Enter must accept
|
|
51862
|
+
* that selection instead of re-opening the same menu.
|
|
51863
|
+
*/
|
|
51864
|
+
autocompleteListTouched = false;
|
|
51029
51865
|
// Paste tracking for large pastes
|
|
51030
51866
|
pastes = /* @__PURE__ */ new Map();
|
|
51031
51867
|
pasteCounter = 0;
|
|
@@ -51262,6 +52098,12 @@ var Editor = class {
|
|
|
51262
52098
|
return;
|
|
51263
52099
|
}
|
|
51264
52100
|
if (kb.matches(data, "selectUp") || kb.matches(data, "selectDown")) {
|
|
52101
|
+
this.autocompleteListTouched = true;
|
|
52102
|
+
this.autocompleteList.handleInput(data);
|
|
52103
|
+
return;
|
|
52104
|
+
}
|
|
52105
|
+
if (kb.matches(data, "cursorLeft") || kb.matches(data, "cursorRight") || kb.matches(data, "pageUp") || kb.matches(data, "pageDown")) {
|
|
52106
|
+
this.autocompleteListTouched = true;
|
|
51265
52107
|
this.autocompleteList.handleInput(data);
|
|
51266
52108
|
return;
|
|
51267
52109
|
}
|
|
@@ -51287,7 +52129,7 @@ var Editor = class {
|
|
|
51287
52129
|
}
|
|
51288
52130
|
if (kb.matches(data, "selectConfirm")) {
|
|
51289
52131
|
const currentLine = this.state.lines[this.state.cursorLine] || "";
|
|
51290
|
-
const isBareSlashSubmit = this.state.lines.length === 1 && currentLine === "/" && this.state.cursorCol === 1;
|
|
52132
|
+
const isBareSlashSubmit = !this.autocompleteListTouched && this.state.lines.length === 1 && currentLine === "/" && this.state.cursorCol === 1;
|
|
51291
52133
|
if (isBareSlashSubmit) {
|
|
51292
52134
|
this.cancelAutocomplete();
|
|
51293
52135
|
} else {
|
|
@@ -52307,12 +53149,29 @@ var Editor = class {
|
|
|
52307
53149
|
);
|
|
52308
53150
|
if (suggestions && suggestions.items.length > 0) {
|
|
52309
53151
|
this.autocompletePrefix = suggestions.prefix;
|
|
52310
|
-
this.
|
|
53152
|
+
this.autocompleteListTouched = false;
|
|
53153
|
+
this.autocompleteList = new SelectList(
|
|
53154
|
+
suggestions.items,
|
|
53155
|
+
this.computeAutocompleteMaxVisible(suggestions.items.length),
|
|
53156
|
+
this.theme.selectList
|
|
53157
|
+
);
|
|
52311
53158
|
this.autocompleteState = "regular";
|
|
52312
53159
|
} else {
|
|
52313
53160
|
this.cancelAutocomplete();
|
|
52314
53161
|
}
|
|
52315
53162
|
}
|
|
53163
|
+
/**
|
|
53164
|
+
* Visible autocomplete rows, scaled with terminal height so tall screens
|
|
53165
|
+
* show the full command list instead of paginating five rows at a time.
|
|
53166
|
+
* Floor: the configured max (default 5). Ceiling: ~45% of rows, capped at
|
|
53167
|
+
* 20 so a huge terminal never dedicates half the screen to suggestions.
|
|
53168
|
+
*/
|
|
53169
|
+
computeAutocompleteMaxVisible(itemCount) {
|
|
53170
|
+
const rows = this.tui.terminal.rows;
|
|
53171
|
+
const heightScaled = Number.isFinite(rows) ? Math.floor(rows * 0.45) : this.autocompleteMaxVisible;
|
|
53172
|
+
const desired = Math.max(this.autocompleteMaxVisible, Math.min(heightScaled, 20));
|
|
53173
|
+
return Math.max(1, Math.min(desired, Math.max(itemCount, 1)));
|
|
53174
|
+
}
|
|
52316
53175
|
handleTabCompletion() {
|
|
52317
53176
|
if (!this.autocompleteProvider) return;
|
|
52318
53177
|
const currentLine = this.state.lines[this.state.cursorLine] || "";
|
|
@@ -52362,7 +53221,12 @@ var Editor = class {
|
|
|
52362
53221
|
return;
|
|
52363
53222
|
}
|
|
52364
53223
|
this.autocompletePrefix = suggestions.prefix;
|
|
52365
|
-
this.
|
|
53224
|
+
this.autocompleteListTouched = false;
|
|
53225
|
+
this.autocompleteList = new SelectList(
|
|
53226
|
+
suggestions.items,
|
|
53227
|
+
this.computeAutocompleteMaxVisible(suggestions.items.length),
|
|
53228
|
+
this.theme.selectList
|
|
53229
|
+
);
|
|
52366
53230
|
this.autocompleteState = "force";
|
|
52367
53231
|
} else {
|
|
52368
53232
|
this.cancelAutocomplete();
|
|
@@ -52372,6 +53236,7 @@ var Editor = class {
|
|
|
52372
53236
|
this.autocompleteState = null;
|
|
52373
53237
|
this.autocompleteList = void 0;
|
|
52374
53238
|
this.autocompletePrefix = "";
|
|
53239
|
+
this.autocompleteListTouched = false;
|
|
52375
53240
|
}
|
|
52376
53241
|
isShowingAutocomplete() {
|
|
52377
53242
|
return this.autocompleteState !== null;
|
|
@@ -52389,7 +53254,11 @@ var Editor = class {
|
|
|
52389
53254
|
);
|
|
52390
53255
|
if (suggestions && suggestions.items.length > 0) {
|
|
52391
53256
|
this.autocompletePrefix = suggestions.prefix;
|
|
52392
|
-
this.autocompleteList = new SelectList(
|
|
53257
|
+
this.autocompleteList = new SelectList(
|
|
53258
|
+
suggestions.items,
|
|
53259
|
+
this.computeAutocompleteMaxVisible(suggestions.items.length),
|
|
53260
|
+
this.theme.selectList
|
|
53261
|
+
);
|
|
52393
53262
|
} else {
|
|
52394
53263
|
this.cancelAutocomplete();
|
|
52395
53264
|
}
|
|
@@ -54573,6 +55442,17 @@ var SettingsList = class {
|
|
|
54573
55442
|
item.currentValue = newValue;
|
|
54574
55443
|
}
|
|
54575
55444
|
}
|
|
55445
|
+
/**
|
|
55446
|
+
* Move the selection to an item by id (respects the active filter).
|
|
55447
|
+
* Used when a command targets a specific row (e.g. /settings/theme).
|
|
55448
|
+
*/
|
|
55449
|
+
focusItemById(id) {
|
|
55450
|
+
const displayItems = this.searchEnabled ? this.filteredItems : this.items;
|
|
55451
|
+
const index = displayItems.findIndex((item) => item.id === id);
|
|
55452
|
+
if (index >= 0) {
|
|
55453
|
+
this.selectedIndex = index;
|
|
55454
|
+
}
|
|
55455
|
+
}
|
|
54576
55456
|
invalidate() {
|
|
54577
55457
|
this.submenuComponent?.invalidate?.();
|
|
54578
55458
|
}
|
|
@@ -55703,6 +56583,267 @@ function wrapToolsWithExtensions(tools, runner) {
|
|
|
55703
56583
|
return tools.map((tool) => wrapToolWithExtensions(tool, runner));
|
|
55704
56584
|
}
|
|
55705
56585
|
|
|
56586
|
+
// src/core/defaults.ts
|
|
56587
|
+
var DEFAULT_THINKING_LEVEL = "medium";
|
|
56588
|
+
|
|
56589
|
+
// src/core/model-resolver.ts
|
|
56590
|
+
function normalizeProviderName(provider) {
|
|
56591
|
+
return provider.toLowerCase().replace(/[^a-z]/g, "");
|
|
56592
|
+
}
|
|
56593
|
+
function selectFallbackModel(registry, preferred) {
|
|
56594
|
+
const availableModels = registry.getAvailable();
|
|
56595
|
+
if (preferred?.provider && preferred?.modelId) {
|
|
56596
|
+
const exact = availableModels.find(
|
|
56597
|
+
(model) => model.provider === preferred.provider && model.id === preferred.modelId
|
|
56598
|
+
);
|
|
56599
|
+
if (exact) return exact;
|
|
56600
|
+
}
|
|
56601
|
+
if (preferred?.provider) {
|
|
56602
|
+
const sameProvider = availableModels.find((model) => model.provider === preferred.provider);
|
|
56603
|
+
if (sameProvider) return sameProvider;
|
|
56604
|
+
}
|
|
56605
|
+
return availableModels[0] || registry.getAll()[0];
|
|
56606
|
+
}
|
|
56607
|
+
function resolveConfiguredModel(registry, provider, modelId) {
|
|
56608
|
+
const exact = registry.find(provider, modelId);
|
|
56609
|
+
if (exact) {
|
|
56610
|
+
return { model: exact, provider, modelId, corrected: false };
|
|
56611
|
+
}
|
|
56612
|
+
const allModels = registry.getAll();
|
|
56613
|
+
if (allModels.length === 0) {
|
|
56614
|
+
throw new Error("No registered models are available.");
|
|
56615
|
+
}
|
|
56616
|
+
const sameIdMatches = allModels.filter((model) => model.id === modelId);
|
|
56617
|
+
const normalizedProviderMatches = sameIdMatches.filter(
|
|
56618
|
+
(model) => normalizeProviderName(model.provider) === normalizeProviderName(provider)
|
|
56619
|
+
);
|
|
56620
|
+
if (normalizedProviderMatches.length === 1) {
|
|
56621
|
+
const matched = normalizedProviderMatches[0];
|
|
56622
|
+
return {
|
|
56623
|
+
model: matched,
|
|
56624
|
+
provider: matched.provider,
|
|
56625
|
+
modelId: matched.id,
|
|
56626
|
+
corrected: true,
|
|
56627
|
+
warning: `Configured model "${provider}/${modelId}" was not found. Using "${matched.provider}/${matched.id}" instead.`
|
|
56628
|
+
};
|
|
56629
|
+
}
|
|
56630
|
+
if (sameIdMatches.length === 1) {
|
|
56631
|
+
const matched = sameIdMatches[0];
|
|
56632
|
+
return {
|
|
56633
|
+
model: matched,
|
|
56634
|
+
provider: matched.provider,
|
|
56635
|
+
modelId: matched.id,
|
|
56636
|
+
corrected: true,
|
|
56637
|
+
warning: `Configured model "${provider}/${modelId}" was not found. Reusing the available model "${matched.provider}/${matched.id}".`
|
|
56638
|
+
};
|
|
56639
|
+
}
|
|
56640
|
+
const providerModels = registry.getByProvider(provider);
|
|
56641
|
+
if (providerModels.length > 0) {
|
|
56642
|
+
const fallback2 = providerModels[0];
|
|
56643
|
+
return {
|
|
56644
|
+
model: fallback2,
|
|
56645
|
+
provider: fallback2.provider,
|
|
56646
|
+
modelId: fallback2.id,
|
|
56647
|
+
corrected: true,
|
|
56648
|
+
warning: `Configured model "${provider}/${modelId}" was not found. Falling back to "${fallback2.provider}/${fallback2.id}".`
|
|
56649
|
+
};
|
|
56650
|
+
}
|
|
56651
|
+
const fallback = selectFallbackModel(registry);
|
|
56652
|
+
if (!fallback) {
|
|
56653
|
+
throw new Error("No registered models are available.");
|
|
56654
|
+
}
|
|
56655
|
+
return {
|
|
56656
|
+
model: fallback,
|
|
56657
|
+
provider: fallback.provider,
|
|
56658
|
+
modelId: fallback.id,
|
|
56659
|
+
corrected: true,
|
|
56660
|
+
warning: `Configured model "${provider}/${modelId}" was not found. Falling back to "${fallback.provider}/${fallback.id}".`
|
|
56661
|
+
};
|
|
56662
|
+
}
|
|
56663
|
+
function findInitialModel(options) {
|
|
56664
|
+
const configDefaults = options.registry.getConfigDefaults();
|
|
56665
|
+
const configuredProvider = options.configuredProvider || configDefaults?.provider;
|
|
56666
|
+
const configuredModelId = options.configuredModelId || configDefaults?.modelId;
|
|
56667
|
+
const resolved = configuredProvider && configuredModelId ? resolveConfiguredModel(options.registry, configuredProvider, configuredModelId) : void 0;
|
|
56668
|
+
const apiKey = resolved ? options.registry.getApiKey(resolved.model) : void 0;
|
|
56669
|
+
if (!resolved || !apiKey) {
|
|
56670
|
+
const fallback = selectFallbackModel(options.registry, {
|
|
56671
|
+
provider: configuredProvider,
|
|
56672
|
+
modelId: configuredModelId
|
|
56673
|
+
});
|
|
56674
|
+
if (!fallback) {
|
|
56675
|
+
return {
|
|
56676
|
+
model: void 0,
|
|
56677
|
+
apiKey: void 0,
|
|
56678
|
+
provider: void 0,
|
|
56679
|
+
modelId: void 0,
|
|
56680
|
+
unconfigured: true,
|
|
56681
|
+
warning: "No models are configured. Add one in ~/.pie/models.json before sending messages."
|
|
56682
|
+
};
|
|
56683
|
+
}
|
|
56684
|
+
const fallbackKey = options.registry.getApiKey(fallback);
|
|
56685
|
+
if (!fallbackKey) {
|
|
56686
|
+
throw new Error(`No API key found for provider "${resolved?.provider || fallback.provider}".`);
|
|
56687
|
+
}
|
|
56688
|
+
return {
|
|
56689
|
+
model: fallback,
|
|
56690
|
+
apiKey: fallbackKey,
|
|
56691
|
+
provider: fallback.provider,
|
|
56692
|
+
modelId: fallback.id,
|
|
56693
|
+
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
|
|
56694
|
+
};
|
|
56695
|
+
}
|
|
56696
|
+
return {
|
|
56697
|
+
model: resolved.model,
|
|
56698
|
+
apiKey,
|
|
56699
|
+
provider: resolved.provider,
|
|
56700
|
+
modelId: resolved.modelId,
|
|
56701
|
+
warning: resolved.warning
|
|
56702
|
+
};
|
|
56703
|
+
}
|
|
56704
|
+
function restoreModelFromSession(options) {
|
|
56705
|
+
const savedProvider = options.savedProvider;
|
|
56706
|
+
const restored = options.registry.find(savedProvider, options.savedModelId);
|
|
56707
|
+
if (restored && options.registry.getApiKey(restored)) {
|
|
56708
|
+
return { model: restored };
|
|
56709
|
+
}
|
|
56710
|
+
if (options.currentModel) {
|
|
56711
|
+
return {
|
|
56712
|
+
model: options.currentModel,
|
|
56713
|
+
fallbackMessage: `Could not restore model ${savedProvider}/${options.savedModelId}. Using ${options.currentModel.provider}/${options.currentModel.id}.`
|
|
56714
|
+
};
|
|
56715
|
+
}
|
|
56716
|
+
const fallback = selectFallbackModel(options.registry, {
|
|
56717
|
+
provider: savedProvider,
|
|
56718
|
+
modelId: options.savedModelId
|
|
56719
|
+
});
|
|
56720
|
+
return fallback ? {
|
|
56721
|
+
model: fallback,
|
|
56722
|
+
fallbackMessage: `Could not restore model ${savedProvider}/${options.savedModelId}. Using ${fallback.provider}/${fallback.id}.`
|
|
56723
|
+
} : { model: void 0 };
|
|
56724
|
+
}
|
|
56725
|
+
|
|
56726
|
+
// src/core/session-model-metadata.ts
|
|
56727
|
+
function getSavedSessionModelSelection(activeSession) {
|
|
56728
|
+
if (!activeSession) return {};
|
|
56729
|
+
const provider = typeof activeSession.metadata.provider === "string" ? activeSession.metadata.provider : typeof activeSession.metadata.defaultProvider === "string" ? activeSession.metadata.defaultProvider : void 0;
|
|
56730
|
+
const modelId = typeof activeSession.metadata.modelId === "string" ? activeSession.metadata.modelId : typeof activeSession.metadata.defaultModel === "string" ? activeSession.metadata.defaultModel : void 0;
|
|
56731
|
+
const thinkingLevel = typeof activeSession.metadata.thinkingLevel === "string" ? activeSession.metadata.thinkingLevel : void 0;
|
|
56732
|
+
return { provider, modelId, thinkingLevel };
|
|
56733
|
+
}
|
|
56734
|
+
function syncSessionModelMetadata(sessionManager, model, thinkingLevel) {
|
|
56735
|
+
const activeSession = sessionManager.getActiveSession();
|
|
56736
|
+
if (!activeSession || !model) return;
|
|
56737
|
+
activeSession.metadata.provider = model.provider;
|
|
56738
|
+
activeSession.metadata.modelId = model.id;
|
|
56739
|
+
activeSession.metadata.defaultProvider = model.provider;
|
|
56740
|
+
activeSession.metadata.defaultModel = model.id;
|
|
56741
|
+
activeSession.metadata.thinkingLevel = thinkingLevel;
|
|
56742
|
+
activeSession.isDirty = true;
|
|
56743
|
+
}
|
|
56744
|
+
function restoreSessionModelState(options) {
|
|
56745
|
+
const { provider, modelId, thinkingLevel } = getSavedSessionModelSelection(options.activeSession);
|
|
56746
|
+
if (!provider || !modelId) {
|
|
56747
|
+
return {
|
|
56748
|
+
model: options.currentModel,
|
|
56749
|
+
thinkingLevel
|
|
56750
|
+
};
|
|
56751
|
+
}
|
|
56752
|
+
const restored = restoreModelFromSession({
|
|
56753
|
+
registry: options.registry,
|
|
56754
|
+
savedProvider: provider,
|
|
56755
|
+
savedModelId: modelId,
|
|
56756
|
+
currentModel: options.currentModel
|
|
56757
|
+
});
|
|
56758
|
+
return {
|
|
56759
|
+
model: restored.model,
|
|
56760
|
+
thinkingLevel,
|
|
56761
|
+
fallbackMessage: restored.fallbackMessage
|
|
56762
|
+
};
|
|
56763
|
+
}
|
|
56764
|
+
|
|
56765
|
+
// src/core/interactive-model-state.ts
|
|
56766
|
+
var THINKING_LEVELS = [
|
|
56767
|
+
"off",
|
|
56768
|
+
"minimal",
|
|
56769
|
+
"low",
|
|
56770
|
+
"medium",
|
|
56771
|
+
"high",
|
|
56772
|
+
"xhigh"
|
|
56773
|
+
];
|
|
56774
|
+
var THINKING_LEVEL_DESCRIPTIONS = {
|
|
56775
|
+
off: "No reasoning",
|
|
56776
|
+
minimal: "Very brief reasoning (~1k tokens)",
|
|
56777
|
+
low: "Light reasoning (~2k tokens)",
|
|
56778
|
+
medium: "Moderate reasoning (~8k tokens)",
|
|
56779
|
+
high: "Deep reasoning (~16k tokens)",
|
|
56780
|
+
xhigh: "Maximum reasoning (~32k tokens)"
|
|
56781
|
+
};
|
|
56782
|
+
function isThinkingLevel(value) {
|
|
56783
|
+
return THINKING_LEVELS.includes(value);
|
|
56784
|
+
}
|
|
56785
|
+
function resolveInitialThinkingLevel(options) {
|
|
56786
|
+
const sessionLevel = options.session?.metadata.thinkingLevel;
|
|
56787
|
+
if (typeof sessionLevel === "string" && isThinkingLevel(sessionLevel)) {
|
|
56788
|
+
return sessionLevel;
|
|
56789
|
+
}
|
|
56790
|
+
return options.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;
|
|
56791
|
+
}
|
|
56792
|
+
function maskApiKey(key) {
|
|
56793
|
+
if (key.length <= 6) return "***";
|
|
56794
|
+
return key.slice(0, 6) + "***";
|
|
56795
|
+
}
|
|
56796
|
+
function applyThinkingLevel(options) {
|
|
56797
|
+
options.agent.setThinkingLevel(options.level);
|
|
56798
|
+
options.settingsManager.setDefaultThinkingLevel(options.level);
|
|
56799
|
+
syncSessionModelMetadata(options.sessionManager, options.model, options.level);
|
|
56800
|
+
}
|
|
56801
|
+
function switchInteractiveModel(options) {
|
|
56802
|
+
const [provider, modelId] = options.fullModelId.split("/");
|
|
56803
|
+
const model = options.registry.find(provider, modelId);
|
|
56804
|
+
if (!model) {
|
|
56805
|
+
throw new Error(`Model "${options.fullModelId}" not found`);
|
|
56806
|
+
}
|
|
56807
|
+
const apiKey = options.registry.getApiKey(model);
|
|
56808
|
+
options.agent.setModel(model);
|
|
56809
|
+
if (apiKey) {
|
|
56810
|
+
options.agent.apiKey = apiKey;
|
|
56811
|
+
fileLogger.log("cli", `Switched model to ${options.fullModelId}, updated API key`, {
|
|
56812
|
+
keyPrefix: maskApiKey(apiKey)
|
|
56813
|
+
});
|
|
56814
|
+
} else {
|
|
56815
|
+
fileLogger.log("cli", `Switched model to ${options.fullModelId}, no API key found`);
|
|
56816
|
+
}
|
|
56817
|
+
options.settingsManager.setDefaultModelAndProvider(provider, modelId);
|
|
56818
|
+
syncSessionModelMetadata(options.sessionManager, model, options.thinkingLevel);
|
|
56819
|
+
return { model, apiKey };
|
|
56820
|
+
}
|
|
56821
|
+
function restoreInteractiveSessionState(options) {
|
|
56822
|
+
const restored = restoreSessionModelState({
|
|
56823
|
+
activeSession: options.activeSession,
|
|
56824
|
+
registry: options.registry,
|
|
56825
|
+
currentModel: options.currentModel
|
|
56826
|
+
});
|
|
56827
|
+
const thinkingLevel = restored.thinkingLevel && isThinkingLevel(restored.thinkingLevel) ? restored.thinkingLevel : void 0;
|
|
56828
|
+
if (thinkingLevel) {
|
|
56829
|
+
options.agent.setThinkingLevel(thinkingLevel);
|
|
56830
|
+
}
|
|
56831
|
+
let apiKey;
|
|
56832
|
+
if (restored.model) {
|
|
56833
|
+
options.agent.setModel(restored.model);
|
|
56834
|
+
apiKey = options.registry.getApiKey(restored.model);
|
|
56835
|
+
if (apiKey) {
|
|
56836
|
+
options.agent.apiKey = apiKey;
|
|
56837
|
+
}
|
|
56838
|
+
}
|
|
56839
|
+
return {
|
|
56840
|
+
model: restored.model,
|
|
56841
|
+
apiKey,
|
|
56842
|
+
thinkingLevel,
|
|
56843
|
+
fallbackMessage: restored.fallbackMessage
|
|
56844
|
+
};
|
|
56845
|
+
}
|
|
56846
|
+
|
|
55706
56847
|
// src/keybindings.ts
|
|
55707
56848
|
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
|
|
55708
56849
|
import { join as join7 } from "path";
|
|
@@ -56829,23 +57970,23 @@ function parseThemeJson(label, json) {
|
|
|
56829
57970
|
otherErrors.push(` - ${e.path}: ${e.message}`);
|
|
56830
57971
|
}
|
|
56831
57972
|
}
|
|
56832
|
-
let
|
|
57973
|
+
let errorMessage4 = `Invalid theme "${label}":
|
|
56833
57974
|
`;
|
|
56834
57975
|
if (missingColors.length > 0) {
|
|
56835
|
-
|
|
56836
|
-
|
|
56837
|
-
|
|
57976
|
+
errorMessage4 += "\nMissing required color tokens:\n";
|
|
57977
|
+
errorMessage4 += missingColors.map((c) => ` - ${c}`).join("\n");
|
|
57978
|
+
errorMessage4 += `
|
|
56838
57979
|
|
|
56839
57980
|
Please add these colors to your theme's "colors" object.`;
|
|
56840
|
-
|
|
57981
|
+
errorMessage4 += "\nSee the built-in themes (dark.json, light.json) for reference values.";
|
|
56841
57982
|
}
|
|
56842
57983
|
if (otherErrors.length > 0) {
|
|
56843
|
-
|
|
57984
|
+
errorMessage4 += `
|
|
56844
57985
|
|
|
56845
57986
|
Other errors:
|
|
56846
57987
|
${otherErrors.join("\n")}`;
|
|
56847
57988
|
}
|
|
56848
|
-
throw new Error(
|
|
57989
|
+
throw new Error(errorMessage4);
|
|
56849
57990
|
}
|
|
56850
57991
|
return json;
|
|
56851
57992
|
}
|
|
@@ -61259,263 +62400,15 @@ var SettingsSelectorComponent = class extends Container {
|
|
|
61259
62400
|
{ enableSearch: true }
|
|
61260
62401
|
);
|
|
61261
62402
|
this.addChild(this.settingsList);
|
|
62403
|
+
if (config.focusItem) {
|
|
62404
|
+
this.settingsList.focusItemById(config.focusItem);
|
|
62405
|
+
}
|
|
61262
62406
|
}
|
|
61263
62407
|
getSettingsList() {
|
|
61264
62408
|
return this.settingsList;
|
|
61265
62409
|
}
|
|
61266
62410
|
};
|
|
61267
62411
|
|
|
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
62412
|
// src/core/session-display.ts
|
|
61520
62413
|
function deriveSessionTitle(options) {
|
|
61521
62414
|
const { activeSession, messages } = options;
|
|
@@ -61616,36 +62509,6 @@ function selectRuntimeExtensionWinners(infos) {
|
|
|
61616
62509
|
}
|
|
61617
62510
|
return reversed.reverse();
|
|
61618
62511
|
}
|
|
61619
|
-
var ExtensionStateSubmenu = class extends Container {
|
|
61620
|
-
selectList;
|
|
61621
|
-
constructor(identity, currentValue, scope, onSelect, onCommitted, onCancel) {
|
|
61622
|
-
super();
|
|
61623
|
-
this.addChild(new Text(theme.bold(theme.fg("accent", identity)), 0, 0));
|
|
61624
|
-
this.addChild(new Spacer(1));
|
|
61625
|
-
const settingsPath = scope === "project" ? "./.pie/settings.json" : "~/.pie/settings.json";
|
|
61626
|
-
this.addChild(new Text(theme.fg("muted", `Save an override in ${settingsPath}`), 0, 0));
|
|
61627
|
-
this.addChild(new Spacer(1));
|
|
61628
|
-
const options = [
|
|
61629
|
-
{ value: "on", label: "On", description: "Enable on next start" },
|
|
61630
|
-
{ value: "off", label: "Off", description: "Disable on next start" }
|
|
61631
|
-
];
|
|
61632
|
-
this.selectList = new SelectList(options, options.length, getSelectListTheme());
|
|
61633
|
-
this.selectList.setSelectedIndex(currentValue === "off" ? 1 : 0);
|
|
61634
|
-
this.selectList.onSelect = (item) => {
|
|
61635
|
-
const effective = onSelect(item.value === "on");
|
|
61636
|
-
if (effective !== void 0) {
|
|
61637
|
-
onCommitted(effective);
|
|
61638
|
-
}
|
|
61639
|
-
};
|
|
61640
|
-
this.selectList.onCancel = onCancel;
|
|
61641
|
-
this.addChild(this.selectList);
|
|
61642
|
-
this.addChild(new Spacer(1));
|
|
61643
|
-
this.addChild(new Text(theme.fg("dim", " Enter to select \xB7 Esc to go back"), 0, 0));
|
|
61644
|
-
}
|
|
61645
|
-
handleInput(data) {
|
|
61646
|
-
this.selectList.handleInput(data);
|
|
61647
|
-
}
|
|
61648
|
-
};
|
|
61649
62512
|
function unidentifiedLabel(info) {
|
|
61650
62513
|
const parentName = path23.basename(path23.dirname(info.entryPath));
|
|
61651
62514
|
const fileName = path23.basename(info.entryPath);
|
|
@@ -61666,37 +62529,41 @@ var ExtensionEnablementSelectorComponent = class extends Container {
|
|
|
61666
62529
|
0
|
|
61667
62530
|
));
|
|
61668
62531
|
this.addChild(new Spacer(1));
|
|
62532
|
+
const identityById = /* @__PURE__ */ new Map();
|
|
62533
|
+
const lastPersistedValue = /* @__PURE__ */ new Map();
|
|
61669
62534
|
const items = selectRuntimeExtensionWinners(infos).map((info, index) => {
|
|
61670
62535
|
const identity = info.identity;
|
|
61671
62536
|
const descriptionParts = [`Source: ${info.source}`];
|
|
61672
62537
|
if (info.description) descriptionParts.push(info.description);
|
|
61673
62538
|
if (!identity) descriptionParts.push("No stable identity; this entry is read-only.");
|
|
62539
|
+
const id = identity ?? `unidentified:${index}`;
|
|
62540
|
+
if (identity) {
|
|
62541
|
+
identityById.set(id, identity);
|
|
62542
|
+
lastPersistedValue.set(id, info.enabled ? "on" : "off");
|
|
62543
|
+
}
|
|
61674
62544
|
const item = {
|
|
61675
|
-
id
|
|
62545
|
+
id,
|
|
61676
62546
|
label: identity ?? unidentifiedLabel(info),
|
|
61677
62547
|
description: descriptionParts.join(" \xB7 "),
|
|
61678
62548
|
currentValue: info.enabled ? "on" : "off"
|
|
61679
62549
|
};
|
|
61680
|
-
if (identity)
|
|
61681
|
-
item.submenu = (currentValue, done) => {
|
|
61682
|
-
const submenu = new ExtensionStateSubmenu(
|
|
61683
|
-
identity,
|
|
61684
|
-
currentValue,
|
|
61685
|
-
scope,
|
|
61686
|
-
(enabled) => callbacks.onToggle(identity, enabled),
|
|
61687
|
-
(effectiveEnabled) => done(effectiveEnabled ? "on" : "off"),
|
|
61688
|
-
() => done()
|
|
61689
|
-
);
|
|
61690
|
-
return submenu;
|
|
61691
|
-
};
|
|
61692
|
-
}
|
|
62550
|
+
if (identity) item.values = ["on", "off"];
|
|
61693
62551
|
return item;
|
|
61694
62552
|
});
|
|
61695
62553
|
this.settingsList = new SettingsList(
|
|
61696
62554
|
items,
|
|
61697
62555
|
10,
|
|
61698
62556
|
getSettingsListTheme(),
|
|
61699
|
-
() => {
|
|
62557
|
+
(id, newValue) => {
|
|
62558
|
+
const identity = identityById.get(id);
|
|
62559
|
+
if (!identity) return;
|
|
62560
|
+
const previous = lastPersistedValue.get(id) ?? "on";
|
|
62561
|
+
const accepted = callbacks.onToggle(identity, newValue === "on");
|
|
62562
|
+
if (accepted === false) {
|
|
62563
|
+
this.settingsList.updateValue(id, previous);
|
|
62564
|
+
return;
|
|
62565
|
+
}
|
|
62566
|
+
lastPersistedValue.set(id, newValue);
|
|
61700
62567
|
},
|
|
61701
62568
|
callbacks.onCancel,
|
|
61702
62569
|
{ enableSearch: true }
|
|
@@ -61756,9 +62623,9 @@ function createExtensionSelector(host, scope, onCancel) {
|
|
|
61756
62623
|
return new ExtensionEnablementSelectorComponent(infos, scope, {
|
|
61757
62624
|
onToggle: (identity, enabled) => {
|
|
61758
62625
|
const outcome = trySetExtensionEnabled(host, identity, enabled, scope);
|
|
61759
|
-
if (!outcome) return
|
|
62626
|
+
if (!outcome) return false;
|
|
61760
62627
|
host.showStatus(outcome.message);
|
|
61761
|
-
return
|
|
62628
|
+
return true;
|
|
61762
62629
|
},
|
|
61763
62630
|
onCancel
|
|
61764
62631
|
});
|
|
@@ -61833,7 +62700,10 @@ var BUILTIN_SLASH_COMMANDS = [
|
|
|
61833
62700
|
{ name: "sessions/info", description: "Show session info" },
|
|
61834
62701
|
{ name: "sessions/fork", description: "Fork from a message" },
|
|
61835
62702
|
{ name: "settings", description: "Open settings menu" },
|
|
61836
|
-
{ name: "
|
|
62703
|
+
{ name: "extensions", description: "Manage extensions (list/enable/disable)" },
|
|
62704
|
+
{ name: "extensions/list", description: "List discovered extensions (including disabled)" },
|
|
62705
|
+
{ name: "extensions/enable", description: "Enable an extension by identity (writes settings)" },
|
|
62706
|
+
{ name: "extensions/disable", description: "Disable an extension by identity (writes settings)" },
|
|
61837
62707
|
{ name: "settings/help", description: "Show help information (keyboard shortcuts and commands)" },
|
|
61838
62708
|
{ name: "settings/hotkeys", description: "Show keyboard shortcuts" },
|
|
61839
62709
|
{ name: "settings/model", description: "Select AI model" },
|
|
@@ -61841,15 +62711,25 @@ var BUILTIN_SLASH_COMMANDS = [
|
|
|
61841
62711
|
{ name: "settings/thinking", description: "Set thinking level" },
|
|
61842
62712
|
{ name: "settings/calm", description: "Toggle calm mode: show only questions and answers" },
|
|
61843
62713
|
{ name: "settings/yolo", description: "Toggle or set YOLO mode" },
|
|
61844
|
-
{ name: "
|
|
61845
|
-
{ name: "
|
|
61846
|
-
{ name: "
|
|
62714
|
+
{ name: "debugs/cache-test", description: "Run provider cache diagnostics with a dedicated 2-request probe" },
|
|
62715
|
+
{ name: "debugs/context", description: "Append a context summary to ~/.pie/logs/pie-cli.log" },
|
|
62716
|
+
{ name: "debugs/package", description: "Append a package summary to ~/.pie/logs/pie-cli.log" },
|
|
61847
62717
|
{ name: "settings/quit", description: "Exit Pie" },
|
|
61848
|
-
{ name: "skills", description: "
|
|
61849
|
-
{ name: "skills/list", description: "List available skills" },
|
|
62718
|
+
{ name: "skills", description: "Manage skills: list, toggle enable/disable, invoke" },
|
|
62719
|
+
{ name: "skills/list", description: "List available skills (plain text)" },
|
|
62720
|
+
{ name: "skills/create", description: "Create a new skill from a template" },
|
|
62721
|
+
{ name: "skills/enable", description: "Enable a skill by name" },
|
|
62722
|
+
{ name: "skills/disable", description: "Disable a skill by name" },
|
|
61850
62723
|
{ name: "skills/reload", description: "Reload skills from disk" },
|
|
61851
62724
|
{ name: "skills/use", description: "Use a skill" },
|
|
61852
|
-
{ name: "tools
|
|
62725
|
+
{ name: "tools", description: "List tools and manage enable/disable toggles" },
|
|
62726
|
+
{ name: "tools/list", description: "List runtime tools and their state (plain text)" },
|
|
62727
|
+
{ name: "tools/enable", description: "Enable a tool by name" },
|
|
62728
|
+
{ name: "tools/disable", description: "Disable a tool by name" },
|
|
62729
|
+
{ name: "tools/subagent", description: "Spawn subagents in parallel to handle tasks" },
|
|
62730
|
+
{ name: "files/upload", description: "Attach a file to the conversation" },
|
|
62731
|
+
{ name: "files/upload-pic", description: "Attach an image to the conversation" },
|
|
62732
|
+
{ name: "files/upload-video", description: "Attach a video to the conversation" }
|
|
61853
62733
|
];
|
|
61854
62734
|
|
|
61855
62735
|
// src/commands/interactive-debug-commands.ts
|
|
@@ -63958,7 +64838,7 @@ async function handleResumeCommand(host) {
|
|
|
63958
64838
|
return { component: selector, focus: selector.getSelectList() };
|
|
63959
64839
|
});
|
|
63960
64840
|
}
|
|
63961
|
-
async function
|
|
64841
|
+
async function loadSession2(host, sessionId) {
|
|
63962
64842
|
const beforeSwitch = await host.extensionRunner?.emitSessionBeforeSwitch({
|
|
63963
64843
|
type: "session:before_switch",
|
|
63964
64844
|
reason: "resume",
|
|
@@ -64422,6 +65302,81 @@ function errorMessage2(error) {
|
|
|
64422
65302
|
return error instanceof Error ? error.message : String(error);
|
|
64423
65303
|
}
|
|
64424
65304
|
function handleSkillsCommand(host) {
|
|
65305
|
+
host.showSelector((done) => {
|
|
65306
|
+
const settingsManager = host.options.settingsManager;
|
|
65307
|
+
const discovered = listDiscoveredSkills(host);
|
|
65308
|
+
const items = discovered.map((skill) => ({
|
|
65309
|
+
id: `skill:${skill.name}`,
|
|
65310
|
+
label: skill.name,
|
|
65311
|
+
description: `${skill.description} \xB7 Source: ${skill.source ?? "unknown"}`,
|
|
65312
|
+
currentValue: settingsManager.isSkillEnabled(skill.name) ? "on" : "off",
|
|
65313
|
+
values: ["on", "off"]
|
|
65314
|
+
}));
|
|
65315
|
+
const settingsList = new SettingsList(
|
|
65316
|
+
items,
|
|
65317
|
+
12,
|
|
65318
|
+
{
|
|
65319
|
+
label: (text, selected) => selected ? theme.fg("accent", text) : theme.fg("text", text),
|
|
65320
|
+
value: (text, selected) => selected ? theme.fg("accent", text) : theme.fg("accent", text),
|
|
65321
|
+
description: (text) => theme.fg("muted", text),
|
|
65322
|
+
cursor: "> ",
|
|
65323
|
+
hint: (text) => theme.fg("dim", text)
|
|
65324
|
+
},
|
|
65325
|
+
(id, newValue) => {
|
|
65326
|
+
const name = id.slice("skill:".length);
|
|
65327
|
+
const enabled = newValue === "on";
|
|
65328
|
+
try {
|
|
65329
|
+
settingsManager.setSkillEnabled(name, enabled);
|
|
65330
|
+
} catch (error) {
|
|
65331
|
+
host.showError(`Failed to update skill "${name}": ${errorMessage2(error)}`);
|
|
65332
|
+
return;
|
|
65333
|
+
}
|
|
65334
|
+
applyReloadedSkills(host, discoverSkills(host));
|
|
65335
|
+
host.showStatus(`Skill "${name}" ${enabled ? "enabled" : "disabled"} (reloaded).`);
|
|
65336
|
+
},
|
|
65337
|
+
() => done(),
|
|
65338
|
+
{ enableSearch: true }
|
|
65339
|
+
);
|
|
65340
|
+
const component = {
|
|
65341
|
+
render: (width) => [
|
|
65342
|
+
theme.bold(theme.fg("accent", "Skills")),
|
|
65343
|
+
"",
|
|
65344
|
+
theme.fg("muted", "Enter/Space toggles \xB7 changes apply immediately \xB7 Esc to close"),
|
|
65345
|
+
theme.fg("dim", `Usage: /skills/skill:<name> <your request> (${discovered.length} discovered)`),
|
|
65346
|
+
"",
|
|
65347
|
+
...settingsList.render(width)
|
|
65348
|
+
],
|
|
65349
|
+
handleInput: (data) => settingsList.handleInput(data),
|
|
65350
|
+
invalidate: () => settingsList.invalidate()
|
|
65351
|
+
};
|
|
65352
|
+
return { component, focus: settingsList };
|
|
65353
|
+
});
|
|
65354
|
+
}
|
|
65355
|
+
function discoverSkills(host) {
|
|
65356
|
+
const builtinDir = path25.join(getBuiltinDir(), "skills");
|
|
65357
|
+
const userDir = path25.join(os7.homedir(), ".pie", "skills");
|
|
65358
|
+
const projectDir = path25.join(process.cwd(), ".pie", "skills");
|
|
65359
|
+
return loadSkills({ dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: process.cwd() }) });
|
|
65360
|
+
}
|
|
65361
|
+
function listDiscoveredSkills(host) {
|
|
65362
|
+
return discoverSkills(host).skills;
|
|
65363
|
+
}
|
|
65364
|
+
function applyReloadedSkills(host, result) {
|
|
65365
|
+
host.skills = result.skills.filter((skill) => host.options.settingsManager.isSkillEnabled(skill.name));
|
|
65366
|
+
host.skillsSection = formatSkillsForPrompt(host.skills);
|
|
65367
|
+
host.applyRuntimeToolMode(host.allTools.length > 0 ? host.allTools : host.agent.state.tools);
|
|
65368
|
+
host.updateSystemPromptTools();
|
|
65369
|
+
for (const skill of host.skills) {
|
|
65370
|
+
const skillPath = ["skills", `skill:${skill.name}`];
|
|
65371
|
+
if (!commandTree.find(skillPath)) {
|
|
65372
|
+
commandTree.register(skillPath, {
|
|
65373
|
+
description: skill.description,
|
|
65374
|
+
handler: (_2, args) => host.handleSkillInvoke(skill.name, args || "")
|
|
65375
|
+
});
|
|
65376
|
+
}
|
|
65377
|
+
}
|
|
65378
|
+
}
|
|
65379
|
+
function handleSkillsListCommand(host) {
|
|
64425
65380
|
host.chatContainer.addChild(new Spacer(1));
|
|
64426
65381
|
host.chatContainer.addChild(new Text(theme.bold("Available Skills"), 1, 0));
|
|
64427
65382
|
if (host.skills.length === 0) {
|
|
@@ -64431,6 +65386,14 @@ function handleSkillsCommand(host) {
|
|
|
64431
65386
|
host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${skill.name}: ${skill.description}`), 1, 0));
|
|
64432
65387
|
}
|
|
64433
65388
|
}
|
|
65389
|
+
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));
|
|
65390
|
+
if (disabledNames.length > 0) {
|
|
65391
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
65392
|
+
host.chatContainer.addChild(new Text(theme.fg("dim", "Disabled skills:"), 1, 0));
|
|
65393
|
+
for (const name of disabledNames) {
|
|
65394
|
+
host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${name} (disabled; /skills/enable ${name})`), 1, 0));
|
|
65395
|
+
}
|
|
65396
|
+
}
|
|
64434
65397
|
host.chatContainer.addChild(new Spacer(1));
|
|
64435
65398
|
host.chatContainer.addChild(new Text(theme.fg("dim", "Usage: /skills/skill:<name> <your request>"), 1, 0));
|
|
64436
65399
|
host.chatContainer.addChild(new Text(theme.fg("dim", "Example: /skills/skill:browser-tools navigate to google.com"), 1, 0));
|
|
@@ -64457,7 +65420,11 @@ function handleSkillCommand(host, name) {
|
|
|
64457
65420
|
async function handleSkillInvoke(host, skillName, args) {
|
|
64458
65421
|
const skill = host.skills.find((s) => s.name === skillName);
|
|
64459
65422
|
if (!skill) {
|
|
64460
|
-
host.
|
|
65423
|
+
if (!host.options.settingsManager.isSkillEnabled(skillName)) {
|
|
65424
|
+
host.showError(`Skill disabled: ${skillName}. Use /skills/enable ${skillName} to restore it.`);
|
|
65425
|
+
} else {
|
|
65426
|
+
host.showError(`Skill not found: ${skillName}`);
|
|
65427
|
+
}
|
|
64461
65428
|
return;
|
|
64462
65429
|
}
|
|
64463
65430
|
const skillText = `skill:${skillName} ${args}`.trim();
|
|
@@ -64541,8 +65508,37 @@ function stripFrontmatter(host, content) {
|
|
|
64541
65508
|
}
|
|
64542
65509
|
return content;
|
|
64543
65510
|
}
|
|
65511
|
+
async function handleSkillToggleCommand(host, args, enabled) {
|
|
65512
|
+
const name = args.trim();
|
|
65513
|
+
if (!name) {
|
|
65514
|
+
host.showError(`Usage: /skills/${enabled ? "enable" : "disable"} <name>`);
|
|
65515
|
+
return;
|
|
65516
|
+
}
|
|
65517
|
+
const builtinDir = path25.join(getBuiltinDir(), "skills");
|
|
65518
|
+
const userDir = path25.join(os7.homedir(), ".pie", "skills");
|
|
65519
|
+
const projectDir = path25.join(process.cwd(), ".pie", "skills");
|
|
65520
|
+
const discovered = loadSkills({ dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: process.cwd() }) }).skills;
|
|
65521
|
+
if (!discovered.some((skill) => skill.name === name)) {
|
|
65522
|
+
host.showError(`Skill not found: ${name}`);
|
|
65523
|
+
return;
|
|
65524
|
+
}
|
|
65525
|
+
try {
|
|
65526
|
+
host.options.settingsManager.setSkillEnabled(name, enabled);
|
|
65527
|
+
} catch (error) {
|
|
65528
|
+
host.showError(`Failed to update skill "${name}": ${errorMessage2(error)}`);
|
|
65529
|
+
return;
|
|
65530
|
+
}
|
|
65531
|
+
await handleSkillsReload(host);
|
|
65532
|
+
host.chatContainer.addChild(new Text(theme.fg("accent", `Skill "${name}" ${enabled ? "enabled" : "disabled"} in ~/.pie/settings.json`), 1, 0));
|
|
65533
|
+
host.ui.requestRender();
|
|
65534
|
+
}
|
|
64544
65535
|
async function handleSkillsCreate(host, args) {
|
|
64545
|
-
|
|
65536
|
+
const debugLog2 = (message) => {
|
|
65537
|
+
if (process.env.PIE_VERBOSE) {
|
|
65538
|
+
console.error(`[SkillsCreate] ${message}`);
|
|
65539
|
+
}
|
|
65540
|
+
};
|
|
65541
|
+
debugLog2(`Called with args: "${args}"`);
|
|
64546
65542
|
try {
|
|
64547
65543
|
const trimmed = args.trim();
|
|
64548
65544
|
if (!trimmed) {
|
|
@@ -64573,7 +65569,7 @@ async function handleSkillsCreate(host, args) {
|
|
|
64573
65569
|
description = descPart.replace(/^["']|["']$/g, "");
|
|
64574
65570
|
}
|
|
64575
65571
|
}
|
|
64576
|
-
|
|
65572
|
+
debugLog2(`Parsed name: "${name}", description: "${description}"`);
|
|
64577
65573
|
if (!name) {
|
|
64578
65574
|
host.showSkillCreatePrompt();
|
|
64579
65575
|
return;
|
|
@@ -64589,7 +65585,7 @@ async function handleSkillsCreate(host, args) {
|
|
|
64589
65585
|
const skillsDir = path25.join(os7.homedir(), ".pie", "skills");
|
|
64590
65586
|
const skillDir = path25.join(skillsDir, name);
|
|
64591
65587
|
const skillFile = path25.join(skillDir, "SKILL.md");
|
|
64592
|
-
|
|
65588
|
+
debugLog2(`Creating at: ${skillFile}`);
|
|
64593
65589
|
if (fs23.existsSync(skillDir)) {
|
|
64594
65590
|
host.showError(`Skill "${name}" already exists at ${skillDir}`);
|
|
64595
65591
|
return;
|
|
@@ -64597,7 +65593,7 @@ async function handleSkillsCreate(host, args) {
|
|
|
64597
65593
|
fs23.mkdirSync(skillDir, { recursive: true });
|
|
64598
65594
|
const template = createSkillTemplate(name, description);
|
|
64599
65595
|
fs23.writeFileSync(skillFile, template, "utf-8");
|
|
64600
|
-
|
|
65596
|
+
debugLog2("Successfully created skill");
|
|
64601
65597
|
host.chatContainer.addChild(new Spacer(1));
|
|
64602
65598
|
host.chatContainer.addChild(new Text(theme.fg("accent", `\u2713 Created skill: ${name}`), 1, 0));
|
|
64603
65599
|
host.chatContainer.addChild(new Text(theme.fg("dim", ` Location: ${skillFile}`), 1, 0));
|
|
@@ -64606,7 +65602,7 @@ async function handleSkillsCreate(host, args) {
|
|
|
64606
65602
|
host.chatContainer.addChild(new Spacer(1));
|
|
64607
65603
|
host.ui.requestRender();
|
|
64608
65604
|
} catch (err) {
|
|
64609
|
-
|
|
65605
|
+
debugLog2(`Error: ${errorMessage2(err)}`);
|
|
64610
65606
|
host.showError(`Failed to create skill: ${errorMessage2(err)}`);
|
|
64611
65607
|
}
|
|
64612
65608
|
}
|
|
@@ -64636,7 +65632,7 @@ async function handleSkillsReload(host) {
|
|
|
64636
65632
|
const userDir = path25.join(os7.homedir(), ".pie", "skills");
|
|
64637
65633
|
const projectDir = path25.join(process.cwd(), ".pie", "skills");
|
|
64638
65634
|
const result = loadSkills({ dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: process.cwd() }) });
|
|
64639
|
-
host.skills = result.skills;
|
|
65635
|
+
host.skills = result.skills.filter((skill) => host.options.settingsManager.isSkillEnabled(skill.name));
|
|
64640
65636
|
host.skillsSection = formatSkillsForPrompt(host.skills);
|
|
64641
65637
|
host.applyRuntimeToolMode(host.allTools.length > 0 ? host.allTools : host.agent.state.tools);
|
|
64642
65638
|
host.updateSystemPromptTools();
|
|
@@ -64671,8 +65667,134 @@ async function handleSkillsReload(host) {
|
|
|
64671
65667
|
}
|
|
64672
65668
|
}
|
|
64673
65669
|
|
|
65670
|
+
// src/commands/interactive-tools-command.ts
|
|
65671
|
+
function errorMessage3(error) {
|
|
65672
|
+
return error instanceof Error ? error.message : String(error);
|
|
65673
|
+
}
|
|
65674
|
+
function collectKnownToolNames(host) {
|
|
65675
|
+
const liveNames = (host.allTools.length > 0 ? host.allTools : host.agent?.state.tools ?? []).map((tool) => tool.name);
|
|
65676
|
+
const disabledNames = host.options.settingsManager.getDisabledTools();
|
|
65677
|
+
const disabled = disabledNames.filter((name) => !liveNames.includes(name));
|
|
65678
|
+
return { active: [...liveNames].sort(), disabled: [...disabled].sort() };
|
|
65679
|
+
}
|
|
65680
|
+
function showToolsManager(host) {
|
|
65681
|
+
host.showSelector((done) => {
|
|
65682
|
+
const { active, disabled } = collectKnownToolNames(host);
|
|
65683
|
+
const settingsManager = host.options.settingsManager;
|
|
65684
|
+
const items = [
|
|
65685
|
+
...active.map((name) => ({
|
|
65686
|
+
id: `tool:${name}`,
|
|
65687
|
+
label: name,
|
|
65688
|
+
description: "Runtime agent tool",
|
|
65689
|
+
currentValue: settingsManager.isToolEnabled(name) ? "on" : "off",
|
|
65690
|
+
values: ["on", "off"]
|
|
65691
|
+
})),
|
|
65692
|
+
...disabled.map((name) => ({
|
|
65693
|
+
id: `tool:${name}`,
|
|
65694
|
+
label: name,
|
|
65695
|
+
description: "Not loaded this session (start with it enabled to use it)",
|
|
65696
|
+
currentValue: "off",
|
|
65697
|
+
values: ["on", "off"]
|
|
65698
|
+
}))
|
|
65699
|
+
];
|
|
65700
|
+
const settingsList = new SettingsList(
|
|
65701
|
+
items,
|
|
65702
|
+
14,
|
|
65703
|
+
getSettingsListTheme(),
|
|
65704
|
+
(_id, newValue) => {
|
|
65705
|
+
const name = _id.slice("tool:".length);
|
|
65706
|
+
const enabled = newValue === "on";
|
|
65707
|
+
try {
|
|
65708
|
+
settingsManager.setToolEnabled(name, enabled);
|
|
65709
|
+
} catch (error) {
|
|
65710
|
+
host.showError(`Failed to update tool "${name}": ${errorMessage3(error)}`);
|
|
65711
|
+
return;
|
|
65712
|
+
}
|
|
65713
|
+
host.applyRuntimeToolMode();
|
|
65714
|
+
host.showStatus(
|
|
65715
|
+
enabled ? `Tool "${name}" enabled (active now).` : `Tool "${name}" disabled (removed from this session).`
|
|
65716
|
+
);
|
|
65717
|
+
},
|
|
65718
|
+
() => done(),
|
|
65719
|
+
{ enableSearch: true }
|
|
65720
|
+
);
|
|
65721
|
+
const component = {
|
|
65722
|
+
render: (width) => [
|
|
65723
|
+
...renderHeader(width),
|
|
65724
|
+
...settingsList.render(width)
|
|
65725
|
+
],
|
|
65726
|
+
handleInput: (data) => settingsList.handleInput(data),
|
|
65727
|
+
invalidate: () => settingsList.invalidate()
|
|
65728
|
+
};
|
|
65729
|
+
return { component, focus: settingsList };
|
|
65730
|
+
});
|
|
65731
|
+
}
|
|
65732
|
+
function renderHeader(width) {
|
|
65733
|
+
const lines = [];
|
|
65734
|
+
lines.push(theme.bold(theme.fg("accent", "Tools")));
|
|
65735
|
+
lines.push("");
|
|
65736
|
+
lines.push(theme.fg("muted", "Enter/Space toggles \xB7 changes apply immediately \xB7 Esc to close"));
|
|
65737
|
+
const hint = "Usage: /tools/enable <name> | /tools/disable <name>";
|
|
65738
|
+
if (width > 20) lines.push(theme.fg("dim", hint));
|
|
65739
|
+
return lines;
|
|
65740
|
+
}
|
|
65741
|
+
function handleToolsCommand(host, args) {
|
|
65742
|
+
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
65743
|
+
const subcommand = parts[0];
|
|
65744
|
+
if (subcommand === "enable" || subcommand === "disable") {
|
|
65745
|
+
const name = parts.slice(1).join(" ").trim();
|
|
65746
|
+
if (!name) {
|
|
65747
|
+
host.showError(`Usage: /tools ${subcommand} <tool-name>`);
|
|
65748
|
+
return;
|
|
65749
|
+
}
|
|
65750
|
+
const { active, disabled } = collectKnownToolNames(host);
|
|
65751
|
+
if (!active.includes(name) && !disabled.includes(name)) {
|
|
65752
|
+
host.showError(`Tool not found: ${name}. Use /tools to list tool names.`);
|
|
65753
|
+
return;
|
|
65754
|
+
}
|
|
65755
|
+
const enabled = subcommand === "enable";
|
|
65756
|
+
try {
|
|
65757
|
+
host.options.settingsManager.setToolEnabled(name, enabled);
|
|
65758
|
+
} catch (error) {
|
|
65759
|
+
host.showError(`Failed to update tool "${name}": ${errorMessage3(error)}`);
|
|
65760
|
+
return;
|
|
65761
|
+
}
|
|
65762
|
+
host.applyRuntimeToolMode();
|
|
65763
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
65764
|
+
host.chatContainer.addChild(new Text(
|
|
65765
|
+
theme.fg("accent", `Tool "${name}" ${enabled ? "enabled" : "disabled"} in ~/.pie/settings.json (applied now).`),
|
|
65766
|
+
1,
|
|
65767
|
+
0
|
|
65768
|
+
));
|
|
65769
|
+
host.ui.requestRender();
|
|
65770
|
+
return;
|
|
65771
|
+
}
|
|
65772
|
+
if (subcommand === "list") {
|
|
65773
|
+
const { active, disabled } = collectKnownToolNames(host);
|
|
65774
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
65775
|
+
host.chatContainer.addChild(new Text(theme.bold("Tools"), 1, 0));
|
|
65776
|
+
if (active.length === 0 && disabled.length === 0) {
|
|
65777
|
+
host.chatContainer.addChild(new Text(theme.fg("dim", " No tools available."), 1, 0));
|
|
65778
|
+
}
|
|
65779
|
+
for (const name of active) {
|
|
65780
|
+
const state = host.options.settingsManager.isToolEnabled(name) ? "enabled" : "disabled (removed from this session)";
|
|
65781
|
+
host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${name}: ${state}`), 1, 0));
|
|
65782
|
+
}
|
|
65783
|
+
for (const name of disabled) {
|
|
65784
|
+
host.chatContainer.addChild(new Text(theme.fg("dim", ` \u2022 ${name}: disabled (/tools/enable ${name})`), 1, 0));
|
|
65785
|
+
}
|
|
65786
|
+
host.ui.requestRender();
|
|
65787
|
+
return;
|
|
65788
|
+
}
|
|
65789
|
+
if (subcommand) {
|
|
65790
|
+
host.showError("Usage: /tools [list | enable|disable <tool-name>]");
|
|
65791
|
+
return;
|
|
65792
|
+
}
|
|
65793
|
+
showToolsManager(host);
|
|
65794
|
+
}
|
|
65795
|
+
|
|
64674
65796
|
// src/commands/interactive-command-handlers.ts
|
|
64675
|
-
function showSettingsSelector(host) {
|
|
65797
|
+
function showSettingsSelector(host, focusItem) {
|
|
64676
65798
|
host.showSelector((done) => {
|
|
64677
65799
|
const currentModelId = host.options.model?.id || "unknown";
|
|
64678
65800
|
const currentProvider = host.options.model?.provider || "unknown";
|
|
@@ -64688,7 +65810,8 @@ function showSettingsSelector(host) {
|
|
|
64688
65810
|
yoloMode: host.yoloMode,
|
|
64689
65811
|
calmMode: host.calmMode,
|
|
64690
65812
|
notificationsBell: host.options.settingsManager.getBellNotificationsEnabled(),
|
|
64691
|
-
notificationsDesktop: host.options.settingsManager.getDesktopNotificationsEnabled()
|
|
65813
|
+
notificationsDesktop: host.options.settingsManager.getDesktopNotificationsEnabled(),
|
|
65814
|
+
focusItem
|
|
64692
65815
|
},
|
|
64693
65816
|
{
|
|
64694
65817
|
onThinkingLevelChange: (level) => {
|
|
@@ -65076,7 +66199,19 @@ async function handleClearCommand(host) {
|
|
|
65076
66199
|
host.syncSessionModelMetadata();
|
|
65077
66200
|
host.planModeEnabled = false;
|
|
65078
66201
|
host.pendingPlanModeTransition = null;
|
|
65079
|
-
host.
|
|
66202
|
+
const contextUsage = host.calculateContextUsage();
|
|
66203
|
+
const contextWindow = host.options.model?.contextWindow ?? 0;
|
|
66204
|
+
host.footer.setState({
|
|
66205
|
+
planMode: false,
|
|
66206
|
+
status: "ready",
|
|
66207
|
+
inputTokens: contextUsage.input,
|
|
66208
|
+
outputTokens: contextUsage.output,
|
|
66209
|
+
cacheRead: contextUsage.cacheRead,
|
|
66210
|
+
cacheWrite: contextUsage.cacheWrite,
|
|
66211
|
+
cost: contextUsage.cost,
|
|
66212
|
+
contextPercent: contextWindow > 0 && contextUsage.tokens !== null ? contextUsage.tokens / contextWindow * 100 : 0,
|
|
66213
|
+
contextWindow
|
|
66214
|
+
});
|
|
65080
66215
|
host.updateTerminalTitle();
|
|
65081
66216
|
host.chatContainer.clear();
|
|
65082
66217
|
host.streamingComponent = void 0;
|
|
@@ -65257,7 +66392,7 @@ function registerBuiltinCommands(host) {
|
|
|
65257
66392
|
});
|
|
65258
66393
|
commandTree.register(["settings", "theme"], {
|
|
65259
66394
|
description: "Change theme",
|
|
65260
|
-
handler: () => host.showSettingsSelector()
|
|
66395
|
+
handler: () => host.showSettingsSelector("theme")
|
|
65261
66396
|
});
|
|
65262
66397
|
commandTree.register(["settings", "thinking"], {
|
|
65263
66398
|
description: "Set thinking level (off/minimal/low/medium/high/xhigh)",
|
|
@@ -65271,36 +66406,52 @@ function registerBuiltinCommands(host) {
|
|
|
65271
66406
|
description: "Toggle calm mode: show only questions and answers (on/off/status)",
|
|
65272
66407
|
handler: (_2, args) => host.handleCalmCommand(args)
|
|
65273
66408
|
});
|
|
65274
|
-
commandTree.register(["
|
|
66409
|
+
commandTree.register(["extensions"], {
|
|
65275
66410
|
description: "List extensions and manage enable/disable toggles",
|
|
65276
66411
|
handler: (_2, args) => host.handleExtensionsCommand(args)
|
|
65277
66412
|
});
|
|
65278
|
-
commandTree.register(["
|
|
66413
|
+
commandTree.register(["extensions", "list"], {
|
|
65279
66414
|
description: "List discovered extensions (including disabled)",
|
|
65280
66415
|
handler: (_2, args) => host.handleExtensionsCommand(args ? `list ${args}` : "list")
|
|
65281
66416
|
});
|
|
65282
|
-
commandTree.register(["
|
|
66417
|
+
commandTree.register(["extensions", "enable"], {
|
|
65283
66418
|
description: "Enable an extension by identity (writes settings)",
|
|
65284
66419
|
handler: (_2, args) => host.handleExtensionsCommand(`enable ${args || ""}`)
|
|
65285
66420
|
});
|
|
65286
|
-
commandTree.register(["
|
|
66421
|
+
commandTree.register(["extensions", "disable"], {
|
|
65287
66422
|
description: "Disable an extension by identity (writes settings)",
|
|
65288
66423
|
handler: (_2, args) => host.handleExtensionsCommand(`disable ${args || ""}`)
|
|
65289
66424
|
});
|
|
65290
|
-
commandTree.register(["skills"
|
|
65291
|
-
description: "
|
|
66425
|
+
commandTree.register(["skills"], {
|
|
66426
|
+
description: "Manage skills: list, toggle enable/disable, invoke",
|
|
65292
66427
|
handler: () => host.handleSkillsCommand()
|
|
65293
66428
|
});
|
|
66429
|
+
commandTree.register(["skills", "list"], {
|
|
66430
|
+
description: "List available skills (plain text)",
|
|
66431
|
+
handler: () => host.handleSkillsListCommand()
|
|
66432
|
+
});
|
|
65294
66433
|
commandTree.register(["skills", "use"], {
|
|
65295
66434
|
description: "Use a skill",
|
|
65296
66435
|
handler: (_2, args) => host.handleSkillCommand(args || "")
|
|
65297
66436
|
});
|
|
66437
|
+
commandTree.register(["skills", "create"], {
|
|
66438
|
+
description: "Create a new skill from a template",
|
|
66439
|
+
handler: (_2, args) => host.handleSkillsCreate(args || "")
|
|
66440
|
+
});
|
|
65298
66441
|
commandTree.register(["skills", "reload"], {
|
|
65299
66442
|
description: "Reload skills from disk",
|
|
65300
66443
|
handler: async () => {
|
|
65301
66444
|
await host.handleSkillsReload();
|
|
65302
66445
|
}
|
|
65303
66446
|
});
|
|
66447
|
+
commandTree.register(["skills", "enable"], {
|
|
66448
|
+
description: "Enable a skill by name (writes settings, reloads immediately)",
|
|
66449
|
+
handler: (_2, args) => host.handleSkillToggleCommand(args || "", true)
|
|
66450
|
+
});
|
|
66451
|
+
commandTree.register(["skills", "disable"], {
|
|
66452
|
+
description: "Disable a skill by name (writes settings, reloads immediately)",
|
|
66453
|
+
handler: (_2, args) => host.handleSkillToggleCommand(args || "", false)
|
|
66454
|
+
});
|
|
65304
66455
|
for (const skill of host.skills) {
|
|
65305
66456
|
commandTree.register(["skills", `skill:${skill.name}`], {
|
|
65306
66457
|
description: skill.description,
|
|
@@ -65311,15 +66462,31 @@ function registerBuiltinCommands(host) {
|
|
|
65311
66462
|
description: "Spawn subagents in parallel to handle tasks",
|
|
65312
66463
|
handler: (_2, args) => host.handleSubagentCommand(args || "")
|
|
65313
66464
|
});
|
|
65314
|
-
commandTree.register(["
|
|
66465
|
+
commandTree.register(["tools"], {
|
|
66466
|
+
description: "List runtime tools and manage enable/disable toggles",
|
|
66467
|
+
handler: (_2, args) => host.handleToolsCommand(args || "")
|
|
66468
|
+
});
|
|
66469
|
+
commandTree.register(["tools", "list"], {
|
|
66470
|
+
description: "List runtime tools and their state (plain text)",
|
|
66471
|
+
handler: (_2, args) => host.handleToolsCommand(args ? `list ${args}` : "list")
|
|
66472
|
+
});
|
|
66473
|
+
commandTree.register(["tools", "enable"], {
|
|
66474
|
+
description: "Enable a tool by name (writes settings; applies now)",
|
|
66475
|
+
handler: (_2, args) => host.handleToolsCommand(`enable ${args || ""}`)
|
|
66476
|
+
});
|
|
66477
|
+
commandTree.register(["tools", "disable"], {
|
|
66478
|
+
description: "Disable a tool by name (writes settings; applies now)",
|
|
66479
|
+
handler: (_2, args) => host.handleToolsCommand(`disable ${args || ""}`)
|
|
66480
|
+
});
|
|
66481
|
+
commandTree.register(["debugs", "cache-test"], {
|
|
65315
66482
|
description: "Run provider cache diagnostics with a dedicated 2-request probe",
|
|
65316
66483
|
handler: () => host.handleCacheTest()
|
|
65317
66484
|
});
|
|
65318
|
-
commandTree.register(["
|
|
66485
|
+
commandTree.register(["debugs", "context"], {
|
|
65319
66486
|
description: "Append a context summary to ~/.pie/logs/pie-cli.log",
|
|
65320
66487
|
handler: () => host.handleDebugContextCommand()
|
|
65321
66488
|
});
|
|
65322
|
-
commandTree.register(["
|
|
66489
|
+
commandTree.register(["debugs", "package"], {
|
|
65323
66490
|
description: "Append a package summary to ~/.pie/logs/pie-cli.log",
|
|
65324
66491
|
handler: () => host.handleDebugPackageCommand()
|
|
65325
66492
|
});
|
|
@@ -66238,7 +67405,7 @@ function setupInteractiveEditorSubmitHandler(host) {
|
|
|
66238
67405
|
host.ui.requestRender();
|
|
66239
67406
|
await new Promise((resolve7) => setImmediate(resolve7));
|
|
66240
67407
|
let finalContent = messageContent;
|
|
66241
|
-
const reminderPrefix = host.executionReminder;
|
|
67408
|
+
const reminderPrefix = host.executionState.getReminder() ?? host.executionReminder;
|
|
66242
67409
|
const combinedPrefix = [reminderPrefix].filter((value) => Boolean(value)).join("");
|
|
66243
67410
|
if (combinedPrefix) {
|
|
66244
67411
|
if (typeof messageContent === "string") {
|
|
@@ -67202,17 +68369,17 @@ var MentionHandler = class {
|
|
|
67202
68369
|
} catch (err) {
|
|
67203
68370
|
this.onInsertMention("", pendingMention);
|
|
67204
68371
|
this.clearPendingStatus(pendingStatusKey);
|
|
67205
|
-
const
|
|
67206
|
-
if (
|
|
68372
|
+
const errorMessage4 = err instanceof Error ? err.message : String(err);
|
|
68373
|
+
if (errorMessage4.includes("PLATFORM_NOT_SUPPORTED")) {
|
|
67207
68374
|
this.onError?.("The current AI model does not support file uploads.");
|
|
67208
|
-
} else if (
|
|
68375
|
+
} else if (errorMessage4.includes("ENOENT")) {
|
|
67209
68376
|
this.onError?.("File does not exist or cannot be accessed.");
|
|
67210
|
-
} else if (
|
|
68377
|
+
} else if (errorMessage4.includes("EACCES") || errorMessage4.includes("PERMISSION")) {
|
|
67211
68378
|
this.onError?.("Permission denied while accessing the file.");
|
|
67212
|
-
} else if (
|
|
68379
|
+
} else if (errorMessage4.includes("network") || errorMessage4.includes("ETIMEDOUT") || errorMessage4.includes("ECONNREFUSED")) {
|
|
67213
68380
|
this.onError?.("Network error. Check the connection and try again.");
|
|
67214
68381
|
} else {
|
|
67215
|
-
this.onError?.(`Upload failed: ${
|
|
68382
|
+
this.onError?.(`Upload failed: ${errorMessage4}`);
|
|
67216
68383
|
}
|
|
67217
68384
|
} finally {
|
|
67218
68385
|
this.clearPendingStatus(pendingStatusKey);
|
|
@@ -68412,8 +69579,8 @@ function calculateCliContextUsage(params) {
|
|
|
68412
69579
|
};
|
|
68413
69580
|
}
|
|
68414
69581
|
function createCliAutoCompactDecision(params) {
|
|
68415
|
-
const
|
|
68416
|
-
if (
|
|
69582
|
+
const errorMessage4 = params.message?.role === "assistant" ? params.message.errorMessage : void 0;
|
|
69583
|
+
if (errorMessage4 && params.isContextOverflowError(errorMessage4)) {
|
|
68417
69584
|
return { reason: "overflow", willRetry: true };
|
|
68418
69585
|
}
|
|
68419
69586
|
if (!params.autoCompactEnabled || params.contextWindow <= 0) {
|
|
@@ -68499,9 +69666,9 @@ var INVALID_FILE_REFERENCE_PATTERN = /not the owner of this file|owner of this f
|
|
|
68499
69666
|
var INVALID_REQUEST_PATTERN = /bad request|\b400\b|invalid request|invalid schema|schema validation|invalid parameter|unsupported parameter|malformed/i;
|
|
68500
69667
|
var CLI_RETRY_MAX_RETRIES = 3;
|
|
68501
69668
|
var CLI_RETRY_BASE_DELAY_MS = 2e3;
|
|
68502
|
-
function isCliContextOverflowError(
|
|
69669
|
+
function isCliContextOverflowError(errorMessage4) {
|
|
68503
69670
|
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(
|
|
68504
|
-
|
|
69671
|
+
errorMessage4
|
|
68505
69672
|
);
|
|
68506
69673
|
}
|
|
68507
69674
|
function createClassification(kind, message, overrides) {
|
|
@@ -68516,56 +69683,56 @@ function createClassification(kind, message, overrides) {
|
|
|
68516
69683
|
};
|
|
68517
69684
|
}
|
|
68518
69685
|
function classifyCliFailure(context) {
|
|
68519
|
-
const
|
|
68520
|
-
if (isCliContextOverflowError(
|
|
68521
|
-
return createClassification("context_overflow",
|
|
69686
|
+
const errorMessage4 = typeof context === "string" ? context : context.errorMessage;
|
|
69687
|
+
if (isCliContextOverflowError(errorMessage4)) {
|
|
69688
|
+
return createClassification("context_overflow", errorMessage4, {
|
|
68522
69689
|
compactable: true,
|
|
68523
69690
|
terminal: false
|
|
68524
69691
|
});
|
|
68525
69692
|
}
|
|
68526
|
-
if (USER_ABORT_PATTERN.test(
|
|
68527
|
-
return createClassification("user_abort",
|
|
69693
|
+
if (USER_ABORT_PATTERN.test(errorMessage4)) {
|
|
69694
|
+
return createClassification("user_abort", errorMessage4, {
|
|
68528
69695
|
userAbort: true,
|
|
68529
69696
|
terminal: false
|
|
68530
69697
|
});
|
|
68531
69698
|
}
|
|
68532
|
-
if (INVALID_FILE_REFERENCE_PATTERN.test(
|
|
68533
|
-
return createClassification("invalid_file_reference",
|
|
69699
|
+
if (INVALID_FILE_REFERENCE_PATTERN.test(errorMessage4)) {
|
|
69700
|
+
return createClassification("invalid_file_reference", errorMessage4);
|
|
68534
69701
|
}
|
|
68535
|
-
if (AUTH_CONFIG_PATTERN.test(
|
|
68536
|
-
return createClassification("auth_config",
|
|
69702
|
+
if (AUTH_CONFIG_PATTERN.test(errorMessage4)) {
|
|
69703
|
+
return createClassification("auth_config", errorMessage4);
|
|
68537
69704
|
}
|
|
68538
|
-
if (TRANSIENT_NETWORK_ERROR_PATTERN.test(
|
|
68539
|
-
return createClassification("transient_network",
|
|
69705
|
+
if (TRANSIENT_NETWORK_ERROR_PATTERN.test(errorMessage4)) {
|
|
69706
|
+
return createClassification("transient_network", errorMessage4, {
|
|
68540
69707
|
retryable: true,
|
|
68541
69708
|
terminal: false
|
|
68542
69709
|
});
|
|
68543
69710
|
}
|
|
68544
|
-
if (
|
|
68545
|
-
return createClassification("provider_transient",
|
|
69711
|
+
if (errorMessage4.includes(EMPTY_ASSISTANT_CONTENT_ERROR)) {
|
|
69712
|
+
return createClassification("provider_transient", errorMessage4, {
|
|
68546
69713
|
retryable: true,
|
|
68547
69714
|
terminal: false
|
|
68548
69715
|
});
|
|
68549
69716
|
}
|
|
68550
|
-
if (
|
|
68551
|
-
return createClassification("provider_transient",
|
|
69717
|
+
if (errorMessage4.includes(OPENAI_COMPAT_PROTOCOL_ERROR_CODE)) {
|
|
69718
|
+
return createClassification("provider_transient", errorMessage4, {
|
|
68552
69719
|
retryable: true,
|
|
68553
69720
|
terminal: false
|
|
68554
69721
|
});
|
|
68555
69722
|
}
|
|
68556
|
-
if (PROVIDER_TRANSIENT_ERROR_PATTERN.test(
|
|
68557
|
-
return createClassification("provider_transient",
|
|
69723
|
+
if (PROVIDER_TRANSIENT_ERROR_PATTERN.test(errorMessage4)) {
|
|
69724
|
+
return createClassification("provider_transient", errorMessage4, {
|
|
68558
69725
|
retryable: true,
|
|
68559
69726
|
terminal: false
|
|
68560
69727
|
});
|
|
68561
69728
|
}
|
|
68562
|
-
if (INVALID_REQUEST_PATTERN.test(
|
|
68563
|
-
return createClassification("invalid_request",
|
|
69729
|
+
if (INVALID_REQUEST_PATTERN.test(errorMessage4)) {
|
|
69730
|
+
return createClassification("invalid_request", errorMessage4);
|
|
68564
69731
|
}
|
|
68565
|
-
return createClassification("unknown",
|
|
69732
|
+
return createClassification("unknown", errorMessage4);
|
|
68566
69733
|
}
|
|
68567
|
-
function isCliRetryableError(
|
|
68568
|
-
return classifyCliFailure(
|
|
69734
|
+
function isCliRetryableError(errorMessage4) {
|
|
69735
|
+
return classifyCliFailure(errorMessage4).retryable;
|
|
68569
69736
|
}
|
|
68570
69737
|
function getCliRetryBaseDelayMs() {
|
|
68571
69738
|
const override = process.env.PIE_TEST_CLI_RETRY_BASE_DELAY_MS;
|
|
@@ -68738,23 +69905,23 @@ function setupAutocomplete(host) {
|
|
|
68738
69905
|
};
|
|
68739
69906
|
host.editor.setAutocompleteProvider(provider);
|
|
68740
69907
|
}
|
|
68741
|
-
function isContextOverflowError(
|
|
68742
|
-
return isCliContextOverflowError(
|
|
69908
|
+
function isContextOverflowError(errorMessage4) {
|
|
69909
|
+
return isCliContextOverflowError(errorMessage4);
|
|
68743
69910
|
}
|
|
68744
69911
|
function shouldAutoCompact(host, contextTokens, contextWindow) {
|
|
68745
69912
|
if (!host.options.settingsManager.getAutoCompactEnabled()) return false;
|
|
68746
69913
|
const reserveTokens = host.options.settingsManager.getAutoCompactReserveTokens();
|
|
68747
69914
|
return shouldCliAutoCompactTokens({ tokens: contextTokens, contextWindow, reserveTokens });
|
|
68748
69915
|
}
|
|
68749
|
-
function isRetryableError(
|
|
68750
|
-
return isCliRetryableError(
|
|
69916
|
+
function isRetryableError(errorMessage4) {
|
|
69917
|
+
return isCliRetryableError(errorMessage4);
|
|
68751
69918
|
}
|
|
68752
|
-
function isInvalidFileReferenceError(
|
|
69919
|
+
function isInvalidFileReferenceError(errorMessage4) {
|
|
68753
69920
|
return /not the owner of this file|owner of this file|invalid_authentication_error/i.test(
|
|
68754
|
-
|
|
69921
|
+
errorMessage4
|
|
68755
69922
|
);
|
|
68756
69923
|
}
|
|
68757
|
-
function recoverFromInvalidFileReferenceError(host,
|
|
69924
|
+
function recoverFromInvalidFileReferenceError(host, errorMessage4) {
|
|
68758
69925
|
if (!host.fileManager || !host.agent) return;
|
|
68759
69926
|
const messages = host.agent.state.messages.slice();
|
|
68760
69927
|
const invalidFileIds = /* @__PURE__ */ new Set();
|
|
@@ -68772,7 +69939,7 @@ function recoverFromInvalidFileReferenceError(host, errorMessage3) {
|
|
|
68772
69939
|
}
|
|
68773
69940
|
if (invalidFileIds.size === 0) return;
|
|
68774
69941
|
for (const fileId of invalidFileIds) {
|
|
68775
|
-
host.fileManager.markFileReferenceError(fileId,
|
|
69942
|
+
host.fileManager.markFileReferenceError(fileId, errorMessage4);
|
|
68776
69943
|
}
|
|
68777
69944
|
let changed = false;
|
|
68778
69945
|
const sanitizedMessages = messages.map((message) => {
|
|
@@ -69050,9 +70217,9 @@ function showStatus(host, message) {
|
|
|
69050
70217
|
host.lastStatusText = text;
|
|
69051
70218
|
host.ui.requestRender();
|
|
69052
70219
|
}
|
|
69053
|
-
function showError(host,
|
|
70220
|
+
function showError(host, errorMessage4) {
|
|
69054
70221
|
host.chatContainer.addChild(new Spacer(1));
|
|
69055
|
-
host.chatContainer.addChild(new Text(theme.fg("error", `Error: ${
|
|
70222
|
+
host.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage4}`), 1, 0));
|
|
69056
70223
|
host.ui.requestRender();
|
|
69057
70224
|
}
|
|
69058
70225
|
async function executeCommand(host, command) {
|
|
@@ -69279,7 +70446,7 @@ function createInteractiveAgentSessionController(host) {
|
|
|
69279
70446
|
getAutoContinueMessage: () => host.getTodoAutoContinueMessage(),
|
|
69280
70447
|
classifyFailure: (context) => classifyCliFailure(context),
|
|
69281
70448
|
retry: {
|
|
69282
|
-
isRetryableError: (
|
|
70449
|
+
isRetryableError: (errorMessage4) => !host._isContextOverflowError(errorMessage4) && isCliRetryableError(errorMessage4),
|
|
69283
70450
|
maxRetries: CLI_RETRY_MAX_RETRIES,
|
|
69284
70451
|
baseDelayMs: getCliRetryBaseDelayMs()
|
|
69285
70452
|
},
|
|
@@ -69431,6 +70598,13 @@ function createInteractiveAgentSessionController(host) {
|
|
|
69431
70598
|
host.appendWarningSummary(outcome.terminalSummary);
|
|
69432
70599
|
}
|
|
69433
70600
|
host.setControllerBusy(false);
|
|
70601
|
+
} else if (event.type === "runtime_guard_advisory") {
|
|
70602
|
+
host.noteRuntimeGuardAdvisory(event);
|
|
70603
|
+
host.sessionTrace.noteRuntimeEvent("runtime_guard_advisory", {
|
|
70604
|
+
toolName: event.toolName,
|
|
70605
|
+
repeatCount: event.repeatCount,
|
|
70606
|
+
reason: event.reason
|
|
70607
|
+
});
|
|
69434
70608
|
} else if (event.type === "runtime_guard_triggered") {
|
|
69435
70609
|
host.sessionTrace.noteStalled("runtime_guard_triggered", {
|
|
69436
70610
|
toolName: event.toolName,
|
|
@@ -69631,6 +70805,43 @@ function createRuntimeModeTransformContext(options) {
|
|
|
69631
70805
|
};
|
|
69632
70806
|
}
|
|
69633
70807
|
|
|
70808
|
+
// src/runtime/guard-advisory-context.ts
|
|
70809
|
+
var GUARD_ADVISORY_MARKER = "<runtime-guard-advisory>";
|
|
70810
|
+
var GUARD_ADVISORY_END_MARKER = "</runtime-guard-advisory>";
|
|
70811
|
+
function isMarkerOnlyUserMessage(message) {
|
|
70812
|
+
if (message.role !== "user") return false;
|
|
70813
|
+
const content = message.content;
|
|
70814
|
+
const text = typeof content === "string" ? content : Array.isArray(content) && content.length === 1 && content[0]?.type === "text" ? content[0].text : "";
|
|
70815
|
+
return text.trim().startsWith(GUARD_ADVISORY_MARKER) && text.trim().endsWith(GUARD_ADVISORY_END_MARKER);
|
|
70816
|
+
}
|
|
70817
|
+
function stripGuardAdvisories(messages) {
|
|
70818
|
+
return messages.filter((message) => !isMarkerOnlyUserMessage(message));
|
|
70819
|
+
}
|
|
70820
|
+
function findLatestUserIndex2(messages) {
|
|
70821
|
+
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
70822
|
+
if (messages[index].role === "user") return index;
|
|
70823
|
+
}
|
|
70824
|
+
return -1;
|
|
70825
|
+
}
|
|
70826
|
+
function injectGuardAdvisory(messages, guidance) {
|
|
70827
|
+
const advisoryMessage = {
|
|
70828
|
+
role: "user",
|
|
70829
|
+
content: `${GUARD_ADVISORY_MARKER}
|
|
70830
|
+
${guidance}
|
|
70831
|
+
${GUARD_ADVISORY_END_MARKER}`,
|
|
70832
|
+
timestamp: Date.now()
|
|
70833
|
+
};
|
|
70834
|
+
const latestUserIndex = findLatestUserIndex2(messages);
|
|
70835
|
+
if (latestUserIndex < 0) {
|
|
70836
|
+
return [...messages, advisoryMessage];
|
|
70837
|
+
}
|
|
70838
|
+
return [
|
|
70839
|
+
...messages.slice(0, latestUserIndex),
|
|
70840
|
+
advisoryMessage,
|
|
70841
|
+
...messages.slice(latestUserIndex)
|
|
70842
|
+
];
|
|
70843
|
+
}
|
|
70844
|
+
|
|
69634
70845
|
// src/runtime/tool-policy.ts
|
|
69635
70846
|
function selectToolsForRuntimeMode(tools, mode) {
|
|
69636
70847
|
return selectToolsForRuntimePolicy(tools, mode);
|
|
@@ -70321,7 +71532,7 @@ async function loadInteractiveExtensions(host) {
|
|
|
70321
71532
|
console.error(`[Extension] Failed to load ${path33}: ${error}`);
|
|
70322
71533
|
}
|
|
70323
71534
|
}
|
|
70324
|
-
const extensionTools = convertExtensionTools(extensions);
|
|
71535
|
+
const extensionTools = filterEnabledTools(convertExtensionTools(extensions), host.options.settingsManager);
|
|
70325
71536
|
const activeTools = [...host.agent.state.tools, ...extensionTools];
|
|
70326
71537
|
host.agent.state.tools = wrapToolsWithExtensions(activeTools, host.extensionRunner);
|
|
70327
71538
|
const availableTools = [
|
|
@@ -70390,12 +71601,13 @@ var InteractiveMode = class {
|
|
|
70390
71601
|
isProcessing = false;
|
|
70391
71602
|
_turnIndex = 0;
|
|
70392
71603
|
_semanticTurnIndex = 0;
|
|
70393
|
-
thinkingLevel =
|
|
71604
|
+
thinkingLevel = DEFAULT_THINKING_LEVEL;
|
|
70394
71605
|
toolOutputExpanded = false;
|
|
70395
71606
|
planModeEnabled = false;
|
|
70396
71607
|
pendingPlanModeTransition = null;
|
|
70397
71608
|
pendingYoloModeTransition = null;
|
|
70398
71609
|
executionReminder = null;
|
|
71610
|
+
pendingRuntimeGuardAdvisory = null;
|
|
70399
71611
|
fileManager;
|
|
70400
71612
|
mentionHandler;
|
|
70401
71613
|
mentionPickerComponent;
|
|
@@ -70634,9 +71846,12 @@ var InteractiveMode = class {
|
|
|
70634
71846
|
const rebuilt = this.rebuildSkillAwareTools(completeToolSet);
|
|
70635
71847
|
const currentTools = this.extensionRunner ? wrapToolsWithExtensions(rebuilt.currentTools, this.extensionRunner) : rebuilt.currentTools;
|
|
70636
71848
|
const originalTools = this.extensionRunner ? wrapToolsWithExtensions(rebuilt.originalTools, this.extensionRunner) : rebuilt.originalTools;
|
|
70637
|
-
const activeTools =
|
|
70638
|
-
|
|
70639
|
-
|
|
71849
|
+
const activeTools = filterEnabledTools(
|
|
71850
|
+
selectToolsForRuntimeMode(
|
|
71851
|
+
currentTools,
|
|
71852
|
+
this.planModeEnabled ? "plan" : "normal"
|
|
71853
|
+
),
|
|
71854
|
+
this.options.settingsManager
|
|
70640
71855
|
);
|
|
70641
71856
|
this.agent.setTools(activeTools);
|
|
70642
71857
|
this.allTools = [...currentTools];
|
|
@@ -70647,7 +71862,8 @@ var InteractiveMode = class {
|
|
|
70647
71862
|
planMode: this.planModeEnabled ? "planning" : "off",
|
|
70648
71863
|
filesystemScope: this.yoloMode ? "all" : "workspace",
|
|
70649
71864
|
toolCount: activeTools.length,
|
|
70650
|
-
availableToolCount: currentTools.length
|
|
71865
|
+
availableToolCount: currentTools.length,
|
|
71866
|
+
disabledToolCount: this.options.settingsManager.getDisabledTools().length
|
|
70651
71867
|
});
|
|
70652
71868
|
}
|
|
70653
71869
|
noteRuntimeModeChanged(trigger) {
|
|
@@ -70705,12 +71921,9 @@ var InteractiveMode = class {
|
|
|
70705
71921
|
});
|
|
70706
71922
|
}
|
|
70707
71923
|
async init() {
|
|
70708
|
-
const savedLevel = this.options.settingsManager.getDefaultThinkingLevel();
|
|
70709
|
-
if (savedLevel) {
|
|
70710
|
-
this.thinkingLevel = savedLevel;
|
|
70711
|
-
}
|
|
70712
|
-
const { Agent } = await import("./chunks/src-HYZFAW4V.js");
|
|
70713
71924
|
const activeSession = this.sessionManager.getActiveSession();
|
|
71925
|
+
this.thinkingLevel = resolveInitialThinkingLevel({ session: activeSession, settingsManager: this.options.settingsManager });
|
|
71926
|
+
const { Agent } = await import("./chunks/src-HYZFAW4V.js");
|
|
70714
71927
|
this.agent = new Agent({
|
|
70715
71928
|
initialState: {
|
|
70716
71929
|
systemPrompt: this.buildSystemPrompt(),
|
|
@@ -70721,20 +71934,27 @@ var InteractiveMode = class {
|
|
|
70721
71934
|
apiKey: this.options.apiKey,
|
|
70722
71935
|
sessionId: activeSession?.id,
|
|
70723
71936
|
streamFn: this.options.streamFn,
|
|
70724
|
-
transformContext:
|
|
70725
|
-
|
|
70726
|
-
|
|
70727
|
-
|
|
70728
|
-
|
|
70729
|
-
|
|
70730
|
-
|
|
70731
|
-
|
|
70732
|
-
|
|
70733
|
-
|
|
70734
|
-
|
|
70735
|
-
|
|
70736
|
-
|
|
70737
|
-
|
|
71937
|
+
transformContext: async (messages) => {
|
|
71938
|
+
const runtimeModeTransform = createRuntimeModeTransformContext({
|
|
71939
|
+
getState: () => this.getRuntimeModeState(),
|
|
71940
|
+
consumeTransition: () => this.consumeRuntimeModeTransition(),
|
|
71941
|
+
onInjected: (state) => this.sessionTrace.noteRuntimeEvent("runtime_context_injected", {
|
|
71942
|
+
yoloMode: state.yoloMode,
|
|
71943
|
+
planMode: state.planMode,
|
|
71944
|
+
filesystemScope: state.filesystemScope,
|
|
71945
|
+
pendingTransition: state.pendingTransition,
|
|
71946
|
+
currentDate: state.currentDate,
|
|
71947
|
+
timeZone: state.timeZone,
|
|
71948
|
+
activeToolCount: state.activeToolNames.length
|
|
71949
|
+
}),
|
|
71950
|
+
onStripped: (count) => this.sessionTrace.noteRuntimeEvent("stale_runtime_context_stripped", { count })
|
|
71951
|
+
});
|
|
71952
|
+
let transformed = await runtimeModeTransform(messages);
|
|
71953
|
+
const advisory = this.pendingRuntimeGuardAdvisory;
|
|
71954
|
+
this.pendingRuntimeGuardAdvisory = null;
|
|
71955
|
+
transformed = advisory ? injectGuardAdvisory(transformed, advisory) : stripGuardAdvisories(transformed);
|
|
71956
|
+
return transformed;
|
|
71957
|
+
}
|
|
70738
71958
|
});
|
|
70739
71959
|
this.agentSessionController = createInteractiveAgentSessionController(this.controllerSetupHost);
|
|
70740
71960
|
this.updateTerminalTitle();
|
|
@@ -70837,6 +72057,10 @@ var InteractiveMode = class {
|
|
|
70837
72057
|
calculateContextUsage() {
|
|
70838
72058
|
return calculateContextUsage(this.contextUiHost);
|
|
70839
72059
|
}
|
|
72060
|
+
noteRuntimeGuardAdvisory(event) {
|
|
72061
|
+
this.pendingRuntimeGuardAdvisory = event.guidance;
|
|
72062
|
+
this.showStatus(`Runtime guard: ${event.toolName} failed ${event.repeatCount}x identically; advisory queued for next request.`);
|
|
72063
|
+
}
|
|
70840
72064
|
persistExecutionState() {
|
|
70841
72065
|
const activeSession = this.sessionManager.getActiveSession();
|
|
70842
72066
|
if (!activeSession) return;
|
|
@@ -70865,20 +72089,20 @@ var InteractiveMode = class {
|
|
|
70865
72089
|
setupAgentSubscription() {
|
|
70866
72090
|
bindInteractiveRuntimeEvents(this.runtimeEventHost);
|
|
70867
72091
|
}
|
|
70868
|
-
_isContextOverflowError(
|
|
70869
|
-
return isContextOverflowError(
|
|
72092
|
+
_isContextOverflowError(errorMessage4) {
|
|
72093
|
+
return isContextOverflowError(errorMessage4);
|
|
70870
72094
|
}
|
|
70871
72095
|
_shouldAutoCompact(contextTokens, contextWindow) {
|
|
70872
72096
|
return shouldAutoCompact(this.contextUiHost, contextTokens, contextWindow);
|
|
70873
72097
|
}
|
|
70874
|
-
_isRetryableError(
|
|
70875
|
-
return isRetryableError(
|
|
72098
|
+
_isRetryableError(errorMessage4) {
|
|
72099
|
+
return isRetryableError(errorMessage4);
|
|
70876
72100
|
}
|
|
70877
|
-
_isInvalidFileReferenceError(
|
|
70878
|
-
return isInvalidFileReferenceError(
|
|
72101
|
+
_isInvalidFileReferenceError(errorMessage4) {
|
|
72102
|
+
return isInvalidFileReferenceError(errorMessage4);
|
|
70879
72103
|
}
|
|
70880
|
-
_recoverFromInvalidFileReferenceError(
|
|
70881
|
-
return recoverFromInvalidFileReferenceError(this.contextUiHost,
|
|
72104
|
+
_recoverFromInvalidFileReferenceError(errorMessage4) {
|
|
72105
|
+
return recoverFromInvalidFileReferenceError(this.contextUiHost, errorMessage4);
|
|
70882
72106
|
}
|
|
70883
72107
|
async handleCompactCommand() {
|
|
70884
72108
|
return handleCompactCommand(this.compactCommandHost);
|
|
@@ -70892,8 +72116,8 @@ var InteractiveMode = class {
|
|
|
70892
72116
|
async selectMentionOption(option) {
|
|
70893
72117
|
return selectMentionOption(this.filePipelineHost, option);
|
|
70894
72118
|
}
|
|
70895
|
-
showSettingsSelector() {
|
|
70896
|
-
return showSettingsSelector(this);
|
|
72119
|
+
showSettingsSelector(focusItem) {
|
|
72120
|
+
return showSettingsSelector(this, focusItem);
|
|
70897
72121
|
}
|
|
70898
72122
|
async handleModelCommand(searchTerm) {
|
|
70899
72123
|
return handleModelCommand(this, searchTerm);
|
|
@@ -70969,7 +72193,7 @@ var InteractiveMode = class {
|
|
|
70969
72193
|
return handleResumeCommand(this);
|
|
70970
72194
|
}
|
|
70971
72195
|
async loadSession(sessionId) {
|
|
70972
|
-
return
|
|
72196
|
+
return loadSession2(this, sessionId);
|
|
70973
72197
|
}
|
|
70974
72198
|
updateTerminalTitle() {
|
|
70975
72199
|
return updateTerminalTitle(this);
|
|
@@ -71004,6 +72228,9 @@ var InteractiveMode = class {
|
|
|
71004
72228
|
handleSkillsCommand() {
|
|
71005
72229
|
return handleSkillsCommand(this);
|
|
71006
72230
|
}
|
|
72231
|
+
handleSkillsListCommand() {
|
|
72232
|
+
return handleSkillsListCommand(this);
|
|
72233
|
+
}
|
|
71007
72234
|
handleSkillCommand(name) {
|
|
71008
72235
|
return handleSkillCommand(this, name);
|
|
71009
72236
|
}
|
|
@@ -71031,6 +72258,12 @@ var InteractiveMode = class {
|
|
|
71031
72258
|
async handleSkillsReload() {
|
|
71032
72259
|
return handleSkillsReload(this);
|
|
71033
72260
|
}
|
|
72261
|
+
async handleSkillToggleCommand(args, enabled) {
|
|
72262
|
+
return handleSkillToggleCommand(this, args, enabled);
|
|
72263
|
+
}
|
|
72264
|
+
handleToolsCommand(args) {
|
|
72265
|
+
return handleToolsCommand(this, args);
|
|
72266
|
+
}
|
|
71034
72267
|
isInteractiveCommand(commandPath) {
|
|
71035
72268
|
const interactiveCommands = [
|
|
71036
72269
|
"/skills/create",
|
|
@@ -71049,8 +72282,8 @@ var InteractiveMode = class {
|
|
|
71049
72282
|
showStatus(message) {
|
|
71050
72283
|
return showStatus(this.uiHelperHost, message);
|
|
71051
72284
|
}
|
|
71052
|
-
showError(
|
|
71053
|
-
return showError(this.uiHelperHost,
|
|
72285
|
+
showError(errorMessage4) {
|
|
72286
|
+
return showError(this.uiHelperHost, errorMessage4);
|
|
71054
72287
|
}
|
|
71055
72288
|
async handleDirectBash(command) {
|
|
71056
72289
|
return handleDirectBash(this.directBashHost, command);
|
|
@@ -71224,8 +72457,8 @@ async function composeCliRuntime(params) {
|
|
|
71224
72457
|
} else {
|
|
71225
72458
|
await sessionManager.createSession();
|
|
71226
72459
|
}
|
|
71227
|
-
syncSessionModelMetadata(sessionManager, model, settingsManager.getDefaultThinkingLevel() || "off");
|
|
71228
72460
|
const activeSession = sessionManager.getActiveSession();
|
|
72461
|
+
syncSessionModelMetadata(sessionManager, model, resolveInitialThinkingLevel({ session: activeSession, settingsManager }));
|
|
71229
72462
|
if (activeSession && activeSession.metadata.cwd !== cwd) {
|
|
71230
72463
|
activeSession.metadata.cwd = cwd;
|
|
71231
72464
|
await sessionManager.save();
|
|
@@ -71242,7 +72475,7 @@ async function composeCliRuntime(params) {
|
|
|
71242
72475
|
keyPrefix: apiKey ? maskApiKey2(apiKey) : "none"
|
|
71243
72476
|
});
|
|
71244
72477
|
const projectSkillsDir = path30.join(cwd, ".pie", "skills");
|
|
71245
|
-
const { skills, diagnostics } = loadSkills({
|
|
72478
|
+
const { skills: discoveredSkills, diagnostics } = loadSkills({
|
|
71246
72479
|
dirs: buildSkillDirs({
|
|
71247
72480
|
builtinDir: paths.builtinSkillsDir,
|
|
71248
72481
|
userDir: paths.skillsDir,
|
|
@@ -71250,6 +72483,7 @@ async function composeCliRuntime(params) {
|
|
|
71250
72483
|
cwd
|
|
71251
72484
|
})
|
|
71252
72485
|
});
|
|
72486
|
+
const skills = discoveredSkills.filter((skill) => settingsManager.isSkillEnabled(skill.name));
|
|
71253
72487
|
let interactiveOptions;
|
|
71254
72488
|
const getCurrentModel = () => interactiveOptions?.model ?? model;
|
|
71255
72489
|
const cliHostCapabilities = createCliHostCapabilities(cwd, {
|
|
@@ -71273,22 +72507,23 @@ async function composeCliRuntime(params) {
|
|
|
71273
72507
|
...createCliFileSystemTools(cwd, fileSystemToolOptions),
|
|
71274
72508
|
...cliHostCapabilities.tools
|
|
71275
72509
|
];
|
|
72510
|
+
const enabledRawTools = filterEnabledTools(rawTools, settingsManager);
|
|
71276
72511
|
recordCliCompositionStep(compositionTrace, {
|
|
71277
72512
|
id: "host_shared_capabilities",
|
|
71278
72513
|
inputSummary: `cwd=${cwd}`,
|
|
71279
|
-
outputSummary: summarizeToolNames(
|
|
71280
|
-
toolCount:
|
|
72514
|
+
outputSummary: summarizeToolNames(enabledRawTools),
|
|
72515
|
+
toolCount: enabledRawTools.length
|
|
71281
72516
|
});
|
|
71282
|
-
const allTools = createPolicyEnforcedTools(
|
|
72517
|
+
const allTools = createPolicyEnforcedTools(enabledRawTools, {
|
|
71283
72518
|
getContext: () => ({ mode: "normal", confirmationPolicy: "allow" })
|
|
71284
72519
|
});
|
|
71285
72520
|
const tools = [...allTools];
|
|
71286
72521
|
recordCliCompositionStep(compositionTrace, {
|
|
71287
72522
|
id: "policy_filtering",
|
|
71288
|
-
inputSummary: `tools=${
|
|
72523
|
+
inputSummary: `tools=${enabledRawTools.length}`,
|
|
71289
72524
|
outputSummary: summarizeToolNames(tools),
|
|
71290
72525
|
toolCount: tools.length,
|
|
71291
|
-
policyDecisions:
|
|
72526
|
+
policyDecisions: enabledRawTools.length === allTools.length ? ["allow:default"] : [`filtered:${enabledRawTools.length - allTools.length}`]
|
|
71292
72527
|
});
|
|
71293
72528
|
for (const diag of diagnostics.filter((d) => d.type === "collision")) {
|
|
71294
72529
|
console.log(`[CLI] ${diag.message}`);
|
|
@@ -71473,7 +72708,7 @@ async function loadPrintModeExtensions(params) {
|
|
|
71473
72708
|
);
|
|
71474
72709
|
runner.setUIContext(uiContext);
|
|
71475
72710
|
await restoreExtensionProviderCredentials(params.modelRegistry);
|
|
71476
|
-
const extensionTools = convertExtensionTools(extensions);
|
|
72711
|
+
const extensionTools = filterEnabledTools(convertExtensionTools(extensions), params.settingsManager);
|
|
71477
72712
|
availableTools = [...availableTools, ...extensionTools];
|
|
71478
72713
|
return {
|
|
71479
72714
|
extensions,
|
|
@@ -71533,12 +72768,13 @@ async function runPrintMode(params) {
|
|
|
71533
72768
|
knowledgeSection: runtime.knowledgeSection,
|
|
71534
72769
|
tools: printModeTools.map((tool) => ({ name: tool.name, description: tool.description }))
|
|
71535
72770
|
});
|
|
72771
|
+
const printThinkingLevel = resolveInitialThinkingLevel({ session: runtime.sessionManager.getActiveSession(), settingsManager: runtime.settingsManager });
|
|
71536
72772
|
agent = new AgentClass({
|
|
71537
72773
|
initialState: {
|
|
71538
72774
|
systemPrompt: baseSystemPrompt,
|
|
71539
72775
|
model: runtime.model,
|
|
71540
72776
|
tools: printModeTools,
|
|
71541
|
-
thinkingLevel:
|
|
72777
|
+
thinkingLevel: printThinkingLevel
|
|
71542
72778
|
},
|
|
71543
72779
|
apiKey: runtime.apiKey,
|
|
71544
72780
|
streamFn: params.streamFn
|
|
@@ -71673,21 +72909,21 @@ async function runPrintMode(params) {
|
|
|
71673
72909
|
console.log(assistantText);
|
|
71674
72910
|
}
|
|
71675
72911
|
} catch (err) {
|
|
71676
|
-
const
|
|
71677
|
-
sessionTrace.noteStalled(
|
|
72912
|
+
const errorMessage4 = err instanceof Error ? err.message : String(err);
|
|
72913
|
+
sessionTrace.noteStalled(errorMessage4, { mode: "print" });
|
|
71678
72914
|
process.exitCode = 1;
|
|
71679
72915
|
if (params.jsonOutput) {
|
|
71680
72916
|
console.log(
|
|
71681
72917
|
JSON.stringify({
|
|
71682
72918
|
ok: false,
|
|
71683
|
-
error:
|
|
72919
|
+
error: errorMessage4,
|
|
71684
72920
|
sessionId: runtime.sessionManager.getActiveSession()?.id,
|
|
71685
72921
|
provider: runtime.provider,
|
|
71686
72922
|
modelId: runtime.modelId
|
|
71687
72923
|
})
|
|
71688
72924
|
);
|
|
71689
72925
|
}
|
|
71690
|
-
console.error("Error:",
|
|
72926
|
+
console.error("Error:", errorMessage4);
|
|
71691
72927
|
}
|
|
71692
72928
|
if (!params.rawOutput && !params.jsonOutput) {
|
|
71693
72929
|
console.log("");
|
|
@@ -71704,6 +72940,9 @@ var MAX_EVENT_OBJECT_KEYS = 50;
|
|
|
71704
72940
|
var MAX_EVENT_ARRAY_ITEMS = 50;
|
|
71705
72941
|
var MAX_EVENT_VALUE_DEPTH = 4;
|
|
71706
72942
|
var MAX_EVENT_STRING_LENGTH = 4e3;
|
|
72943
|
+
var COMPACT_EVENT_STRING_LENGTH = 800;
|
|
72944
|
+
var FULL_DETAIL = "full";
|
|
72945
|
+
var COMPACT_DETAIL = "compact";
|
|
71707
72946
|
function createNoOpExtensionUIContext2() {
|
|
71708
72947
|
return {
|
|
71709
72948
|
notify: () => {
|
|
@@ -71719,10 +72958,10 @@ function writeEvent(event) {
|
|
|
71719
72958
|
process.stdout.write(`${JSON.stringify(event)}
|
|
71720
72959
|
`);
|
|
71721
72960
|
}
|
|
71722
|
-
function toJsonValue(value, depth = 0) {
|
|
72961
|
+
function toJsonValue(value, depth = 0, cap = MAX_EVENT_STRING_LENGTH) {
|
|
71723
72962
|
if (value === null) return null;
|
|
71724
72963
|
if (typeof value === "string") {
|
|
71725
|
-
return value.length >
|
|
72964
|
+
return value.length > cap ? value.slice(0, cap) : value;
|
|
71726
72965
|
}
|
|
71727
72966
|
if (typeof value === "number") return Number.isFinite(value) ? value : String(value);
|
|
71728
72967
|
if (typeof value === "boolean") return value;
|
|
@@ -71730,17 +72969,33 @@ function toJsonValue(value, depth = 0) {
|
|
|
71730
72969
|
if (typeof value !== "object") return void 0;
|
|
71731
72970
|
if (depth >= MAX_EVENT_VALUE_DEPTH) return "[truncated]";
|
|
71732
72971
|
if (Array.isArray(value)) {
|
|
71733
|
-
return value.slice(0, MAX_EVENT_ARRAY_ITEMS).map((item) => toJsonValue(item, depth + 1) ?? null);
|
|
72972
|
+
return value.slice(0, MAX_EVENT_ARRAY_ITEMS).map((item) => toJsonValue(item, depth + 1, cap) ?? null);
|
|
71734
72973
|
}
|
|
71735
72974
|
const result = {};
|
|
71736
72975
|
for (const [key, item] of Object.entries(value).slice(0, MAX_EVENT_OBJECT_KEYS)) {
|
|
71737
|
-
result[key] = toJsonValue(item, depth + 1);
|
|
72976
|
+
result[key] = toJsonValue(item, depth + 1, cap);
|
|
71738
72977
|
}
|
|
71739
72978
|
return result;
|
|
71740
72979
|
}
|
|
71741
72980
|
function isRecord4(value) {
|
|
71742
72981
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
71743
72982
|
}
|
|
72983
|
+
function truncateForEvent(text, cap) {
|
|
72984
|
+
if (text.length <= cap) {
|
|
72985
|
+
return { value: text, truncated: false, fullLength: text.length };
|
|
72986
|
+
}
|
|
72987
|
+
return { value: text.slice(0, cap), truncated: true, fullLength: text.length };
|
|
72988
|
+
}
|
|
72989
|
+
function hasOversizedValue(value, cap, depth = 0) {
|
|
72990
|
+
if (typeof value === "string") return value.length > cap;
|
|
72991
|
+
if (!value || typeof value !== "object") return false;
|
|
72992
|
+
if (depth >= MAX_EVENT_VALUE_DEPTH) return true;
|
|
72993
|
+
if (Array.isArray(value)) {
|
|
72994
|
+
return value.length > MAX_EVENT_ARRAY_ITEMS || value.some((item) => hasOversizedValue(item, cap, depth + 1));
|
|
72995
|
+
}
|
|
72996
|
+
const entries = Object.entries(value);
|
|
72997
|
+
return entries.length > MAX_EVENT_OBJECT_KEYS || entries.some(([, item]) => hasOversizedValue(item, cap, depth + 1));
|
|
72998
|
+
}
|
|
71744
72999
|
function parseInput(line) {
|
|
71745
73000
|
let parsed;
|
|
71746
73001
|
try {
|
|
@@ -71765,8 +73020,7 @@ function parseInput(line) {
|
|
|
71765
73020
|
type: "session.rewind",
|
|
71766
73021
|
sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : void 0,
|
|
71767
73022
|
requestId: typeof parsed.requestId === "string" ? parsed.requestId : void 0,
|
|
71768
|
-
entryId: typeof parsed.entryId === "string" ? parsed.entryId : void 0
|
|
71769
|
-
checkpointId: typeof parsed.checkpointId === "string" ? parsed.checkpointId : void 0
|
|
73023
|
+
entryId: typeof parsed.entryId === "string" ? parsed.entryId : void 0
|
|
71770
73024
|
};
|
|
71771
73025
|
}
|
|
71772
73026
|
if (parsed.type === "session.fork") {
|
|
@@ -71780,6 +73034,14 @@ function parseInput(line) {
|
|
|
71780
73034
|
cwd: typeof parsed.cwd === "string" ? parsed.cwd : void 0
|
|
71781
73035
|
};
|
|
71782
73036
|
}
|
|
73037
|
+
if (parsed.type === "sidechat.request" && typeof parsed.requestId === "string" && typeof parsed.prompt === "string") {
|
|
73038
|
+
return {
|
|
73039
|
+
type: "sidechat.request",
|
|
73040
|
+
sessionId: typeof parsed.sessionId === "string" ? parsed.sessionId : void 0,
|
|
73041
|
+
requestId: parsed.requestId,
|
|
73042
|
+
prompt: parsed.prompt
|
|
73043
|
+
};
|
|
73044
|
+
}
|
|
71783
73045
|
if ((parsed.type === "turn.request" || parsed.type === "turn.input") && typeof parsed.turnId === "string" && typeof parsed.prompt === "string") {
|
|
71784
73046
|
const streamingBehavior = parsed.streamingBehavior;
|
|
71785
73047
|
if (streamingBehavior !== void 0 && streamingBehavior !== "steer" && streamingBehavior !== "followUp") {
|
|
@@ -71813,6 +73075,12 @@ function assistantTextFromMessage(message) {
|
|
|
71813
73075
|
}
|
|
71814
73076
|
return text;
|
|
71815
73077
|
}
|
|
73078
|
+
function assistantUsageFromAgent(agent) {
|
|
73079
|
+
const messages = agent?.state.messages ?? [];
|
|
73080
|
+
const lastMessage = messages[messages.length - 1];
|
|
73081
|
+
if (lastMessage?.role !== "assistant") return void 0;
|
|
73082
|
+
return toJsonValue(lastMessage.usage);
|
|
73083
|
+
}
|
|
71816
73084
|
function assistantErrorFromAgent(agent) {
|
|
71817
73085
|
const messages = agent?.state.messages ?? [];
|
|
71818
73086
|
const lastMessage = messages[messages.length - 1];
|
|
@@ -71921,7 +73189,7 @@ async function loadJsonModeExtensions(params) {
|
|
|
71921
73189
|
);
|
|
71922
73190
|
runner.setUIContext(uiContext);
|
|
71923
73191
|
await restoreExtensionProviderCredentials(params.runtime.modelRegistry);
|
|
71924
|
-
const extensionTools = convertExtensionTools(extensions);
|
|
73192
|
+
const extensionTools = filterEnabledTools(convertExtensionTools(extensions), params.runtime.settingsManager);
|
|
71925
73193
|
availableTools = [...availableTools, ...extensionTools];
|
|
71926
73194
|
return {
|
|
71927
73195
|
runner,
|
|
@@ -71930,6 +73198,8 @@ async function loadJsonModeExtensions(params) {
|
|
|
71930
73198
|
};
|
|
71931
73199
|
}
|
|
71932
73200
|
async function runJsonEventsMode(params) {
|
|
73201
|
+
const eventDetail = params.eventDetail === FULL_DETAIL ? FULL_DETAIL : COMPACT_DETAIL;
|
|
73202
|
+
const eventStringCap = eventDetail === FULL_DETAIL ? MAX_EVENT_STRING_LENGTH : COMPACT_EVENT_STRING_LENGTH;
|
|
71933
73203
|
const sessionId = params.explicitSessionId || params.runtime?.sessionManager.getActiveSession()?.id || `pie-json-${Date.now()}`;
|
|
71934
73204
|
let activeTurn = null;
|
|
71935
73205
|
let runtime = params.runtime;
|
|
@@ -71940,13 +73210,28 @@ async function runJsonEventsMode(params) {
|
|
|
71940
73210
|
let trace;
|
|
71941
73211
|
let lastRetryEvent;
|
|
71942
73212
|
let mockActiveEntryId;
|
|
71943
|
-
let thinkingLevel =
|
|
73213
|
+
let thinkingLevel = DEFAULT_THINKING_LEVEL;
|
|
73214
|
+
let thinkingLevelInitialized = false;
|
|
71944
73215
|
let defaultRuntime;
|
|
71945
73216
|
let defaultModelState;
|
|
71946
73217
|
const completedSessionControlRequests = /* @__PURE__ */ new Map();
|
|
73218
|
+
const completedSidechatRequests = /* @__PURE__ */ new Map();
|
|
73219
|
+
const ensureRuntimeInFlight = /* @__PURE__ */ new Map();
|
|
73220
|
+
let activeSidechat = null;
|
|
73221
|
+
let activeSidechatPromise = null;
|
|
73222
|
+
let sidechatChainStopped = false;
|
|
71947
73223
|
const noProgressTimeoutMs = Number(process.env.PIE_JSON_EVENTS_NO_PROGRESS_MS || 6e5);
|
|
71948
73224
|
const mockResponseDelayMs = Number(process.env.PIE_TEST_MOCK_RESPONSE_DELAY_MS || 0);
|
|
73225
|
+
const prewarmTimeoutMs = Number(process.env.PIE_JSON_EVENTS_PREWARM_TIMEOUT_MS || 1e4);
|
|
73226
|
+
const sidechatTimeoutMs = Number(process.env.PIE_JSON_EVENTS_SIDECHAT_TIMEOUT_MS || 3e5);
|
|
73227
|
+
await prewarmRuntime();
|
|
71949
73228
|
writeEvent({ type: "agent.ready", sessionId });
|
|
73229
|
+
function trackSidechatPromise(promise) {
|
|
73230
|
+
activeSidechatPromise = promise;
|
|
73231
|
+
void promise.finally(() => {
|
|
73232
|
+
if (activeSidechatPromise === promise) activeSidechatPromise = null;
|
|
73233
|
+
});
|
|
73234
|
+
}
|
|
71950
73235
|
function sessionMismatchError(requestedSessionId) {
|
|
71951
73236
|
return `session mismatch: JSON events process is bound to ${sessionId}, received ${requestedSessionId}`;
|
|
71952
73237
|
}
|
|
@@ -72118,15 +73403,10 @@ async function runJsonEventsMode(params) {
|
|
|
72118
73403
|
}
|
|
72119
73404
|
function resolveRewindEntryId(message) {
|
|
72120
73405
|
const entryId = message.entryId?.trim();
|
|
72121
|
-
|
|
72122
|
-
|
|
72123
|
-
throw invalidSessionControl("entryId and checkpointId must match when both are provided");
|
|
72124
|
-
}
|
|
72125
|
-
const resolved = entryId || checkpointId;
|
|
72126
|
-
if (!resolved) {
|
|
72127
|
-
throw invalidSessionControl("entryId or checkpointId is required");
|
|
73406
|
+
if (!entryId) {
|
|
73407
|
+
throw invalidSessionControl("entryId is required");
|
|
72128
73408
|
}
|
|
72129
|
-
return
|
|
73409
|
+
return entryId;
|
|
72130
73410
|
}
|
|
72131
73411
|
function writeSessionControlFailure(message, operation, error) {
|
|
72132
73412
|
const detail = error instanceof SessionControlError ? error : new SessionControlError("session_io_error", error instanceof Error ? error.message : String(error));
|
|
@@ -72178,14 +73458,12 @@ async function runJsonEventsMode(params) {
|
|
|
72178
73458
|
entryId
|
|
72179
73459
|
});
|
|
72180
73460
|
await syncRuntimeAfterRewind(controlSessionId);
|
|
72181
|
-
mockActiveEntryId = result.
|
|
73461
|
+
mockActiveEntryId = result.activeEntryId;
|
|
72182
73462
|
const event = {
|
|
72183
73463
|
type: "session.rewound",
|
|
72184
73464
|
sessionId: controlSessionId,
|
|
72185
73465
|
requestId,
|
|
72186
73466
|
entryId: result.entryId,
|
|
72187
|
-
checkpointId: result.checkpointId,
|
|
72188
|
-
headEntryId: result.headEntryId,
|
|
72189
73467
|
activeEntryId: result.activeEntryId
|
|
72190
73468
|
};
|
|
72191
73469
|
completedSessionControlRequests.set(requestId, event);
|
|
@@ -72222,11 +73500,8 @@ async function runJsonEventsMode(params) {
|
|
|
72222
73500
|
requestId,
|
|
72223
73501
|
sourceSessionId: result.sourceSessionId,
|
|
72224
73502
|
sourceEntryId: result.sourceEntryId,
|
|
72225
|
-
sourceCheckpointId: result.sourceCheckpointId,
|
|
72226
73503
|
targetSessionId: result.targetSessionId,
|
|
72227
|
-
|
|
72228
|
-
targetActiveEntryId: result.targetActiveEntryId,
|
|
72229
|
-
headEntryId: result.headEntryId
|
|
73504
|
+
targetActiveEntryId: result.targetActiveEntryId
|
|
72230
73505
|
};
|
|
72231
73506
|
completedSessionControlRequests.set(requestId, event);
|
|
72232
73507
|
writeEvent(event);
|
|
@@ -72234,21 +73509,150 @@ async function runJsonEventsMode(params) {
|
|
|
72234
73509
|
writeSessionControlFailure(message, "fork", error);
|
|
72235
73510
|
}
|
|
72236
73511
|
}
|
|
73512
|
+
function writeSidechatFailure(message, error, code) {
|
|
73513
|
+
writeEvent({
|
|
73514
|
+
type: "sidechat.failed",
|
|
73515
|
+
sessionId,
|
|
73516
|
+
requestId: message.requestId.trim(),
|
|
73517
|
+
error,
|
|
73518
|
+
code
|
|
73519
|
+
});
|
|
73520
|
+
}
|
|
73521
|
+
async function handleSidechat(message) {
|
|
73522
|
+
if (isSessionMismatch(message)) {
|
|
73523
|
+
writeSidechatFailure(message, sessionMismatchError(message.sessionId), "session_mismatch");
|
|
73524
|
+
return;
|
|
73525
|
+
}
|
|
73526
|
+
const requestId = message.requestId.trim();
|
|
73527
|
+
if (!requestId) {
|
|
73528
|
+
writeSidechatFailure(message, "requestId is required", "invalid_request");
|
|
73529
|
+
return;
|
|
73530
|
+
}
|
|
73531
|
+
const cached = completedSidechatRequests.get(requestId);
|
|
73532
|
+
if (cached) {
|
|
73533
|
+
writeEvent(cached);
|
|
73534
|
+
return;
|
|
73535
|
+
}
|
|
73536
|
+
if (activeTurn && !activeTurn.finalized) {
|
|
73537
|
+
writeSidechatFailure(message, "Cannot run sidechat while a turn is active", "session_busy");
|
|
73538
|
+
return;
|
|
73539
|
+
}
|
|
73540
|
+
const startedAt = Date.now();
|
|
73541
|
+
if (params.mockResponse !== void 0) {
|
|
73542
|
+
writeEvent({ type: "sidechat.started", sessionId, requestId });
|
|
73543
|
+
const event = {
|
|
73544
|
+
type: "sidechat.completed",
|
|
73545
|
+
sessionId,
|
|
73546
|
+
requestId,
|
|
73547
|
+
text: params.mockResponse,
|
|
73548
|
+
durationMs: Date.now() - startedAt
|
|
73549
|
+
};
|
|
73550
|
+
completedSidechatRequests.set(requestId, event);
|
|
73551
|
+
writeEvent(event);
|
|
73552
|
+
return;
|
|
73553
|
+
}
|
|
73554
|
+
writeEvent({ type: "sidechat.started", sessionId, requestId });
|
|
73555
|
+
const sidechatController = new AbortController();
|
|
73556
|
+
let abortKind;
|
|
73557
|
+
activeSidechat = {
|
|
73558
|
+
abort: () => {
|
|
73559
|
+
if (!abortKind) abortKind = "interrupted";
|
|
73560
|
+
sidechatController.abort();
|
|
73561
|
+
}
|
|
73562
|
+
};
|
|
73563
|
+
try {
|
|
73564
|
+
await ensureRuntime();
|
|
73565
|
+
if (!agent || !runtime) {
|
|
73566
|
+
throw new Error("JSON events runtime was not initialized");
|
|
73567
|
+
}
|
|
73568
|
+
if (runtime.initialModel.unconfigured) {
|
|
73569
|
+
writeSidechatFailure(message, runtime.initialModel.warning || "No models are configured.");
|
|
73570
|
+
return;
|
|
73571
|
+
}
|
|
73572
|
+
if (sidechatController.signal.aborted) {
|
|
73573
|
+
writeSidechatFailure(message, "sidechat aborted before dispatch", "sidechat_interrupted");
|
|
73574
|
+
return;
|
|
73575
|
+
}
|
|
73576
|
+
const parent = agent;
|
|
73577
|
+
const { Agent: AgentClass } = await import("./chunks/src-HYZFAW4V.js");
|
|
73578
|
+
const sideAgent = new AgentClass({
|
|
73579
|
+
initialState: {
|
|
73580
|
+
systemPrompt: parent.state.systemPrompt,
|
|
73581
|
+
model: parent.state.model,
|
|
73582
|
+
thinkingLevel: parent.state.thinkingLevel,
|
|
73583
|
+
tools: [],
|
|
73584
|
+
messages: structuredClone(parent.state.messages)
|
|
73585
|
+
},
|
|
73586
|
+
apiKey: runtime.apiKey,
|
|
73587
|
+
streamFn: params.streamFn
|
|
73588
|
+
});
|
|
73589
|
+
sidechatController.signal.addEventListener("abort", () => sideAgent.abort(), { once: true });
|
|
73590
|
+
const timer = setTimeout(() => {
|
|
73591
|
+
if (!abortKind) abortKind = "timeout";
|
|
73592
|
+
sidechatController.abort();
|
|
73593
|
+
}, sidechatTimeoutMs);
|
|
73594
|
+
timer.unref?.();
|
|
73595
|
+
try {
|
|
73596
|
+
await sideAgent.prompt(message.prompt);
|
|
73597
|
+
} finally {
|
|
73598
|
+
clearTimeout(timer);
|
|
73599
|
+
}
|
|
73600
|
+
if (abortKind) {
|
|
73601
|
+
const code = abortKind === "timeout" ? "sidechat_timeout" : "sidechat_interrupted";
|
|
73602
|
+
writeSidechatFailure(message, sideAgent.state.error || "sidechat aborted", code);
|
|
73603
|
+
return;
|
|
73604
|
+
}
|
|
73605
|
+
const failure = sideAgent.state.error;
|
|
73606
|
+
if (failure) {
|
|
73607
|
+
writeSidechatFailure(message, failure);
|
|
73608
|
+
return;
|
|
73609
|
+
}
|
|
73610
|
+
const sidechatText = assistantTextFromAgent(sideAgent);
|
|
73611
|
+
const capped = sidechatText === void 0 ? void 0 : truncateForEvent(sidechatText, eventStringCap);
|
|
73612
|
+
const event = {
|
|
73613
|
+
type: "sidechat.completed",
|
|
73614
|
+
sessionId,
|
|
73615
|
+
requestId,
|
|
73616
|
+
text: capped?.value,
|
|
73617
|
+
...capped?.truncated ? { truncated: true, fullLength: capped.fullLength } : {},
|
|
73618
|
+
usage: assistantUsageFromAgent(sideAgent),
|
|
73619
|
+
durationMs: Date.now() - startedAt
|
|
73620
|
+
};
|
|
73621
|
+
completedSidechatRequests.set(requestId, event);
|
|
73622
|
+
writeEvent(event);
|
|
73623
|
+
} catch (error) {
|
|
73624
|
+
const detail = errorToFailureDetail(error);
|
|
73625
|
+
writeSidechatFailure(
|
|
73626
|
+
message,
|
|
73627
|
+
typeof detail === "string" ? detail : detail.message,
|
|
73628
|
+
typeof detail === "string" ? void 0 : detail.code
|
|
73629
|
+
);
|
|
73630
|
+
} finally {
|
|
73631
|
+
activeSidechat = null;
|
|
73632
|
+
}
|
|
73633
|
+
}
|
|
72237
73634
|
function finalize(kind, detail) {
|
|
72238
73635
|
const turn = activeTurn;
|
|
72239
73636
|
if (!turn || turn.finalized) return;
|
|
72240
73637
|
turn.finalized = true;
|
|
72241
|
-
const
|
|
73638
|
+
const activeEntryId = activeHeadEntryId();
|
|
72242
73639
|
const base = {
|
|
72243
73640
|
sessionId: turn.sessionId,
|
|
72244
73641
|
turnId: turn.turnId,
|
|
72245
|
-
|
|
72246
|
-
activeEntryId: headEntryId
|
|
73642
|
+
activeEntryId
|
|
72247
73643
|
};
|
|
72248
73644
|
switch (kind) {
|
|
72249
|
-
case "completed":
|
|
72250
|
-
|
|
73645
|
+
case "completed": {
|
|
73646
|
+
const summaryText = (typeof detail === "string" ? detail : turn.summary).trim();
|
|
73647
|
+
const capped = truncateForEvent(summaryText, eventStringCap);
|
|
73648
|
+
writeEvent({
|
|
73649
|
+
type: "turn.completed",
|
|
73650
|
+
...base,
|
|
73651
|
+
summary: capped.value,
|
|
73652
|
+
...capped.truncated ? { truncated: true, fullLength: capped.fullLength } : {}
|
|
73653
|
+
});
|
|
72251
73654
|
break;
|
|
73655
|
+
}
|
|
72252
73656
|
case "failed":
|
|
72253
73657
|
writeEvent({ type: "turn.failed", ...base, ...failureDetail(detail) });
|
|
72254
73658
|
break;
|
|
@@ -72261,13 +73665,12 @@ async function runJsonEventsMode(params) {
|
|
|
72261
73665
|
}
|
|
72262
73666
|
}
|
|
72263
73667
|
function emitSettled(turn) {
|
|
72264
|
-
const
|
|
73668
|
+
const activeEntryId = activeHeadEntryId();
|
|
72265
73669
|
writeEvent({
|
|
72266
73670
|
type: "turn.settled",
|
|
72267
73671
|
sessionId: turn.sessionId,
|
|
72268
73672
|
turnId: turn.turnId,
|
|
72269
|
-
|
|
72270
|
-
activeEntryId: headEntryId
|
|
73673
|
+
activeEntryId
|
|
72271
73674
|
});
|
|
72272
73675
|
}
|
|
72273
73676
|
function rememberTerminal(kind, detail, options) {
|
|
@@ -72290,14 +73693,20 @@ async function runJsonEventsMode(params) {
|
|
|
72290
73693
|
break;
|
|
72291
73694
|
case "tool_started":
|
|
72292
73695
|
touch();
|
|
72293
|
-
|
|
72294
|
-
|
|
72295
|
-
|
|
72296
|
-
|
|
72297
|
-
|
|
72298
|
-
|
|
72299
|
-
|
|
72300
|
-
|
|
73696
|
+
{
|
|
73697
|
+
const argsOversized = eventDetail === COMPACT_DETAIL && hasOversizedValue(event.args, eventStringCap);
|
|
73698
|
+
writeEvent({
|
|
73699
|
+
type: "tool.started",
|
|
73700
|
+
sessionId: activeTurn.sessionId,
|
|
73701
|
+
turnId: activeTurn.turnId,
|
|
73702
|
+
toolCallId: event.toolCallId,
|
|
73703
|
+
name: event.toolName,
|
|
73704
|
+
data: toJsonValue({
|
|
73705
|
+
args: event.args,
|
|
73706
|
+
...argsOversized ? { truncated: true } : {}
|
|
73707
|
+
}, 0, eventStringCap)
|
|
73708
|
+
});
|
|
73709
|
+
}
|
|
72301
73710
|
break;
|
|
72302
73711
|
case "tool_progressed":
|
|
72303
73712
|
touch();
|
|
@@ -72311,18 +73720,23 @@ async function runJsonEventsMode(params) {
|
|
|
72311
73720
|
break;
|
|
72312
73721
|
case "tool_finished":
|
|
72313
73722
|
touch();
|
|
72314
|
-
|
|
72315
|
-
|
|
72316
|
-
|
|
72317
|
-
|
|
72318
|
-
|
|
72319
|
-
|
|
72320
|
-
|
|
72321
|
-
|
|
72322
|
-
|
|
72323
|
-
|
|
72324
|
-
|
|
72325
|
-
|
|
73723
|
+
{
|
|
73724
|
+
const resultText = extractJsonEventsToolProgressText(event.result);
|
|
73725
|
+
const capped = resultText === void 0 || resultText === null ? void 0 : truncateForEvent(resultText, eventStringCap);
|
|
73726
|
+
writeEvent({
|
|
73727
|
+
type: "tool.completed",
|
|
73728
|
+
sessionId: activeTurn.sessionId,
|
|
73729
|
+
turnId: activeTurn.turnId,
|
|
73730
|
+
toolCallId: event.toolCallId,
|
|
73731
|
+
name: event.toolName,
|
|
73732
|
+
status: event.isError ? "error" : "ok",
|
|
73733
|
+
data: toJsonValue({
|
|
73734
|
+
resultText: capped?.value,
|
|
73735
|
+
isError: event.isError,
|
|
73736
|
+
...capped?.truncated ? { truncated: true, fullLength: capped.fullLength } : {}
|
|
73737
|
+
}, 0, eventStringCap)
|
|
73738
|
+
});
|
|
73739
|
+
}
|
|
72326
73740
|
break;
|
|
72327
73741
|
}
|
|
72328
73742
|
}
|
|
@@ -72448,9 +73862,30 @@ async function runJsonEventsMode(params) {
|
|
|
72448
73862
|
trace = void 0;
|
|
72449
73863
|
cleanupBashOutputArtifacts();
|
|
72450
73864
|
}
|
|
73865
|
+
async function prewarmRuntime() {
|
|
73866
|
+
if (params.mockResponse !== void 0) return;
|
|
73867
|
+
if (!params.createRuntime && !params.runtime) return;
|
|
73868
|
+
try {
|
|
73869
|
+
await new Promise((resolve7, reject) => {
|
|
73870
|
+
const timer = setTimeout(() => reject(new Error("prewarm timeout")), prewarmTimeoutMs);
|
|
73871
|
+
timer.unref?.();
|
|
73872
|
+
void ensureRuntime().then(resolve7, reject).finally(() => clearTimeout(timer));
|
|
73873
|
+
});
|
|
73874
|
+
} catch {
|
|
73875
|
+
}
|
|
73876
|
+
}
|
|
72451
73877
|
async function ensureRuntime(requestedCwd) {
|
|
72452
73878
|
if (params.mockResponse !== void 0) return;
|
|
72453
73879
|
const effectiveCwd = requestedCwd ?? process.cwd();
|
|
73880
|
+
const inFlight = ensureRuntimeInFlight.get(effectiveCwd);
|
|
73881
|
+
if (inFlight) return inFlight;
|
|
73882
|
+
const composed = composeRuntime(effectiveCwd);
|
|
73883
|
+
ensureRuntimeInFlight.set(effectiveCwd, composed);
|
|
73884
|
+
void composed.finally(() => ensureRuntimeInFlight.delete(effectiveCwd)).catch(() => {
|
|
73885
|
+
});
|
|
73886
|
+
return composed;
|
|
73887
|
+
}
|
|
73888
|
+
async function composeRuntime(effectiveCwd) {
|
|
72454
73889
|
if (params.createRuntime && (!runtime || runtime.cwd !== effectiveCwd)) {
|
|
72455
73890
|
await disposeRuntime();
|
|
72456
73891
|
runtime = await params.createRuntime({ cwd: effectiveCwd, sessionId });
|
|
@@ -72545,6 +73980,11 @@ async function runJsonEventsMode(params) {
|
|
|
72545
73980
|
agent.setTools(wrapToolsWithExtensions(agent.state.tools, jsonModeExtensions.runner));
|
|
72546
73981
|
controller.updateRuntimeContext({ tools: agent.state.tools });
|
|
72547
73982
|
disposeSemanticSubscription = agent.subscribeSemantic(handleSemanticEvent);
|
|
73983
|
+
if (!thinkingLevelInitialized) {
|
|
73984
|
+
thinkingLevelInitialized = true;
|
|
73985
|
+
thinkingLevel = resolveInitialThinkingLevel({ session: runtime.sessionManager.getActiveSession(), settingsManager: runtime.settingsManager });
|
|
73986
|
+
agent.setThinkingLevel(thinkingLevel);
|
|
73987
|
+
}
|
|
72548
73988
|
}
|
|
72549
73989
|
function metadataSelection(metadata, key) {
|
|
72550
73990
|
if (!metadata || !(key in metadata)) return void 0;
|
|
@@ -72606,6 +74046,7 @@ async function runJsonEventsMode(params) {
|
|
|
72606
74046
|
const nextLevel = requestedThinkingLevel === null ? "off" : requestedThinkingLevel;
|
|
72607
74047
|
if (!isThinkingLevel(nextLevel)) throw new Error(`Unsupported thinkingLevel: ${nextLevel}`);
|
|
72608
74048
|
thinkingLevel = nextLevel;
|
|
74049
|
+
thinkingLevelInitialized = true;
|
|
72609
74050
|
applyThinkingLevel({
|
|
72610
74051
|
level: thinkingLevel,
|
|
72611
74052
|
agent,
|
|
@@ -72865,6 +74306,8 @@ async function runJsonEventsMode(params) {
|
|
|
72865
74306
|
}
|
|
72866
74307
|
if (message.type === "shutdown") {
|
|
72867
74308
|
shutdownActiveTurn(message.reason);
|
|
74309
|
+
sidechatChainStopped = true;
|
|
74310
|
+
activeSidechat?.abort();
|
|
72868
74311
|
break;
|
|
72869
74312
|
}
|
|
72870
74313
|
if (message.type === "turn.interrupt") {
|
|
@@ -72879,6 +74322,24 @@ async function runJsonEventsMode(params) {
|
|
|
72879
74322
|
await handleSessionFork(message);
|
|
72880
74323
|
continue;
|
|
72881
74324
|
}
|
|
74325
|
+
if (message.type === "sidechat.request") {
|
|
74326
|
+
const prior = activeSidechatPromise ?? Promise.resolve();
|
|
74327
|
+
trackSidechatPromise(prior.then(async () => {
|
|
74328
|
+
if (sidechatChainStopped) {
|
|
74329
|
+
const cached = completedSidechatRequests.get(message.requestId.trim());
|
|
74330
|
+
if (cached) {
|
|
74331
|
+
writeEvent(cached);
|
|
74332
|
+
} else {
|
|
74333
|
+
writeSidechatFailure(message, "sidechat discarded on shutdown", "sidechat_interrupted");
|
|
74334
|
+
}
|
|
74335
|
+
return;
|
|
74336
|
+
}
|
|
74337
|
+
await handleSidechat(message).catch((error) => {
|
|
74338
|
+
writeSidechatFailure(message, error instanceof Error ? error.message : String(error));
|
|
74339
|
+
});
|
|
74340
|
+
}));
|
|
74341
|
+
continue;
|
|
74342
|
+
}
|
|
72882
74343
|
const shouldTrackTurn = !activeTurn || activeTurn.finalized;
|
|
72883
74344
|
const turnPromise = runTurn(message).catch((error) => {
|
|
72884
74345
|
writeEvent({
|
|
@@ -72897,6 +74358,7 @@ async function runJsonEventsMode(params) {
|
|
|
72897
74358
|
}
|
|
72898
74359
|
}
|
|
72899
74360
|
await activeTurnPromise;
|
|
74361
|
+
await activeSidechatPromise;
|
|
72900
74362
|
await disposeRuntime();
|
|
72901
74363
|
}
|
|
72902
74364
|
|
|
@@ -72953,6 +74415,7 @@ Commands:
|
|
|
72953
74415
|
sessions List, read, rename, rewind, and fork Pie sessions
|
|
72954
74416
|
extensions List and enable/disable extensions (list/enable/disable)
|
|
72955
74417
|
permissions Explain Pie tool and shell safety defaults
|
|
74418
|
+
capabilities Report command surface and flags for agents (add --json)
|
|
72956
74419
|
help Show this help message
|
|
72957
74420
|
|
|
72958
74421
|
Interactive Mode Key Bindings:
|
|
@@ -73001,86 +74464,13 @@ setupGlobalErrorHandlers(logError);
|
|
|
73001
74464
|
migrateConfigFromAgentDir();
|
|
73002
74465
|
var STABLE_CLI_COMMANDS = {
|
|
73003
74466
|
chat: "chat",
|
|
74467
|
+
capabilities: "capabilities",
|
|
73004
74468
|
doctor: "doctor",
|
|
73005
74469
|
models: "models",
|
|
73006
74470
|
sessions: "sessions",
|
|
73007
74471
|
extensions: "extensions",
|
|
73008
74472
|
permissions: "permissions"
|
|
73009
74473
|
};
|
|
73010
|
-
async function runDoctorCommand(args) {
|
|
73011
|
-
const json = args.includes("--json");
|
|
73012
|
-
const report = await runDoctor();
|
|
73013
|
-
if (json) {
|
|
73014
|
-
console.log(JSON.stringify(report, null, 2));
|
|
73015
|
-
} else {
|
|
73016
|
-
console.log(formatDoctorReport(report));
|
|
73017
|
-
}
|
|
73018
|
-
if (!report.ok) {
|
|
73019
|
-
process.exitCode = 1;
|
|
73020
|
-
}
|
|
73021
|
-
}
|
|
73022
|
-
async function runModelsCommand(args) {
|
|
73023
|
-
const subcommand = args[0] || "help";
|
|
73024
|
-
const parsed = parseModelsCommandArgs(args.slice(1));
|
|
73025
|
-
if (subcommand === "init") {
|
|
73026
|
-
const result = initModelsConfig(parsed);
|
|
73027
|
-
if (parsed.stdout) {
|
|
73028
|
-
process.stdout.write(result.content);
|
|
73029
|
-
} else {
|
|
73030
|
-
console.log(`Wrote models.json template: ${result.path}`);
|
|
73031
|
-
}
|
|
73032
|
-
return;
|
|
73033
|
-
}
|
|
73034
|
-
if (subcommand === "validate") {
|
|
73035
|
-
const result = validateModelsConfig({ path: parsed.path });
|
|
73036
|
-
if (parsed.json) {
|
|
73037
|
-
const probe = result.ok && parsed.probe ? await probeModelsConfig({ path: parsed.path, probe: parsed.probe }) : void 0;
|
|
73038
|
-
console.log(JSON.stringify({ ...result, ...probe ? { probe } : {} }, null, 2));
|
|
73039
|
-
if (!result.ok || probe?.status === "failed") process.exitCode = 1;
|
|
73040
|
-
return;
|
|
73041
|
-
}
|
|
73042
|
-
if (!result.ok) {
|
|
73043
|
-
console.error(result.message);
|
|
73044
|
-
process.exitCode = 1;
|
|
73045
|
-
return;
|
|
73046
|
-
}
|
|
73047
|
-
console.log(result.message);
|
|
73048
|
-
if (result.profiles.length > 0) {
|
|
73049
|
-
console.log(`Profiles: ${result.profiles.join(", ")}`);
|
|
73050
|
-
console.log(`Models: ${result.modelCount}`);
|
|
73051
|
-
}
|
|
73052
|
-
if (result.defaultModel) {
|
|
73053
|
-
console.log(`Default: ${result.defaultModel}`);
|
|
73054
|
-
}
|
|
73055
|
-
if (result.modelClasses && result.modelClasses.length > 0) {
|
|
73056
|
-
console.log(`Model classes: ${result.modelClasses.join(", ")}`);
|
|
73057
|
-
}
|
|
73058
|
-
if (result.webSearchModels && result.webSearchModels.length > 0) {
|
|
73059
|
-
console.log(`Web search: ${result.webSearchModels.join(", ")}`);
|
|
73060
|
-
}
|
|
73061
|
-
if (result.webSearchRouteCandidates && result.webSearchRouteCandidates.length > 0) {
|
|
73062
|
-
console.log(`Web search routes: ${result.webSearchRouteCandidates.join(", ")}`);
|
|
73063
|
-
}
|
|
73064
|
-
if (result.fileCapabilityModels && result.fileCapabilityModels.length > 0) {
|
|
73065
|
-
console.log(`File capabilities: ${result.fileCapabilityModels.join(", ")}`);
|
|
73066
|
-
}
|
|
73067
|
-
if (result.toolModelRoutes && result.toolModelRoutes.length > 0) {
|
|
73068
|
-
console.log(`Tool model routes: ${result.toolModelRoutes.join(", ")}`);
|
|
73069
|
-
}
|
|
73070
|
-
if (parsed.probe) {
|
|
73071
|
-
const probe = await probeModelsConfig({ path: parsed.path, probe: parsed.probe });
|
|
73072
|
-
console.log(`Probe ${probe.purpose}: ${probe.message}`);
|
|
73073
|
-
for (const attempt of probe.attempts) {
|
|
73074
|
-
console.log(`- ${attempt.status} ${attempt.route} sources=${attempt.sourceCount}${attempt.failureCategory ? ` failure=${attempt.failureCategory}` : ""}`);
|
|
73075
|
-
}
|
|
73076
|
-
if (probe.status === "failed") process.exitCode = 1;
|
|
73077
|
-
}
|
|
73078
|
-
return;
|
|
73079
|
-
}
|
|
73080
|
-
console.log(`Usage:
|
|
73081
|
-
pie models init [--path <path>] [--force] [--stdout]
|
|
73082
|
-
pie models validate [--path <path>] [--probe web_search] [--json]`);
|
|
73083
|
-
}
|
|
73084
74474
|
async function runWithJsonEventsConsoleIsolation(fn) {
|
|
73085
74475
|
const originalLog = console.log;
|
|
73086
74476
|
const originalInfo = console.info;
|
|
@@ -73099,7 +74489,21 @@ async function runWithJsonEventsConsoleIsolation(fn) {
|
|
|
73099
74489
|
}
|
|
73100
74490
|
async function createCliTestStreamFnFromEnv() {
|
|
73101
74491
|
if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) return void 0;
|
|
73102
|
-
return (await import("./chunks/test-stream-
|
|
74492
|
+
return (await import("./chunks/test-stream-5T7E7C25.js")).createTestStreamFnFromSequenceEnv();
|
|
74493
|
+
}
|
|
74494
|
+
function resolveJsonEventsDetailFlag() {
|
|
74495
|
+
for (let index = 0; index < process.argv.length; index += 1) {
|
|
74496
|
+
const arg = process.argv[index];
|
|
74497
|
+
if (arg === "--event-detail") {
|
|
74498
|
+
const raw = process.argv[index + 1] ?? "";
|
|
74499
|
+
return raw === "compact" || raw === "full" ? { value: raw } : { error: raw || "(missing)" };
|
|
74500
|
+
}
|
|
74501
|
+
if (arg.startsWith("--event-detail=")) {
|
|
74502
|
+
const raw = arg.slice("--event-detail=".length);
|
|
74503
|
+
return raw === "compact" || raw === "full" ? { value: raw } : { error: raw };
|
|
74504
|
+
}
|
|
74505
|
+
}
|
|
74506
|
+
return { value: "compact" };
|
|
73103
74507
|
}
|
|
73104
74508
|
async function startChat(initialPrompt, testCommand) {
|
|
73105
74509
|
const rawOutput = process.argv.includes("--raw-output");
|
|
@@ -73111,6 +74515,12 @@ async function startChat(initialPrompt, testCommand) {
|
|
|
73111
74515
|
const extensionPaths = parseRepeatedFlag(process.argv, "--extension-path");
|
|
73112
74516
|
const extensionFlags = parseExtensionFlags(process.argv);
|
|
73113
74517
|
if (jsonEvents) {
|
|
74518
|
+
const detailFlag = resolveJsonEventsDetailFlag();
|
|
74519
|
+
if ("error" in detailFlag) {
|
|
74520
|
+
console.error(`Invalid --event-detail value: ${detailFlag.error}. Use compact or full.`);
|
|
74521
|
+
process.exit(2);
|
|
74522
|
+
}
|
|
74523
|
+
const eventDetail = detailFlag.value;
|
|
73114
74524
|
let developerInstructions;
|
|
73115
74525
|
try {
|
|
73116
74526
|
developerInstructions = resolveDeveloperInstructionsFromArgs(process.argv);
|
|
@@ -73124,7 +74534,8 @@ async function startChat(initialPrompt, testCommand) {
|
|
|
73124
74534
|
explicitSessionId,
|
|
73125
74535
|
resumeRequired,
|
|
73126
74536
|
developerInstructions,
|
|
73127
|
-
mockResponse: process.env.PIE_TEST_MOCK_RESPONSE
|
|
74537
|
+
mockResponse: process.env.PIE_TEST_MOCK_RESPONSE,
|
|
74538
|
+
eventDetail
|
|
73128
74539
|
});
|
|
73129
74540
|
return;
|
|
73130
74541
|
}
|
|
@@ -73132,6 +74543,7 @@ async function startChat(initialPrompt, testCommand) {
|
|
|
73132
74543
|
explicitSessionId,
|
|
73133
74544
|
resumeRequired,
|
|
73134
74545
|
developerInstructions,
|
|
74546
|
+
eventDetail,
|
|
73135
74547
|
streamFn: await createCliTestStreamFnFromEnv(),
|
|
73136
74548
|
createRuntime: async ({ cwd, sessionId }) => composeCliRuntime({
|
|
73137
74549
|
explicitSessionId: explicitSessionId ?? sessionId,
|
|
@@ -73218,6 +74630,16 @@ async function main() {
|
|
|
73218
74630
|
console.log(VERSION);
|
|
73219
74631
|
return;
|
|
73220
74632
|
}
|
|
74633
|
+
if (args.length === 0 && !process.stdin.isTTY) {
|
|
74634
|
+
console.error("pie: no arguments and stdin is not a terminal; refusing to start interactive mode.");
|
|
74635
|
+
showHelp();
|
|
74636
|
+
process.exitCode = 1;
|
|
74637
|
+
return;
|
|
74638
|
+
}
|
|
74639
|
+
if (args[0] === STABLE_CLI_COMMANDS.capabilities) {
|
|
74640
|
+
runCapabilitiesCommand(args.slice(1));
|
|
74641
|
+
return;
|
|
74642
|
+
}
|
|
73221
74643
|
if (args[0] === STABLE_CLI_COMMANDS.doctor) {
|
|
73222
74644
|
await runDoctorCommand(args.slice(1));
|
|
73223
74645
|
return;
|
|
@@ -73240,7 +74662,7 @@ async function main() {
|
|
|
73240
74662
|
return;
|
|
73241
74663
|
}
|
|
73242
74664
|
if (args[0] === STABLE_CLI_COMMANDS.permissions) {
|
|
73243
|
-
|
|
74665
|
+
runPermissionsCommand(args.slice(1));
|
|
73244
74666
|
return;
|
|
73245
74667
|
}
|
|
73246
74668
|
const parsed = parseCliInvocation(args);
|