@cydm/pie 2.5.1 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builtin/extensions/ask-user/index.js +3 -3
- package/dist/builtin/extensions/computer-use/index.js +17 -2
- package/dist/builtin/extensions/computer-use/prebuilt/macos/arm64/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/universal/pie-computer-use.app/Contents/MacOS/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/prebuilt/macos/x64/pie-computer-use +0 -0
- package/dist/builtin/extensions/computer-use/scripts/setup-helper.mjs +90 -9
- package/dist/builtin/extensions/mcp-adapter/index.js +135 -27
- package/dist/builtin/extensions/plan-mode/index.js +3 -3
- package/dist/builtin/extensions/subagent/index.js +8 -5
- package/dist/builtin/extensions/todo/index.js +3 -3
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-bridge.js +199 -40
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-cli.js +5 -2
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-runtime.js +1 -1
- package/dist/builtin/skills/chrome-devtools-axi/{cli-P4VG6ZZG.js → cli-GB37NZHQ.js} +78 -29
- package/dist/builtin/skills/tui-use/SKILL.md +44 -0
- package/dist/builtin/skills/tui-use/tui-use-cli.cjs +40 -16
- package/dist/builtin/skills/tui-use/tui-use-daemon.cjs +7 -1
- package/dist/chunks/{chunk-REP6QANY.js → chunk-AZ336HKF.js} +405 -70
- package/dist/chunks/{chunk-N2MK46AE.js → chunk-G6KCJA6B.js} +7 -2
- package/dist/chunks/{chunk-YRXXRLMQ.js → chunk-O2DKMLNX.js} +152 -8
- package/dist/chunks/{chunk-ZKHMNEXL.js → chunk-Y4CYXJR7.js} +27 -2
- package/dist/chunks/src-VCWCE7YV.js +20 -0
- package/dist/chunks/{test-stream-OD3B57AS.js → test-stream-GOSEWMJ3.js} +1 -1
- package/dist/cli.js +67 -17
- package/package.json +2 -2
- package/dist/chunks/src-SXUQ7OY6.js +0 -14
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
createSharedWebSearchTool,
|
|
9
9
|
interpretShellExit,
|
|
10
10
|
requestInteraction
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-AZ336HKF.js";
|
|
12
12
|
import {
|
|
13
13
|
getBuiltinDir,
|
|
14
14
|
getConfigDir
|
|
@@ -1176,7 +1176,12 @@ function createCliRenderedPageReader() {
|
|
|
1176
1176
|
networkRequests: linesOf(stripHelpHints(networkOutput))
|
|
1177
1177
|
};
|
|
1178
1178
|
} finally {
|
|
1179
|
-
|
|
1179
|
+
try {
|
|
1180
|
+
await runAxi(["stop"], { env, timeoutMs: 15e3 });
|
|
1181
|
+
} catch (error) {
|
|
1182
|
+
process.stderr.write(`[rendered-page-reader] axi stop after read failed: ${error instanceof Error ? error.message : String(error)}
|
|
1183
|
+
`);
|
|
1184
|
+
}
|
|
1180
1185
|
}
|
|
1181
1186
|
};
|
|
1182
1187
|
}
|
|
@@ -2191,15 +2191,120 @@ var FileSystemGateway = class {
|
|
|
2191
2191
|
return true;
|
|
2192
2192
|
}
|
|
2193
2193
|
}
|
|
2194
|
-
return
|
|
2194
|
+
return this.allowedViaCaseAlias(path, normalized);
|
|
2195
2195
|
}
|
|
2196
2196
|
/**
|
|
2197
|
-
* Normalize path for comparison
|
|
2197
|
+
* Normalize path for comparison.
|
|
2198
|
+
*
|
|
2199
|
+
* Both sides of every comparison get the identical structural
|
|
2200
|
+
* transformation (backslashes to slashes, repeated separators collapsed,
|
|
2201
|
+
* trailing separators trimmed) so boundary checks stay segment-exact.
|
|
2202
|
+
* Case is folded only where the compared path is Windows-shaped: a drive
|
|
2203
|
+
* letter, a backslash UNC root (`\\server\share`), or any path on a win32
|
|
2204
|
+
* host. POSIX paths keep their case — on a case-sensitive volume a
|
|
2205
|
+
* different-case spelling is a different directory, and a leading "//" on
|
|
2206
|
+
* a POSIX host is an ordinary POSIX path, not a UNC share, so it must never
|
|
2207
|
+
* earn case-insensitive treatment there (that would let `//Tmp/...`-style
|
|
2208
|
+
* spellings borrow the identity of case-distinct siblings).
|
|
2198
2209
|
*/
|
|
2199
2210
|
normalizePath(path) {
|
|
2200
|
-
const
|
|
2201
|
-
|
|
2202
|
-
|
|
2211
|
+
const slashed = path.replace(/\\/g, "/");
|
|
2212
|
+
const collapsed = slashed.replace(/\/+/g, "/");
|
|
2213
|
+
const trimmed = collapsed === "/" ? collapsed : collapsed.replace(/\/+$/, "");
|
|
2214
|
+
return this.usesCaseInsensitiveComparison(path, trimmed) ? trimmed.toLowerCase() : trimmed;
|
|
2215
|
+
}
|
|
2216
|
+
/**
|
|
2217
|
+
* Windows compares all path names case-insensitively; UNC roots are
|
|
2218
|
+
* recognized by their backslash form. Forward-slash "//" prefixes on a
|
|
2219
|
+
* POSIX host stay case-sensitive POSIX paths.
|
|
2220
|
+
*/
|
|
2221
|
+
usesCaseInsensitiveComparison(rawPath, normalizedPath) {
|
|
2222
|
+
if (rawPath.startsWith("\\\\")) return true;
|
|
2223
|
+
if (/^[a-zA-Z]:/.test(normalizedPath)) return true;
|
|
2224
|
+
return typeof process !== "undefined" && process.platform === "win32";
|
|
2225
|
+
}
|
|
2226
|
+
/**
|
|
2227
|
+
* Slow path for POSIX hosts: preserve legitimate case aliases (the default
|
|
2228
|
+
* macOS volume resolves `/Users/alice` and `/Users/Alice` to the same
|
|
2229
|
+
* directory) without blanket darwin case-folding and without probing the
|
|
2230
|
+
* filesystem with writes. A candidate is allowed only when the canonical
|
|
2231
|
+
* identity of its nearest existing ancestor — rebuilt segment by segment
|
|
2232
|
+
* with read-only stat/readdir probes — lands inside the canonical identity
|
|
2233
|
+
* of an allowed root. On a case-sensitive volume a case-variant spelling of
|
|
2234
|
+
* a different directory never resolves through this walk (the exact
|
|
2235
|
+
* spelling wins whenever it exists), so it stays denied. Windows-shaped
|
|
2236
|
+
* candidates skip this path: their comparison is already case-folded.
|
|
2237
|
+
*/
|
|
2238
|
+
allowedViaCaseAlias(rawPath, normalizedPath) {
|
|
2239
|
+
if (!normalizedPath.startsWith("/")) return false;
|
|
2240
|
+
if (this.usesCaseInsensitiveComparison(rawPath, normalizedPath)) return false;
|
|
2241
|
+
if (typeof process !== "undefined" && process.platform === "win32") return false;
|
|
2242
|
+
if (detectPlatform() === "puerts") return false;
|
|
2243
|
+
let fs;
|
|
2244
|
+
try {
|
|
2245
|
+
fs = nodeRequire("fs");
|
|
2246
|
+
} catch {
|
|
2247
|
+
return false;
|
|
2248
|
+
}
|
|
2249
|
+
let resolved;
|
|
2250
|
+
try {
|
|
2251
|
+
resolved = this.resolveCaseAlias(fs, normalizedPath);
|
|
2252
|
+
} catch {
|
|
2253
|
+
return false;
|
|
2254
|
+
}
|
|
2255
|
+
for (const root of this.allowedRoots) {
|
|
2256
|
+
const normalizedRoot = this.normalizePath(root);
|
|
2257
|
+
if (!normalizedRoot.startsWith("/")) continue;
|
|
2258
|
+
try {
|
|
2259
|
+
const resolvedRoot = this.resolveCaseAlias(fs, normalizedRoot);
|
|
2260
|
+
if (resolved === resolvedRoot || resolved.startsWith(this.withTrailingSep(resolvedRoot))) {
|
|
2261
|
+
return true;
|
|
2262
|
+
}
|
|
2263
|
+
} catch {
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
return false;
|
|
2267
|
+
}
|
|
2268
|
+
/**
|
|
2269
|
+
* Rebuild a POSIX path with its true on-disk case. The canonical prefix
|
|
2270
|
+
* grows only through segments the filesystem itself accepts in the
|
|
2271
|
+
* requested spelling (a read-only stat probe): on a case-insensitive
|
|
2272
|
+
* volume a different-case spelling still resolves and is rewritten to the
|
|
2273
|
+
* directory's actual entry name; on a case-sensitive volume it does not
|
|
2274
|
+
* resolve, the walk stops, and the remaining segments stay verbatim — so
|
|
2275
|
+
* they can never borrow a sibling directory's identity.
|
|
2276
|
+
*/
|
|
2277
|
+
resolveCaseAlias(fs, normalizedPath) {
|
|
2278
|
+
const segments = normalizedPath.slice(1).split("/").filter((segment) => segment.length > 0 && segment !== ".");
|
|
2279
|
+
let canonical = "";
|
|
2280
|
+
let index = 0;
|
|
2281
|
+
while (index < segments.length) {
|
|
2282
|
+
const segment = segments[index];
|
|
2283
|
+
const probe = `${canonical}/${segment}`;
|
|
2284
|
+
if (!fs.statSync(probe, { throwIfNoEntry: false })) break;
|
|
2285
|
+
canonical = `${canonical}/${this.trueCaseName(fs, canonical, segment)}`;
|
|
2286
|
+
index += 1;
|
|
2287
|
+
}
|
|
2288
|
+
const tail = segments.slice(index).join("/");
|
|
2289
|
+
return tail ? `${canonical}/${tail}` : canonical;
|
|
2290
|
+
}
|
|
2291
|
+
/**
|
|
2292
|
+
* Actual directory-entry name for a segment the filesystem already
|
|
2293
|
+
* resolved. Exact spelling wins; a different-case entry can only be the
|
|
2294
|
+
* same file (case-insensitive volume), otherwise statSync above would have
|
|
2295
|
+
* failed. Read-only; never falls back to writing a probe.
|
|
2296
|
+
*/
|
|
2297
|
+
trueCaseName(fs, directory, name) {
|
|
2298
|
+
try {
|
|
2299
|
+
const entries = fs.readdirSync(directory === "" ? "/" : directory);
|
|
2300
|
+
if (entries.includes(name)) return name;
|
|
2301
|
+
const lowered = name.toLowerCase();
|
|
2302
|
+
for (const entry of entries) {
|
|
2303
|
+
if (entry.toLowerCase() === lowered) return entry;
|
|
2304
|
+
}
|
|
2305
|
+
} catch {
|
|
2306
|
+
}
|
|
2307
|
+
return name;
|
|
2203
2308
|
}
|
|
2204
2309
|
/**
|
|
2205
2310
|
* Normalize root path for prefix comparison
|
|
@@ -2914,7 +3019,7 @@ function convertMessages(model, context, compat) {
|
|
|
2914
3019
|
if (typeof msg.content === "string") {
|
|
2915
3020
|
params.push({ role: "user", content: msg.content });
|
|
2916
3021
|
} else {
|
|
2917
|
-
const content = msg.content.flatMap((item) =>
|
|
3022
|
+
const content = msg.content.flatMap((item) => convertCheckedContent(item, model));
|
|
2918
3023
|
const filteredContent = content.filter((c) => {
|
|
2919
3024
|
if (c.type === "text") return true;
|
|
2920
3025
|
if (c.type === "image_url") return model.input.includes("image");
|
|
@@ -2960,6 +3065,7 @@ function convertMessages(model, context, compat) {
|
|
|
2960
3065
|
const hasContent = content !== null && content !== void 0 && (typeof content === "string" ? content.length > 0 : Array.isArray(content) && content.length > 0);
|
|
2961
3066
|
if (hasContent || assistantMsg.tool_calls) params.push(assistantMsg);
|
|
2962
3067
|
} else if (msg.role === "toolResult") {
|
|
3068
|
+
const attachments = [];
|
|
2963
3069
|
for (; i < transformedMessages.length && transformedMessages[i].role === "toolResult"; i++) {
|
|
2964
3070
|
const toolMsg = transformedMessages[i];
|
|
2965
3071
|
const textResult = toolMsg.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
@@ -2970,12 +3076,50 @@ function convertMessages(model, context, compat) {
|
|
|
2970
3076
|
};
|
|
2971
3077
|
if (compat.requiresToolResultName && toolMsg.toolName) toolResultMsg.name = toolMsg.toolName;
|
|
2972
3078
|
params.push(toolResultMsg);
|
|
3079
|
+
{
|
|
3080
|
+
const images = toolMsg.content.filter((c) => c.type !== "text");
|
|
3081
|
+
if (images.length > 0) {
|
|
3082
|
+
attachments.push({ type: "text", text: `Images from tool ${toolMsg.toolName ?? "unknown"} (call ${toolMsg.toolCallId}):` });
|
|
3083
|
+
for (const image of images) {
|
|
3084
|
+
const kind = image.type;
|
|
3085
|
+
const capability = kind === "audio" || kind === "video" ? model.fileCapabilities?.[kind] : void 0;
|
|
3086
|
+
if ((kind === "audio" || kind === "video") && !(capability && typeof capability === "object" && capability.supported !== false && capability.nativeInline === true)) {
|
|
3087
|
+
attachments.push({ type: "text", text: `[${kind} attachment omitted: endpoint nativeInline transport is not enabled. Re-read with a compatible model.]` });
|
|
3088
|
+
} else attachments.push(...convertCheckedContent(image, model));
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
}
|
|
2973
3092
|
}
|
|
3093
|
+
if (attachments.length > 0) params.push({ role: "user", content: attachments });
|
|
2974
3094
|
i -= 1;
|
|
2975
3095
|
}
|
|
2976
3096
|
}
|
|
2977
3097
|
return params;
|
|
2978
3098
|
}
|
|
3099
|
+
function convertCheckedContent(item, model) {
|
|
3100
|
+
const modality = item.type === "fileRef" ? item.modality : item.type;
|
|
3101
|
+
if (modality === "image" || modality === "video" || modality === "audio") {
|
|
3102
|
+
if (!model.input.includes(modality)) return [{ type: "text", text: `[${modality} attachment omitted: current model does not support this modality. Re-read with a compatible model.]` }];
|
|
3103
|
+
if (item.type === "audio") {
|
|
3104
|
+
const audio = item;
|
|
3105
|
+
if (audioFormatFor(audio.mimeType) === void 0) {
|
|
3106
|
+
return [{ type: "text", text: `[audio attachment omitted: unsupported format ${audio.mimeType}. Convert to WAV or MP3 first.]` }];
|
|
3107
|
+
}
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
return convertUserContentItem(item);
|
|
3111
|
+
}
|
|
3112
|
+
function audioFormatFor(mimeType) {
|
|
3113
|
+
const mime = mimeType.toLowerCase().split(";")[0].trim();
|
|
3114
|
+
if (["audio/wav", "audio/x-wav", "audio/wave", "audio/vnd.wave"].includes(mime)) return "wav";
|
|
3115
|
+
if (["audio/mpeg", "audio/mp3"].includes(mime)) return "mp3";
|
|
3116
|
+
return void 0;
|
|
3117
|
+
}
|
|
3118
|
+
function audioFormat(mimeType) {
|
|
3119
|
+
const format = audioFormatFor(mimeType);
|
|
3120
|
+
if (format === void 0) throw new Error(`Unsupported audio attachment format: ${mimeType}. Convert to WAV or MP3 first.`);
|
|
3121
|
+
return format;
|
|
3122
|
+
}
|
|
2979
3123
|
function convertUserContentItem(item) {
|
|
2980
3124
|
if (item.type === "text") return [{ type: "text", text: item.text }];
|
|
2981
3125
|
if (item.type === "image") return [{ type: "image_url", image_url: { url: `data:${item.mimeType};base64,${item.data}` } }];
|
|
@@ -2985,7 +3129,7 @@ function convertUserContentItem(item) {
|
|
|
2985
3129
|
}
|
|
2986
3130
|
if (item.type === "audio") {
|
|
2987
3131
|
const audio = item;
|
|
2988
|
-
return [{ type: "input_audio", input_audio: { data: audio.data, format: audio.mimeType
|
|
3132
|
+
return [{ type: "input_audio", input_audio: { data: audio.data, format: audioFormat(audio.mimeType) } }];
|
|
2989
3133
|
}
|
|
2990
3134
|
if (item.type === "fileRef") {
|
|
2991
3135
|
const ref = item;
|
|
@@ -3632,7 +3776,7 @@ function mapStopReason(reason) {
|
|
|
3632
3776
|
}
|
|
3633
3777
|
}
|
|
3634
3778
|
function convertContentBlocks(content) {
|
|
3635
|
-
const supportedBlocks = content.
|
|
3779
|
+
const supportedBlocks = content.map((block) => block.type === "text" || block.type === "image" ? block : { type: "text", text: `[${block.type} attachment omitted: unsupported by this provider. Re-read with a compatible model.]` });
|
|
3636
3780
|
const hasImages = supportedBlocks.some((c) => c.type === "image");
|
|
3637
3781
|
if (!hasImages) {
|
|
3638
3782
|
const text = supportedBlocks.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
EventStream,
|
|
4
4
|
streamSimple,
|
|
5
5
|
validateToolArguments
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-O2DKMLNX.js";
|
|
7
7
|
|
|
8
8
|
// ../../packages/agent-core/src/agent-loop.ts
|
|
9
9
|
function createLoopErrorMessage(error, config, signal) {
|
|
@@ -409,6 +409,19 @@ function skipToolCall(toolCall, stream) {
|
|
|
409
409
|
return toolResultMessage;
|
|
410
410
|
}
|
|
411
411
|
|
|
412
|
+
// ../../packages/agent-core/src/tool-caller-identity.ts
|
|
413
|
+
var kToolCallerIdentity = /* @__PURE__ */ Symbol("pie.toolCallerIdentity");
|
|
414
|
+
function createToolCallerIdentity() {
|
|
415
|
+
return { kind: "pie.toolCallerIdentity" };
|
|
416
|
+
}
|
|
417
|
+
function bindToolCallerIdentity(signal, identity) {
|
|
418
|
+
signal[kToolCallerIdentity] = identity;
|
|
419
|
+
}
|
|
420
|
+
function getToolCallerIdentity(signal) {
|
|
421
|
+
if (!signal) return void 0;
|
|
422
|
+
return signal[kToolCallerIdentity];
|
|
423
|
+
}
|
|
424
|
+
|
|
412
425
|
// ../../packages/agent-core/src/agent.ts
|
|
413
426
|
function defaultConvertToLlm(messages) {
|
|
414
427
|
return messages.filter((m) => m.role === "user" || m.role === "assistant" || m.role === "toolResult");
|
|
@@ -443,11 +456,16 @@ var Agent = class {
|
|
|
443
456
|
_thinkingBudgets;
|
|
444
457
|
_maxRetryDelayMs;
|
|
445
458
|
hooks;
|
|
459
|
+
/** Stable identity for this agent instance, bound onto every run signal
|
|
460
|
+
* handed to tools (signals themselves are per-run; see tool-caller-identity.ts). */
|
|
461
|
+
toolCallerIdentity = createToolCallerIdentity();
|
|
446
462
|
statusSnapshot = {
|
|
447
463
|
phase: "idle",
|
|
448
464
|
turnState: "completed",
|
|
449
465
|
hasPendingToolContinuation: false
|
|
450
466
|
};
|
|
467
|
+
/** Assistant message already reported as turn_failed during this run. */
|
|
468
|
+
reportedFailureMessage;
|
|
451
469
|
constructor(opts = {}) {
|
|
452
470
|
this._state = {
|
|
453
471
|
systemPrompt: "",
|
|
@@ -729,6 +747,7 @@ var Agent = class {
|
|
|
729
747
|
const model = this._state.model;
|
|
730
748
|
if (!model) throw new Error("No model configured");
|
|
731
749
|
this.abortController = new AbortController();
|
|
750
|
+
bindToolCallerIdentity(this.abortController.signal, this.toolCallerIdentity);
|
|
732
751
|
this._state.isStreaming = true;
|
|
733
752
|
this._state.streamMessage = null;
|
|
734
753
|
this._state.error = void 0;
|
|
@@ -954,6 +973,7 @@ var Agent = class {
|
|
|
954
973
|
const stopReason = event.message.role === "assistant" ? event.message.stopReason : void 0;
|
|
955
974
|
const hasToolCalls = event.message.role === "assistant" && Array.isArray(event.message.content) && event.message.content.some((block) => block.type === "toolCall");
|
|
956
975
|
if (stopReason === "error" || stopReason === "aborted") {
|
|
976
|
+
this.reportedFailureMessage = event.message;
|
|
957
977
|
this.updateStatusSnapshot({
|
|
958
978
|
phase: "failed",
|
|
959
979
|
turnState: "failed",
|
|
@@ -997,7 +1017,9 @@ var Agent = class {
|
|
|
997
1017
|
}
|
|
998
1018
|
case "agent_end": {
|
|
999
1019
|
const lastMessage = event.messages[event.messages.length - 1];
|
|
1000
|
-
|
|
1020
|
+
const alreadyReported = lastMessage !== void 0 && lastMessage === this.reportedFailureMessage;
|
|
1021
|
+
this.reportedFailureMessage = void 0;
|
|
1022
|
+
if (!alreadyReported && lastMessage?.role === "assistant" && (lastMessage.stopReason === "error" || lastMessage.stopReason === "aborted")) {
|
|
1001
1023
|
this.updateStatusSnapshot({
|
|
1002
1024
|
phase: "failed",
|
|
1003
1025
|
turnState: "failed",
|
|
@@ -1025,5 +1047,8 @@ var Agent = class {
|
|
|
1025
1047
|
export {
|
|
1026
1048
|
agentLoop,
|
|
1027
1049
|
agentLoopContinue,
|
|
1050
|
+
createToolCallerIdentity,
|
|
1051
|
+
bindToolCallerIdentity,
|
|
1052
|
+
getToolCallerIdentity,
|
|
1028
1053
|
Agent
|
|
1029
1054
|
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
Agent,
|
|
4
|
+
agentLoop,
|
|
5
|
+
agentLoopContinue,
|
|
6
|
+
bindToolCallerIdentity,
|
|
7
|
+
createToolCallerIdentity,
|
|
8
|
+
getToolCallerIdentity
|
|
9
|
+
} from "./chunk-Y4CYXJR7.js";
|
|
10
|
+
import "./chunk-O2DKMLNX.js";
|
|
11
|
+
import "./chunk-XXGYUYXI.js";
|
|
12
|
+
import "./chunk-LZQXQOPJ.js";
|
|
13
|
+
export {
|
|
14
|
+
Agent,
|
|
15
|
+
agentLoop,
|
|
16
|
+
agentLoopContinue,
|
|
17
|
+
bindToolCallerIdentity,
|
|
18
|
+
createToolCallerIdentity,
|
|
19
|
+
getToolCallerIdentity
|
|
20
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
EventStream
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-O2DKMLNX.js";
|
|
5
5
|
import "./chunk-XXGYUYXI.js";
|
|
6
6
|
import "./chunk-LZQXQOPJ.js";
|
|
7
7
|
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
createCliWebResearchHealthStore,
|
|
8
8
|
formatSize,
|
|
9
9
|
truncateHeadTail
|
|
10
|
-
} from "./chunks/chunk-
|
|
10
|
+
} from "./chunks/chunk-G6KCJA6B.js";
|
|
11
11
|
import {
|
|
12
12
|
AGENTS_CONTEXT_FILE_NAME,
|
|
13
13
|
AgentSessionController,
|
|
@@ -60,8 +60,8 @@ import {
|
|
|
60
60
|
setExtensionEnabledInSettings,
|
|
61
61
|
shouldPreserveExecutionStateForUserText,
|
|
62
62
|
supersedeExecutionState
|
|
63
|
-
} from "./chunks/chunk-
|
|
64
|
-
import "./chunks/chunk-
|
|
63
|
+
} from "./chunks/chunk-AZ336HKF.js";
|
|
64
|
+
import "./chunks/chunk-Y4CYXJR7.js";
|
|
65
65
|
import {
|
|
66
66
|
Deref,
|
|
67
67
|
EMPTY_ASSISTANT_CONTENT_ERROR,
|
|
@@ -85,7 +85,7 @@ import {
|
|
|
85
85
|
setLogger,
|
|
86
86
|
sortToolModelCandidatesByCapability,
|
|
87
87
|
type_exports
|
|
88
|
-
} from "./chunks/chunk-
|
|
88
|
+
} from "./chunks/chunk-O2DKMLNX.js";
|
|
89
89
|
import {
|
|
90
90
|
VERSION,
|
|
91
91
|
getAgentDir,
|
|
@@ -52476,8 +52476,9 @@ function validateFileCapabilities(value, label) {
|
|
|
52476
52476
|
if (!["image", "video", "audio", "document"].includes(kind)) throw new Error(`${label}.${kind} is unsupported`);
|
|
52477
52477
|
if (typeof capability === "boolean") continue;
|
|
52478
52478
|
if (!isPlainRecord(capability)) throw new Error(`${label}.${kind} is invalid`);
|
|
52479
|
-
assertOnlyKeys(capability, ["supported", "formats", "maxFileSizeMb", "maxDurationSeconds"], `${label}.${kind}`);
|
|
52479
|
+
assertOnlyKeys(capability, ["supported", "formats", "maxFileSizeMb", "maxDurationSeconds", "nativeInline"], `${label}.${kind}`);
|
|
52480
52480
|
assertOptionalBoolean(capability.supported, `${label}.${kind}.supported`);
|
|
52481
|
+
assertOptionalBoolean(capability.nativeInline, `${label}.${kind}.nativeInline`);
|
|
52481
52482
|
if (capability.formats !== void 0 && (!Array.isArray(capability.formats) || capability.formats.some((item) => typeof item !== "string" || !item))) {
|
|
52482
52483
|
throw new Error(`${label}.${kind}.formats is invalid`);
|
|
52483
52484
|
}
|
|
@@ -55210,8 +55211,11 @@ function publishJournalPath(sessionsDir, safeTargetId) {
|
|
|
55210
55211
|
return path7.join(sessionsDir, PUBLISH_JOURNAL_DIR, `${safeTargetId}.json`);
|
|
55211
55212
|
}
|
|
55212
55213
|
var FSYNC_UNSUPPORTED_CODES = /* @__PURE__ */ new Set(["EPERM", "EINVAL", "ENOTSUP", "EOPNOTSUPP", "EACCES", "EBADF"]);
|
|
55214
|
+
var fsyncDirectoryFaultForTests = {};
|
|
55213
55215
|
function fsyncDirectory(dirPath) {
|
|
55214
55216
|
try {
|
|
55217
|
+
const injected = fsyncDirectoryFaultForTests.fault?.(dirPath);
|
|
55218
|
+
if (injected) throw injected;
|
|
55215
55219
|
const fd = fs7.openSync(dirPath, "r");
|
|
55216
55220
|
try {
|
|
55217
55221
|
fs7.fsyncSync(fd);
|
|
@@ -55430,11 +55434,21 @@ async function forkStoredSession(params) {
|
|
|
55430
55434
|
if (hadPreviousTarget) {
|
|
55431
55435
|
try {
|
|
55432
55436
|
params.store.moveSession(params.targetSessionId, backupId);
|
|
55433
|
-
if (params.sessionsDir) fsyncDirectory(params.sessionsDir);
|
|
55434
55437
|
} catch (error) {
|
|
55435
55438
|
clearPublishJournal(journalPath);
|
|
55436
55439
|
throw error;
|
|
55437
55440
|
}
|
|
55441
|
+
try {
|
|
55442
|
+
if (params.sessionsDir) fsyncDirectory(params.sessionsDir);
|
|
55443
|
+
} catch (error) {
|
|
55444
|
+
markPublishJournalFailed(journalPath);
|
|
55445
|
+
preserveStagingForRecovery = true;
|
|
55446
|
+
throw new SessionControlError(
|
|
55447
|
+
"session_io_error",
|
|
55448
|
+
`Fork publish durability failure after moving the previous session aside; it is preserved as ${backupId} and startup recovery will restore it: ${String(error)}`,
|
|
55449
|
+
false
|
|
55450
|
+
);
|
|
55451
|
+
}
|
|
55438
55452
|
}
|
|
55439
55453
|
try {
|
|
55440
55454
|
params.store.moveSession(stagingId, params.targetSessionId);
|
|
@@ -70137,22 +70151,40 @@ var SettingsSelectorComponent = class extends Container {
|
|
|
70137
70151
|
};
|
|
70138
70152
|
|
|
70139
70153
|
// src/core/session-display.ts
|
|
70154
|
+
function looksAutoGeneratedSessionName(name) {
|
|
70155
|
+
return /^Session (\d|[a-z0-9]{6,8}$)/i.test(name.trim());
|
|
70156
|
+
}
|
|
70157
|
+
function persistedNameIsAuthoritative(metadata) {
|
|
70158
|
+
if (metadata.nameSource === "derived") return true;
|
|
70159
|
+
if (metadata.nameSource === void 0) return !looksAutoGeneratedSessionName(metadata.name);
|
|
70160
|
+
return false;
|
|
70161
|
+
}
|
|
70140
70162
|
function deriveSessionTitle(options) {
|
|
70141
70163
|
const { activeSession, messages } = options;
|
|
70142
70164
|
if (!activeSession) {
|
|
70143
70165
|
return "No session";
|
|
70144
70166
|
}
|
|
70167
|
+
if (activeSession.metadata.nameSource === "manual") {
|
|
70168
|
+
const manual = normalizeSessionTitle(activeSession.metadata.name);
|
|
70169
|
+
return manual || activeSession.metadata.name.trim() || `S:${activeSession.id.slice(-6)}`;
|
|
70170
|
+
}
|
|
70171
|
+
if (persistedNameIsAuthoritative(activeSession.metadata)) {
|
|
70172
|
+
const persisted = normalizeSessionTitle(activeSession.metadata.name);
|
|
70173
|
+
if (persisted) return persisted;
|
|
70174
|
+
}
|
|
70145
70175
|
for (const msg of messages) {
|
|
70146
70176
|
if (msg.role !== "user") continue;
|
|
70147
70177
|
const text = extractUserText(msg);
|
|
70148
70178
|
if (isCompactSummaryMessage(text.trimStart())) continue;
|
|
70149
70179
|
const normalized = normalizeSessionTitle(text);
|
|
70150
70180
|
if (normalized) {
|
|
70181
|
+
activeSession.metadata.name = normalized;
|
|
70182
|
+
activeSession.metadata.nameSource = "derived";
|
|
70151
70183
|
return normalized;
|
|
70152
70184
|
}
|
|
70153
70185
|
}
|
|
70154
70186
|
const metadataName = normalizeSessionTitle(activeSession.metadata.name);
|
|
70155
|
-
if (metadataName &&
|
|
70187
|
+
if (metadataName && persistedNameIsAuthoritative(activeSession.metadata)) {
|
|
70156
70188
|
return metadataName;
|
|
70157
70189
|
}
|
|
70158
70190
|
return `S:${activeSession.id.slice(-6)}`;
|
|
@@ -77094,7 +77126,9 @@ function updatePendingMessagesDisplay(host) {
|
|
|
77094
77126
|
host.pendingMessagesContainer.addChild(new Text(text, 1, 0));
|
|
77095
77127
|
}
|
|
77096
77128
|
const dequeueHint = host.keybindings.getKeys("dequeue")[0] || "alt+up";
|
|
77097
|
-
const
|
|
77129
|
+
const steerHint = host.keybindings.getKeys("steer")[0];
|
|
77130
|
+
const promotionHint = followUpMessages.length > 0 && !followUpMessages[followUpMessages.length - 1].deliveredToAgent && steerHint ? `${steerHint} with empty editor: steer latest follow-up \xB7 ` : "";
|
|
77131
|
+
const hintText = theme.fg("dim", `\u21B3 ${promotionHint}${dequeueHint}: edit all queued messages`);
|
|
77098
77132
|
host.pendingMessagesContainer.addChild(new Text(hintText, 1, 0));
|
|
77099
77133
|
}
|
|
77100
77134
|
function dequeueMessages(host) {
|
|
@@ -77150,7 +77184,7 @@ function queueMessage(host, text, mode, options = {}) {
|
|
|
77150
77184
|
}
|
|
77151
77185
|
updatePendingMessagesDisplay(host);
|
|
77152
77186
|
host.showStatus(
|
|
77153
|
-
options.statusMessage ||
|
|
77187
|
+
options.statusMessage || (mode === "steer" ? "Queued message for steering" : `Queued for follow-up after the current task.${host.keybindings.getKeys("steer")[0] ? ` With empty editor, press ${host.keybindings.getKeys("steer")[0]} to steer the current task instead.` : ""}`)
|
|
77154
77188
|
);
|
|
77155
77189
|
host.ui.requestRender();
|
|
77156
77190
|
}
|
|
@@ -77169,7 +77203,22 @@ function handleFollowUp(host) {
|
|
|
77169
77203
|
}
|
|
77170
77204
|
function handleSteer(host) {
|
|
77171
77205
|
const text = host.editor.getText().trim();
|
|
77172
|
-
if (!text)
|
|
77206
|
+
if (!text) {
|
|
77207
|
+
const promoted = host.agentSessionController?.promoteLatestFollowUpToSteer();
|
|
77208
|
+
if (!promoted) {
|
|
77209
|
+
host.showStatus("No waiting follow-up to steer (it may already be processing)");
|
|
77210
|
+
return;
|
|
77211
|
+
}
|
|
77212
|
+
if (host.executionState.applyUserTextLifecycle(promoted.displayText)) {
|
|
77213
|
+
host.persistExecutionState();
|
|
77214
|
+
void host.refreshTodoWidget();
|
|
77215
|
+
}
|
|
77216
|
+
host.logDebug("queue:promote", { id: promoted.id, mode: promoted.mode });
|
|
77217
|
+
updatePendingMessagesDisplay(host);
|
|
77218
|
+
host.showStatus("Latest follow-up changed to steer; it will guide the current task at the next message boundary");
|
|
77219
|
+
host.ui.requestRender();
|
|
77220
|
+
return;
|
|
77221
|
+
}
|
|
77173
77222
|
if (isCommandLikeInput(text)) {
|
|
77174
77223
|
host.editor.onSubmit?.(text);
|
|
77175
77224
|
return;
|
|
@@ -77593,9 +77642,10 @@ function stripStaleUsageBeforeCompaction(messages, latestCompactionTimestamp) {
|
|
|
77593
77642
|
|
|
77594
77643
|
// src/runtime/retry-policy.ts
|
|
77595
77644
|
var TRANSIENT_NETWORK_ERROR_PATTERN = /sse stream aborted|sse stream closed before end|sse stream ended before response completed|(?:read\s+)?ECONNRESET|ETIMEDOUT|EAI_AGAIN|ENOTFOUND|ECONNREFUSED|(?:read\s+|write\s+)?EPIPE|socket hang up|request timeout|client network socket disconnected before secure TLS connection was established|certificate (?:has )?expired|unable to verify (?:the first certificate|certificate)|self[- ]signed cert|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated/i;
|
|
77596
|
-
var PROVIDER_TRANSIENT_ERROR_PATTERN = /overloaded|rate.?limit|too many requests|\b429\b|\b500\b|\b502\b|\b503\b|\b504\b|service.?unavailable|server error|internal error|retry delay/i;
|
|
77645
|
+
var PROVIDER_TRANSIENT_ERROR_PATTERN = /overloaded|rate.?limit|too many requests|\b429\b|\b500\b|\b502\b|\b503\b|\b504\b|service.?unavailable|server error|internal error|retry delay|quota (?:has been |is )?exhausted/i;
|
|
77597
77646
|
var USER_ABORT_PATTERN = /request was aborted|local abort signal|user abort|user_interrupt|interrupted by user|esc pressed|ctrl\+c/i;
|
|
77598
77647
|
var AUTH_CONFIG_PATTERN = /missing api key|invalid api key|api key.*invalid|unauthorized|\b401\b|\b403\b|forbidden|authentication failed|no configured model|no models? are configured/i;
|
|
77648
|
+
var QUOTA_EXHAUSTED_PATTERN = /insufficient[_ ]quota|exceeded[_ ]current[_ ]quota|exceeded your current quota|billing[_ ]hard[_ ]limit|insufficient[_ ]balance|credit balance is too low|\barrearage\b|余额不足|\b(?:account|monthly|billing) quota (?:has been |is )?exhausted/i;
|
|
77599
77649
|
var INVALID_FILE_REFERENCE_PATTERN = /not the owner of this file|owner of this file|invalid_authentication_error/i;
|
|
77600
77650
|
var INVALID_REQUEST_PATTERN = /bad request|\b400\b|invalid request|invalid schema|schema validation|invalid parameter|unsupported parameter|malformed/i;
|
|
77601
77651
|
var CLI_RETRY_MAX_RETRIES = 3;
|
|
@@ -77635,7 +77685,7 @@ function classifyCliFailure(context) {
|
|
|
77635
77685
|
if (INVALID_FILE_REFERENCE_PATTERN.test(errorMessage4)) {
|
|
77636
77686
|
return createClassification("invalid_file_reference", errorMessage4);
|
|
77637
77687
|
}
|
|
77638
|
-
if (AUTH_CONFIG_PATTERN.test(errorMessage4)) {
|
|
77688
|
+
if (AUTH_CONFIG_PATTERN.test(errorMessage4) || QUOTA_EXHAUSTED_PATTERN.test(errorMessage4)) {
|
|
77639
77689
|
return createClassification("auth_config", errorMessage4);
|
|
77640
77690
|
}
|
|
77641
77691
|
if (TRANSIENT_NETWORK_ERROR_PATTERN.test(errorMessage4)) {
|
|
@@ -79986,7 +80036,7 @@ var InteractiveMode = class {
|
|
|
79986
80036
|
async init() {
|
|
79987
80037
|
const activeSession = this.sessionManager.getActiveSession();
|
|
79988
80038
|
this.thinkingLevel = resolveInitialThinkingLevel({ session: activeSession, settingsManager: this.options.settingsManager });
|
|
79989
|
-
const { Agent } = await import("./chunks/src-
|
|
80039
|
+
const { Agent } = await import("./chunks/src-VCWCE7YV.js");
|
|
79990
80040
|
this.agent = new Agent({
|
|
79991
80041
|
initialState: {
|
|
79992
80042
|
systemPrompt: this.buildSystemPrompt(),
|
|
@@ -80820,7 +80870,7 @@ async function runPrintMode(params) {
|
|
|
80820
80870
|
`);
|
|
80821
80871
|
console.log("Assistant: ");
|
|
80822
80872
|
}
|
|
80823
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
80873
|
+
const { Agent: AgentClass } = await import("./chunks/src-VCWCE7YV.js");
|
|
80824
80874
|
let agent;
|
|
80825
80875
|
const printModeExtensions = await loadPrintModeExtensions({
|
|
80826
80876
|
cwd: runtime.cwd,
|
|
@@ -81681,7 +81731,7 @@ async function runJsonEventsMode(params) {
|
|
|
81681
81731
|
return;
|
|
81682
81732
|
}
|
|
81683
81733
|
const parent = agent;
|
|
81684
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
81734
|
+
const { Agent: AgentClass } = await import("./chunks/src-VCWCE7YV.js");
|
|
81685
81735
|
const sideAgent = new AgentClass({
|
|
81686
81736
|
initialState: {
|
|
81687
81737
|
systemPrompt: parent.state.systemPrompt,
|
|
@@ -82025,7 +82075,7 @@ async function runJsonEventsMode(params) {
|
|
|
82025
82075
|
if (runtime.initialModel.unconfigured || controller) {
|
|
82026
82076
|
return;
|
|
82027
82077
|
}
|
|
82028
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
82078
|
+
const { Agent: AgentClass } = await import("./chunks/src-VCWCE7YV.js");
|
|
82029
82079
|
const jsonModeExtensions = await loadJsonModeExtensions({ runtime, getAgent: () => agent });
|
|
82030
82080
|
extensionRunner = jsonModeExtensions.runner;
|
|
82031
82081
|
const tools = [...runtime.tools, ...jsonModeExtensions.extensionTools];
|
|
@@ -82614,7 +82664,7 @@ async function runWithJsonEventsConsoleIsolation(fn) {
|
|
|
82614
82664
|
}
|
|
82615
82665
|
async function createCliTestStreamFnFromEnv() {
|
|
82616
82666
|
if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) return void 0;
|
|
82617
|
-
return (await import("./chunks/test-stream-
|
|
82667
|
+
return (await import("./chunks/test-stream-GOSEWMJ3.js")).createTestStreamFnFromSequenceEnv();
|
|
82618
82668
|
}
|
|
82619
82669
|
function resolveJsonEventsDetailFlag() {
|
|
82620
82670
|
for (let index = 0; index < process.argv.length; index += 1) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cydm/pie",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "Pie AI Agent CLI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"validate:models": "tsx scripts/validate-models-config.ts",
|
|
18
18
|
"test": "npm run test:offline",
|
|
19
19
|
"pretest:offline": "npm run build --workspace @pie/agent-framework && npm run build --workspace @pie/shared-headless-capabilities && npm run build && npm run test:skill-regressions",
|
|
20
|
-
"test:skill-regressions": "node --test --import tsx test/bash-lifecycle.test.ts test/skill-creator-runner.test.ts test/tui-use-contract.test.ts test/tui-use-runtime.test.ts test/browser-runtime.test.ts test/computer-evidence.test.ts test/interactive-lifecycle.test.ts",
|
|
20
|
+
"test:skill-regressions": "node --test --import tsx test/bash-lifecycle.test.ts test/skill-creator-runner.test.ts test/tui-use-contract.test.ts test/tui-use-runtime.test.ts test/browser-runtime.test.ts test/axi-stop-semantics.test.ts test/computer-evidence.test.ts test/interactive-lifecycle.test.ts",
|
|
21
21
|
"posttest:offline": "node --test --import tsx test/remote-model-catalog.test.ts",
|
|
22
22
|
"test:offline": "node --test --test-concurrency=4 --import tsx test/builtin-extensions.test.ts test/core-services.test.ts test/cli.test.ts test/cli-auto-compaction.test.ts test/execution-state-manager.test.ts test/queued-steer-execution-state.test.ts test/architecture-boundaries.test.ts test/attachment-resolver.test.ts test/kimi-attachment-provider.test.ts test/document-attachment-extension.test.ts test/auto-compact-overflow.test.ts test/auto-compaction-ui.test.ts test/hierarchical-command-system.test.ts test/mcp-adapter.test.ts test/herdr-agent-state.test.ts test/extensions-enablement.test.ts test/extension-selector-shortcuts.test.ts test/skill-tool-enablement.test.ts test/message-queue-unit.test.ts test/evals-harness.test.ts test/session-trace.test.ts test/runtime-mode-context.test.ts test/tool-policy.test.ts test/retry-policy.test.ts test/yolo-command.test.ts test/footer-lifecycle.test.ts test/files-utils.test.ts test/source-size-guard.test.ts test/runtime-logger.test.ts test/release-readiness.test.ts test/package-artifacts.test.ts test/code-intel-typescript-provider.test.ts test/init-extension-contract.test.ts test/skills-runtime.test.ts test/skills-agents-discovery.test.ts test/skills-symlink.test.ts test/model-overrides.test.ts test/auth-storage.test.ts test/extension-register-provider.test.ts test/extension-reload.test.ts test/extension-terminal-input.test.ts test/extension-session-before-events.test.ts test/extension-widgets.test.ts test/extension-render-hint.test.ts test/extension-oauth-restore.test.ts test/cross-host-parity.test.ts test/tool-name-rendering.test.ts test/session-selector.test.ts test/tree-selector-pagination.test.ts test/session-control.test.ts test/terminal-title.test.ts test/interactive-controller-title.test.ts test/todo-title.terminal.test.ts test/plan-mode-extension.test.ts test/rendered-page-reader.test.ts test/tools-registry.test.ts test/system-prompt-contract.test.ts test/bash-yolo.test.ts test/bash-process-group.test.ts test/bash-artifact-sink.test.ts test/direct-bash.test.ts test/terminal-bell.test.ts test/ctrl-d-exit.test.ts test/session-display-title.test.ts test/calm-mode.test.ts test/project-root.test.ts test/guard-advisory-context.test.ts test/clear-command-usage.test.ts test/daily-agent-smoke.terminal.test.ts test/slash-menu-toggles.terminal.test.ts test/cli-args.test.ts test/extensions-configured-paths.test.ts test/extensions-loader-path.test.ts test/file-picker.test.ts test/interrupt-recovery.test.ts test/mention-insert-regression.test.ts test/mention-picker-navigation.test.ts test/pie-unity-rpc-skill.test.ts test/skill-creator-scripts.test.ts",
|
|
23
23
|
"test:all": "npm run test:offline && npm run test:terminal:vitest",
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
|
-
import {
|
|
3
|
-
Agent,
|
|
4
|
-
agentLoop,
|
|
5
|
-
agentLoopContinue
|
|
6
|
-
} from "./chunk-ZKHMNEXL.js";
|
|
7
|
-
import "./chunk-YRXXRLMQ.js";
|
|
8
|
-
import "./chunk-XXGYUYXI.js";
|
|
9
|
-
import "./chunk-LZQXQOPJ.js";
|
|
10
|
-
export {
|
|
11
|
-
Agent,
|
|
12
|
-
agentLoop,
|
|
13
|
-
agentLoopContinue
|
|
14
|
-
};
|