@cydm/pie 2.3.0 → 2.5.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 +26 -4
- package/dist/builtin/extensions/computer-use/package.json +3 -0
- 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/build-native.mjs +2 -1
- package/dist/builtin/extensions/computer-use/scripts/setup-helper.mjs +2 -2
- package/dist/builtin/extensions/computer-use/scripts/test-native-retention.mjs +204 -0
- package/dist/builtin/extensions/mcp-adapter/index.js +48 -13
- package/dist/builtin/extensions/plan-mode/index.js +3 -3
- package/dist/builtin/extensions/subagent/index.js +5 -4
- package/dist/builtin/extensions/todo/index.js +3 -3
- package/dist/builtin/skills/chrome-devtools-axi/chrome-devtools-axi-runtime.js +1 -1
- package/dist/builtin/skills/chrome-devtools-axi/{cli-F2VCSVL4.js → cli-P4VG6ZZG.js} +48 -8
- package/dist/builtin/skills/skill-creator/scripts/pie_runner.mjs +33 -12
- package/dist/builtin/skills/tui-use/tui-use-daemon.cjs +5 -7
- package/dist/chunks/{chunk-UPPICLVS.js → chunk-JXY3YLDS.js} +8247 -7345
- package/dist/chunks/{chunk-P3QPJXS7.js → chunk-PU7IIEKH.js} +108 -36
- package/dist/chunks/{chunk-IM43UYVV.js → chunk-YRXXRLMQ.js} +75 -14
- package/dist/chunks/{chunk-QJH6YN2W.js → chunk-ZKHMNEXL.js} +1 -1
- package/dist/chunks/{src-QSP2OPHU.js → src-SXUQ7OY6.js} +2 -2
- package/dist/chunks/{test-stream-CVGWFLSX.js → test-stream-OD3B57AS.js} +1 -1
- package/dist/cli.js +1350 -876
- package/package.json +2 -2
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-PU7IIEKH.js";
|
|
11
11
|
import {
|
|
12
12
|
AGENTS_CONTEXT_FILE_NAME,
|
|
13
13
|
AgentSessionController,
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
evaluateTodoClosureAfterFailedTurn,
|
|
41
41
|
extensionFallbackName,
|
|
42
42
|
extractExtensionSettings,
|
|
43
|
-
|
|
43
|
+
findFirstKeptEntrySummaryId,
|
|
44
44
|
formatSkillSummariesForPrompt,
|
|
45
45
|
generateEntryId,
|
|
46
46
|
getAutoCompactTokenLimit,
|
|
@@ -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-JXY3YLDS.js";
|
|
64
|
+
import "./chunks/chunk-ZKHMNEXL.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-YRXXRLMQ.js";
|
|
89
89
|
import {
|
|
90
90
|
VERSION,
|
|
91
91
|
getAgentDir,
|
|
@@ -994,15 +994,15 @@ var require_route = __commonJS({
|
|
|
994
994
|
};
|
|
995
995
|
}
|
|
996
996
|
function wrapConversion(toModel, graph) {
|
|
997
|
-
const
|
|
997
|
+
const path34 = [graph[toModel].parent, toModel];
|
|
998
998
|
let fn = conversions[graph[toModel].parent][toModel];
|
|
999
999
|
let cur = graph[toModel].parent;
|
|
1000
1000
|
while (graph[cur].parent) {
|
|
1001
|
-
|
|
1001
|
+
path34.unshift(graph[cur].parent);
|
|
1002
1002
|
fn = link(conversions[graph[cur].parent][cur], fn);
|
|
1003
1003
|
cur = graph[cur].parent;
|
|
1004
1004
|
}
|
|
1005
|
-
fn.conversion =
|
|
1005
|
+
fn.conversion = path34;
|
|
1006
1006
|
return fn;
|
|
1007
1007
|
}
|
|
1008
1008
|
module.exports = function(fromModel) {
|
|
@@ -1925,7 +1925,7 @@ var require_core = __commonJS({
|
|
|
1925
1925
|
return match && match.index === 0;
|
|
1926
1926
|
}
|
|
1927
1927
|
var BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
|
|
1928
|
-
function
|
|
1928
|
+
function join22(regexps, separator = "|") {
|
|
1929
1929
|
let numCaptures = 0;
|
|
1930
1930
|
return regexps.map((regex) => {
|
|
1931
1931
|
numCaptures += 1;
|
|
@@ -2229,7 +2229,7 @@ var require_core = __commonJS({
|
|
|
2229
2229
|
this.exec = () => null;
|
|
2230
2230
|
}
|
|
2231
2231
|
const terminators = this.regexes.map((el) => el[1]);
|
|
2232
|
-
this.matcherRe = langRe(
|
|
2232
|
+
this.matcherRe = langRe(join22(terminators), true);
|
|
2233
2233
|
this.lastIndex = 0;
|
|
2234
2234
|
}
|
|
2235
2235
|
/** @param {string} s */
|
|
@@ -44042,17 +44042,17 @@ var require_visit = __commonJS({
|
|
|
44042
44042
|
visit.BREAK = BREAK;
|
|
44043
44043
|
visit.SKIP = SKIP;
|
|
44044
44044
|
visit.REMOVE = REMOVE;
|
|
44045
|
-
function visit_(key, node, visitor,
|
|
44046
|
-
const ctrl = callVisitor(key, node, visitor,
|
|
44045
|
+
function visit_(key, node, visitor, path34) {
|
|
44046
|
+
const ctrl = callVisitor(key, node, visitor, path34);
|
|
44047
44047
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
44048
|
-
replaceNode(key,
|
|
44049
|
-
return visit_(key, ctrl, visitor,
|
|
44048
|
+
replaceNode(key, path34, ctrl);
|
|
44049
|
+
return visit_(key, ctrl, visitor, path34);
|
|
44050
44050
|
}
|
|
44051
44051
|
if (typeof ctrl !== "symbol") {
|
|
44052
44052
|
if (identity.isCollection(node)) {
|
|
44053
|
-
|
|
44053
|
+
path34 = Object.freeze(path34.concat(node));
|
|
44054
44054
|
for (let i = 0; i < node.items.length; ++i) {
|
|
44055
|
-
const ci = visit_(i, node.items[i], visitor,
|
|
44055
|
+
const ci = visit_(i, node.items[i], visitor, path34);
|
|
44056
44056
|
if (typeof ci === "number")
|
|
44057
44057
|
i = ci - 1;
|
|
44058
44058
|
else if (ci === BREAK)
|
|
@@ -44063,13 +44063,13 @@ var require_visit = __commonJS({
|
|
|
44063
44063
|
}
|
|
44064
44064
|
}
|
|
44065
44065
|
} else if (identity.isPair(node)) {
|
|
44066
|
-
|
|
44067
|
-
const ck = visit_("key", node.key, visitor,
|
|
44066
|
+
path34 = Object.freeze(path34.concat(node));
|
|
44067
|
+
const ck = visit_("key", node.key, visitor, path34);
|
|
44068
44068
|
if (ck === BREAK)
|
|
44069
44069
|
return BREAK;
|
|
44070
44070
|
else if (ck === REMOVE)
|
|
44071
44071
|
node.key = null;
|
|
44072
|
-
const cv = visit_("value", node.value, visitor,
|
|
44072
|
+
const cv = visit_("value", node.value, visitor, path34);
|
|
44073
44073
|
if (cv === BREAK)
|
|
44074
44074
|
return BREAK;
|
|
44075
44075
|
else if (cv === REMOVE)
|
|
@@ -44090,17 +44090,17 @@ var require_visit = __commonJS({
|
|
|
44090
44090
|
visitAsync.BREAK = BREAK;
|
|
44091
44091
|
visitAsync.SKIP = SKIP;
|
|
44092
44092
|
visitAsync.REMOVE = REMOVE;
|
|
44093
|
-
async function visitAsync_(key, node, visitor,
|
|
44094
|
-
const ctrl = await callVisitor(key, node, visitor,
|
|
44093
|
+
async function visitAsync_(key, node, visitor, path34) {
|
|
44094
|
+
const ctrl = await callVisitor(key, node, visitor, path34);
|
|
44095
44095
|
if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
|
|
44096
|
-
replaceNode(key,
|
|
44097
|
-
return visitAsync_(key, ctrl, visitor,
|
|
44096
|
+
replaceNode(key, path34, ctrl);
|
|
44097
|
+
return visitAsync_(key, ctrl, visitor, path34);
|
|
44098
44098
|
}
|
|
44099
44099
|
if (typeof ctrl !== "symbol") {
|
|
44100
44100
|
if (identity.isCollection(node)) {
|
|
44101
|
-
|
|
44101
|
+
path34 = Object.freeze(path34.concat(node));
|
|
44102
44102
|
for (let i = 0; i < node.items.length; ++i) {
|
|
44103
|
-
const ci = await visitAsync_(i, node.items[i], visitor,
|
|
44103
|
+
const ci = await visitAsync_(i, node.items[i], visitor, path34);
|
|
44104
44104
|
if (typeof ci === "number")
|
|
44105
44105
|
i = ci - 1;
|
|
44106
44106
|
else if (ci === BREAK)
|
|
@@ -44111,13 +44111,13 @@ var require_visit = __commonJS({
|
|
|
44111
44111
|
}
|
|
44112
44112
|
}
|
|
44113
44113
|
} else if (identity.isPair(node)) {
|
|
44114
|
-
|
|
44115
|
-
const ck = await visitAsync_("key", node.key, visitor,
|
|
44114
|
+
path34 = Object.freeze(path34.concat(node));
|
|
44115
|
+
const ck = await visitAsync_("key", node.key, visitor, path34);
|
|
44116
44116
|
if (ck === BREAK)
|
|
44117
44117
|
return BREAK;
|
|
44118
44118
|
else if (ck === REMOVE)
|
|
44119
44119
|
node.key = null;
|
|
44120
|
-
const cv = await visitAsync_("value", node.value, visitor,
|
|
44120
|
+
const cv = await visitAsync_("value", node.value, visitor, path34);
|
|
44121
44121
|
if (cv === BREAK)
|
|
44122
44122
|
return BREAK;
|
|
44123
44123
|
else if (cv === REMOVE)
|
|
@@ -44144,23 +44144,23 @@ var require_visit = __commonJS({
|
|
|
44144
44144
|
}
|
|
44145
44145
|
return visitor;
|
|
44146
44146
|
}
|
|
44147
|
-
function callVisitor(key, node, visitor,
|
|
44147
|
+
function callVisitor(key, node, visitor, path34) {
|
|
44148
44148
|
if (typeof visitor === "function")
|
|
44149
|
-
return visitor(key, node,
|
|
44149
|
+
return visitor(key, node, path34);
|
|
44150
44150
|
if (identity.isMap(node))
|
|
44151
|
-
return visitor.Map?.(key, node,
|
|
44151
|
+
return visitor.Map?.(key, node, path34);
|
|
44152
44152
|
if (identity.isSeq(node))
|
|
44153
|
-
return visitor.Seq?.(key, node,
|
|
44153
|
+
return visitor.Seq?.(key, node, path34);
|
|
44154
44154
|
if (identity.isPair(node))
|
|
44155
|
-
return visitor.Pair?.(key, node,
|
|
44155
|
+
return visitor.Pair?.(key, node, path34);
|
|
44156
44156
|
if (identity.isScalar(node))
|
|
44157
|
-
return visitor.Scalar?.(key, node,
|
|
44157
|
+
return visitor.Scalar?.(key, node, path34);
|
|
44158
44158
|
if (identity.isAlias(node))
|
|
44159
|
-
return visitor.Alias?.(key, node,
|
|
44159
|
+
return visitor.Alias?.(key, node, path34);
|
|
44160
44160
|
return void 0;
|
|
44161
44161
|
}
|
|
44162
|
-
function replaceNode(key,
|
|
44163
|
-
const parent =
|
|
44162
|
+
function replaceNode(key, path34, node) {
|
|
44163
|
+
const parent = path34[path34.length - 1];
|
|
44164
44164
|
if (identity.isCollection(parent)) {
|
|
44165
44165
|
parent.items[key] = node;
|
|
44166
44166
|
} else if (identity.isPair(parent)) {
|
|
@@ -44768,10 +44768,10 @@ var require_Collection = __commonJS({
|
|
|
44768
44768
|
var createNode = require_createNode();
|
|
44769
44769
|
var identity = require_identity();
|
|
44770
44770
|
var Node = require_Node();
|
|
44771
|
-
function collectionFromPath(schema,
|
|
44771
|
+
function collectionFromPath(schema, path34, value) {
|
|
44772
44772
|
let v2 = value;
|
|
44773
|
-
for (let i =
|
|
44774
|
-
const k2 =
|
|
44773
|
+
for (let i = path34.length - 1; i >= 0; --i) {
|
|
44774
|
+
const k2 = path34[i];
|
|
44775
44775
|
if (typeof k2 === "number" && Number.isInteger(k2) && k2 >= 0) {
|
|
44776
44776
|
const a = [];
|
|
44777
44777
|
a[k2] = v2;
|
|
@@ -44790,7 +44790,7 @@ var require_Collection = __commonJS({
|
|
|
44790
44790
|
sourceObjects: /* @__PURE__ */ new Map()
|
|
44791
44791
|
});
|
|
44792
44792
|
}
|
|
44793
|
-
var isEmptyPath = (
|
|
44793
|
+
var isEmptyPath = (path34) => path34 == null || typeof path34 === "object" && !!path34[Symbol.iterator]().next().done;
|
|
44794
44794
|
var Collection = class extends Node.NodeBase {
|
|
44795
44795
|
constructor(type, schema) {
|
|
44796
44796
|
super(type);
|
|
@@ -44820,11 +44820,11 @@ var require_Collection = __commonJS({
|
|
|
44820
44820
|
* be a Pair instance or a `{ key, value }` object, which may not have a key
|
|
44821
44821
|
* that already exists in the map.
|
|
44822
44822
|
*/
|
|
44823
|
-
addIn(
|
|
44824
|
-
if (isEmptyPath(
|
|
44823
|
+
addIn(path34, value) {
|
|
44824
|
+
if (isEmptyPath(path34))
|
|
44825
44825
|
this.add(value);
|
|
44826
44826
|
else {
|
|
44827
|
-
const [key, ...rest] =
|
|
44827
|
+
const [key, ...rest] = path34;
|
|
44828
44828
|
const node = this.get(key, true);
|
|
44829
44829
|
if (identity.isCollection(node))
|
|
44830
44830
|
node.addIn(rest, value);
|
|
@@ -44838,8 +44838,8 @@ var require_Collection = __commonJS({
|
|
|
44838
44838
|
* Removes a value from the collection.
|
|
44839
44839
|
* @returns `true` if the item was found and removed.
|
|
44840
44840
|
*/
|
|
44841
|
-
deleteIn(
|
|
44842
|
-
const [key, ...rest] =
|
|
44841
|
+
deleteIn(path34) {
|
|
44842
|
+
const [key, ...rest] = path34;
|
|
44843
44843
|
if (rest.length === 0)
|
|
44844
44844
|
return this.delete(key);
|
|
44845
44845
|
const node = this.get(key, true);
|
|
@@ -44853,8 +44853,8 @@ var require_Collection = __commonJS({
|
|
|
44853
44853
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
44854
44854
|
* `true` (collections are always returned intact).
|
|
44855
44855
|
*/
|
|
44856
|
-
getIn(
|
|
44857
|
-
const [key, ...rest] =
|
|
44856
|
+
getIn(path34, keepScalar) {
|
|
44857
|
+
const [key, ...rest] = path34;
|
|
44858
44858
|
const node = this.get(key, true);
|
|
44859
44859
|
if (rest.length === 0)
|
|
44860
44860
|
return !keepScalar && identity.isScalar(node) ? node.value : node;
|
|
@@ -44872,8 +44872,8 @@ var require_Collection = __commonJS({
|
|
|
44872
44872
|
/**
|
|
44873
44873
|
* Checks if the collection includes a value with the key `key`.
|
|
44874
44874
|
*/
|
|
44875
|
-
hasIn(
|
|
44876
|
-
const [key, ...rest] =
|
|
44875
|
+
hasIn(path34) {
|
|
44876
|
+
const [key, ...rest] = path34;
|
|
44877
44877
|
if (rest.length === 0)
|
|
44878
44878
|
return this.has(key);
|
|
44879
44879
|
const node = this.get(key, true);
|
|
@@ -44883,8 +44883,8 @@ var require_Collection = __commonJS({
|
|
|
44883
44883
|
* Sets a value in this collection. For `!!set`, `value` needs to be a
|
|
44884
44884
|
* boolean to add/remove the item from the set.
|
|
44885
44885
|
*/
|
|
44886
|
-
setIn(
|
|
44887
|
-
const [key, ...rest] =
|
|
44886
|
+
setIn(path34, value) {
|
|
44887
|
+
const [key, ...rest] = path34;
|
|
44888
44888
|
if (rest.length === 0) {
|
|
44889
44889
|
this.set(key, value);
|
|
44890
44890
|
} else {
|
|
@@ -47396,9 +47396,9 @@ var require_Document = __commonJS({
|
|
|
47396
47396
|
this.contents.add(value);
|
|
47397
47397
|
}
|
|
47398
47398
|
/** Adds a value to the document. */
|
|
47399
|
-
addIn(
|
|
47399
|
+
addIn(path34, value) {
|
|
47400
47400
|
if (assertCollection(this.contents))
|
|
47401
|
-
this.contents.addIn(
|
|
47401
|
+
this.contents.addIn(path34, value);
|
|
47402
47402
|
}
|
|
47403
47403
|
/**
|
|
47404
47404
|
* Create a new `Alias` node, ensuring that the target `node` has the required anchor.
|
|
@@ -47473,14 +47473,14 @@ var require_Document = __commonJS({
|
|
|
47473
47473
|
* Removes a value from the document.
|
|
47474
47474
|
* @returns `true` if the item was found and removed.
|
|
47475
47475
|
*/
|
|
47476
|
-
deleteIn(
|
|
47477
|
-
if (Collection.isEmptyPath(
|
|
47476
|
+
deleteIn(path34) {
|
|
47477
|
+
if (Collection.isEmptyPath(path34)) {
|
|
47478
47478
|
if (this.contents == null)
|
|
47479
47479
|
return false;
|
|
47480
47480
|
this.contents = null;
|
|
47481
47481
|
return true;
|
|
47482
47482
|
}
|
|
47483
|
-
return assertCollection(this.contents) ? this.contents.deleteIn(
|
|
47483
|
+
return assertCollection(this.contents) ? this.contents.deleteIn(path34) : false;
|
|
47484
47484
|
}
|
|
47485
47485
|
/**
|
|
47486
47486
|
* Returns item at `key`, or `undefined` if not found. By default unwraps
|
|
@@ -47495,10 +47495,10 @@ var require_Document = __commonJS({
|
|
|
47495
47495
|
* scalar values from their surrounding node; to disable set `keepScalar` to
|
|
47496
47496
|
* `true` (collections are always returned intact).
|
|
47497
47497
|
*/
|
|
47498
|
-
getIn(
|
|
47499
|
-
if (Collection.isEmptyPath(
|
|
47498
|
+
getIn(path34, keepScalar) {
|
|
47499
|
+
if (Collection.isEmptyPath(path34))
|
|
47500
47500
|
return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
|
|
47501
|
-
return identity.isCollection(this.contents) ? this.contents.getIn(
|
|
47501
|
+
return identity.isCollection(this.contents) ? this.contents.getIn(path34, keepScalar) : void 0;
|
|
47502
47502
|
}
|
|
47503
47503
|
/**
|
|
47504
47504
|
* Checks if the document includes a value with the key `key`.
|
|
@@ -47509,10 +47509,10 @@ var require_Document = __commonJS({
|
|
|
47509
47509
|
/**
|
|
47510
47510
|
* Checks if the document includes a value at `path`.
|
|
47511
47511
|
*/
|
|
47512
|
-
hasIn(
|
|
47513
|
-
if (Collection.isEmptyPath(
|
|
47512
|
+
hasIn(path34) {
|
|
47513
|
+
if (Collection.isEmptyPath(path34))
|
|
47514
47514
|
return this.contents !== void 0;
|
|
47515
|
-
return identity.isCollection(this.contents) ? this.contents.hasIn(
|
|
47515
|
+
return identity.isCollection(this.contents) ? this.contents.hasIn(path34) : false;
|
|
47516
47516
|
}
|
|
47517
47517
|
/**
|
|
47518
47518
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
@@ -47529,13 +47529,13 @@ var require_Document = __commonJS({
|
|
|
47529
47529
|
* Sets a value in this document. For `!!set`, `value` needs to be a
|
|
47530
47530
|
* boolean to add/remove the item from the set.
|
|
47531
47531
|
*/
|
|
47532
|
-
setIn(
|
|
47533
|
-
if (Collection.isEmptyPath(
|
|
47532
|
+
setIn(path34, value) {
|
|
47533
|
+
if (Collection.isEmptyPath(path34)) {
|
|
47534
47534
|
this.contents = value;
|
|
47535
47535
|
} else if (this.contents == null) {
|
|
47536
|
-
this.contents = Collection.collectionFromPath(this.schema, Array.from(
|
|
47536
|
+
this.contents = Collection.collectionFromPath(this.schema, Array.from(path34), value);
|
|
47537
47537
|
} else if (assertCollection(this.contents)) {
|
|
47538
|
-
this.contents.setIn(
|
|
47538
|
+
this.contents.setIn(path34, value);
|
|
47539
47539
|
}
|
|
47540
47540
|
}
|
|
47541
47541
|
/**
|
|
@@ -49492,9 +49492,9 @@ var require_cst_visit = __commonJS({
|
|
|
49492
49492
|
visit.BREAK = BREAK;
|
|
49493
49493
|
visit.SKIP = SKIP;
|
|
49494
49494
|
visit.REMOVE = REMOVE;
|
|
49495
|
-
visit.itemAtPath = (cst,
|
|
49495
|
+
visit.itemAtPath = (cst, path34) => {
|
|
49496
49496
|
let item = cst;
|
|
49497
|
-
for (const [field, index] of
|
|
49497
|
+
for (const [field, index] of path34) {
|
|
49498
49498
|
const tok = item?.[field];
|
|
49499
49499
|
if (tok && "items" in tok) {
|
|
49500
49500
|
item = tok.items[index];
|
|
@@ -49503,23 +49503,23 @@ var require_cst_visit = __commonJS({
|
|
|
49503
49503
|
}
|
|
49504
49504
|
return item;
|
|
49505
49505
|
};
|
|
49506
|
-
visit.parentCollection = (cst,
|
|
49507
|
-
const parent = visit.itemAtPath(cst,
|
|
49508
|
-
const field =
|
|
49506
|
+
visit.parentCollection = (cst, path34) => {
|
|
49507
|
+
const parent = visit.itemAtPath(cst, path34.slice(0, -1));
|
|
49508
|
+
const field = path34[path34.length - 1][0];
|
|
49509
49509
|
const coll = parent?.[field];
|
|
49510
49510
|
if (coll && "items" in coll)
|
|
49511
49511
|
return coll;
|
|
49512
49512
|
throw new Error("Parent collection not found");
|
|
49513
49513
|
};
|
|
49514
|
-
function _visit(
|
|
49515
|
-
let ctrl = visitor(item,
|
|
49514
|
+
function _visit(path34, item, visitor) {
|
|
49515
|
+
let ctrl = visitor(item, path34);
|
|
49516
49516
|
if (typeof ctrl === "symbol")
|
|
49517
49517
|
return ctrl;
|
|
49518
49518
|
for (const field of ["key", "value"]) {
|
|
49519
49519
|
const token = item[field];
|
|
49520
49520
|
if (token && "items" in token) {
|
|
49521
49521
|
for (let i = 0; i < token.items.length; ++i) {
|
|
49522
|
-
const ci = _visit(Object.freeze(
|
|
49522
|
+
const ci = _visit(Object.freeze(path34.concat([[field, i]])), token.items[i], visitor);
|
|
49523
49523
|
if (typeof ci === "number")
|
|
49524
49524
|
i = ci - 1;
|
|
49525
49525
|
else if (ci === BREAK)
|
|
@@ -49530,10 +49530,10 @@ var require_cst_visit = __commonJS({
|
|
|
49530
49530
|
}
|
|
49531
49531
|
}
|
|
49532
49532
|
if (typeof ctrl === "function" && field === "key")
|
|
49533
|
-
ctrl = ctrl(item,
|
|
49533
|
+
ctrl = ctrl(item, path34);
|
|
49534
49534
|
}
|
|
49535
49535
|
}
|
|
49536
|
-
return typeof ctrl === "function" ? ctrl(item,
|
|
49536
|
+
return typeof ctrl === "function" ? ctrl(item, path34) : ctrl;
|
|
49537
49537
|
}
|
|
49538
49538
|
exports.visit = visit;
|
|
49539
49539
|
}
|
|
@@ -50818,14 +50818,14 @@ var require_parser2 = __commonJS({
|
|
|
50818
50818
|
case "scalar":
|
|
50819
50819
|
case "single-quoted-scalar":
|
|
50820
50820
|
case "double-quoted-scalar": {
|
|
50821
|
-
const
|
|
50821
|
+
const fs30 = this.flowScalar(this.type);
|
|
50822
50822
|
if (atNextItem || it.value) {
|
|
50823
|
-
map.items.push({ start, key:
|
|
50823
|
+
map.items.push({ start, key: fs30, sep: [] });
|
|
50824
50824
|
this.onKeyLine = true;
|
|
50825
50825
|
} else if (it.sep) {
|
|
50826
|
-
this.stack.push(
|
|
50826
|
+
this.stack.push(fs30);
|
|
50827
50827
|
} else {
|
|
50828
|
-
Object.assign(it, { key:
|
|
50828
|
+
Object.assign(it, { key: fs30, sep: [] });
|
|
50829
50829
|
this.onKeyLine = true;
|
|
50830
50830
|
}
|
|
50831
50831
|
return;
|
|
@@ -50953,13 +50953,13 @@ var require_parser2 = __commonJS({
|
|
|
50953
50953
|
case "scalar":
|
|
50954
50954
|
case "single-quoted-scalar":
|
|
50955
50955
|
case "double-quoted-scalar": {
|
|
50956
|
-
const
|
|
50956
|
+
const fs30 = this.flowScalar(this.type);
|
|
50957
50957
|
if (!it || it.value)
|
|
50958
|
-
fc.items.push({ start: [], key:
|
|
50958
|
+
fc.items.push({ start: [], key: fs30, sep: [] });
|
|
50959
50959
|
else if (it.sep)
|
|
50960
|
-
this.stack.push(
|
|
50960
|
+
this.stack.push(fs30);
|
|
50961
50961
|
else
|
|
50962
|
-
Object.assign(it, { key:
|
|
50962
|
+
Object.assign(it, { key: fs30, sep: [] });
|
|
50963
50963
|
return;
|
|
50964
50964
|
}
|
|
50965
50965
|
case "flow-map-end":
|
|
@@ -51268,8 +51268,8 @@ var require_dist2 = __commonJS({
|
|
|
51268
51268
|
});
|
|
51269
51269
|
|
|
51270
51270
|
// src/cli.ts
|
|
51271
|
-
import * as
|
|
51272
|
-
import * as
|
|
51271
|
+
import * as fs29 from "fs";
|
|
51272
|
+
import * as path33 from "path";
|
|
51273
51273
|
|
|
51274
51274
|
// src/cli-args.ts
|
|
51275
51275
|
var FLAGS_WITH_VALUES = /* @__PURE__ */ new Set(["--session-id", "--extension-path", "--developer-instructions", "--developer-instructions-file"]);
|
|
@@ -53356,6 +53356,46 @@ var ModelRegistry = class {
|
|
|
53356
53356
|
}
|
|
53357
53357
|
return { model, apiKey };
|
|
53358
53358
|
}
|
|
53359
|
+
/** Resolve an explicit model reference for user-requested overrides.
|
|
53360
|
+
* Accepts "provider/model-id" (exact lookup) or a bare model id (only
|
|
53361
|
+
* when it matches exactly one configured model). Never guesses across
|
|
53362
|
+
* providers; ambiguity and missing keys are reported as fallback reasons. */
|
|
53363
|
+
resolveModelRef(ref) {
|
|
53364
|
+
const trimmed = ref.trim();
|
|
53365
|
+
if (!trimmed) {
|
|
53366
|
+
return { fallbackReason: "empty model reference" };
|
|
53367
|
+
}
|
|
53368
|
+
const separator = trimmed.indexOf("/");
|
|
53369
|
+
if (separator >= 0) {
|
|
53370
|
+
if (separator === 0 || separator === trimmed.length - 1) {
|
|
53371
|
+
return { fallbackReason: `invalid model reference "${trimmed}"; expected provider/model-id` };
|
|
53372
|
+
}
|
|
53373
|
+
const provider = trimmed.slice(0, separator);
|
|
53374
|
+
const modelId = trimmed.slice(separator + 1);
|
|
53375
|
+
const model2 = this.find(provider, modelId);
|
|
53376
|
+
if (!model2) {
|
|
53377
|
+
return { fallbackReason: `model "${trimmed}" is not configured` };
|
|
53378
|
+
}
|
|
53379
|
+
const apiKey2 = this.getApiKey(model2);
|
|
53380
|
+
if (!apiKey2) {
|
|
53381
|
+
return { model: model2, fallbackReason: `no API key available for model "${trimmed}"` };
|
|
53382
|
+
}
|
|
53383
|
+
return { model: model2, apiKey: apiKey2 };
|
|
53384
|
+
}
|
|
53385
|
+
const matches = this.getAll().filter((model2) => model2.id === trimmed);
|
|
53386
|
+
if (matches.length === 0) {
|
|
53387
|
+
return { fallbackReason: `model "${trimmed}" is not configured; use provider/model-id` };
|
|
53388
|
+
}
|
|
53389
|
+
if (matches.length > 1) {
|
|
53390
|
+
return { fallbackReason: `model "${trimmed}" is ambiguous across providers (${matches.map((model2) => `${model2.provider}/${model2.id}`).join(", ")}); use provider/model-id` };
|
|
53391
|
+
}
|
|
53392
|
+
const model = matches[0];
|
|
53393
|
+
const apiKey = this.getApiKey(model);
|
|
53394
|
+
if (!apiKey) {
|
|
53395
|
+
return { model, fallbackReason: `no API key available for model "${model.provider}/${model.id}"` };
|
|
53396
|
+
}
|
|
53397
|
+
return { model, apiKey };
|
|
53398
|
+
}
|
|
53359
53399
|
hasExternalProviderConfig() {
|
|
53360
53400
|
return this.usingExternalProviders;
|
|
53361
53401
|
}
|
|
@@ -55129,9 +55169,11 @@ function runCapabilitiesCommand(args) {
|
|
|
55129
55169
|
}
|
|
55130
55170
|
|
|
55131
55171
|
// src/commands/sessions.ts
|
|
55132
|
-
import
|
|
55172
|
+
import fs8 from "node:fs";
|
|
55133
55173
|
|
|
55134
55174
|
// src/session-control.ts
|
|
55175
|
+
import * as fs7 from "node:fs";
|
|
55176
|
+
import * as path7 from "node:path";
|
|
55135
55177
|
var SessionControlError = class extends Error {
|
|
55136
55178
|
constructor(code, message, recoverable = sessionControlErrorRecoverable(code)) {
|
|
55137
55179
|
super(message);
|
|
@@ -55145,27 +55187,70 @@ var SessionControlError = class extends Error {
|
|
|
55145
55187
|
function sessionControlErrorRecoverable(code) {
|
|
55146
55188
|
return code !== "session_unrecoverable" && code !== "session_mismatch";
|
|
55147
55189
|
}
|
|
55148
|
-
|
|
55149
|
-
|
|
55150
|
-
|
|
55151
|
-
|
|
55152
|
-
|
|
55153
|
-
exists ? "session_unrecoverable" : "session_not_found",
|
|
55154
|
-
exists ? `Session could not be recovered: ${sessionId}` : `Session not found: ${sessionId}`
|
|
55155
|
-
);
|
|
55190
|
+
var FORK_BATCH_ENTRIES = 64;
|
|
55191
|
+
var FORK_BATCH_BYTES = 256 * 1024;
|
|
55192
|
+
var STAGING_SESSION_ID_PREFIX = "__pie-staging-";
|
|
55193
|
+
function stagingIdFor(targetSessionId) {
|
|
55194
|
+
return `${STAGING_SESSION_ID_PREFIX}${targetSessionId}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
55156
55195
|
}
|
|
55157
|
-
|
|
55158
|
-
|
|
55159
|
-
|
|
55160
|
-
|
|
55196
|
+
var PUBLISH_JOURNAL_DIR = ".pie-publish-journal";
|
|
55197
|
+
function safeSessionDirName(sessionId) {
|
|
55198
|
+
return sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
55199
|
+
}
|
|
55200
|
+
function canonicalSessionDir(sessionsDir, sessionId) {
|
|
55201
|
+
const dir = path7.join(sessionsDir, safeSessionDirName(sessionId));
|
|
55202
|
+
try {
|
|
55203
|
+
if (!fs7.existsSync(dir)) return null;
|
|
55204
|
+
return fs7.realpathSync(dir);
|
|
55205
|
+
} catch {
|
|
55206
|
+
return null;
|
|
55207
|
+
}
|
|
55208
|
+
}
|
|
55209
|
+
function publishJournalPath(sessionsDir, safeTargetId) {
|
|
55210
|
+
return path7.join(sessionsDir, PUBLISH_JOURNAL_DIR, `${safeTargetId}.json`);
|
|
55211
|
+
}
|
|
55212
|
+
function writePublishJournal(journalPath, record) {
|
|
55213
|
+
fs7.mkdirSync(path7.dirname(journalPath), { recursive: true });
|
|
55214
|
+
const tempPath = `${journalPath}.tmp`;
|
|
55215
|
+
fs7.writeFileSync(tempPath, JSON.stringify(record, void 0, " "));
|
|
55216
|
+
fs7.renameSync(tempPath, journalPath);
|
|
55217
|
+
}
|
|
55218
|
+
function clearPublishJournal(journalPath) {
|
|
55219
|
+
if (!journalPath) return;
|
|
55220
|
+
try {
|
|
55221
|
+
fs7.rmSync(journalPath, { force: true });
|
|
55222
|
+
} catch {
|
|
55223
|
+
}
|
|
55224
|
+
}
|
|
55225
|
+
function toIoError(error) {
|
|
55226
|
+
if (error instanceof SessionControlError) return error;
|
|
55227
|
+
return new SessionControlError("session_io_error", error instanceof Error ? error.message : String(error));
|
|
55228
|
+
}
|
|
55229
|
+
function loadRequiredSessionHead(store, sessionId) {
|
|
55230
|
+
const status = store.headStatus(sessionId);
|
|
55231
|
+
if (status === "legacy") {
|
|
55232
|
+
throw new SessionControlError(
|
|
55233
|
+
"session_unsupported_format",
|
|
55234
|
+
`Session uses an unsupported old format: ${sessionId}`
|
|
55235
|
+
);
|
|
55236
|
+
}
|
|
55237
|
+
if (status === "corrupt") {
|
|
55238
|
+
throw new SessionControlError("session_unrecoverable", `Session could not be recovered: ${sessionId}`);
|
|
55239
|
+
}
|
|
55240
|
+
const head = store.readHead(sessionId);
|
|
55241
|
+
if (!head) {
|
|
55242
|
+
throw new SessionControlError("session_not_found", `Session not found: ${sessionId}`);
|
|
55161
55243
|
}
|
|
55244
|
+
return head;
|
|
55245
|
+
}
|
|
55246
|
+
async function rewindStoredSession(params) {
|
|
55162
55247
|
try {
|
|
55163
|
-
|
|
55164
|
-
|
|
55165
|
-
|
|
55166
|
-
|
|
55167
|
-
|
|
55168
|
-
const metadata =
|
|
55248
|
+
loadRequiredSessionHead(params.store, params.sessionId);
|
|
55249
|
+
if (params.store.getEntrySummary(params.sessionId, params.entryId) === null) {
|
|
55250
|
+
throw new SessionControlError("entry_not_found", `Entry not found: ${params.entryId}`);
|
|
55251
|
+
}
|
|
55252
|
+
params.store.setActiveEntry(params.sessionId, params.entryId);
|
|
55253
|
+
const metadata = params.store.getMetadata(params.sessionId);
|
|
55169
55254
|
if (!metadata) {
|
|
55170
55255
|
throw new SessionControlError("session_unrecoverable", `Session could not be recovered after rewind: ${params.sessionId}`, false);
|
|
55171
55256
|
}
|
|
@@ -55176,52 +55261,179 @@ async function rewindStoredSession(params) {
|
|
|
55176
55261
|
metadata
|
|
55177
55262
|
};
|
|
55178
55263
|
} catch (error) {
|
|
55179
|
-
|
|
55180
|
-
throw new SessionControlError("session_io_error", error instanceof Error ? error.message : String(error));
|
|
55264
|
+
throw toIoError(error);
|
|
55181
55265
|
}
|
|
55182
55266
|
}
|
|
55183
55267
|
async function forkStoredSession(params) {
|
|
55268
|
+
let stagingId;
|
|
55184
55269
|
try {
|
|
55270
|
+
const sanitizedTargetId = params.targetSessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
55271
|
+
if (sanitizedTargetId.startsWith(STAGING_SESSION_ID_PREFIX)) {
|
|
55272
|
+
throw new SessionControlError(
|
|
55273
|
+
"invalid_request",
|
|
55274
|
+
`Target session id starts with a reserved internal prefix: ${params.targetSessionId}`
|
|
55275
|
+
);
|
|
55276
|
+
}
|
|
55277
|
+
if (params.sourceSessionId.replace(/[^a-zA-Z0-9_-]/g, "_").toLowerCase() === sanitizedTargetId.toLowerCase()) {
|
|
55278
|
+
throw new SessionControlError(
|
|
55279
|
+
"invalid_request",
|
|
55280
|
+
"Fork source and target must be different sessions: " + params.sourceSessionId
|
|
55281
|
+
);
|
|
55282
|
+
}
|
|
55283
|
+
if (params.sessionsDir) {
|
|
55284
|
+
const canonicalSourceDir = canonicalSessionDir(params.sessionsDir, params.sourceSessionId);
|
|
55285
|
+
const canonicalTargetDir = canonicalSessionDir(params.sessionsDir, params.targetSessionId);
|
|
55286
|
+
if (canonicalSourceDir !== null && canonicalTargetDir !== null && canonicalSourceDir === canonicalTargetDir) {
|
|
55287
|
+
throw new SessionControlError(
|
|
55288
|
+
"invalid_request",
|
|
55289
|
+
`Fork source and target resolve to the same session directory: ${params.sourceSessionId} -> ${params.targetSessionId}`
|
|
55290
|
+
);
|
|
55291
|
+
}
|
|
55292
|
+
}
|
|
55185
55293
|
if (!params.force) {
|
|
55186
55294
|
const existingTarget = await maybeLoadExistingForkTarget(params);
|
|
55187
55295
|
if (existingTarget) return existingTarget;
|
|
55188
55296
|
}
|
|
55189
|
-
const source =
|
|
55190
|
-
const
|
|
55191
|
-
if (
|
|
55297
|
+
const source = loadRequiredSessionHead(params.store, params.sourceSessionId);
|
|
55298
|
+
const pathSummaries = params.store.getPathSummaries(params.sourceSessionId, params.sourceEntryId);
|
|
55299
|
+
if (pathSummaries.length === 0 || pathSummaries[pathSummaries.length - 1]?.id !== params.sourceEntryId) {
|
|
55192
55300
|
throw new SessionControlError("entry_not_found", `Entry not found: ${params.sourceEntryId}`);
|
|
55193
55301
|
}
|
|
55194
55302
|
const now = params.now ?? Date.now();
|
|
55303
|
+
stagingId = stagingIdFor(params.targetSessionId);
|
|
55304
|
+
params.store.createHead(stagingId, {
|
|
55305
|
+
name: params.name,
|
|
55306
|
+
createdAt: now
|
|
55307
|
+
});
|
|
55195
55308
|
const idMap = /* @__PURE__ */ new Map();
|
|
55196
|
-
|
|
55197
|
-
|
|
55198
|
-
|
|
55199
|
-
|
|
55200
|
-
|
|
55201
|
-
|
|
55202
|
-
|
|
55203
|
-
|
|
55204
|
-
|
|
55309
|
+
let seq = 1;
|
|
55310
|
+
let batch = [];
|
|
55311
|
+
let batchBytes = 0;
|
|
55312
|
+
let lastCopiedId = null;
|
|
55313
|
+
let firstCopiedId = null;
|
|
55314
|
+
const flushBatch = () => {
|
|
55315
|
+
if (batch.length === 0) return;
|
|
55316
|
+
params.store.appendEntries(stagingId, batch, null);
|
|
55317
|
+
batch = [];
|
|
55318
|
+
batchBytes = 0;
|
|
55319
|
+
};
|
|
55320
|
+
for (const summary of pathSummaries) {
|
|
55321
|
+
let entry = null;
|
|
55322
|
+
try {
|
|
55323
|
+
entry = params.store.readEntry(params.sourceSessionId, summary.id);
|
|
55324
|
+
} catch {
|
|
55325
|
+
entry = null;
|
|
55326
|
+
}
|
|
55327
|
+
if (!entry) {
|
|
55328
|
+
throw new SessionControlError(
|
|
55329
|
+
"session_unrecoverable",
|
|
55330
|
+
`Fork source entry is not readable: ${summary.id}`,
|
|
55331
|
+
false
|
|
55332
|
+
);
|
|
55333
|
+
}
|
|
55334
|
+
const copy = {
|
|
55335
|
+
...entry,
|
|
55336
|
+
id: generateEntryId(seq),
|
|
55337
|
+
parentId: lastCopiedId,
|
|
55205
55338
|
timestamp: entry.timestamp
|
|
55206
55339
|
};
|
|
55207
|
-
|
|
55208
|
-
|
|
55209
|
-
|
|
55210
|
-
|
|
55340
|
+
if (copy.compactionData) {
|
|
55341
|
+
const keptId = idMap.get(copy.compactionData.firstKeptEntryId);
|
|
55342
|
+
copy.compactionData = {
|
|
55343
|
+
...copy.compactionData,
|
|
55344
|
+
firstKeptEntryId: keptId ?? firstCopiedId ?? copy.id
|
|
55345
|
+
};
|
|
55346
|
+
}
|
|
55347
|
+
idMap.set(summary.id, copy.id);
|
|
55348
|
+
if (firstCopiedId === null) {
|
|
55349
|
+
firstCopiedId = copy.id;
|
|
55350
|
+
}
|
|
55351
|
+
const copyBytes = Buffer.byteLength(JSON.stringify(copy), "utf8");
|
|
55352
|
+
if (batch.length > 0 && batchBytes + copyBytes > FORK_BATCH_BYTES) flushBatch();
|
|
55353
|
+
batch.push(copy);
|
|
55354
|
+
batchBytes += copyBytes;
|
|
55355
|
+
lastCopiedId = copy.id;
|
|
55356
|
+
seq += 1;
|
|
55357
|
+
if (batch.length >= FORK_BATCH_ENTRIES || batchBytes >= FORK_BATCH_BYTES) {
|
|
55358
|
+
flushBatch();
|
|
55359
|
+
}
|
|
55360
|
+
}
|
|
55361
|
+
flushBatch();
|
|
55362
|
+
if (!lastCopiedId) {
|
|
55363
|
+
throw new SessionControlError("session_unrecoverable", `Fork source has no readable entries: ${params.sourceSessionId}`, false);
|
|
55211
55364
|
}
|
|
55212
|
-
|
|
55365
|
+
params.store.setActiveEntry(stagingId, lastCopiedId);
|
|
55366
|
+
params.store.updateMetadata(stagingId, {
|
|
55213
55367
|
name: params.name,
|
|
55214
55368
|
createdAt: now,
|
|
55215
|
-
updatedAt: now,
|
|
55216
|
-
activeEntryId,
|
|
55217
55369
|
cwd: params.cwd ?? source.metadata.cwd,
|
|
55218
55370
|
sourceSessionId: params.sourceSessionId,
|
|
55219
55371
|
sourceEntryId: params.sourceEntryId,
|
|
55220
55372
|
sourceActiveEntryId: source.metadata.activeEntryId ?? void 0,
|
|
55221
|
-
forkBaseEntryId:
|
|
55373
|
+
forkBaseEntryId: lastCopiedId,
|
|
55222
55374
|
...params.requestId ? { sessionControlRequestId: params.requestId } : {}
|
|
55223
55375
|
});
|
|
55224
|
-
const
|
|
55376
|
+
const backupId = `${params.targetSessionId}-previous-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
55377
|
+
const targetStatus = params.store.headStatus(params.targetSessionId);
|
|
55378
|
+
if (targetStatus === "legacy" || targetStatus === "corrupt") {
|
|
55379
|
+
loadRequiredSessionHead(params.store, params.targetSessionId);
|
|
55380
|
+
}
|
|
55381
|
+
const hadPreviousTarget = targetStatus === "ok";
|
|
55382
|
+
if (hadPreviousTarget && !params.force) {
|
|
55383
|
+
throw new SessionControlError("target_exists", `Target session already exists: ${params.targetSessionId}`);
|
|
55384
|
+
}
|
|
55385
|
+
const safeTargetId = safeSessionDirName(params.targetSessionId);
|
|
55386
|
+
const journalPath = params.sessionsDir ? publishJournalPath(params.sessionsDir, safeTargetId) : null;
|
|
55387
|
+
if (journalPath) {
|
|
55388
|
+
writePublishJournal(journalPath, {
|
|
55389
|
+
v: 1,
|
|
55390
|
+
targetId: safeTargetId,
|
|
55391
|
+
stagingId: safeSessionDirName(stagingId),
|
|
55392
|
+
backupDir: hadPreviousTarget ? safeSessionDirName(backupId) : null,
|
|
55393
|
+
writtenAt: Date.now()
|
|
55394
|
+
});
|
|
55395
|
+
}
|
|
55396
|
+
if (hadPreviousTarget) {
|
|
55397
|
+
try {
|
|
55398
|
+
params.store.moveSession(params.targetSessionId, backupId);
|
|
55399
|
+
} catch (error) {
|
|
55400
|
+
clearPublishJournal(journalPath);
|
|
55401
|
+
throw error;
|
|
55402
|
+
}
|
|
55403
|
+
}
|
|
55404
|
+
try {
|
|
55405
|
+
params.store.moveSession(stagingId, params.targetSessionId);
|
|
55406
|
+
} catch (error) {
|
|
55407
|
+
if (hadPreviousTarget) {
|
|
55408
|
+
try {
|
|
55409
|
+
if (params.store.headStatus(params.targetSessionId) !== "missing") {
|
|
55410
|
+
throw new Error("target path is occupied");
|
|
55411
|
+
}
|
|
55412
|
+
params.store.moveSession(backupId, params.targetSessionId);
|
|
55413
|
+
clearPublishJournal(journalPath);
|
|
55414
|
+
} catch (restoreError) {
|
|
55415
|
+
throw new SessionControlError(
|
|
55416
|
+
"session_io_error",
|
|
55417
|
+
`Fork publication failed; previous session is preserved as ${backupId}. Restore failed: ${String(restoreError)}`,
|
|
55418
|
+
false
|
|
55419
|
+
);
|
|
55420
|
+
}
|
|
55421
|
+
}
|
|
55422
|
+
clearPublishJournal(journalPath);
|
|
55423
|
+
throw error;
|
|
55424
|
+
}
|
|
55425
|
+
let backupDeleted = !hadPreviousTarget;
|
|
55426
|
+
if (hadPreviousTarget) {
|
|
55427
|
+
try {
|
|
55428
|
+
params.store.delete(backupId);
|
|
55429
|
+
backupDeleted = true;
|
|
55430
|
+
} catch {
|
|
55431
|
+
}
|
|
55432
|
+
}
|
|
55433
|
+
if (backupDeleted) {
|
|
55434
|
+
clearPublishJournal(journalPath);
|
|
55435
|
+
}
|
|
55436
|
+
const metadata = params.store.getMetadata(params.targetSessionId);
|
|
55225
55437
|
if (!metadata) {
|
|
55226
55438
|
throw new SessionControlError("session_unrecoverable", `Session could not be recovered after fork: ${params.targetSessionId}`, false);
|
|
55227
55439
|
}
|
|
@@ -55232,13 +55444,23 @@ async function forkStoredSession(params) {
|
|
|
55232
55444
|
sourceActiveEntryId: source.metadata.activeEntryId ?? null
|
|
55233
55445
|
});
|
|
55234
55446
|
} catch (error) {
|
|
55235
|
-
|
|
55236
|
-
|
|
55447
|
+
throw toIoError(error);
|
|
55448
|
+
} finally {
|
|
55449
|
+
if (stagingId) {
|
|
55450
|
+
try {
|
|
55451
|
+
params.store.delete(stagingId);
|
|
55452
|
+
} catch {
|
|
55453
|
+
}
|
|
55454
|
+
}
|
|
55237
55455
|
}
|
|
55238
55456
|
}
|
|
55239
55457
|
async function maybeLoadExistingForkTarget(params) {
|
|
55240
|
-
|
|
55241
|
-
|
|
55458
|
+
const status = params.store.headStatus(params.targetSessionId);
|
|
55459
|
+
if (status === "missing") return null;
|
|
55460
|
+
if (status === "legacy") {
|
|
55461
|
+
throw new SessionControlError("session_unsupported_format", `Target session uses an unsupported old format: ${params.targetSessionId}`);
|
|
55462
|
+
}
|
|
55463
|
+
const target = params.store.readHead(params.targetSessionId);
|
|
55242
55464
|
if (!target) {
|
|
55243
55465
|
throw new SessionControlError("session_unrecoverable", `Session could not be recovered: ${params.targetSessionId}`, false);
|
|
55244
55466
|
}
|
|
@@ -55269,20 +55491,93 @@ function buildForkResult(params) {
|
|
|
55269
55491
|
metadata: params.metadata
|
|
55270
55492
|
};
|
|
55271
55493
|
}
|
|
55272
|
-
function
|
|
55273
|
-
const
|
|
55274
|
-
const
|
|
55275
|
-
let
|
|
55276
|
-
|
|
55277
|
-
|
|
55278
|
-
|
|
55279
|
-
|
|
55280
|
-
|
|
55494
|
+
function recoverInterruptedPublishes(params) {
|
|
55495
|
+
const outcomes = [];
|
|
55496
|
+
const journalDir = path7.join(params.sessionsDir, PUBLISH_JOURNAL_DIR);
|
|
55497
|
+
let entries;
|
|
55498
|
+
try {
|
|
55499
|
+
entries = fs7.readdirSync(journalDir);
|
|
55500
|
+
} catch {
|
|
55501
|
+
return outcomes;
|
|
55502
|
+
}
|
|
55503
|
+
for (const entry of entries) {
|
|
55504
|
+
if (!entry.endsWith(".json")) continue;
|
|
55505
|
+
outcomes.push(recoverOnePublishJournal({
|
|
55506
|
+
sessionsDir: params.sessionsDir,
|
|
55507
|
+
journalPath: path7.join(journalDir, entry),
|
|
55508
|
+
warn: params.warn
|
|
55509
|
+
}));
|
|
55281
55510
|
}
|
|
55282
|
-
return
|
|
55511
|
+
return outcomes;
|
|
55283
55512
|
}
|
|
55284
|
-
function
|
|
55285
|
-
|
|
55513
|
+
function recoverOnePublishJournal(params) {
|
|
55514
|
+
const journalName = path7.basename(params.journalPath);
|
|
55515
|
+
const warn = (message) => {
|
|
55516
|
+
(params.warn ?? ((text) => console.warn(text)))(message);
|
|
55517
|
+
};
|
|
55518
|
+
let record;
|
|
55519
|
+
try {
|
|
55520
|
+
const parsed = JSON.parse(fs7.readFileSync(params.journalPath, "utf8"));
|
|
55521
|
+
const safeId = /^[a-zA-Z0-9_-]+$/;
|
|
55522
|
+
if (parsed?.v !== 1 || !safeId.test(parsed.targetId ?? "") || !safeId.test(parsed.stagingId ?? "") || !((parsed.backupDir ?? null) === null || safeId.test(parsed.backupDir))) {
|
|
55523
|
+
throw new Error("journal record has unexpected shape");
|
|
55524
|
+
}
|
|
55525
|
+
record = parsed;
|
|
55526
|
+
} catch (error) {
|
|
55527
|
+
const message = `[session-control] Unreadable publish journal ${journalName}; left in place for manual inspection: ${String(error)}`;
|
|
55528
|
+
warn(message);
|
|
55529
|
+
return { action: "unreadable-journal", journal: journalName, message };
|
|
55530
|
+
}
|
|
55531
|
+
const dirExists = (id) => {
|
|
55532
|
+
try {
|
|
55533
|
+
return fs7.statSync(path7.join(params.sessionsDir, id)).isDirectory();
|
|
55534
|
+
} catch {
|
|
55535
|
+
return false;
|
|
55536
|
+
}
|
|
55537
|
+
};
|
|
55538
|
+
const removeSessionDir = (id) => {
|
|
55539
|
+
fs7.rmSync(path7.join(params.sessionsDir, id), { recursive: true, force: true });
|
|
55540
|
+
};
|
|
55541
|
+
const removeJournal = () => {
|
|
55542
|
+
fs7.rmSync(params.journalPath, { force: true });
|
|
55543
|
+
};
|
|
55544
|
+
const targetExists = dirExists(record.targetId);
|
|
55545
|
+
const backupExists = record.backupDir ? dirExists(record.backupDir) : false;
|
|
55546
|
+
const stagingExists = dirExists(record.stagingId);
|
|
55547
|
+
try {
|
|
55548
|
+
if (targetExists && !stagingExists) {
|
|
55549
|
+
if (backupExists && record.backupDir) removeSessionDir(record.backupDir);
|
|
55550
|
+
removeJournal();
|
|
55551
|
+
return { action: "publish-completed", targetId: record.targetId };
|
|
55552
|
+
}
|
|
55553
|
+
if (!targetExists && backupExists && record.backupDir) {
|
|
55554
|
+
fs7.renameSync(
|
|
55555
|
+
path7.join(params.sessionsDir, record.backupDir),
|
|
55556
|
+
path7.join(params.sessionsDir, record.targetId)
|
|
55557
|
+
);
|
|
55558
|
+
removeJournal();
|
|
55559
|
+
if (stagingExists) {
|
|
55560
|
+
try {
|
|
55561
|
+
removeSessionDir(record.stagingId);
|
|
55562
|
+
} catch (error) {
|
|
55563
|
+
warn(`[session-control] Restored ${record.targetId} but could not remove its abandoned staging copy ${record.stagingId}: ${String(error)}`);
|
|
55564
|
+
}
|
|
55565
|
+
}
|
|
55566
|
+
return { action: "restored-previous-target", targetId: record.targetId };
|
|
55567
|
+
}
|
|
55568
|
+
if (!targetExists && !backupExists) {
|
|
55569
|
+
if (stagingExists) removeSessionDir(record.stagingId);
|
|
55570
|
+
removeJournal();
|
|
55571
|
+
return stagingExists ? { action: "discarded-incomplete-fork", targetId: record.targetId } : { action: "nothing-to-recover", targetId: record.targetId };
|
|
55572
|
+
}
|
|
55573
|
+
const message = `[session-control] Ambiguous interrupted publish for target ${record.targetId} (target=${targetExists}, backup=${backupExists}, staging=${stagingExists}); nothing was deleted \u2014 inspect ${params.sessionsDir} and ${journalName} manually`;
|
|
55574
|
+
warn(message);
|
|
55575
|
+
return { action: "ambiguous-preserved", targetId: record.targetId, message };
|
|
55576
|
+
} catch (error) {
|
|
55577
|
+
const message = `[session-control] Recovery of publish journal ${journalName} failed; state preserved for manual inspection: ${String(error)}`;
|
|
55578
|
+
warn(message);
|
|
55579
|
+
return { action: "ambiguous-preserved", targetId: record.targetId, message };
|
|
55580
|
+
}
|
|
55286
55581
|
}
|
|
55287
55582
|
|
|
55288
55583
|
// src/commands/sessions.ts
|
|
@@ -55339,6 +55634,7 @@ function toSessionCommandError(error, kind) {
|
|
|
55339
55634
|
if (error instanceof SessionControlError) {
|
|
55340
55635
|
const hints = {
|
|
55341
55636
|
session_not_found: "list sessions: pie sessions list --json",
|
|
55637
|
+
session_unsupported_format: "old-format sessions cannot be read by this version",
|
|
55342
55638
|
target_exists: "choose a new --target, or add --force to overwrite"
|
|
55343
55639
|
};
|
|
55344
55640
|
return new CommandError(kind, error.code, error.message, { hint: hints[error.code] });
|
|
@@ -55427,15 +55723,18 @@ async function readSession(parsed) {
|
|
|
55427
55723
|
throw new CommandError("sessions.read", "missing_positional", renderCommandUsage(SESSIONS_READ_SPEC), { usage: true });
|
|
55428
55724
|
}
|
|
55429
55725
|
const store = new FileSessionStore(getSessionsDir());
|
|
55430
|
-
const data =
|
|
55431
|
-
const events = activeTranscriptEvents(
|
|
55726
|
+
const data = loadSessionHead(store, sessionId, "sessions.read");
|
|
55727
|
+
const events = await activeTranscriptEvents(store, sessionId, data.metadata.activeEntryId);
|
|
55432
55728
|
const end = resolveBeforeCursor(events, before);
|
|
55433
55729
|
const start = Math.max(0, end - limit);
|
|
55434
55730
|
const page = events.slice(start, end);
|
|
55731
|
+
for (const event of page) {
|
|
55732
|
+
hydrateTranscriptEvent(store, sessionId, event);
|
|
55733
|
+
}
|
|
55435
55734
|
if (!json) {
|
|
55436
55735
|
console.log(`${data.metadata.id}: ${data.metadata.name}`);
|
|
55437
|
-
for (const
|
|
55438
|
-
console.log(`${
|
|
55736
|
+
for (const event of page) {
|
|
55737
|
+
console.log(`${event.logicalSeq} ${event.type}${event.role ? `:${event.role}` : ""} ${event.content ?? ""}`);
|
|
55439
55738
|
}
|
|
55440
55739
|
return;
|
|
55441
55740
|
}
|
|
@@ -55481,9 +55780,9 @@ async function renameSession(parsed) {
|
|
|
55481
55780
|
throw new CommandError("sessions.rename", "missing_positional", renderCommandUsage(SESSIONS_RENAME_SPEC), { usage: true });
|
|
55482
55781
|
}
|
|
55483
55782
|
const store = new FileSessionStore(getSessionsDir());
|
|
55484
|
-
|
|
55485
|
-
|
|
55486
|
-
const updated =
|
|
55783
|
+
loadSessionHead(store, sessionId, "sessions.rename");
|
|
55784
|
+
store.updateMetadata(sessionId, { name, nameSource: "manual", ...cwd ? { cwd } : {}, updatedAt: Date.now() });
|
|
55785
|
+
const updated = store.getMetadata(sessionId);
|
|
55487
55786
|
if (!updated) throw new CommandError("sessions.rename", "session_not_found", `Session not found after rename: ${sessionId}`);
|
|
55488
55787
|
if (json) {
|
|
55489
55788
|
printSuccessEnvelope("sessions.rename", { session: fullSessionRow(updated) });
|
|
@@ -55523,6 +55822,7 @@ async function forkSession(parsed) {
|
|
|
55523
55822
|
const store = new FileSessionStore(getSessionsDir());
|
|
55524
55823
|
const result = await forkStoredSession({
|
|
55525
55824
|
store,
|
|
55825
|
+
sessionsDir: getSessionsDir(),
|
|
55526
55826
|
sourceSessionId: sessionId,
|
|
55527
55827
|
sourceEntryId,
|
|
55528
55828
|
targetSessionId,
|
|
@@ -55542,10 +55842,19 @@ async function forkSession(parsed) {
|
|
|
55542
55842
|
}
|
|
55543
55843
|
console.log(`Forked ${sessionId} at ${sourceEntryId} into ${targetSessionId}.`);
|
|
55544
55844
|
}
|
|
55545
|
-
|
|
55546
|
-
const
|
|
55547
|
-
if (
|
|
55548
|
-
|
|
55845
|
+
function loadSessionHead(store, sessionId, kind) {
|
|
55846
|
+
const status = store.headStatus(sessionId);
|
|
55847
|
+
if (status === "legacy") {
|
|
55848
|
+
throw new CommandError(kind, "session_unsupported_format", `Session uses an unsupported old format: ${sessionId}`, {
|
|
55849
|
+
hint: "old-format sessions cannot be read by this version"
|
|
55850
|
+
});
|
|
55851
|
+
}
|
|
55852
|
+
if (status === "corrupt") {
|
|
55853
|
+
throw new CommandError(kind, "session_unrecoverable", `Session could not be recovered: ${sessionId}`);
|
|
55854
|
+
}
|
|
55855
|
+
const head = store.readHead(sessionId);
|
|
55856
|
+
if (!head) throw new CommandError(kind, "session_not_found", `Session not found: ${sessionId}`, { hint: "list sessions: pie sessions list --json" });
|
|
55857
|
+
return { metadata: head.metadata };
|
|
55549
55858
|
}
|
|
55550
55859
|
function fullSessionRow(metadata) {
|
|
55551
55860
|
return {
|
|
@@ -55599,31 +55908,30 @@ function cwdMatches(sessionCwd, requestedCwd) {
|
|
|
55599
55908
|
}
|
|
55600
55909
|
function realpathOrInput(value) {
|
|
55601
55910
|
try {
|
|
55602
|
-
return
|
|
55911
|
+
return fs8.realpathSync.native(value);
|
|
55603
55912
|
} catch {
|
|
55604
55913
|
return value;
|
|
55605
55914
|
}
|
|
55606
55915
|
}
|
|
55607
|
-
function activeTranscriptEvents(
|
|
55608
|
-
return entries.map((entry, index) => {
|
|
55609
|
-
const role = isRecord2(entry.message) && typeof entry.message.role === "string" ? entry.message.role : void 0;
|
|
55610
|
-
const turnId = isRecord2(entry.message) && typeof entry.message.turnId === "string" ? entry.message.turnId : void 0;
|
|
55611
|
-
return {
|
|
55612
|
-
logicalSeq: index + 1,
|
|
55613
|
-
entryId: entry.id,
|
|
55614
|
-
type: entry.type,
|
|
55615
|
-
timestamp: entry.timestamp,
|
|
55616
|
-
role,
|
|
55617
|
-
turnId,
|
|
55618
|
-
content: textFromMessage(entry.message),
|
|
55619
|
-
message: entry.message ? cloneJson2(entry.message) : void 0
|
|
55620
|
-
};
|
|
55621
|
-
});
|
|
55622
|
-
}
|
|
55623
|
-
function activePathEntries(data) {
|
|
55624
|
-
const activeEntryId = data.metadata.activeEntryId;
|
|
55916
|
+
async function activeTranscriptEvents(store, sessionId, activeEntryId) {
|
|
55625
55917
|
if (!activeEntryId) return [];
|
|
55626
|
-
|
|
55918
|
+
const summaries = store.getPathSummaries(sessionId, activeEntryId);
|
|
55919
|
+
return summaries.map((summary, index) => ({
|
|
55920
|
+
logicalSeq: index + 1,
|
|
55921
|
+
seq: summary.seq,
|
|
55922
|
+
entryId: summary.id,
|
|
55923
|
+
type: summary.type,
|
|
55924
|
+
timestamp: summary.timestamp,
|
|
55925
|
+
role: summary.role,
|
|
55926
|
+
content: summary.preview || void 0
|
|
55927
|
+
}));
|
|
55928
|
+
}
|
|
55929
|
+
function hydrateTranscriptEvent(store, sessionId, event) {
|
|
55930
|
+
const entry = store.readEntry(sessionId, event.entryId);
|
|
55931
|
+
if (!entry) return;
|
|
55932
|
+
event.turnId = isRecord2(entry.message) && typeof entry.message.turnId === "string" ? entry.message.turnId : void 0;
|
|
55933
|
+
event.content = textFromMessage(entry.message);
|
|
55934
|
+
event.message = entry.message ? cloneJson(entry.message) : void 0;
|
|
55627
55935
|
}
|
|
55628
55936
|
function resolveBeforeCursor(events, cursor) {
|
|
55629
55937
|
if (!cursor) return events.length;
|
|
@@ -55634,7 +55942,7 @@ function resolveBeforeCursor(events, cursor) {
|
|
|
55634
55942
|
const index = events.findIndex((event) => event.entryId === cursor);
|
|
55635
55943
|
return index >= 0 ? index : events.length;
|
|
55636
55944
|
}
|
|
55637
|
-
function
|
|
55945
|
+
function cloneJson(value) {
|
|
55638
55946
|
return JSON.parse(JSON.stringify(value));
|
|
55639
55947
|
}
|
|
55640
55948
|
function listCursorQueryKey(input) {
|
|
@@ -55671,9 +55979,9 @@ function isRecord2(value) {
|
|
|
55671
55979
|
}
|
|
55672
55980
|
|
|
55673
55981
|
// src/extensions/loader.ts
|
|
55674
|
-
import * as
|
|
55982
|
+
import * as fs9 from "node:fs";
|
|
55675
55983
|
import * as os2 from "os";
|
|
55676
|
-
import * as
|
|
55984
|
+
import * as path8 from "path";
|
|
55677
55985
|
import { pathToFileURL } from "node:url";
|
|
55678
55986
|
|
|
55679
55987
|
// src/command-tree.ts
|
|
@@ -55686,19 +55994,19 @@ var CommandTree = class {
|
|
|
55686
55994
|
* register(["session", "new"], { description, handler })
|
|
55687
55995
|
* register(["tools", "subagent", "spawn", "local"], { description, handler })
|
|
55688
55996
|
*/
|
|
55689
|
-
register(
|
|
55690
|
-
if (
|
|
55997
|
+
register(path34, info) {
|
|
55998
|
+
if (path34.length === 0) {
|
|
55691
55999
|
throw new Error("Command path cannot be empty");
|
|
55692
56000
|
}
|
|
55693
56001
|
let current = this.root;
|
|
55694
56002
|
const fullPath = [];
|
|
55695
|
-
for (let i = 0; i <
|
|
55696
|
-
const segment =
|
|
56003
|
+
for (let i = 0; i < path34.length; i++) {
|
|
56004
|
+
const segment = path34[i];
|
|
55697
56005
|
fullPath.push(segment);
|
|
55698
56006
|
if (!current.children) {
|
|
55699
56007
|
current.children = [];
|
|
55700
56008
|
}
|
|
55701
|
-
const isLast = i ===
|
|
56009
|
+
const isLast = i === path34.length - 1;
|
|
55702
56010
|
let node = current.children.find((n) => n.name === segment);
|
|
55703
56011
|
if (!node) {
|
|
55704
56012
|
node = {
|
|
@@ -55728,31 +56036,31 @@ var CommandTree = class {
|
|
|
55728
56036
|
/**
|
|
55729
56037
|
* Find a node by path
|
|
55730
56038
|
*/
|
|
55731
|
-
find(
|
|
55732
|
-
if (
|
|
56039
|
+
find(path34) {
|
|
56040
|
+
if (path34.length === 0) {
|
|
55733
56041
|
return this.root;
|
|
55734
56042
|
}
|
|
55735
|
-
const key =
|
|
56043
|
+
const key = path34.join("/");
|
|
55736
56044
|
return this.pathCache.get(key) || null;
|
|
55737
56045
|
}
|
|
55738
56046
|
/**
|
|
55739
56047
|
* Get children of a path
|
|
55740
56048
|
*/
|
|
55741
|
-
getChildren(
|
|
55742
|
-
const node = this.find(
|
|
56049
|
+
getChildren(path34) {
|
|
56050
|
+
const node = this.find(path34);
|
|
55743
56051
|
return (node?.children || []).filter((child) => !child.hidden);
|
|
55744
56052
|
}
|
|
55745
56053
|
/**
|
|
55746
56054
|
* Check if a path exists (as category or command)
|
|
55747
56055
|
*/
|
|
55748
|
-
exists(
|
|
55749
|
-
return this.find(
|
|
56056
|
+
exists(path34) {
|
|
56057
|
+
return this.find(path34) !== null;
|
|
55750
56058
|
}
|
|
55751
56059
|
/**
|
|
55752
56060
|
* Check if path is a category (has children)
|
|
55753
56061
|
*/
|
|
55754
|
-
isCategory(
|
|
55755
|
-
const node = this.find(
|
|
56062
|
+
isCategory(path34) {
|
|
56063
|
+
const node = this.find(path34);
|
|
55756
56064
|
return node?.isCategory || false;
|
|
55757
56065
|
}
|
|
55758
56066
|
/**
|
|
@@ -55831,8 +56139,8 @@ var CommandTree = class {
|
|
|
55831
56139
|
* Supports dot notation: "tools.subagent.spawn.local"
|
|
55832
56140
|
*/
|
|
55833
56141
|
registerFromPath(pathStr, info) {
|
|
55834
|
-
const
|
|
55835
|
-
this.register(
|
|
56142
|
+
const path34 = pathStr.split(/[./]/).filter(Boolean);
|
|
56143
|
+
this.register(path34, info);
|
|
55836
56144
|
}
|
|
55837
56145
|
};
|
|
55838
56146
|
var commandTree = new CommandTree();
|
|
@@ -55938,6 +56246,9 @@ function createExtensionContext(extension, cwd, uiContext, abortFn, isIdleFn, ha
|
|
|
55938
56246
|
resolveModelClass(modelClass) {
|
|
55939
56247
|
return actions?.resolveModelClass?.(modelClass) ?? {};
|
|
55940
56248
|
},
|
|
56249
|
+
resolveModelRef(modelRef) {
|
|
56250
|
+
return actions?.resolveModelRef?.(modelRef) ?? {};
|
|
56251
|
+
},
|
|
55941
56252
|
getMessages() {
|
|
55942
56253
|
return actions?.getMessages?.() ?? [];
|
|
55943
56254
|
},
|
|
@@ -55995,19 +56306,19 @@ function createExtension(extensionPath, resolvedPath, identity, source) {
|
|
|
55995
56306
|
}
|
|
55996
56307
|
function expandPath(p) {
|
|
55997
56308
|
if (p.startsWith("~/")) {
|
|
55998
|
-
return
|
|
56309
|
+
return path8.join(os2.homedir(), p.slice(2));
|
|
55999
56310
|
}
|
|
56000
56311
|
if (p.startsWith("~")) {
|
|
56001
|
-
return
|
|
56312
|
+
return path8.join(os2.homedir(), p.slice(1));
|
|
56002
56313
|
}
|
|
56003
56314
|
return p;
|
|
56004
56315
|
}
|
|
56005
56316
|
function resolvePath(extPath, cwd) {
|
|
56006
56317
|
const expanded = expandPath(extPath);
|
|
56007
|
-
if (
|
|
56318
|
+
if (path8.isAbsolute(expanded)) {
|
|
56008
56319
|
return expanded;
|
|
56009
56320
|
}
|
|
56010
|
-
return
|
|
56321
|
+
return path8.resolve(cwd, expanded);
|
|
56011
56322
|
}
|
|
56012
56323
|
async function loadExtensionModule(extensionPath) {
|
|
56013
56324
|
try {
|
|
@@ -56027,14 +56338,14 @@ function normalizeExtensionImportPath(extensionPath) {
|
|
|
56027
56338
|
if (/^[a-zA-Z]:[\\/]/.test(extensionPath)) {
|
|
56028
56339
|
return `file:///${extensionPath.replace(/\\/g, "/")}`;
|
|
56029
56340
|
}
|
|
56030
|
-
if (
|
|
56341
|
+
if (path8.isAbsolute(extensionPath)) {
|
|
56031
56342
|
return pathToFileURL(extensionPath).href;
|
|
56032
56343
|
}
|
|
56033
56344
|
return extensionPath;
|
|
56034
56345
|
}
|
|
56035
56346
|
async function loadExtension(extensionPath, cwd, uiContext, abortFn, isIdleFn, hasUI, actions, discovered) {
|
|
56036
56347
|
const resolvedPath = resolvePath(extensionPath, cwd);
|
|
56037
|
-
if (!
|
|
56348
|
+
if (!fs9.existsSync(resolvedPath)) {
|
|
56038
56349
|
return { extension: null, error: `Extension not found: ${extensionPath}` };
|
|
56039
56350
|
}
|
|
56040
56351
|
try {
|
|
@@ -56060,17 +56371,17 @@ async function loadExtension(extensionPath, cwd, uiContext, abortFn, isIdleFn, h
|
|
|
56060
56371
|
}
|
|
56061
56372
|
}
|
|
56062
56373
|
function discoverExtensionsInDir(dir, source) {
|
|
56063
|
-
if (!
|
|
56374
|
+
if (!fs9.existsSync(dir)) {
|
|
56064
56375
|
return [];
|
|
56065
56376
|
}
|
|
56066
56377
|
const discovered = [];
|
|
56067
56378
|
try {
|
|
56068
|
-
const entries =
|
|
56379
|
+
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
56069
56380
|
for (const entry of entries) {
|
|
56070
56381
|
if (entry.name.endsWith(".disabled")) {
|
|
56071
56382
|
continue;
|
|
56072
56383
|
}
|
|
56073
|
-
const entryPath =
|
|
56384
|
+
const entryPath = path8.join(dir, entry.name);
|
|
56074
56385
|
if (entry.isFile() && (entry.name.endsWith(".cjs") || entry.name.endsWith(".js") || entry.name.endsWith(".ts"))) {
|
|
56075
56386
|
discovered.push({
|
|
56076
56387
|
entryPath,
|
|
@@ -56080,13 +56391,13 @@ function discoverExtensionsInDir(dir, source) {
|
|
|
56080
56391
|
continue;
|
|
56081
56392
|
}
|
|
56082
56393
|
if (entry.isDirectory()) {
|
|
56083
|
-
const packageJsonPath =
|
|
56394
|
+
const packageJsonPath = path8.join(entryPath, "package.json");
|
|
56084
56395
|
let packageIdentity;
|
|
56085
56396
|
let packageDescription;
|
|
56086
56397
|
let packageMainPath;
|
|
56087
|
-
if (
|
|
56398
|
+
if (fs9.existsSync(packageJsonPath)) {
|
|
56088
56399
|
try {
|
|
56089
|
-
const pkg = JSON.parse(
|
|
56400
|
+
const pkg = JSON.parse(fs9.readFileSync(packageJsonPath, "utf-8"));
|
|
56090
56401
|
const manifest = pkg.pie && typeof pkg.pie === "object" && !Array.isArray(pkg.pie) ? pkg.pie : void 0;
|
|
56091
56402
|
packageIdentity = resolveExtensionIdentity({
|
|
56092
56403
|
pieName: typeof manifest?.name === "string" ? manifest.name : void 0,
|
|
@@ -56095,8 +56406,8 @@ function discoverExtensionsInDir(dir, source) {
|
|
|
56095
56406
|
});
|
|
56096
56407
|
packageDescription = typeof pkg.description === "string" ? pkg.description : void 0;
|
|
56097
56408
|
if (typeof manifest?.main === "string" && manifest.main.trim().length > 0) {
|
|
56098
|
-
const candidate =
|
|
56099
|
-
if (
|
|
56409
|
+
const candidate = path8.resolve(entryPath, manifest.main);
|
|
56410
|
+
if (fs9.existsSync(candidate)) {
|
|
56100
56411
|
packageMainPath = candidate;
|
|
56101
56412
|
}
|
|
56102
56413
|
}
|
|
@@ -56112,8 +56423,8 @@ function discoverExtensionsInDir(dir, source) {
|
|
|
56112
56423
|
});
|
|
56113
56424
|
continue;
|
|
56114
56425
|
}
|
|
56115
|
-
const indexCjs =
|
|
56116
|
-
if (
|
|
56426
|
+
const indexCjs = path8.join(entryPath, "index.cjs");
|
|
56427
|
+
if (fs9.existsSync(indexCjs)) {
|
|
56117
56428
|
discovered.push({
|
|
56118
56429
|
entryPath: indexCjs,
|
|
56119
56430
|
source,
|
|
@@ -56122,8 +56433,8 @@ function discoverExtensionsInDir(dir, source) {
|
|
|
56122
56433
|
});
|
|
56123
56434
|
continue;
|
|
56124
56435
|
}
|
|
56125
|
-
const indexJs =
|
|
56126
|
-
if (
|
|
56436
|
+
const indexJs = path8.join(entryPath, "index.js");
|
|
56437
|
+
if (fs9.existsSync(indexJs)) {
|
|
56127
56438
|
discovered.push({
|
|
56128
56439
|
entryPath: indexJs,
|
|
56129
56440
|
source,
|
|
@@ -56132,8 +56443,8 @@ function discoverExtensionsInDir(dir, source) {
|
|
|
56132
56443
|
});
|
|
56133
56444
|
continue;
|
|
56134
56445
|
}
|
|
56135
|
-
const indexTs =
|
|
56136
|
-
if (
|
|
56446
|
+
const indexTs = path8.join(entryPath, "index.ts");
|
|
56447
|
+
if (fs9.existsSync(indexTs)) {
|
|
56137
56448
|
discovered.push({
|
|
56138
56449
|
entryPath: indexTs,
|
|
56139
56450
|
source,
|
|
@@ -56154,21 +56465,21 @@ function collectDiscoveredExtensions(configuredPaths, cwd, options) {
|
|
|
56154
56465
|
const errors = [];
|
|
56155
56466
|
if (!options?.noExtensions) {
|
|
56156
56467
|
if (!options?.noBuiltinExtensions) {
|
|
56157
|
-
const builtinExtDir =
|
|
56468
|
+
const builtinExtDir = path8.join(getBuiltinDir(), "extensions");
|
|
56158
56469
|
discovered.push(...discoverExtensionsInDir(builtinExtDir, "builtin"));
|
|
56159
56470
|
}
|
|
56160
|
-
const globalExtDir =
|
|
56471
|
+
const globalExtDir = path8.join(os2.homedir(), ".pie", "extensions");
|
|
56161
56472
|
discovered.push(...discoverExtensionsInDir(globalExtDir, "global"));
|
|
56162
|
-
const localExtDir =
|
|
56473
|
+
const localExtDir = path8.join(cwd, ".pie", "extensions");
|
|
56163
56474
|
discovered.push(...discoverExtensionsInDir(localExtDir, "project"));
|
|
56164
56475
|
}
|
|
56165
56476
|
for (const p of configuredPaths) {
|
|
56166
56477
|
const resolved = resolvePath(p, cwd);
|
|
56167
|
-
if (!
|
|
56478
|
+
if (!fs9.existsSync(resolved)) {
|
|
56168
56479
|
errors.push({ path: p, error: `Extension path not found: ${p}` });
|
|
56169
56480
|
continue;
|
|
56170
56481
|
}
|
|
56171
|
-
if (!
|
|
56482
|
+
if (!fs9.statSync(resolved).isDirectory()) {
|
|
56172
56483
|
errors.push({ path: p, error: `Extension path must be a directory: ${p}` });
|
|
56173
56484
|
continue;
|
|
56174
56485
|
}
|
|
@@ -57023,8 +57334,8 @@ function wrapSingleLine(line, width) {
|
|
|
57023
57334
|
if (!line) {
|
|
57024
57335
|
return [""];
|
|
57025
57336
|
}
|
|
57026
|
-
const
|
|
57027
|
-
if (
|
|
57337
|
+
const visibleLength = visibleWidth(line);
|
|
57338
|
+
if (visibleLength <= width) {
|
|
57028
57339
|
return [line];
|
|
57029
57340
|
}
|
|
57030
57341
|
const wrapped = [];
|
|
@@ -58056,9 +58367,9 @@ var KillRing = class {
|
|
|
58056
58367
|
};
|
|
58057
58368
|
|
|
58058
58369
|
// ../../packages/tui/src/tui.ts
|
|
58059
|
-
import * as
|
|
58370
|
+
import * as fs10 from "node:fs";
|
|
58060
58371
|
import * as os3 from "node:os";
|
|
58061
|
-
import * as
|
|
58372
|
+
import * as path9 from "node:path";
|
|
58062
58373
|
|
|
58063
58374
|
// ../../packages/tui/src/terminal-image.ts
|
|
58064
58375
|
var cachedCapabilities = null;
|
|
@@ -58738,11 +59049,11 @@ var TUI = class extends Container {
|
|
|
58738
59049
|
const debugRedraw = process.env.PIE_DEBUG_REDRAW === "1";
|
|
58739
59050
|
const logRedraw = (reason) => {
|
|
58740
59051
|
if (!debugRedraw) return;
|
|
58741
|
-
const logPath =
|
|
58742
|
-
|
|
59052
|
+
const logPath = path9.join(os3.homedir(), ".pie", "logs", "pie-cli.log");
|
|
59053
|
+
fs10.mkdirSync(path9.dirname(logPath), { recursive: true });
|
|
58743
59054
|
const msg = `[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] [ui] fullRender: ${reason} (prev=${this.previousLines.length}, new=${newLines.length}, height=${height})
|
|
58744
59055
|
`;
|
|
58745
|
-
|
|
59056
|
+
fs10.appendFileSync(logPath, msg);
|
|
58746
59057
|
};
|
|
58747
59058
|
if (this.previousLines.length === 0 && !widthChanged) {
|
|
58748
59059
|
logRedraw("first render");
|
|
@@ -58835,7 +59146,7 @@ var TUI = class extends Container {
|
|
|
58835
59146
|
const line = newLines[i];
|
|
58836
59147
|
const isImage = isImageLine(line);
|
|
58837
59148
|
if (!isImage && visibleWidth(line) > width) {
|
|
58838
|
-
const crashLogPath =
|
|
59149
|
+
const crashLogPath = path9.join(os3.homedir(), ".pie", "pie-crash.log");
|
|
58839
59150
|
const crashData = [
|
|
58840
59151
|
`Crash at ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
58841
59152
|
`Terminal width: ${width}`,
|
|
@@ -58845,8 +59156,8 @@ var TUI = class extends Container {
|
|
|
58845
59156
|
...newLines.map((l, idx) => `[${idx}] (w=${visibleWidth(l)}) ${l}`),
|
|
58846
59157
|
""
|
|
58847
59158
|
].join("\n");
|
|
58848
|
-
|
|
58849
|
-
|
|
59159
|
+
fs10.mkdirSync(path9.dirname(crashLogPath), { recursive: true });
|
|
59160
|
+
fs10.writeFileSync(crashLogPath, crashData);
|
|
58850
59161
|
this.stop();
|
|
58851
59162
|
const errorMsg = [
|
|
58852
59163
|
`Rendered line ${i} exceeds terminal width (${visibleWidth(line)} > ${width}).`,
|
|
@@ -58876,8 +59187,8 @@ var TUI = class extends Container {
|
|
|
58876
59187
|
buffer += "\x1B[?2026l";
|
|
58877
59188
|
if (process.env.PIE_TUI_DEBUG === "1") {
|
|
58878
59189
|
const debugDir = "/tmp/tui";
|
|
58879
|
-
|
|
58880
|
-
const debugPath =
|
|
59190
|
+
fs10.mkdirSync(debugDir, { recursive: true });
|
|
59191
|
+
const debugPath = path9.join(debugDir, `render-${Date.now()}-${Math.random().toString(36).slice(2)}.log`);
|
|
58881
59192
|
const debugData = [
|
|
58882
59193
|
`firstChanged: ${firstChanged}`,
|
|
58883
59194
|
`viewportTop: ${viewportTop}`,
|
|
@@ -58900,7 +59211,7 @@ var TUI = class extends Container {
|
|
|
58900
59211
|
"=== buffer ===",
|
|
58901
59212
|
JSON.stringify(buffer)
|
|
58902
59213
|
].join("\n");
|
|
58903
|
-
|
|
59214
|
+
fs10.writeFileSync(debugPath, debugData);
|
|
58904
59215
|
}
|
|
58905
59216
|
this.terminal.write(buffer);
|
|
58906
59217
|
this.cursorRow = Math.max(0, newLines.length - 1);
|
|
@@ -63189,7 +63500,7 @@ var StdinBuffer = class extends EventEmitter {
|
|
|
63189
63500
|
};
|
|
63190
63501
|
|
|
63191
63502
|
// ../../packages/tui/src/terminal.ts
|
|
63192
|
-
import * as
|
|
63503
|
+
import * as fs11 from "node:fs";
|
|
63193
63504
|
import koffi from "koffi";
|
|
63194
63505
|
var ProcessTerminal = class {
|
|
63195
63506
|
wasRaw = false;
|
|
@@ -63352,7 +63663,7 @@ var ProcessTerminal = class {
|
|
|
63352
63663
|
process.stdout.write(data);
|
|
63353
63664
|
if (this.writeLogPath) {
|
|
63354
63665
|
try {
|
|
63355
|
-
|
|
63666
|
+
fs11.appendFileSync(this.writeLogPath, data, { encoding: "utf8" });
|
|
63356
63667
|
} catch {
|
|
63357
63668
|
}
|
|
63358
63669
|
}
|
|
@@ -63617,6 +63928,7 @@ var ExtensionRunner = class {
|
|
|
63617
63928
|
getAllTools: () => runner.actions.getAllTools(),
|
|
63618
63929
|
getRuntimeTools: () => runner.actions.getRuntimeTools(),
|
|
63619
63930
|
resolveModelClass: (modelClass) => runner.actions.resolveModelClass?.(modelClass) ?? {},
|
|
63931
|
+
resolveModelRef: (modelRef) => runner.actions.resolveModelRef?.(modelRef) ?? {},
|
|
63620
63932
|
getMessages: () => runner.actions.getMessages(),
|
|
63621
63933
|
getSessionMetadata: () => runner.actions.getSessionMetadata(),
|
|
63622
63934
|
setSessionMetadata: (key, value) => runner.actions.setSessionMetadata(key, value),
|
|
@@ -64197,8 +64509,8 @@ function restoreInteractiveSessionState(options) {
|
|
|
64197
64509
|
}
|
|
64198
64510
|
|
|
64199
64511
|
// src/keybindings.ts
|
|
64200
|
-
import { existsSync as
|
|
64201
|
-
import { join as
|
|
64512
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
|
|
64513
|
+
import { join as join8 } from "path";
|
|
64202
64514
|
var DEFAULT_APP_KEYBINDINGS = {
|
|
64203
64515
|
interrupt: "escape",
|
|
64204
64516
|
clear: "ctrl+c",
|
|
@@ -64262,7 +64574,7 @@ var KeybindingsManager = class _KeybindingsManager {
|
|
|
64262
64574
|
* Create from config file and set up editor keybindings.
|
|
64263
64575
|
*/
|
|
64264
64576
|
static create(agentDir = getAgentDir()) {
|
|
64265
|
-
const configPath =
|
|
64577
|
+
const configPath = join8(agentDir, "keybindings.json");
|
|
64266
64578
|
const config = _KeybindingsManager.loadFromFile(configPath);
|
|
64267
64579
|
const manager = new _KeybindingsManager(config);
|
|
64268
64580
|
const editorConfig = {};
|
|
@@ -64280,10 +64592,10 @@ var KeybindingsManager = class _KeybindingsManager {
|
|
|
64280
64592
|
static inMemory(config = {}) {
|
|
64281
64593
|
return new _KeybindingsManager(config);
|
|
64282
64594
|
}
|
|
64283
|
-
static loadFromFile(
|
|
64284
|
-
if (!
|
|
64595
|
+
static loadFromFile(path34) {
|
|
64596
|
+
if (!existsSync9(path34)) return {};
|
|
64285
64597
|
try {
|
|
64286
|
-
return JSON.parse(
|
|
64598
|
+
return JSON.parse(readFileSync8(path34, "utf-8"));
|
|
64287
64599
|
} catch {
|
|
64288
64600
|
return {};
|
|
64289
64601
|
}
|
|
@@ -64332,19 +64644,19 @@ var KeybindingsManager = class _KeybindingsManager {
|
|
|
64332
64644
|
};
|
|
64333
64645
|
|
|
64334
64646
|
// src/project-knowledge.ts
|
|
64335
|
-
import
|
|
64336
|
-
import
|
|
64647
|
+
import fs12 from "node:fs";
|
|
64648
|
+
import path10 from "node:path";
|
|
64337
64649
|
function collectAncestorAgentsFiles(cwd) {
|
|
64338
|
-
const resolvedCwd =
|
|
64650
|
+
const resolvedCwd = path10.resolve(cwd || process.cwd());
|
|
64339
64651
|
const projectRoot = resolveCliProjectRoot(resolvedCwd);
|
|
64340
64652
|
const candidates = [];
|
|
64341
64653
|
let current = resolvedCwd;
|
|
64342
64654
|
while (true) {
|
|
64343
|
-
candidates.unshift(
|
|
64655
|
+
candidates.unshift(path10.join(current, AGENTS_CONTEXT_FILE_NAME));
|
|
64344
64656
|
if (current === projectRoot) {
|
|
64345
64657
|
break;
|
|
64346
64658
|
}
|
|
64347
|
-
const parent =
|
|
64659
|
+
const parent = path10.dirname(current);
|
|
64348
64660
|
if (parent === current) {
|
|
64349
64661
|
break;
|
|
64350
64662
|
}
|
|
@@ -64352,13 +64664,13 @@ function collectAncestorAgentsFiles(cwd) {
|
|
|
64352
64664
|
}
|
|
64353
64665
|
const files = [];
|
|
64354
64666
|
for (const candidate of candidates) {
|
|
64355
|
-
if (!
|
|
64667
|
+
if (!fs12.existsSync(candidate)) {
|
|
64356
64668
|
continue;
|
|
64357
64669
|
}
|
|
64358
64670
|
try {
|
|
64359
64671
|
files.push({
|
|
64360
|
-
path:
|
|
64361
|
-
content:
|
|
64672
|
+
path: path10.relative(resolvedCwd, candidate) || AGENTS_CONTEXT_FILE_NAME,
|
|
64673
|
+
content: fs12.readFileSync(candidate, "utf-8")
|
|
64362
64674
|
});
|
|
64363
64675
|
} catch {
|
|
64364
64676
|
}
|
|
@@ -64370,14 +64682,14 @@ function buildCliProjectContextSection(cwd) {
|
|
|
64370
64682
|
}
|
|
64371
64683
|
|
|
64372
64684
|
// src/file-access-context.ts
|
|
64373
|
-
import * as
|
|
64685
|
+
import * as path11 from "node:path";
|
|
64374
64686
|
function uniqueNormalizedPaths(paths) {
|
|
64375
64687
|
const seen = /* @__PURE__ */ new Set();
|
|
64376
64688
|
const result = [];
|
|
64377
64689
|
for (const entry of paths) {
|
|
64378
64690
|
const trimmed = String(entry || "").trim();
|
|
64379
64691
|
if (!trimmed) continue;
|
|
64380
|
-
const normalized =
|
|
64692
|
+
const normalized = path11.normalize(trimmed);
|
|
64381
64693
|
if (seen.has(normalized)) continue;
|
|
64382
64694
|
seen.add(normalized);
|
|
64383
64695
|
result.push(normalized);
|
|
@@ -64396,8 +64708,8 @@ function buildCliFileAccessOptions(params) {
|
|
|
64396
64708
|
}
|
|
64397
64709
|
|
|
64398
64710
|
// src/theme/theme.ts
|
|
64399
|
-
import * as
|
|
64400
|
-
import * as
|
|
64711
|
+
import * as fs13 from "node:fs";
|
|
64712
|
+
import * as path12 from "node:path";
|
|
64401
64713
|
|
|
64402
64714
|
// ../../node_modules/@sinclair/typebox/build/esm/compiler/compiler.mjs
|
|
64403
64715
|
var TypeCheck = class {
|
|
@@ -65284,11 +65596,11 @@ var BUILTIN_THEMES;
|
|
|
65284
65596
|
function getBuiltinThemes() {
|
|
65285
65597
|
if (!BUILTIN_THEMES) {
|
|
65286
65598
|
const themesDir = getThemesDir();
|
|
65287
|
-
const darkPath =
|
|
65288
|
-
const lightPath =
|
|
65599
|
+
const darkPath = path12.join(themesDir, "dark.json");
|
|
65600
|
+
const lightPath = path12.join(themesDir, "light.json");
|
|
65289
65601
|
BUILTIN_THEMES = {
|
|
65290
|
-
dark: JSON.parse(
|
|
65291
|
-
light: JSON.parse(
|
|
65602
|
+
dark: JSON.parse(fs13.readFileSync(darkPath, "utf-8")),
|
|
65603
|
+
light: JSON.parse(fs13.readFileSync(lightPath, "utf-8"))
|
|
65292
65604
|
};
|
|
65293
65605
|
}
|
|
65294
65606
|
return BUILTIN_THEMES;
|
|
@@ -65296,8 +65608,8 @@ function getBuiltinThemes() {
|
|
|
65296
65608
|
function getAvailableThemes() {
|
|
65297
65609
|
const themes = new Set(Object.keys(getBuiltinThemes()));
|
|
65298
65610
|
const customThemesDir = getCustomThemesDir();
|
|
65299
|
-
if (
|
|
65300
|
-
const files =
|
|
65611
|
+
if (fs13.existsSync(customThemesDir)) {
|
|
65612
|
+
const files = fs13.readdirSync(customThemesDir);
|
|
65301
65613
|
for (const file of files) {
|
|
65302
65614
|
if (file.endsWith(".json")) {
|
|
65303
65615
|
themes.add(file.slice(0, -5));
|
|
@@ -65358,18 +65670,18 @@ function loadThemeJson(name) {
|
|
|
65358
65670
|
}
|
|
65359
65671
|
const registeredTheme = registeredThemes.get(name);
|
|
65360
65672
|
if (registeredTheme?.sourcePath) {
|
|
65361
|
-
const content2 =
|
|
65673
|
+
const content2 = fs13.readFileSync(registeredTheme.sourcePath, "utf-8");
|
|
65362
65674
|
return parseThemeJsonContent(registeredTheme.sourcePath, content2);
|
|
65363
65675
|
}
|
|
65364
65676
|
if (registeredTheme) {
|
|
65365
65677
|
throw new Error(`Theme "${name}" does not have a source path for export`);
|
|
65366
65678
|
}
|
|
65367
65679
|
const customThemesDir = getCustomThemesDir();
|
|
65368
|
-
const themePath =
|
|
65369
|
-
if (!
|
|
65680
|
+
const themePath = path12.join(customThemesDir, `${name}.json`);
|
|
65681
|
+
if (!fs13.existsSync(themePath)) {
|
|
65370
65682
|
throw new Error(`Theme not found: ${name}`);
|
|
65371
65683
|
}
|
|
65372
|
-
const content =
|
|
65684
|
+
const content = fs13.readFileSync(themePath, "utf-8");
|
|
65373
65685
|
return parseThemeJsonContent(name, content);
|
|
65374
65686
|
}
|
|
65375
65687
|
function createTheme(themeJson, mode, sourcePath) {
|
|
@@ -65482,12 +65794,12 @@ function startThemeWatcher() {
|
|
|
65482
65794
|
return;
|
|
65483
65795
|
}
|
|
65484
65796
|
const customThemesDir = getCustomThemesDir();
|
|
65485
|
-
const themeFile =
|
|
65486
|
-
if (!
|
|
65797
|
+
const themeFile = path12.join(customThemesDir, `${currentThemeName}.json`);
|
|
65798
|
+
if (!fs13.existsSync(themeFile)) {
|
|
65487
65799
|
return;
|
|
65488
65800
|
}
|
|
65489
65801
|
try {
|
|
65490
|
-
themeWatcher =
|
|
65802
|
+
themeWatcher = fs13.watch(themeFile, (eventType) => {
|
|
65491
65803
|
if (eventType === "change") {
|
|
65492
65804
|
setTimeout(() => {
|
|
65493
65805
|
try {
|
|
@@ -65500,7 +65812,7 @@ function startThemeWatcher() {
|
|
|
65500
65812
|
}, 100);
|
|
65501
65813
|
} else if (eventType === "rename") {
|
|
65502
65814
|
setTimeout(() => {
|
|
65503
|
-
if (!
|
|
65815
|
+
if (!fs13.existsSync(themeFile)) {
|
|
65504
65816
|
currentThemeName = "dark";
|
|
65505
65817
|
setGlobalTheme(loadTheme("dark"));
|
|
65506
65818
|
if (themeWatcher) {
|
|
@@ -65681,9 +65993,9 @@ function getSettingsListTheme() {
|
|
|
65681
65993
|
|
|
65682
65994
|
// src/skills/loader.ts
|
|
65683
65995
|
var import_yaml = __toESM(require_dist2(), 1);
|
|
65684
|
-
import * as
|
|
65996
|
+
import * as fs14 from "fs";
|
|
65685
65997
|
import * as os4 from "os";
|
|
65686
|
-
import * as
|
|
65998
|
+
import * as path13 from "path";
|
|
65687
65999
|
function parseSkillDescription(content) {
|
|
65688
66000
|
content = content.replace(/^\uFEFF/, "").replace(/\r\n/g, "\n");
|
|
65689
66001
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---(?:\n|$)/);
|
|
@@ -65707,19 +66019,19 @@ function parseSkillDescription(content) {
|
|
|
65707
66019
|
}
|
|
65708
66020
|
var USER_CONTROLLED_SOURCES = /* @__PURE__ */ new Set(["user-agents", "user"]);
|
|
65709
66021
|
function pathIsInside(child, parent) {
|
|
65710
|
-
const relative3 =
|
|
65711
|
-
return relative3 !== "" && !relative3.startsWith(`..${
|
|
66022
|
+
const relative3 = path13.relative(parent, child);
|
|
66023
|
+
return relative3 !== "" && !relative3.startsWith(`..${path13.sep}`) && relative3 !== ".." && !path13.isAbsolute(relative3);
|
|
65712
66024
|
}
|
|
65713
66025
|
function resolveSkillSymlink(fullPath, dir, source) {
|
|
65714
66026
|
let target;
|
|
65715
66027
|
let stats;
|
|
65716
66028
|
try {
|
|
65717
|
-
target =
|
|
65718
|
-
stats =
|
|
66029
|
+
target = fs14.realpathSync(fullPath);
|
|
66030
|
+
stats = fs14.statSync(target);
|
|
65719
66031
|
} catch {
|
|
65720
66032
|
return { error: `broken skill symlink: ${fullPath}` };
|
|
65721
66033
|
}
|
|
65722
|
-
if (!USER_CONTROLLED_SOURCES.has(source) && !pathIsInside(target,
|
|
66034
|
+
if (!USER_CONTROLLED_SOURCES.has(source) && !pathIsInside(target, fs14.realpathSync(dir))) {
|
|
65723
66035
|
return { error: `skill symlink escapes the "${source}" layer (not loaded): ${fullPath} -> ${target}` };
|
|
65724
66036
|
}
|
|
65725
66037
|
return { target, isDirectory: stats.isDirectory(), isFile: stats.isFile() };
|
|
@@ -65727,13 +66039,13 @@ function resolveSkillSymlink(fullPath, dir, source) {
|
|
|
65727
66039
|
function loadSkillsFromDir(dir, source) {
|
|
65728
66040
|
const skills = [];
|
|
65729
66041
|
const diagnostics = [];
|
|
65730
|
-
if (!
|
|
66042
|
+
if (!fs14.existsSync(dir)) {
|
|
65731
66043
|
return { skills, diagnostics };
|
|
65732
66044
|
}
|
|
65733
|
-
const entries =
|
|
66045
|
+
const entries = fs14.readdirSync(dir, { withFileTypes: true });
|
|
65734
66046
|
for (const entry of entries) {
|
|
65735
66047
|
if (entry.name.startsWith(".")) continue;
|
|
65736
|
-
const fullPath =
|
|
66048
|
+
const fullPath = path13.join(dir, entry.name);
|
|
65737
66049
|
let entryPath = fullPath;
|
|
65738
66050
|
let entryIsDirectory = entry.isDirectory();
|
|
65739
66051
|
let entryIsFile = entry.isFile();
|
|
@@ -65748,10 +66060,10 @@ function loadSkillsFromDir(dir, source) {
|
|
|
65748
66060
|
entryIsFile = resolved.isFile;
|
|
65749
66061
|
}
|
|
65750
66062
|
if (entryIsDirectory) {
|
|
65751
|
-
const skillMdPath =
|
|
65752
|
-
if (
|
|
66063
|
+
const skillMdPath = path13.join(entryPath, "SKILL.md");
|
|
66064
|
+
if (fs14.existsSync(skillMdPath)) {
|
|
65753
66065
|
try {
|
|
65754
|
-
const content =
|
|
66066
|
+
const content = fs14.readFileSync(skillMdPath, "utf-8");
|
|
65755
66067
|
const description = parseSkillDescription(content);
|
|
65756
66068
|
skills.push({
|
|
65757
66069
|
name: entry.name,
|
|
@@ -65772,7 +66084,7 @@ function loadSkillsFromDir(dir, source) {
|
|
|
65772
66084
|
} else if (entryIsFile && entry.name.endsWith(".md")) {
|
|
65773
66085
|
const name = entry.name.slice(0, -3);
|
|
65774
66086
|
try {
|
|
65775
|
-
const content =
|
|
66087
|
+
const content = fs14.readFileSync(entryPath, "utf-8");
|
|
65776
66088
|
const description = parseSkillDescription(content);
|
|
65777
66089
|
skills.push({
|
|
65778
66090
|
name,
|
|
@@ -65780,7 +66092,7 @@ function loadSkillsFromDir(dir, source) {
|
|
|
65780
66092
|
content,
|
|
65781
66093
|
filePath: entryPath,
|
|
65782
66094
|
source,
|
|
65783
|
-
baseDir:
|
|
66095
|
+
baseDir: path13.dirname(entryPath)
|
|
65784
66096
|
});
|
|
65785
66097
|
} catch (e) {
|
|
65786
66098
|
diagnostics.push({
|
|
@@ -65794,18 +66106,18 @@ function loadSkillsFromDir(dir, source) {
|
|
|
65794
66106
|
return { skills, diagnostics };
|
|
65795
66107
|
}
|
|
65796
66108
|
function discoverAgentsSkillsDirs(cwd) {
|
|
65797
|
-
const resolvedCwd =
|
|
66109
|
+
const resolvedCwd = path13.resolve(cwd || process.cwd());
|
|
65798
66110
|
const projectRoot = resolveCliProjectRoot(resolvedCwd);
|
|
65799
66111
|
const projectAgentsDirs = [];
|
|
65800
66112
|
let current = projectRoot;
|
|
65801
66113
|
while (true) {
|
|
65802
|
-
projectAgentsDirs.push(
|
|
66114
|
+
projectAgentsDirs.push(path13.join(current, ".agents", "skills"));
|
|
65803
66115
|
if (current === resolvedCwd) break;
|
|
65804
|
-
const child =
|
|
66116
|
+
const child = path13.relative(current, resolvedCwd).split(path13.sep)[0];
|
|
65805
66117
|
if (!child) break;
|
|
65806
|
-
current =
|
|
66118
|
+
current = path13.join(current, child);
|
|
65807
66119
|
}
|
|
65808
|
-
return { userAgentsDir:
|
|
66120
|
+
return { userAgentsDir: path13.join(os4.homedir(), ".agents", "skills"), projectAgentsDirs };
|
|
65809
66121
|
}
|
|
65810
66122
|
function buildSkillDirs(options) {
|
|
65811
66123
|
const { userAgentsDir, projectAgentsDirs } = discoverAgentsSkillsDirs(options.cwd);
|
|
@@ -65976,11 +66288,11 @@ function validateSkillName(name) {
|
|
|
65976
66288
|
}
|
|
65977
66289
|
|
|
65978
66290
|
// src/interactive-mode.ts
|
|
65979
|
-
import * as
|
|
66291
|
+
import * as path30 from "path";
|
|
65980
66292
|
|
|
65981
66293
|
// src/capabilities/read-file-understanding.ts
|
|
65982
|
-
import * as
|
|
65983
|
-
import * as
|
|
66294
|
+
import * as path22 from "node:path";
|
|
66295
|
+
import * as fs22 from "node:fs/promises";
|
|
65984
66296
|
|
|
65985
66297
|
// src/core/provider-capabilities.ts
|
|
65986
66298
|
var PLATFORM_DISPLAY_NAMES = {
|
|
@@ -66006,8 +66318,8 @@ function getProviderDisplayName(platform2) {
|
|
|
66006
66318
|
}
|
|
66007
66319
|
|
|
66008
66320
|
// src/files/adapters/kimi-adapter.ts
|
|
66009
|
-
import * as
|
|
66010
|
-
import * as
|
|
66321
|
+
import * as fs15 from "node:fs";
|
|
66322
|
+
import * as path14 from "node:path";
|
|
66011
66323
|
|
|
66012
66324
|
// src/files/errors.ts
|
|
66013
66325
|
var FileErrorMessages = {
|
|
@@ -66144,17 +66456,17 @@ var KimiFileAdapter = class {
|
|
|
66144
66456
|
// Upload
|
|
66145
66457
|
// ============================================================================
|
|
66146
66458
|
async upload(filePath, options = {}) {
|
|
66147
|
-
const fileName = options.sourceName ||
|
|
66459
|
+
const fileName = options.sourceName || path14.basename(filePath);
|
|
66148
66460
|
const mimeType = options.mimeType || this.guessMimeType(fileName);
|
|
66149
66461
|
const purpose = this.detectPurpose(filePath, options.purpose, mimeType);
|
|
66150
|
-
const stats =
|
|
66462
|
+
const stats = fs15.statSync(filePath);
|
|
66151
66463
|
if (stats.size > this.capabilities.maxFileSize) {
|
|
66152
66464
|
throw new FileManagerError(
|
|
66153
66465
|
"FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
|
|
66154
66466
|
`File size ${(stats.size / 1024 / 1024).toFixed(1)}MB exceeds Kimi limit of 100MB`
|
|
66155
66467
|
);
|
|
66156
66468
|
}
|
|
66157
|
-
const fileBuffer =
|
|
66469
|
+
const fileBuffer = fs15.readFileSync(filePath);
|
|
66158
66470
|
const file = new File([fileBuffer], fileName, { type: mimeType });
|
|
66159
66471
|
const formData = new FormData();
|
|
66160
66472
|
formData.append("file", file);
|
|
@@ -66206,7 +66518,7 @@ var KimiFileAdapter = class {
|
|
|
66206
66518
|
return "file-extract";
|
|
66207
66519
|
}
|
|
66208
66520
|
guessMimeType(filename) {
|
|
66209
|
-
const ext =
|
|
66521
|
+
const ext = path14.extname(filename).toLowerCase();
|
|
66210
66522
|
switch (ext) {
|
|
66211
66523
|
case ".jpg":
|
|
66212
66524
|
case ".jpeg":
|
|
@@ -66368,8 +66680,8 @@ var KimiFileAdapter = class {
|
|
|
66368
66680
|
};
|
|
66369
66681
|
|
|
66370
66682
|
// src/files/adapters/gemini-adapter.ts
|
|
66371
|
-
import * as
|
|
66372
|
-
import * as
|
|
66683
|
+
import * as fs16 from "node:fs";
|
|
66684
|
+
import * as path15 from "node:path";
|
|
66373
66685
|
import { Readable } from "node:stream";
|
|
66374
66686
|
var GeminiFileAdapter = class {
|
|
66375
66687
|
platform = "gemini";
|
|
@@ -66426,7 +66738,7 @@ var GeminiFileAdapter = class {
|
|
|
66426
66738
|
// Upload
|
|
66427
66739
|
// ============================================================================
|
|
66428
66740
|
async upload(filePath, options = {}) {
|
|
66429
|
-
const stats =
|
|
66741
|
+
const stats = fs16.statSync(filePath);
|
|
66430
66742
|
if (stats.size > this.capabilities.maxFileSize) {
|
|
66431
66743
|
throw new FileManagerError(
|
|
66432
66744
|
"FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
|
|
@@ -66434,7 +66746,7 @@ var GeminiFileAdapter = class {
|
|
|
66434
66746
|
);
|
|
66435
66747
|
}
|
|
66436
66748
|
const mimeType = options.mimeType || this.guessMimeType(filePath);
|
|
66437
|
-
const displayName = options.sourceName ||
|
|
66749
|
+
const displayName = options.sourceName || path15.basename(filePath);
|
|
66438
66750
|
const startResponse = await fetch(
|
|
66439
66751
|
`${this.baseUrl}/upload/v1beta/files?key=${this.apiKey}`,
|
|
66440
66752
|
{
|
|
@@ -66465,7 +66777,7 @@ var GeminiFileAdapter = class {
|
|
|
66465
66777
|
"No upload URL received"
|
|
66466
66778
|
);
|
|
66467
66779
|
}
|
|
66468
|
-
const fileStream = Readable.toWeb(
|
|
66780
|
+
const fileStream = Readable.toWeb(fs16.createReadStream(filePath));
|
|
66469
66781
|
const uploadResponse = await fetch(uploadUrl, {
|
|
66470
66782
|
method: "POST",
|
|
66471
66783
|
headers: {
|
|
@@ -66669,8 +66981,8 @@ var GeminiFileAdapter = class {
|
|
|
66669
66981
|
};
|
|
66670
66982
|
|
|
66671
66983
|
// src/files/adapters/openai-compatible-files-adapter.ts
|
|
66672
|
-
import * as
|
|
66673
|
-
import * as
|
|
66984
|
+
import * as fs17 from "node:fs";
|
|
66985
|
+
import * as path16 from "node:path";
|
|
66674
66986
|
var OpenAICompatibleFilesAdapter = class {
|
|
66675
66987
|
constructor(apiKey, baseUrl, extraHeaders = {}) {
|
|
66676
66988
|
this.apiKey = apiKey;
|
|
@@ -66696,16 +67008,16 @@ var OpenAICompatibleFilesAdapter = class {
|
|
|
66696
67008
|
]
|
|
66697
67009
|
};
|
|
66698
67010
|
async upload(filePath, options = {}) {
|
|
66699
|
-
const fileName = options.sourceName ||
|
|
67011
|
+
const fileName = options.sourceName || path16.basename(filePath);
|
|
66700
67012
|
const mimeType = options.mimeType || guessMimeType(fileName);
|
|
66701
|
-
const stats =
|
|
67013
|
+
const stats = fs17.statSync(filePath);
|
|
66702
67014
|
if (stats.size > this.capabilities.maxFileSize) {
|
|
66703
67015
|
throw new FileManagerError(
|
|
66704
67016
|
"FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
|
|
66705
67017
|
`File size ${(stats.size / 1024 / 1024).toFixed(1)}MB exceeds OpenAI-compatible Files limit of ${this.capabilities.maxFileSize / 1024 / 1024}MB`
|
|
66706
67018
|
);
|
|
66707
67019
|
}
|
|
66708
|
-
const file = new File([
|
|
67020
|
+
const file = new File([fs17.readFileSync(filePath)], fileName, { type: mimeType });
|
|
66709
67021
|
const formData = new FormData();
|
|
66710
67022
|
formData.append("file", file);
|
|
66711
67023
|
formData.append("purpose", options.purpose && options.purpose !== "auto" ? options.purpose : "file-extract");
|
|
@@ -66822,7 +67134,7 @@ function extractContentText(raw) {
|
|
|
66822
67134
|
return raw;
|
|
66823
67135
|
}
|
|
66824
67136
|
function guessMimeType(filename) {
|
|
66825
|
-
const ext =
|
|
67137
|
+
const ext = path16.extname(filename).toLowerCase();
|
|
66826
67138
|
switch (ext) {
|
|
66827
67139
|
case ".pdf":
|
|
66828
67140
|
return "application/pdf";
|
|
@@ -66838,13 +67150,13 @@ function guessMimeType(filename) {
|
|
|
66838
67150
|
}
|
|
66839
67151
|
|
|
66840
67152
|
// src/files/file-manager.ts
|
|
66841
|
-
import * as
|
|
66842
|
-
import * as
|
|
67153
|
+
import * as fs21 from "node:fs";
|
|
67154
|
+
import * as path21 from "node:path";
|
|
66843
67155
|
import * as crypto2 from "node:crypto";
|
|
66844
67156
|
|
|
66845
67157
|
// src/files/file-cache.ts
|
|
66846
|
-
import * as
|
|
66847
|
-
import * as
|
|
67158
|
+
import * as fs18 from "node:fs";
|
|
67159
|
+
import * as path18 from "node:path";
|
|
66848
67160
|
import * as crypto from "node:crypto";
|
|
66849
67161
|
|
|
66850
67162
|
// src/files/logger.ts
|
|
@@ -66939,7 +67251,7 @@ var DEFAULT_PIC_OPTIONS = {
|
|
|
66939
67251
|
};
|
|
66940
67252
|
|
|
66941
67253
|
// src/files/utils.ts
|
|
66942
|
-
import * as
|
|
67254
|
+
import * as path17 from "node:path";
|
|
66943
67255
|
import { homedir as homedir5 } from "node:os";
|
|
66944
67256
|
var WINDOWS_ABSOLUTE_PATH_RE = /^(?:[a-zA-Z]:[\\/]|[\\/]{2}[^\\/]+[\\/][^\\/]+)/;
|
|
66945
67257
|
function isWindowsAbsolutePath(filePath) {
|
|
@@ -66960,13 +67272,13 @@ function formatBytes(bytes) {
|
|
|
66960
67272
|
}
|
|
66961
67273
|
function resolvePath2(inputPath) {
|
|
66962
67274
|
if (inputPath.startsWith("~")) {
|
|
66963
|
-
return
|
|
67275
|
+
return path17.join(getHomeDirectory(), inputPath.slice(1));
|
|
66964
67276
|
}
|
|
66965
67277
|
if (isWindowsAbsolutePath(inputPath)) {
|
|
66966
67278
|
return inputPath;
|
|
66967
67279
|
}
|
|
66968
|
-
if (!
|
|
66969
|
-
return
|
|
67280
|
+
if (!path17.isAbsolute(inputPath)) {
|
|
67281
|
+
return path17.resolve(process.cwd(), inputPath);
|
|
66970
67282
|
}
|
|
66971
67283
|
return inputPath;
|
|
66972
67284
|
}
|
|
@@ -66994,8 +67306,8 @@ var FileCache = class _FileCache {
|
|
|
66994
67306
|
maxEntries;
|
|
66995
67307
|
constructor(baseDir, maxEntries = DEFAULT_MAX_CACHE_ENTRIES) {
|
|
66996
67308
|
this.baseDir = baseDir;
|
|
66997
|
-
this.dataDir =
|
|
66998
|
-
this.indexPath =
|
|
67309
|
+
this.dataDir = path18.join(baseDir, "data");
|
|
67310
|
+
this.indexPath = path18.join(baseDir, "index.json");
|
|
66999
67311
|
this.maxEntries = maxEntries;
|
|
67000
67312
|
this.index = this.loadIndex();
|
|
67001
67313
|
this.ensureDirectories();
|
|
@@ -67004,22 +67316,22 @@ var FileCache = class _FileCache {
|
|
|
67004
67316
|
// Directory Management
|
|
67005
67317
|
// ============================================================================
|
|
67006
67318
|
ensureDirectories() {
|
|
67007
|
-
if (!
|
|
67008
|
-
|
|
67319
|
+
if (!fs18.existsSync(this.baseDir)) {
|
|
67320
|
+
fs18.mkdirSync(this.baseDir, { recursive: true });
|
|
67009
67321
|
}
|
|
67010
|
-
if (!
|
|
67011
|
-
|
|
67322
|
+
if (!fs18.existsSync(this.dataDir)) {
|
|
67323
|
+
fs18.mkdirSync(this.dataDir, { recursive: true });
|
|
67012
67324
|
}
|
|
67013
67325
|
}
|
|
67014
67326
|
// ============================================================================
|
|
67015
67327
|
// Index Management
|
|
67016
67328
|
// ============================================================================
|
|
67017
67329
|
loadIndex() {
|
|
67018
|
-
if (!
|
|
67330
|
+
if (!fs18.existsSync(this.indexPath)) {
|
|
67019
67331
|
return { version: CACHE_VERSION, files: {}, pathHints: {} };
|
|
67020
67332
|
}
|
|
67021
67333
|
try {
|
|
67022
|
-
const data = JSON.parse(
|
|
67334
|
+
const data = JSON.parse(fs18.readFileSync(this.indexPath, "utf-8"));
|
|
67023
67335
|
if (data.version !== CACHE_VERSION) {
|
|
67024
67336
|
cacheLogger.warn(`Index version mismatch: ${data.version} vs ${CACHE_VERSION}`);
|
|
67025
67337
|
}
|
|
@@ -67035,7 +67347,7 @@ var FileCache = class _FileCache {
|
|
|
67035
67347
|
}
|
|
67036
67348
|
saveIndex() {
|
|
67037
67349
|
try {
|
|
67038
|
-
|
|
67350
|
+
fs18.writeFileSync(this.indexPath, JSON.stringify(this.index, null, 2));
|
|
67039
67351
|
} catch (err) {
|
|
67040
67352
|
cacheLogger.error(" Failed to save index:", err);
|
|
67041
67353
|
throw err;
|
|
@@ -67047,7 +67359,7 @@ var FileCache = class _FileCache {
|
|
|
67047
67359
|
async computeHash(filePath) {
|
|
67048
67360
|
return new Promise((resolve7, reject) => {
|
|
67049
67361
|
const hash = crypto.createHash("sha256");
|
|
67050
|
-
const stream =
|
|
67362
|
+
const stream = fs18.createReadStream(filePath);
|
|
67051
67363
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
67052
67364
|
stream.on("end", () => resolve7(hash.digest("hex")));
|
|
67053
67365
|
stream.on("error", reject);
|
|
@@ -67061,25 +67373,25 @@ var FileCache = class _FileCache {
|
|
|
67061
67373
|
// ============================================================================
|
|
67062
67374
|
getStoragePath(hash) {
|
|
67063
67375
|
const subdir = hash.slice(0, 2);
|
|
67064
|
-
const fullDir =
|
|
67065
|
-
if (!
|
|
67066
|
-
|
|
67376
|
+
const fullDir = path18.join(this.dataDir, subdir);
|
|
67377
|
+
if (!fs18.existsSync(fullDir)) {
|
|
67378
|
+
fs18.mkdirSync(fullDir, { recursive: true });
|
|
67067
67379
|
}
|
|
67068
|
-
return
|
|
67380
|
+
return path18.join(fullDir, hash);
|
|
67069
67381
|
}
|
|
67070
67382
|
getStorageRelativePath(hash) {
|
|
67071
67383
|
const subdir = hash.slice(0, 2);
|
|
67072
|
-
return
|
|
67384
|
+
return path18.join(subdir, hash);
|
|
67073
67385
|
}
|
|
67074
67386
|
async storeFile(sourcePath, name, mimeType) {
|
|
67075
67387
|
const hash = await this.computeHash(sourcePath);
|
|
67076
67388
|
const storagePath = this.getStoragePath(hash);
|
|
67077
67389
|
this.rememberPathHint(sourcePath, hash, name);
|
|
67078
|
-
if (
|
|
67390
|
+
if (fs18.existsSync(storagePath)) {
|
|
67079
67391
|
return { hash, localPath: storagePath };
|
|
67080
67392
|
}
|
|
67081
|
-
|
|
67082
|
-
const stat2 =
|
|
67393
|
+
fs18.copyFileSync(sourcePath, storagePath);
|
|
67394
|
+
const stat2 = fs18.statSync(storagePath);
|
|
67083
67395
|
this.index.files[hash] = {
|
|
67084
67396
|
hash,
|
|
67085
67397
|
name,
|
|
@@ -67096,10 +67408,10 @@ var FileCache = class _FileCache {
|
|
|
67096
67408
|
async storeBuffer(data, name, mimeType) {
|
|
67097
67409
|
const hash = this.computeHashSync(data);
|
|
67098
67410
|
const storagePath = this.getStoragePath(hash);
|
|
67099
|
-
if (
|
|
67411
|
+
if (fs18.existsSync(storagePath)) {
|
|
67100
67412
|
return { hash, localPath: storagePath };
|
|
67101
67413
|
}
|
|
67102
|
-
|
|
67414
|
+
fs18.writeFileSync(storagePath, data);
|
|
67103
67415
|
this.index.files[hash] = {
|
|
67104
67416
|
hash,
|
|
67105
67417
|
name,
|
|
@@ -67131,7 +67443,7 @@ var FileCache = class _FileCache {
|
|
|
67131
67443
|
getLocalPath(hash) {
|
|
67132
67444
|
const entry = this.index.files[hash];
|
|
67133
67445
|
if (!entry) return void 0;
|
|
67134
|
-
return
|
|
67446
|
+
return path18.join(this.dataDir, entry.localPath);
|
|
67135
67447
|
}
|
|
67136
67448
|
exists(hash) {
|
|
67137
67449
|
return hash in this.index.files;
|
|
@@ -67171,7 +67483,7 @@ var FileCache = class _FileCache {
|
|
|
67171
67483
|
getPathHint(filePath) {
|
|
67172
67484
|
try {
|
|
67173
67485
|
const resolvedPath = this.getResolvedHintPath(filePath);
|
|
67174
|
-
const stat2 =
|
|
67486
|
+
const stat2 = fs18.statSync(resolvedPath);
|
|
67175
67487
|
if (!stat2.isFile()) return void 0;
|
|
67176
67488
|
const normalizedMtimeMs = this.normalizeHintMtimeMs(stat2.mtimeMs);
|
|
67177
67489
|
const key = this.getPathHintKey(resolvedPath);
|
|
@@ -67201,7 +67513,7 @@ var FileCache = class _FileCache {
|
|
|
67201
67513
|
rememberPathHint(filePath, hash, name) {
|
|
67202
67514
|
try {
|
|
67203
67515
|
const resolvedPath = this.getResolvedHintPath(filePath);
|
|
67204
|
-
const stat2 =
|
|
67516
|
+
const stat2 = fs18.statSync(resolvedPath);
|
|
67205
67517
|
if (!stat2.isFile()) return;
|
|
67206
67518
|
const entry = this.index.files[hash];
|
|
67207
67519
|
const normalizedMtimeMs = this.normalizeHintMtimeMs(stat2.mtimeMs);
|
|
@@ -67211,7 +67523,7 @@ var FileCache = class _FileCache {
|
|
|
67211
67523
|
this.index.pathHints[this.getPathHintKey(resolvedPath)] = {
|
|
67212
67524
|
path: resolvedPath,
|
|
67213
67525
|
hash,
|
|
67214
|
-
name: name || entry?.name ||
|
|
67526
|
+
name: name || entry?.name || path18.basename(resolvedPath),
|
|
67215
67527
|
size: stat2.size,
|
|
67216
67528
|
mtimeMs: normalizedMtimeMs,
|
|
67217
67529
|
lastSeenAt: Date.now(),
|
|
@@ -67259,9 +67571,9 @@ var FileCache = class _FileCache {
|
|
|
67259
67571
|
deleteEntry(hash, entry) {
|
|
67260
67572
|
entry = entry || this.index.files[hash];
|
|
67261
67573
|
if (!entry) return;
|
|
67262
|
-
const localPath =
|
|
67263
|
-
if (
|
|
67264
|
-
|
|
67574
|
+
const localPath = path18.join(this.dataDir, entry.localPath);
|
|
67575
|
+
if (fs18.existsSync(localPath)) {
|
|
67576
|
+
fs18.unlinkSync(localPath);
|
|
67265
67577
|
}
|
|
67266
67578
|
delete this.index.files[hash];
|
|
67267
67579
|
if (this.index.pathHints) {
|
|
@@ -67275,9 +67587,9 @@ var FileCache = class _FileCache {
|
|
|
67275
67587
|
}
|
|
67276
67588
|
clear() {
|
|
67277
67589
|
for (const entry of Object.values(this.index.files)) {
|
|
67278
|
-
const localPath =
|
|
67279
|
-
if (
|
|
67280
|
-
|
|
67590
|
+
const localPath = path18.join(this.dataDir, entry.localPath);
|
|
67591
|
+
if (fs18.existsSync(localPath)) {
|
|
67592
|
+
fs18.unlinkSync(localPath);
|
|
67281
67593
|
}
|
|
67282
67594
|
}
|
|
67283
67595
|
this.index = { version: CACHE_VERSION, files: {}, pathHints: {} };
|
|
@@ -67330,11 +67642,11 @@ var FileCache = class _FileCache {
|
|
|
67330
67642
|
};
|
|
67331
67643
|
}
|
|
67332
67644
|
static getMimeType(fileName) {
|
|
67333
|
-
const ext =
|
|
67645
|
+
const ext = path18.extname(fileName).toLowerCase();
|
|
67334
67646
|
return MIME_TYPES[ext] || "application/octet-stream";
|
|
67335
67647
|
}
|
|
67336
67648
|
static getFileTypeFromName(fileName) {
|
|
67337
|
-
const baseName =
|
|
67649
|
+
const baseName = path18.basename(fileName);
|
|
67338
67650
|
if (!baseName || baseName.startsWith(".")) {
|
|
67339
67651
|
return void 0;
|
|
67340
67652
|
}
|
|
@@ -67365,7 +67677,7 @@ var FileCache = class _FileCache {
|
|
|
67365
67677
|
getResolvedHintPath(filePath) {
|
|
67366
67678
|
const resolvedPath = resolvePath2(filePath);
|
|
67367
67679
|
try {
|
|
67368
|
-
return
|
|
67680
|
+
return fs18.realpathSync.native ? fs18.realpathSync.native(resolvedPath) : fs18.realpathSync(resolvedPath);
|
|
67369
67681
|
} catch {
|
|
67370
67682
|
return resolvedPath;
|
|
67371
67683
|
}
|
|
@@ -67373,8 +67685,8 @@ var FileCache = class _FileCache {
|
|
|
67373
67685
|
};
|
|
67374
67686
|
|
|
67375
67687
|
// src/files/session-file-manager.ts
|
|
67376
|
-
import * as
|
|
67377
|
-
import * as
|
|
67688
|
+
import * as fs19 from "node:fs";
|
|
67689
|
+
import * as path19 from "node:path";
|
|
67378
67690
|
var INITIAL_REFRESH_BACKOFF_MS = 6e4;
|
|
67379
67691
|
var MAX_REFRESH_BACKOFF_MS = 60 * 60 * 1e3;
|
|
67380
67692
|
var SessionFileManager = class {
|
|
@@ -67388,7 +67700,7 @@ var SessionFileManager = class {
|
|
|
67388
67700
|
constructor(sessionId, sessionsDir, fileCache, authFingerprint) {
|
|
67389
67701
|
this.sessionId = sessionId;
|
|
67390
67702
|
this.sessionsDir = sessionsDir;
|
|
67391
|
-
this.statePath =
|
|
67703
|
+
this.statePath = path19.join(this.sessionsDir, `${sessionId}-files.json`);
|
|
67392
67704
|
this.fileCache = fileCache;
|
|
67393
67705
|
this.authFingerprint = authFingerprint;
|
|
67394
67706
|
this.state = this.loadState();
|
|
@@ -67398,15 +67710,15 @@ var SessionFileManager = class {
|
|
|
67398
67710
|
// Directory Management
|
|
67399
67711
|
// ============================================================================
|
|
67400
67712
|
ensureDirectories() {
|
|
67401
|
-
if (!
|
|
67402
|
-
|
|
67713
|
+
if (!fs19.existsSync(this.sessionsDir)) {
|
|
67714
|
+
fs19.mkdirSync(this.sessionsDir, { recursive: true });
|
|
67403
67715
|
}
|
|
67404
67716
|
}
|
|
67405
67717
|
// ============================================================================
|
|
67406
67718
|
// State Management
|
|
67407
67719
|
// ============================================================================
|
|
67408
67720
|
loadState() {
|
|
67409
|
-
if (!
|
|
67721
|
+
if (!fs19.existsSync(this.statePath)) {
|
|
67410
67722
|
return {
|
|
67411
67723
|
sessionId: this.sessionId,
|
|
67412
67724
|
lastSyncedAt: 0,
|
|
@@ -67414,7 +67726,7 @@ var SessionFileManager = class {
|
|
|
67414
67726
|
};
|
|
67415
67727
|
}
|
|
67416
67728
|
try {
|
|
67417
|
-
return JSON.parse(
|
|
67729
|
+
return JSON.parse(fs19.readFileSync(this.statePath, "utf-8"));
|
|
67418
67730
|
} catch (err) {
|
|
67419
67731
|
sessionLogger.error(" Failed to load state:", err);
|
|
67420
67732
|
return {
|
|
@@ -67427,12 +67739,12 @@ var SessionFileManager = class {
|
|
|
67427
67739
|
saveState() {
|
|
67428
67740
|
try {
|
|
67429
67741
|
if (Object.keys(this.state.files).length === 0) {
|
|
67430
|
-
if (
|
|
67431
|
-
|
|
67742
|
+
if (fs19.existsSync(this.statePath)) {
|
|
67743
|
+
fs19.unlinkSync(this.statePath);
|
|
67432
67744
|
}
|
|
67433
67745
|
return;
|
|
67434
67746
|
}
|
|
67435
|
-
|
|
67747
|
+
fs19.writeFileSync(this.statePath, JSON.stringify(this.state, null, 2));
|
|
67436
67748
|
} catch (err) {
|
|
67437
67749
|
sessionLogger.error(" Failed to save state:", err);
|
|
67438
67750
|
}
|
|
@@ -67578,7 +67890,7 @@ var SessionFileManager = class {
|
|
|
67578
67890
|
return { success: false, coolingDown: true };
|
|
67579
67891
|
}
|
|
67580
67892
|
const localPath = this.fileCache.getLocalPath(entry.hash);
|
|
67581
|
-
if (!localPath || !
|
|
67893
|
+
if (!localPath || !fs19.existsSync(localPath)) {
|
|
67582
67894
|
sessionLogger.warn(`Local file not found for ${fileId}`);
|
|
67583
67895
|
entry.status = "expired";
|
|
67584
67896
|
entry.error = "Local file missing";
|
|
@@ -67729,15 +68041,15 @@ var SessionFileManager = class {
|
|
|
67729
68041
|
// Static Utilities
|
|
67730
68042
|
// ============================================================================
|
|
67731
68043
|
static cleanupOldSessions(sessionsDir, maxAge = 30 * 24 * 60 * 60 * 1e3) {
|
|
67732
|
-
if (!
|
|
68044
|
+
if (!fs19.existsSync(sessionsDir)) return;
|
|
67733
68045
|
const now = Date.now();
|
|
67734
|
-
const files =
|
|
68046
|
+
const files = fs19.readdirSync(sessionsDir);
|
|
67735
68047
|
for (const file of files) {
|
|
67736
68048
|
if (!file.endsWith(".json")) continue;
|
|
67737
|
-
const filePath =
|
|
67738
|
-
const stat2 =
|
|
68049
|
+
const filePath = path19.join(sessionsDir, file);
|
|
68050
|
+
const stat2 = fs19.statSync(filePath);
|
|
67739
68051
|
if (now - stat2.mtime.getTime() > maxAge) {
|
|
67740
|
-
|
|
68052
|
+
fs19.unlinkSync(filePath);
|
|
67741
68053
|
sessionLogger.debug(`Cleaned up old session: ${file}`);
|
|
67742
68054
|
}
|
|
67743
68055
|
}
|
|
@@ -67745,8 +68057,8 @@ var SessionFileManager = class {
|
|
|
67745
68057
|
};
|
|
67746
68058
|
|
|
67747
68059
|
// src/files/ffmpeg-processor.ts
|
|
67748
|
-
import * as
|
|
67749
|
-
import * as
|
|
68060
|
+
import * as fs20 from "node:fs";
|
|
68061
|
+
import * as path20 from "node:path";
|
|
67750
68062
|
import { spawn } from "node:child_process";
|
|
67751
68063
|
var FFmpegProcessor = class {
|
|
67752
68064
|
ffmpegPath = "ffmpeg";
|
|
@@ -67850,7 +68162,7 @@ var FFmpegProcessor = class {
|
|
|
67850
68162
|
}
|
|
67851
68163
|
async compressVideo(inputPath, outputDir, info, opts, onProgress) {
|
|
67852
68164
|
const outputName = `compressed_${Date.now()}.mp4`;
|
|
67853
|
-
const outputPath =
|
|
68165
|
+
const outputPath = path20.join(outputDir, outputName);
|
|
67854
68166
|
const adaptiveParams = this.calculateAdaptiveParams(info.duration, opts);
|
|
67855
68167
|
const args = [
|
|
67856
68168
|
"-i",
|
|
@@ -67881,7 +68193,7 @@ var FFmpegProcessor = class {
|
|
|
67881
68193
|
onProgress?.(percent);
|
|
67882
68194
|
}
|
|
67883
68195
|
});
|
|
67884
|
-
const outputStat =
|
|
68196
|
+
const outputStat = fs20.statSync(outputPath);
|
|
67885
68197
|
return {
|
|
67886
68198
|
type: "video",
|
|
67887
68199
|
output: outputPath,
|
|
@@ -67912,9 +68224,9 @@ var FFmpegProcessor = class {
|
|
|
67912
68224
|
}
|
|
67913
68225
|
async extractKeyframes(inputPath, outputDir, info, opts, onProgress) {
|
|
67914
68226
|
const interval = Math.floor(info.duration / opts.keyframeCount);
|
|
67915
|
-
const framesDir =
|
|
67916
|
-
|
|
67917
|
-
const outputPattern =
|
|
68227
|
+
const framesDir = path20.join(outputDir, `keyframes_${Date.now()}`);
|
|
68228
|
+
fs20.mkdirSync(framesDir, { recursive: true });
|
|
68229
|
+
const outputPattern = path20.join(framesDir, "frame_%03d.jpg");
|
|
67918
68230
|
const args = [
|
|
67919
68231
|
"-i",
|
|
67920
68232
|
inputPath,
|
|
@@ -67932,10 +68244,10 @@ var FFmpegProcessor = class {
|
|
|
67932
68244
|
onProgress?.(percent);
|
|
67933
68245
|
}
|
|
67934
68246
|
});
|
|
67935
|
-
let frames =
|
|
68247
|
+
let frames = fs20.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path20.join(framesDir, f));
|
|
67936
68248
|
if (frames.length < opts.keyframeCount / 2) {
|
|
67937
|
-
|
|
67938
|
-
|
|
68249
|
+
fs20.rmSync(framesDir, { recursive: true, force: true });
|
|
68250
|
+
fs20.mkdirSync(framesDir, { recursive: true });
|
|
67939
68251
|
const uniformArgs = [
|
|
67940
68252
|
"-i",
|
|
67941
68253
|
inputPath,
|
|
@@ -67951,10 +68263,10 @@ var FFmpegProcessor = class {
|
|
|
67951
68263
|
onProgress?.(percent);
|
|
67952
68264
|
}
|
|
67953
68265
|
});
|
|
67954
|
-
frames =
|
|
68266
|
+
frames = fs20.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path20.join(framesDir, f));
|
|
67955
68267
|
}
|
|
67956
68268
|
const totalOutputSize = frames.reduce(
|
|
67957
|
-
(sum, f) => sum +
|
|
68269
|
+
(sum, f) => sum + fs20.statSync(f).size,
|
|
67958
68270
|
0
|
|
67959
68271
|
);
|
|
67960
68272
|
return {
|
|
@@ -67975,7 +68287,7 @@ var FFmpegProcessor = class {
|
|
|
67975
68287
|
const opts = { ...DEFAULT_PIC_OPTIONS, ...options };
|
|
67976
68288
|
const ext = opts.format === "webp" ? ".webp" : ".jpg";
|
|
67977
68289
|
const outputName = `optimized_${Date.now()}${ext}`;
|
|
67978
|
-
const outputPath =
|
|
68290
|
+
const outputPath = path20.join(outputDir, outputName);
|
|
67979
68291
|
const args = [
|
|
67980
68292
|
"-i",
|
|
67981
68293
|
inputPath,
|
|
@@ -68150,8 +68462,8 @@ var DIRECTORY_LISTING_TTL_MS = 1500;
|
|
|
68150
68462
|
var FileManager = class {
|
|
68151
68463
|
constructor(options) {
|
|
68152
68464
|
this.options = options;
|
|
68153
|
-
const baseDir = options.baseDir ||
|
|
68154
|
-
const sessionsDir = options.sessionsDir ||
|
|
68465
|
+
const baseDir = options.baseDir || path21.join(process.env.HOME || ".", ".pie", "files");
|
|
68466
|
+
const sessionsDir = options.sessionsDir || path21.join(process.env.HOME || ".", ".pie", "sessions");
|
|
68155
68467
|
this.fileCache = new FileCache(baseDir);
|
|
68156
68468
|
this.authFingerprint = options.apiKey ? this.buildAuthFingerprint(options.apiKey) : void 0;
|
|
68157
68469
|
this.sessionManager = new SessionFileManager(
|
|
@@ -68162,7 +68474,7 @@ var FileManager = class {
|
|
|
68162
68474
|
);
|
|
68163
68475
|
this.ffmpeg = new FFmpegProcessor(options.ffmpegPath);
|
|
68164
68476
|
this.platform = normalizeFileManagerPlatform(options.platform);
|
|
68165
|
-
this.tempDir =
|
|
68477
|
+
this.tempDir = path21.join(baseDir, "temp");
|
|
68166
68478
|
this.ensureDirectories();
|
|
68167
68479
|
}
|
|
68168
68480
|
options;
|
|
@@ -68174,8 +68486,8 @@ var FileManager = class {
|
|
|
68174
68486
|
directoryListingCache = /* @__PURE__ */ new Map();
|
|
68175
68487
|
authFingerprint;
|
|
68176
68488
|
ensureDirectories() {
|
|
68177
|
-
if (!
|
|
68178
|
-
|
|
68489
|
+
if (!fs21.existsSync(this.tempDir)) {
|
|
68490
|
+
fs21.mkdirSync(this.tempDir, { recursive: true });
|
|
68179
68491
|
}
|
|
68180
68492
|
}
|
|
68181
68493
|
// ============================================================================
|
|
@@ -68209,8 +68521,8 @@ var FileManager = class {
|
|
|
68209
68521
|
// ============================================================================
|
|
68210
68522
|
async stageLocal(filePath, options = {}) {
|
|
68211
68523
|
const resolvedPath = resolvePath2(filePath);
|
|
68212
|
-
const sourceName = options.sourceName ||
|
|
68213
|
-
if (!
|
|
68524
|
+
const sourceName = options.sourceName || path21.basename(resolvedPath);
|
|
68525
|
+
if (!fs21.existsSync(resolvedPath)) {
|
|
68214
68526
|
throw new FileManagerError(
|
|
68215
68527
|
"LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
|
|
68216
68528
|
`File not found: ${filePath}`
|
|
@@ -68225,7 +68537,7 @@ var FileManager = class {
|
|
|
68225
68537
|
this.fileCache.rememberPathHint(resolvedPath, hash, sourceName);
|
|
68226
68538
|
this.invalidateDirectoryListingCacheForPath(resolvedPath);
|
|
68227
68539
|
const entry = this.fileCache.getByHash(hash);
|
|
68228
|
-
const size = entry?.size ??
|
|
68540
|
+
const size = entry?.size ?? fs21.statSync(resolvedPath).size;
|
|
68229
68541
|
return {
|
|
68230
68542
|
success: true,
|
|
68231
68543
|
hash,
|
|
@@ -68239,8 +68551,8 @@ var FileManager = class {
|
|
|
68239
68551
|
}
|
|
68240
68552
|
async upload(filePath, options = {}) {
|
|
68241
68553
|
const resolvedPath = resolvePath2(filePath);
|
|
68242
|
-
const sourceName = options.sourceName ||
|
|
68243
|
-
if (!
|
|
68554
|
+
const sourceName = options.sourceName || path21.basename(resolvedPath);
|
|
68555
|
+
if (!fs21.existsSync(resolvedPath)) {
|
|
68244
68556
|
throw new FileManagerError(
|
|
68245
68557
|
"LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
|
|
68246
68558
|
`File not found: ${filePath}`
|
|
@@ -68321,7 +68633,7 @@ var FileManager = class {
|
|
|
68321
68633
|
// ============================================================================
|
|
68322
68634
|
async uploadPic(filePath, options = {}) {
|
|
68323
68635
|
const resolvedPath = resolvePath2(filePath);
|
|
68324
|
-
if (!
|
|
68636
|
+
if (!fs21.existsSync(resolvedPath)) {
|
|
68325
68637
|
throw new FileManagerError(
|
|
68326
68638
|
"LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
|
|
68327
68639
|
`File not found: ${filePath}`
|
|
@@ -68329,7 +68641,7 @@ var FileManager = class {
|
|
|
68329
68641
|
}
|
|
68330
68642
|
const cachedResult = await this.tryReuseCachedSourceUpload(
|
|
68331
68643
|
resolvedPath,
|
|
68332
|
-
options.sourceName ||
|
|
68644
|
+
options.sourceName || path21.basename(resolvedPath),
|
|
68333
68645
|
options.platform || this.platform
|
|
68334
68646
|
);
|
|
68335
68647
|
if (cachedResult) {
|
|
@@ -68346,12 +68658,12 @@ var FileManager = class {
|
|
|
68346
68658
|
const result = await this.upload(optimizedPath, {
|
|
68347
68659
|
...options,
|
|
68348
68660
|
purpose: "image",
|
|
68349
|
-
sourceName:
|
|
68661
|
+
sourceName: path21.basename(resolvedPath)
|
|
68350
68662
|
});
|
|
68351
|
-
this.fileCache.rememberPathHint(resolvedPath, result.hash,
|
|
68663
|
+
this.fileCache.rememberPathHint(resolvedPath, result.hash, path21.basename(resolvedPath));
|
|
68352
68664
|
this.invalidateDirectoryListingCacheForPath(resolvedPath);
|
|
68353
68665
|
try {
|
|
68354
|
-
|
|
68666
|
+
fs21.unlinkSync(optimizedPath);
|
|
68355
68667
|
} catch {
|
|
68356
68668
|
}
|
|
68357
68669
|
return result;
|
|
@@ -68361,7 +68673,7 @@ var FileManager = class {
|
|
|
68361
68673
|
// ============================================================================
|
|
68362
68674
|
async uploadVideo(filePath, options = {}) {
|
|
68363
68675
|
const resolvedPath = resolvePath2(filePath);
|
|
68364
|
-
if (!
|
|
68676
|
+
if (!fs21.existsSync(resolvedPath)) {
|
|
68365
68677
|
throw new FileManagerError(
|
|
68366
68678
|
"LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
|
|
68367
68679
|
`File not found: ${filePath}`
|
|
@@ -68369,7 +68681,7 @@ var FileManager = class {
|
|
|
68369
68681
|
}
|
|
68370
68682
|
const cachedResult = await this.tryReuseCachedSourceUpload(
|
|
68371
68683
|
resolvedPath,
|
|
68372
|
-
options.sourceName ||
|
|
68684
|
+
options.sourceName || path21.basename(resolvedPath),
|
|
68373
68685
|
options.platform || this.platform
|
|
68374
68686
|
);
|
|
68375
68687
|
if (cachedResult) {
|
|
@@ -68419,9 +68731,9 @@ var FileManager = class {
|
|
|
68419
68731
|
result = await this.upload(preprocessResult.output, {
|
|
68420
68732
|
...options,
|
|
68421
68733
|
purpose: "video",
|
|
68422
|
-
sourceName:
|
|
68734
|
+
sourceName: path21.basename(resolvedPath)
|
|
68423
68735
|
});
|
|
68424
|
-
this.fileCache.rememberPathHint(resolvedPath, result.hash,
|
|
68736
|
+
this.fileCache.rememberPathHint(resolvedPath, result.hash, path21.basename(resolvedPath));
|
|
68425
68737
|
this.invalidateDirectoryListingCacheForPath(resolvedPath);
|
|
68426
68738
|
} else {
|
|
68427
68739
|
throw new FileManagerError(
|
|
@@ -68713,7 +69025,7 @@ var FileManager = class {
|
|
|
68713
69025
|
* Detect purpose from file path based on extension
|
|
68714
69026
|
*/
|
|
68715
69027
|
detectPurpose(filePath) {
|
|
68716
|
-
const ext =
|
|
69028
|
+
const ext = path21.extname(filePath).toLowerCase();
|
|
68717
69029
|
switch (ext) {
|
|
68718
69030
|
case ".mp4":
|
|
68719
69031
|
case ".mov":
|
|
@@ -68755,13 +69067,13 @@ var FileManager = class {
|
|
|
68755
69067
|
cleanupTempFiles(output) {
|
|
68756
69068
|
try {
|
|
68757
69069
|
if (typeof output === "string") {
|
|
68758
|
-
if (
|
|
68759
|
-
|
|
69070
|
+
if (fs21.existsSync(output)) {
|
|
69071
|
+
fs21.unlinkSync(output);
|
|
68760
69072
|
}
|
|
68761
69073
|
} else {
|
|
68762
69074
|
for (const file of output) {
|
|
68763
|
-
if (
|
|
68764
|
-
|
|
69075
|
+
if (fs21.existsSync(file)) {
|
|
69076
|
+
fs21.unlinkSync(file);
|
|
68765
69077
|
}
|
|
68766
69078
|
}
|
|
68767
69079
|
}
|
|
@@ -68793,7 +69105,7 @@ var FileManager = class {
|
|
|
68793
69105
|
}];
|
|
68794
69106
|
}
|
|
68795
69107
|
const localPath = this.fileCache.getLocalPath(entry.hash);
|
|
68796
|
-
if (localPath &&
|
|
69108
|
+
if (localPath && fs21.existsSync(localPath)) {
|
|
68797
69109
|
return [{
|
|
68798
69110
|
fileId,
|
|
68799
69111
|
name: cacheEntry.name,
|
|
@@ -68890,12 +69202,12 @@ var FileManager = class {
|
|
|
68890
69202
|
directories: []
|
|
68891
69203
|
};
|
|
68892
69204
|
try {
|
|
68893
|
-
const entries =
|
|
69205
|
+
const entries = fs21.readdirSync(resolvedDir, { withFileTypes: true });
|
|
68894
69206
|
for (const entry of entries) {
|
|
68895
69207
|
if (!entry.name || entry.name.startsWith(".")) {
|
|
68896
69208
|
continue;
|
|
68897
69209
|
}
|
|
68898
|
-
const fullPath =
|
|
69210
|
+
const fullPath = path21.join(resolvedDir, entry.name);
|
|
68899
69211
|
if (entry.isDirectory()) {
|
|
68900
69212
|
listing.directories.push({ name: entry.name, path: fullPath });
|
|
68901
69213
|
continue;
|
|
@@ -68904,7 +69216,7 @@ var FileManager = class {
|
|
|
68904
69216
|
let isFile = entry.isFile();
|
|
68905
69217
|
if (entry.isSymbolicLink()) {
|
|
68906
69218
|
try {
|
|
68907
|
-
const targetStat =
|
|
69219
|
+
const targetStat = fs21.statSync(fullPath);
|
|
68908
69220
|
isDirectory = targetStat.isDirectory();
|
|
68909
69221
|
isFile = targetStat.isFile();
|
|
68910
69222
|
} catch {
|
|
@@ -68922,7 +69234,7 @@ var FileManager = class {
|
|
|
68922
69234
|
if (!type) {
|
|
68923
69235
|
continue;
|
|
68924
69236
|
}
|
|
68925
|
-
const stat2 =
|
|
69237
|
+
const stat2 = fs21.statSync(fullPath);
|
|
68926
69238
|
listing.files.push({
|
|
68927
69239
|
name: entry.name,
|
|
68928
69240
|
path: fullPath,
|
|
@@ -68936,7 +69248,7 @@ var FileManager = class {
|
|
|
68936
69248
|
return listing;
|
|
68937
69249
|
}
|
|
68938
69250
|
invalidateDirectoryListingCacheForPath(filePath) {
|
|
68939
|
-
this.directoryListingCache.delete(
|
|
69251
|
+
this.directoryListingCache.delete(path21.dirname(resolvePath2(filePath)));
|
|
68940
69252
|
}
|
|
68941
69253
|
buildAuthFingerprint(apiKey) {
|
|
68942
69254
|
return crypto2.createHash("sha256").update(apiKey).digest("hex").slice(0, 16);
|
|
@@ -68985,8 +69297,8 @@ function createFileManagerForModel(params) {
|
|
|
68985
69297
|
sessionId: params.sessionId,
|
|
68986
69298
|
platform: platform2,
|
|
68987
69299
|
apiKey: params.apiKey,
|
|
68988
|
-
baseDir:
|
|
68989
|
-
sessionsDir:
|
|
69300
|
+
baseDir: path22.join(params.configDir, "files"),
|
|
69301
|
+
sessionsDir: path22.join(params.configDir, "sessions")
|
|
68990
69302
|
});
|
|
68991
69303
|
switch (getFileManagerAdapterKind(platform2)) {
|
|
68992
69304
|
case "kimi":
|
|
@@ -69021,15 +69333,15 @@ function isInlineMediaRequest(request) {
|
|
|
69021
69333
|
return request.kind === "image" || request.kind === "video";
|
|
69022
69334
|
}
|
|
69023
69335
|
async function prepareInlineMediaContent(params) {
|
|
69024
|
-
const stat2 = await
|
|
69336
|
+
const stat2 = await fs22.stat(params.request.absolutePath);
|
|
69025
69337
|
const limitMb = getCapabilityLimitMb(params.model, params.request.kind);
|
|
69026
69338
|
const limitBytes = limitMb * 1024 * 1024;
|
|
69027
69339
|
if (stat2.size > limitBytes) {
|
|
69028
69340
|
throw new Error(
|
|
69029
|
-
`${params.request.kind} understanding for ${params.model.provider}/${params.model.id} supports inline files up to ${limitMb}MB; ${
|
|
69341
|
+
`${params.request.kind} understanding for ${params.model.provider}/${params.model.id} supports inline files up to ${limitMb}MB; ${path22.basename(params.request.displayPath)} is ${(stat2.size / 1024 / 1024).toFixed(1)}MB. Configure a model with a file upload adapter, or compress/trim the file before reading it.`
|
|
69030
69342
|
);
|
|
69031
69343
|
}
|
|
69032
|
-
const data = await
|
|
69344
|
+
const data = await fs22.readFile(params.request.absolutePath, "base64");
|
|
69033
69345
|
const content = params.request.kind === "video" ? [{ type: "video", data, mimeType: params.request.mimeType }] : [{ type: "image", data, mimeType: params.request.mimeType }];
|
|
69034
69346
|
return {
|
|
69035
69347
|
content,
|
|
@@ -69065,7 +69377,7 @@ async function prepareFileContent(configDir, params) {
|
|
|
69065
69377
|
});
|
|
69066
69378
|
if (params.request.kind === "document") {
|
|
69067
69379
|
const upload2 = await manager.upload(params.request.absolutePath, {
|
|
69068
|
-
sourceName:
|
|
69380
|
+
sourceName: path22.basename(params.request.displayPath),
|
|
69069
69381
|
purpose: "file-extract"
|
|
69070
69382
|
});
|
|
69071
69383
|
await waitForReady({ manager, fileId: upload2.fileId, timeoutMs: 12e4, signal: params.request.signal });
|
|
@@ -69088,8 +69400,8 @@ async function prepareFileContent(configDir, params) {
|
|
|
69088
69400
|
}
|
|
69089
69401
|
};
|
|
69090
69402
|
}
|
|
69091
|
-
const upload = params.request.kind === "video" ? await manager.uploadVideo(params.request.absolutePath, { sourceName:
|
|
69092
|
-
sourceName:
|
|
69403
|
+
const upload = params.request.kind === "video" ? await manager.uploadVideo(params.request.absolutePath, { sourceName: path22.basename(params.request.displayPath), strategy: "compress" }) : await manager.upload(params.request.absolutePath, {
|
|
69404
|
+
sourceName: path22.basename(params.request.displayPath),
|
|
69093
69405
|
purpose: params.request.kind === "image" ? "image" : "file-extract"
|
|
69094
69406
|
});
|
|
69095
69407
|
if (params.request.kind !== "video") {
|
|
@@ -69510,22 +69822,22 @@ var ExecutionStateManager = class {
|
|
|
69510
69822
|
};
|
|
69511
69823
|
|
|
69512
69824
|
// src/session-trace.ts
|
|
69513
|
-
import * as
|
|
69514
|
-
import * as
|
|
69825
|
+
import * as fs23 from "node:fs";
|
|
69826
|
+
import * as path23 from "node:path";
|
|
69515
69827
|
function saveTraceFileBestEffort(tracePath, content) {
|
|
69516
69828
|
const tempPath = `${tracePath}.${process.pid}.${Date.now()}.tmp`;
|
|
69517
69829
|
try {
|
|
69518
|
-
|
|
69830
|
+
fs23.writeFileSync(tempPath, content, "utf8");
|
|
69519
69831
|
try {
|
|
69520
|
-
|
|
69832
|
+
fs23.renameSync(tempPath, tracePath);
|
|
69521
69833
|
return;
|
|
69522
69834
|
} catch {
|
|
69523
69835
|
try {
|
|
69524
|
-
|
|
69836
|
+
fs23.copyFileSync(tempPath, tracePath);
|
|
69525
69837
|
} catch {
|
|
69526
69838
|
} finally {
|
|
69527
69839
|
try {
|
|
69528
|
-
|
|
69840
|
+
fs23.unlinkSync(tempPath);
|
|
69529
69841
|
} catch {
|
|
69530
69842
|
}
|
|
69531
69843
|
}
|
|
@@ -69538,16 +69850,16 @@ var SessionTraceWriter = class extends SessionTraceSnapshotWriter {
|
|
|
69538
69850
|
super({
|
|
69539
69851
|
getSessionId: () => sessionManager.getActiveSessionId(),
|
|
69540
69852
|
loadTrace: (sessionId) => {
|
|
69541
|
-
const tracePath =
|
|
69542
|
-
if (!
|
|
69853
|
+
const tracePath = path23.join(sessionsDir, `${sessionId}.trace.json`);
|
|
69854
|
+
if (!fs23.existsSync(tracePath)) return null;
|
|
69543
69855
|
try {
|
|
69544
|
-
return JSON.parse(
|
|
69856
|
+
return JSON.parse(fs23.readFileSync(tracePath, "utf8"));
|
|
69545
69857
|
} catch {
|
|
69546
69858
|
return null;
|
|
69547
69859
|
}
|
|
69548
69860
|
},
|
|
69549
69861
|
saveTrace: (trace) => {
|
|
69550
|
-
const tracePath =
|
|
69862
|
+
const tracePath = path23.join(sessionsDir, `${trace.sessionId}.trace.json`);
|
|
69551
69863
|
saveTraceFileBestEffort(tracePath, JSON.stringify(trace, null, 2));
|
|
69552
69864
|
}
|
|
69553
69865
|
});
|
|
@@ -69837,7 +70149,7 @@ function normalizeSessionTitle(raw) {
|
|
|
69837
70149
|
}
|
|
69838
70150
|
|
|
69839
70151
|
// src/components/extension-selector.ts
|
|
69840
|
-
import * as
|
|
70152
|
+
import * as path24 from "node:path";
|
|
69841
70153
|
var ExtensionSelectorComponent = class extends Container {
|
|
69842
70154
|
selectList;
|
|
69843
70155
|
shortcuts;
|
|
@@ -69893,8 +70205,8 @@ function selectRuntimeExtensionWinners(infos) {
|
|
|
69893
70205
|
return reversed.reverse();
|
|
69894
70206
|
}
|
|
69895
70207
|
function unidentifiedLabel(info) {
|
|
69896
|
-
const parentName =
|
|
69897
|
-
const fileName =
|
|
70208
|
+
const parentName = path24.basename(path24.dirname(info.entryPath));
|
|
70209
|
+
const fileName = path24.basename(info.entryPath);
|
|
69898
70210
|
return `(unidentified) ${parentName || fileName}`;
|
|
69899
70211
|
}
|
|
69900
70212
|
var ExtensionEnablementSelectorComponent = class extends Container {
|
|
@@ -70442,7 +70754,7 @@ async function handleDebugPackageCommand(host) {
|
|
|
70442
70754
|
import * as os6 from "os";
|
|
70443
70755
|
|
|
70444
70756
|
// src/components/session-selector.ts
|
|
70445
|
-
import * as
|
|
70757
|
+
import * as path25 from "node:path";
|
|
70446
70758
|
function formatDate(timestamp) {
|
|
70447
70759
|
const date = new Date(timestamp);
|
|
70448
70760
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -70473,7 +70785,7 @@ function getPathFlavor(value, peer) {
|
|
|
70473
70785
|
return "posix";
|
|
70474
70786
|
}
|
|
70475
70787
|
function getPathApi(flavor) {
|
|
70476
|
-
return flavor === "windows" ?
|
|
70788
|
+
return flavor === "windows" ? path25.win32 : path25.posix;
|
|
70477
70789
|
}
|
|
70478
70790
|
function normalizeForComparison(value, flavor) {
|
|
70479
70791
|
const pathApi = getPathApi(flavor);
|
|
@@ -70630,102 +70942,37 @@ var SessionSelectorComponent = class extends Container {
|
|
|
70630
70942
|
var RESET = "\x1B[0m";
|
|
70631
70943
|
var INVERSE = "\x1B[7m";
|
|
70632
70944
|
var DIM = "\x1B[2m";
|
|
70633
|
-
|
|
70634
|
-
return visibleWidth(str2);
|
|
70635
|
-
}
|
|
70945
|
+
var searchSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
70636
70946
|
var TREE_CHARS = {
|
|
70637
70947
|
branch: "\u251C\u2500\u2500 ",
|
|
70638
70948
|
corner: "\u2514\u2500\u2500 ",
|
|
70639
70949
|
pipe: "\u2502 ",
|
|
70640
70950
|
space: " ",
|
|
70641
70951
|
active: "\u25CF ",
|
|
70642
|
-
inactive: "\u25CB "
|
|
70952
|
+
inactive: "\u25CB ",
|
|
70953
|
+
/** Marks rows whose full ancestry is not visible in the window. */
|
|
70954
|
+
hiddenAncestry: "\u2026"
|
|
70643
70955
|
};
|
|
70644
|
-
|
|
70645
|
-
|
|
70646
|
-
|
|
70647
|
-
|
|
70648
|
-
|
|
70649
|
-
|
|
70650
|
-
|
|
70651
|
-
|
|
70652
|
-
if (
|
|
70653
|
-
|
|
70654
|
-
|
|
70655
|
-
|
|
70656
|
-
|
|
70657
|
-
|
|
70658
|
-
for (const c of content) {
|
|
70659
|
-
if (typeof c !== "object" || c === null) continue;
|
|
70660
|
-
if ("type" in c) {
|
|
70661
|
-
if (c.type === "text") {
|
|
70662
|
-
parts.push(c.text || "");
|
|
70663
|
-
} else if (c.type === "thinking") {
|
|
70664
|
-
parts.push("(thinking...)");
|
|
70665
|
-
} else if (c.type === "toolCall") {
|
|
70666
|
-
const name = c.name || "tool";
|
|
70667
|
-
parts.push(`[${name}]`);
|
|
70668
|
-
}
|
|
70669
|
-
}
|
|
70670
|
-
}
|
|
70671
|
-
return parts.join(" ");
|
|
70672
|
-
}
|
|
70673
|
-
return "";
|
|
70674
|
-
};
|
|
70675
|
-
if (msg.role === "user") {
|
|
70676
|
-
return extractTextFromContent(msg.content) || "(empty)";
|
|
70677
|
-
}
|
|
70678
|
-
if (msg.role === "assistant") {
|
|
70679
|
-
const textContent = extractTextFromContent(msg.content);
|
|
70680
|
-
if (textContent) {
|
|
70681
|
-
return textContent;
|
|
70682
|
-
}
|
|
70683
|
-
if (msg.stopReason === "aborted") {
|
|
70684
|
-
return "(aborted)";
|
|
70685
|
-
}
|
|
70686
|
-
if (msg.errorMessage) {
|
|
70687
|
-
return `(error: ${msg.errorMessage.slice(0, 50)})`;
|
|
70688
|
-
}
|
|
70689
|
-
return "(no content)";
|
|
70690
|
-
}
|
|
70691
|
-
if (msg.role === "toolResult") {
|
|
70692
|
-
const content = msg.content;
|
|
70693
|
-
let contentPreview = "";
|
|
70694
|
-
if (Array.isArray(content)) {
|
|
70695
|
-
const textParts = content.filter((c) => typeof c === "object" && c !== null && "type" in c && c.type === "text").map((c) => c.text || "").join("");
|
|
70696
|
-
contentPreview = textParts.slice(0, 80);
|
|
70697
|
-
if (textParts.length > 80) contentPreview += "...";
|
|
70698
|
-
}
|
|
70699
|
-
const toolName = msg.toolName || "tool";
|
|
70700
|
-
if (contentPreview) {
|
|
70701
|
-
return `[${toolName}]: ${contentPreview}`;
|
|
70702
|
-
}
|
|
70703
|
-
return `[${toolName}]`;
|
|
70704
|
-
}
|
|
70705
|
-
return `[${msg.role || "unknown"}]`;
|
|
70706
|
-
}
|
|
70707
|
-
function getRoleName(entry) {
|
|
70708
|
-
if (entry.type === "fork") return "fork";
|
|
70709
|
-
if (entry.type === "compaction") return "compact";
|
|
70710
|
-
if (!entry.message) return "unknown";
|
|
70711
|
-
const role = entry.message.role;
|
|
70712
|
-
switch (role) {
|
|
70713
|
-
case "user":
|
|
70714
|
-
return "user";
|
|
70715
|
-
case "assistant":
|
|
70716
|
-
return "assistant";
|
|
70717
|
-
case "toolResult":
|
|
70718
|
-
return "tool";
|
|
70719
|
-
default:
|
|
70720
|
-
return role || "unknown";
|
|
70721
|
-
}
|
|
70722
|
-
}
|
|
70723
|
-
function getRoleColor(role) {
|
|
70956
|
+
var MIN_PAGE_SIZE = 48;
|
|
70957
|
+
var MAX_PAGE_SIZE = 256;
|
|
70958
|
+
var SEGMENT_WIDTH = 4;
|
|
70959
|
+
var MIN_BODY_WIDTH = 12;
|
|
70960
|
+
var PREFIX_DEPTH_ABS_CAP = 24;
|
|
70961
|
+
var SEARCH_SCAN_PAGE_LIMIT = 16;
|
|
70962
|
+
var COLLAPSED_CAP = 256;
|
|
70963
|
+
function roleName(summary) {
|
|
70964
|
+
if (summary.type === "fork") return "fork";
|
|
70965
|
+
if (summary.type === "compaction") return "compact";
|
|
70966
|
+
if (summary.type === "custom") return "custom";
|
|
70967
|
+
return summary.role ?? "entry";
|
|
70968
|
+
}
|
|
70969
|
+
function roleColor(role) {
|
|
70724
70970
|
switch (role) {
|
|
70725
70971
|
case "user":
|
|
70726
70972
|
return theme.fg("accent", role);
|
|
70727
70973
|
case "assistant":
|
|
70728
70974
|
return theme.fg("text", role);
|
|
70975
|
+
case "toolResult":
|
|
70729
70976
|
case "tool":
|
|
70730
70977
|
return theme.fg("dim", role);
|
|
70731
70978
|
case "fork":
|
|
@@ -70736,57 +70983,47 @@ function getRoleColor(role) {
|
|
|
70736
70983
|
return theme.fg("muted", role);
|
|
70737
70984
|
}
|
|
70738
70985
|
}
|
|
70986
|
+
function seqFromEntryId(entryId) {
|
|
70987
|
+
if (!entryId) return null;
|
|
70988
|
+
const match = /^e(\d+)-/.exec(entryId);
|
|
70989
|
+
if (!match) return null;
|
|
70990
|
+
const seq = Number(match[1]);
|
|
70991
|
+
return Number.isInteger(seq) && seq > 0 ? seq : null;
|
|
70992
|
+
}
|
|
70739
70993
|
function createLine(content, width, isSelected) {
|
|
70740
|
-
const normalized = content.replace(/[\r\n]+/g, " ")
|
|
70741
|
-
|
|
70742
|
-
|
|
70743
|
-
line = INVERSE + normalized + RESET;
|
|
70744
|
-
} else {
|
|
70745
|
-
line = RESET + normalized;
|
|
70746
|
-
}
|
|
70747
|
-
const visibleLen = line.replace(/\x1b\[[0-9;]*m/g, "").length;
|
|
70748
|
-
if (visibleLen < width) {
|
|
70749
|
-
line += " ".repeat(width - visibleLen);
|
|
70750
|
-
}
|
|
70751
|
-
line += RESET;
|
|
70752
|
-
return truncateToWidth(line, width);
|
|
70994
|
+
const normalized = content.replace(/[\r\n]+/g, " ");
|
|
70995
|
+
const body = isSelected ? INVERSE + normalized : normalized;
|
|
70996
|
+
return truncateToWidth(body + RESET, width, "...", true);
|
|
70753
70997
|
}
|
|
70754
|
-
function
|
|
70755
|
-
|
|
70756
|
-
|
|
70757
|
-
|
|
70758
|
-
|
|
70759
|
-
const isLast = i === nodes.length - 1;
|
|
70760
|
-
result.push({
|
|
70761
|
-
node,
|
|
70762
|
-
depth: node.depth,
|
|
70763
|
-
isLast,
|
|
70764
|
-
parentPrefixes: [...parentPrefixes],
|
|
70765
|
-
index: currentIndex++
|
|
70766
|
-
});
|
|
70767
|
-
if (node.children.length > 0) {
|
|
70768
|
-
const childPrefix = isLast ? TREE_CHARS.space : TREE_CHARS.pipe;
|
|
70769
|
-
const childItems = flattenTree(
|
|
70770
|
-
node.children,
|
|
70771
|
-
[...parentPrefixes, childPrefix],
|
|
70772
|
-
currentIndex
|
|
70773
|
-
);
|
|
70774
|
-
result.push(...childItems);
|
|
70775
|
-
currentIndex += childItems.length;
|
|
70776
|
-
}
|
|
70777
|
-
}
|
|
70778
|
-
return result;
|
|
70998
|
+
function clampPrefixForDisplay(prefix, budget) {
|
|
70999
|
+
if (budget <= 0) return "";
|
|
71000
|
+
if (prefix.length <= budget) return prefix;
|
|
71001
|
+
const keep = Math.floor((budget - 1) / SEGMENT_WIDTH) * SEGMENT_WIDTH;
|
|
71002
|
+
return TREE_CHARS.hiddenAncestry + (keep > 0 ? prefix.slice(-keep) : "");
|
|
70779
71003
|
}
|
|
70780
71004
|
var TreeSelectorComponent = class {
|
|
70781
|
-
|
|
70782
|
-
|
|
70783
|
-
|
|
71005
|
+
options;
|
|
71006
|
+
/** The single resident window of headers (bounded by pageSize). */
|
|
71007
|
+
pageSummaries = [];
|
|
71008
|
+
totalEntries;
|
|
71009
|
+
hasPrev = false;
|
|
71010
|
+
hasNext = false;
|
|
71011
|
+
rows = [];
|
|
71012
|
+
filteredRows = [];
|
|
70784
71013
|
selectedIndex = 0;
|
|
70785
71014
|
maxVisibleLines;
|
|
71015
|
+
pageSizeValue;
|
|
71016
|
+
prefixDepthCap;
|
|
70786
71017
|
filterMode = "all";
|
|
70787
71018
|
searchQuery = "";
|
|
70788
|
-
|
|
70789
|
-
|
|
71019
|
+
statusMessage = null;
|
|
71020
|
+
collapsed = /* @__PURE__ */ new Map();
|
|
71021
|
+
// Bounded-memory instrumentation (tests/telemetry).
|
|
71022
|
+
maxResidentHeadersSeen = 0;
|
|
71023
|
+
maxPrefixCharsSeen = 0;
|
|
71024
|
+
currentTotalPrefixChars = 0;
|
|
71025
|
+
fetchCallCount = 0;
|
|
71026
|
+
headersFetchedTotal = 0;
|
|
70790
71027
|
onSelect;
|
|
70791
71028
|
onCancel;
|
|
70792
71029
|
_focused = false;
|
|
@@ -70796,189 +71033,387 @@ var TreeSelectorComponent = class {
|
|
|
70796
71033
|
set focused(value) {
|
|
70797
71034
|
this._focused = value;
|
|
70798
71035
|
}
|
|
70799
|
-
constructor(
|
|
70800
|
-
this.
|
|
70801
|
-
this.
|
|
70802
|
-
this.
|
|
70803
|
-
this.
|
|
70804
|
-
this.
|
|
70805
|
-
this.
|
|
70806
|
-
|
|
70807
|
-
|
|
70808
|
-
|
|
70809
|
-
|
|
70810
|
-
|
|
70811
|
-
|
|
71036
|
+
constructor(options) {
|
|
71037
|
+
this.options = options;
|
|
71038
|
+
this.totalEntries = options.totalEntries;
|
|
71039
|
+
this.maxVisibleLines = Math.max(15, Math.floor(options.terminalHeight * 0.6));
|
|
71040
|
+
this.pageSizeValue = Math.max(MIN_PAGE_SIZE, Math.min(MAX_PAGE_SIZE, this.maxVisibleLines * 3));
|
|
71041
|
+
this.prefixDepthCap = Math.max(3, Math.min(PREFIX_DEPTH_ABS_CAP, this.maxVisibleLines));
|
|
71042
|
+
this.onSelect = options.onSelect;
|
|
71043
|
+
this.onCancel = options.onCancel;
|
|
71044
|
+
if (options.totalEntries === 0) {
|
|
71045
|
+
setTimeout(() => options.onCancel(), 100);
|
|
71046
|
+
return;
|
|
71047
|
+
}
|
|
71048
|
+
const activeSeq = this.resolveActiveSeq() ?? options.totalEntries;
|
|
71049
|
+
const afterSeq = Math.max(0, activeSeq - Math.floor(this.pageSizeValue / 2));
|
|
71050
|
+
this.loadWindow(afterSeq);
|
|
71051
|
+
this.selectNearestSeq(activeSeq);
|
|
71052
|
+
}
|
|
71053
|
+
/**
|
|
71054
|
+
* Locate the active entry without loading bodies: prefer the commit
|
|
71055
|
+
* sequence encoded in the entry id, then the deepest active-path seq
|
|
71056
|
+
* (children always commit after parents, so the max is the active leaf).
|
|
71057
|
+
*/
|
|
71058
|
+
resolveActiveSeq() {
|
|
71059
|
+
const fromId = seqFromEntryId(this.options.activeEntryId);
|
|
71060
|
+
if (fromId !== null) return fromId;
|
|
71061
|
+
let deepest = 0;
|
|
71062
|
+
for (const seq of this.options.activePathSeqs) {
|
|
71063
|
+
if (seq > deepest) deepest = seq;
|
|
71064
|
+
}
|
|
71065
|
+
return deepest > 0 ? deepest : null;
|
|
71066
|
+
}
|
|
71067
|
+
/** Select the row whose seq equals `target`, else the nearest earlier row. */
|
|
71068
|
+
selectNearestSeq(target) {
|
|
71069
|
+
let chosen = -1;
|
|
71070
|
+
for (let i = 0; i < this.filteredRows.length; i++) {
|
|
71071
|
+
const seq = this.filteredRows[i].summary.seq;
|
|
71072
|
+
if (seq === target) {
|
|
71073
|
+
chosen = i;
|
|
71074
|
+
break;
|
|
70812
71075
|
}
|
|
70813
|
-
|
|
70814
|
-
this.selectedIndex = this.flatItems.length - 1;
|
|
71076
|
+
if (seq < target) chosen = i;
|
|
70815
71077
|
}
|
|
70816
|
-
|
|
70817
|
-
|
|
71078
|
+
this.selectedIndex = chosen === -1 ? 0 : chosen;
|
|
71079
|
+
}
|
|
71080
|
+
/** Current resident header count (tests/telemetry; one window only). */
|
|
71081
|
+
get loadedCount() {
|
|
71082
|
+
return this.pageSummaries.length;
|
|
71083
|
+
}
|
|
71084
|
+
/** High-water mark of resident headers across the component lifetime. */
|
|
71085
|
+
get maxResidentHeaders() {
|
|
71086
|
+
return this.maxResidentHeadersSeen;
|
|
71087
|
+
}
|
|
71088
|
+
/** High-water mark of per-row prefix characters. */
|
|
71089
|
+
get maxPrefixChars() {
|
|
71090
|
+
return this.maxPrefixCharsSeen;
|
|
71091
|
+
}
|
|
71092
|
+
/** Sum of prefix characters across the current rows. */
|
|
71093
|
+
get totalPrefixChars() {
|
|
71094
|
+
return this.currentTotalPrefixChars;
|
|
71095
|
+
}
|
|
71096
|
+
/** Configured header window size. */
|
|
71097
|
+
get pageSize() {
|
|
71098
|
+
return this.pageSizeValue;
|
|
71099
|
+
}
|
|
71100
|
+
/** Number of fetchSummaries calls issued. */
|
|
71101
|
+
get fetchCount() {
|
|
71102
|
+
return this.fetchCallCount;
|
|
71103
|
+
}
|
|
71104
|
+
/** Cumulative headers returned by fetchSummaries (all pages ever fetched). */
|
|
71105
|
+
get headersFetched() {
|
|
71106
|
+
return this.headersFetchedTotal;
|
|
71107
|
+
}
|
|
71108
|
+
/** Current collapsed-id count (bounded by COLLAPSED_CAP). */
|
|
71109
|
+
get collapsedCount() {
|
|
71110
|
+
return this.collapsed.size;
|
|
71111
|
+
}
|
|
71112
|
+
/** Seq of the selected row, or null when nothing is selected. */
|
|
71113
|
+
get selectedSeq() {
|
|
71114
|
+
return this.filteredRows[this.selectedIndex]?.summary.seq ?? null;
|
|
71115
|
+
}
|
|
71116
|
+
/** First and last seq of the resident window, or null when empty. */
|
|
71117
|
+
get windowSeqRange() {
|
|
71118
|
+
if (this.pageSummaries.length === 0) return null;
|
|
71119
|
+
return [this.pageSummaries[0].seq, this.pageSummaries[this.pageSummaries.length - 1].seq];
|
|
71120
|
+
}
|
|
71121
|
+
/**
|
|
71122
|
+
* Fetch one window of headers and adopt it as the single resident page.
|
|
71123
|
+
* The previous window is replaced (not merged), keeping residency at
|
|
71124
|
+
* O(pageSize). `upperExclusiveSeq` trims overlap when paging backward;
|
|
71125
|
+
* entries trimmed away still count toward hasNext so the forward
|
|
71126
|
+
* direction never strands a short history behind a backward page.
|
|
71127
|
+
* Returns false when the fetch adopted nothing (boundary/gap).
|
|
71128
|
+
*/
|
|
71129
|
+
fetchWindow(afterSeq, upperExclusiveSeq) {
|
|
71130
|
+
const page = this.options.fetchSummaries(afterSeq > 0 ? afterSeq : void 0, this.pageSizeValue);
|
|
71131
|
+
this.fetchCallCount++;
|
|
71132
|
+
this.headersFetchedTotal += page.summaries.length;
|
|
71133
|
+
let summaries = page.summaries.length > this.pageSizeValue ? page.summaries.slice(0, this.pageSizeValue) : page.summaries;
|
|
71134
|
+
let trimmedAway = 0;
|
|
71135
|
+
if (upperExclusiveSeq !== null) {
|
|
71136
|
+
const kept = summaries.filter((summary) => summary.seq < upperExclusiveSeq);
|
|
71137
|
+
trimmedAway = summaries.length - kept.length;
|
|
71138
|
+
summaries = kept;
|
|
71139
|
+
}
|
|
71140
|
+
this.hasNext = page.hasMore || trimmedAway > 0;
|
|
71141
|
+
this.totalEntries = page.total;
|
|
71142
|
+
if (summaries.length === 0) {
|
|
71143
|
+
return false;
|
|
70818
71144
|
}
|
|
71145
|
+
this.pageSummaries = summaries;
|
|
71146
|
+
this.maxResidentHeadersSeen = Math.max(this.maxResidentHeadersSeen, this.pageSummaries.length);
|
|
71147
|
+
this.hasPrev = summaries[0].seq > 1;
|
|
71148
|
+
this.rebuildRows();
|
|
71149
|
+
return true;
|
|
70819
71150
|
}
|
|
70820
|
-
|
|
70821
|
-
|
|
70822
|
-
|
|
70823
|
-
|
|
70824
|
-
|
|
70825
|
-
|
|
70826
|
-
|
|
71151
|
+
loadWindow(afterSeq) {
|
|
71152
|
+
this.fetchWindow(afterSeq, null);
|
|
71153
|
+
}
|
|
71154
|
+
/**
|
|
71155
|
+
* Load the window immediately before the current one. Backs off (up to a
|
|
71156
|
+
* few attempts) around seq gaps, then reports the oldest boundary.
|
|
71157
|
+
*/
|
|
71158
|
+
goToPreviousPage() {
|
|
71159
|
+
if (this.pageSummaries.length === 0 || !this.hasPrev) return false;
|
|
71160
|
+
const firstSeq = this.pageSummaries[0].seq;
|
|
71161
|
+
let back = Math.max(0, firstSeq - 1 - this.pageSizeValue);
|
|
71162
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
71163
|
+
if (this.fetchWindow(back, firstSeq)) {
|
|
71164
|
+
this.selectedIndex = Math.max(0, this.filteredRows.length - 1);
|
|
71165
|
+
return true;
|
|
70827
71166
|
}
|
|
70828
|
-
|
|
70829
|
-
|
|
71167
|
+
if (back === 0) break;
|
|
71168
|
+
back = Math.max(0, back - this.pageSizeValue);
|
|
71169
|
+
}
|
|
71170
|
+
this.hasPrev = false;
|
|
71171
|
+
return false;
|
|
70830
71172
|
}
|
|
70831
|
-
|
|
70832
|
-
|
|
70833
|
-
|
|
70834
|
-
|
|
70835
|
-
|
|
70836
|
-
|
|
70837
|
-
|
|
71173
|
+
/** Load the window immediately after the current one. */
|
|
71174
|
+
goToNextPage() {
|
|
71175
|
+
if (this.pageSummaries.length === 0 || !this.hasNext) return false;
|
|
71176
|
+
const lastSeq = this.pageSummaries[this.pageSummaries.length - 1].seq;
|
|
71177
|
+
let anchor = lastSeq;
|
|
71178
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
71179
|
+
if (this.fetchWindow(anchor, null)) {
|
|
71180
|
+
this.selectedIndex = 0;
|
|
71181
|
+
return true;
|
|
70838
71182
|
}
|
|
70839
|
-
|
|
70840
|
-
|
|
70841
|
-
|
|
70842
|
-
|
|
70843
|
-
|
|
70844
|
-
|
|
70845
|
-
|
|
70846
|
-
|
|
70847
|
-
|
|
70848
|
-
|
|
70849
|
-
|
|
70850
|
-
|
|
70851
|
-
|
|
70852
|
-
const
|
|
70853
|
-
|
|
71183
|
+
if (!this.hasNext) break;
|
|
71184
|
+
anchor += this.pageSizeValue;
|
|
71185
|
+
}
|
|
71186
|
+
return false;
|
|
71187
|
+
}
|
|
71188
|
+
/**
|
|
71189
|
+
* Iteratively flatten the resident window. Parents always commit before
|
|
71190
|
+
* children, so one forward pass resolves in-window ancestry; an explicit
|
|
71191
|
+
* stack (no recursion) emits DFS rows whose prefixes are capped to
|
|
71192
|
+
* prefixDepthCap segments, so prefix memory stays O(rows).
|
|
71193
|
+
*/
|
|
71194
|
+
rebuildRows() {
|
|
71195
|
+
const count = this.pageSummaries.length;
|
|
71196
|
+
const seqToIndex = /* @__PURE__ */ new Map();
|
|
71197
|
+
const depth = new Int32Array(count);
|
|
71198
|
+
const parentIndex = new Int32Array(count).fill(-1);
|
|
71199
|
+
const childLists = new Array(count);
|
|
71200
|
+
for (let i = 0; i < count; i++) {
|
|
71201
|
+
const summary = this.pageSummaries[i];
|
|
71202
|
+
seqToIndex.set(summary.seq, i);
|
|
71203
|
+
const parent = summary.parentSeq === null ? -1 : seqToIndex.get(summary.parentSeq) ?? -1;
|
|
71204
|
+
if (parent >= 0) {
|
|
71205
|
+
depth[i] = depth[parent] + 1;
|
|
71206
|
+
parentIndex[i] = parent;
|
|
71207
|
+
const bucket = childLists[parent];
|
|
71208
|
+
if (bucket) bucket.push(i);
|
|
71209
|
+
else childLists[parent] = [i];
|
|
71210
|
+
}
|
|
71211
|
+
}
|
|
71212
|
+
const capChars = this.prefixDepthCap * SEGMENT_WIDTH;
|
|
71213
|
+
const capSegments = (segments) => segments.length > capChars ? segments.slice(segments.length - capChars) : segments;
|
|
71214
|
+
const roots = [];
|
|
71215
|
+
for (let i = 0; i < count; i++) {
|
|
71216
|
+
if (parentIndex[i] === -1) roots.push(i);
|
|
71217
|
+
}
|
|
71218
|
+
const rows = [];
|
|
71219
|
+
const stack = [];
|
|
71220
|
+
for (let i = roots.length - 1; i >= 0; i--) {
|
|
71221
|
+
stack.push({ index: roots[i], base: "", isLast: i === roots.length - 1 });
|
|
71222
|
+
}
|
|
71223
|
+
while (stack.length > 0) {
|
|
71224
|
+
const item = stack.pop();
|
|
71225
|
+
const summary = this.pageSummaries[item.index];
|
|
71226
|
+
const rowDepth = depth[item.index];
|
|
71227
|
+
const connector = rowDepth === 0 ? "" : item.isLast ? TREE_CHARS.corner : TREE_CHARS.branch;
|
|
71228
|
+
const segments = capSegments(item.base + connector);
|
|
71229
|
+
const ancestryHidden = rowDepth > this.prefixDepthCap || summary.parentSeq !== null && parentIndex[item.index] === -1;
|
|
71230
|
+
const prefix = ancestryHidden ? TREE_CHARS.hiddenAncestry + segments : segments;
|
|
71231
|
+
rows.push({
|
|
71232
|
+
summary,
|
|
71233
|
+
prefix,
|
|
71234
|
+
hasChildren: summary.childCount > 0,
|
|
71235
|
+
inWindowChildren: childLists[item.index] !== void 0
|
|
71236
|
+
});
|
|
71237
|
+
if (prefix.length > this.maxPrefixCharsSeen) this.maxPrefixCharsSeen = prefix.length;
|
|
71238
|
+
if (this.collapsed.has(summary.id)) continue;
|
|
71239
|
+
const children = childLists[item.index];
|
|
71240
|
+
if (children === void 0) continue;
|
|
71241
|
+
const childBase = capSegments(item.base + (item.isLast ? TREE_CHARS.space : TREE_CHARS.pipe));
|
|
71242
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
71243
|
+
stack.push({ index: children[i], base: childBase, isLast: i === children.length - 1 });
|
|
71244
|
+
}
|
|
71245
|
+
}
|
|
71246
|
+
this.rows = rows;
|
|
71247
|
+
let totalPrefix = 0;
|
|
71248
|
+
for (const row of rows) totalPrefix += row.prefix.length;
|
|
71249
|
+
this.currentTotalPrefixChars = totalPrefix;
|
|
70854
71250
|
this.applyFilter();
|
|
70855
71251
|
}
|
|
70856
71252
|
applyFilter() {
|
|
70857
71253
|
if (!this.searchQuery && this.filterMode === "all") {
|
|
70858
|
-
this.
|
|
70859
|
-
|
|
70860
|
-
|
|
70861
|
-
|
|
70862
|
-
|
|
70863
|
-
const entry = item.node.entry;
|
|
70864
|
-
if (this.filterMode === "user-only") {
|
|
70865
|
-
if (entry.type !== "message" || entry.message?.role !== "user") {
|
|
71254
|
+
this.filteredRows = this.rows;
|
|
71255
|
+
} else {
|
|
71256
|
+
const tokens = this.searchQuery.toLowerCase().split(/\s+/).filter(Boolean);
|
|
71257
|
+
this.filteredRows = this.rows.filter((row) => {
|
|
71258
|
+
if (this.filterMode === "user-only" && (row.summary.type !== "message" || row.summary.role !== "user")) {
|
|
70866
71259
|
return false;
|
|
70867
71260
|
}
|
|
70868
|
-
|
|
70869
|
-
|
|
70870
|
-
|
|
70871
|
-
|
|
70872
|
-
|
|
70873
|
-
|
|
70874
|
-
);
|
|
70875
|
-
}
|
|
70876
|
-
return true;
|
|
70877
|
-
});
|
|
70878
|
-
this.selectedIndex = Math.max(
|
|
70879
|
-
0,
|
|
70880
|
-
Math.min(this.selectedIndex, this.filteredItems.length - 1)
|
|
70881
|
-
);
|
|
71261
|
+
if (tokens.length === 0) return true;
|
|
71262
|
+
const text = `${row.summary.preview ?? ""} ${roleName(row.summary)} ${row.summary.customType ?? ""} ${row.summary.label ?? ""} ${row.summary.seq}`.toLowerCase();
|
|
71263
|
+
return tokens.every((token) => text.includes(token));
|
|
71264
|
+
});
|
|
71265
|
+
}
|
|
71266
|
+
this.selectedIndex = Math.max(0, Math.min(this.selectedIndex, this.filteredRows.length - 1));
|
|
70882
71267
|
}
|
|
70883
|
-
|
|
70884
|
-
|
|
70885
|
-
|
|
70886
|
-
|
|
70887
|
-
|
|
70888
|
-
|
|
70889
|
-
|
|
71268
|
+
moveUp() {
|
|
71269
|
+
if (this.selectedIndex > 0) {
|
|
71270
|
+
this.selectedIndex--;
|
|
71271
|
+
this.statusMessage = null;
|
|
71272
|
+
return;
|
|
71273
|
+
}
|
|
71274
|
+
if (this.goToPreviousPage()) {
|
|
71275
|
+
this.statusMessage = null;
|
|
71276
|
+
return;
|
|
71277
|
+
}
|
|
71278
|
+
this.selectedIndex = 0;
|
|
71279
|
+
this.statusMessage = "at oldest entry";
|
|
71280
|
+
}
|
|
71281
|
+
moveDown() {
|
|
71282
|
+
if (this.selectedIndex < this.filteredRows.length - 1) {
|
|
71283
|
+
this.selectedIndex++;
|
|
71284
|
+
this.statusMessage = null;
|
|
71285
|
+
return;
|
|
71286
|
+
}
|
|
71287
|
+
if (this.goToNextPage()) {
|
|
71288
|
+
this.statusMessage = null;
|
|
71289
|
+
return;
|
|
71290
|
+
}
|
|
71291
|
+
this.statusMessage = this.filteredRows.length === 0 && this.searchQuery ? "no matches on this page - tab scans ahead" : "at latest entry";
|
|
71292
|
+
}
|
|
71293
|
+
pageNext() {
|
|
71294
|
+
if (this.goToNextPage()) {
|
|
71295
|
+
this.statusMessage = null;
|
|
70890
71296
|
} else {
|
|
70891
|
-
|
|
71297
|
+
this.statusMessage = this.pageSummaries.length === 0 ? "no entries" : "latest page";
|
|
70892
71298
|
}
|
|
70893
|
-
|
|
70894
|
-
|
|
71299
|
+
}
|
|
71300
|
+
pagePrev() {
|
|
71301
|
+
if (this.goToPreviousPage()) {
|
|
71302
|
+
this.statusMessage = null;
|
|
71303
|
+
} else {
|
|
71304
|
+
this.statusMessage = this.pageSummaries.length === 0 ? "no entries" : "oldest page";
|
|
70895
71305
|
}
|
|
70896
|
-
|
|
71306
|
+
}
|
|
71307
|
+
/**
|
|
71308
|
+
* Bounded "next match": step to the next in-page match, otherwise scan
|
|
71309
|
+
* forward at most SEARCH_SCAN_PAGE_LIMIT pages per press. Never scans
|
|
71310
|
+
* the whole history eagerly and never accumulates fetched pages.
|
|
71311
|
+
*/
|
|
71312
|
+
findNextMatch() {
|
|
71313
|
+
if (!this.searchQuery && this.filterMode === "all") {
|
|
71314
|
+
this.pageNext();
|
|
71315
|
+
return;
|
|
71316
|
+
}
|
|
71317
|
+
if (this.filteredRows.length > 1 && this.selectedIndex < this.filteredRows.length - 1) {
|
|
71318
|
+
this.selectedIndex++;
|
|
71319
|
+
this.statusMessage = null;
|
|
71320
|
+
return;
|
|
71321
|
+
}
|
|
71322
|
+
let scanned = 0;
|
|
71323
|
+
while (this.hasNext && scanned < SEARCH_SCAN_PAGE_LIMIT) {
|
|
71324
|
+
if (!this.goToNextPage()) break;
|
|
71325
|
+
scanned++;
|
|
71326
|
+
if (this.filteredRows.length > 0) {
|
|
71327
|
+
this.selectedIndex = 0;
|
|
71328
|
+
this.statusMessage = scanned === 1 ? "match on next page" : `match ${scanned} pages ahead`;
|
|
71329
|
+
return;
|
|
71330
|
+
}
|
|
71331
|
+
}
|
|
71332
|
+
if (!this.hasNext) {
|
|
71333
|
+
this.statusMessage = "no more matches - end of history";
|
|
71334
|
+
} else {
|
|
71335
|
+
this.statusMessage = `no matches in next ${scanned} pages - tab to continue`;
|
|
71336
|
+
}
|
|
71337
|
+
}
|
|
71338
|
+
toggleCollapse() {
|
|
71339
|
+
const selected = this.filteredRows[this.selectedIndex];
|
|
71340
|
+
if (!selected) return;
|
|
71341
|
+
if (this.collapsed.has(selected.summary.id)) {
|
|
71342
|
+
this.collapsed.delete(selected.summary.id);
|
|
71343
|
+
} else {
|
|
71344
|
+
if (this.collapsed.size >= COLLAPSED_CAP) {
|
|
71345
|
+
const oldest = this.collapsed.keys().next().value;
|
|
71346
|
+
if (oldest !== void 0) this.collapsed.delete(oldest);
|
|
71347
|
+
}
|
|
71348
|
+
this.collapsed.set(selected.summary.id, true);
|
|
71349
|
+
}
|
|
71350
|
+
this.rebuildRows();
|
|
70897
71351
|
}
|
|
70898
71352
|
render(width) {
|
|
70899
71353
|
const lines = [];
|
|
70900
71354
|
const totalLines = this.maxVisibleLines + 5;
|
|
71355
|
+
const range = this.windowSeqRange;
|
|
71356
|
+
const rangeLabel = range === null ? "empty" : `seqs ${range[0]}-${range[1]} of ${this.totalEntries}`;
|
|
70901
71357
|
lines.push(createLine(" Conversation Tree", width, false));
|
|
70902
71358
|
lines.push(
|
|
70903
71359
|
createLine(
|
|
70904
|
-
" \u2191\u2193:move \u2190\u2192:page e:
|
|
71360
|
+
" \u2191\u2193:move \u2190\u2192:page e:collapse tab:next match F:fork Enter:navigate Esc:cancel",
|
|
70905
71361
|
width,
|
|
70906
71362
|
false
|
|
70907
71363
|
)
|
|
70908
71364
|
);
|
|
70909
71365
|
lines.push(
|
|
70910
71366
|
createLine(
|
|
70911
|
-
this.searchQuery ? ` Search: ${this.searchQuery}` :
|
|
71367
|
+
this.searchQuery ? ` Search: ${this.searchQuery} (${this.filteredRows.length} on this page, tab:next match)` : ` Type to search (${rangeLabel})`,
|
|
70912
71368
|
width,
|
|
70913
71369
|
false
|
|
70914
71370
|
)
|
|
70915
71371
|
);
|
|
70916
|
-
lines.push(createLine("", width, false));
|
|
70917
|
-
if (this.
|
|
70918
|
-
|
|
71372
|
+
lines.push(createLine(this.statusMessage ? ` ${this.statusMessage}` : "", width, false));
|
|
71373
|
+
if (this.filteredRows.length === 0) {
|
|
71374
|
+
const notice = this.searchQuery || this.filterMode === "user-only" ? " (no matching entries on this page)" : " (no entries)";
|
|
71375
|
+
lines.push(createLine(notice, width, false));
|
|
71376
|
+
for (let i = 1; i < this.maxVisibleLines; i++) {
|
|
70919
71377
|
lines.push(createLine("", width, false));
|
|
70920
71378
|
}
|
|
70921
71379
|
} else {
|
|
70922
|
-
this.selectedIndex = Math.max(
|
|
70923
|
-
0,
|
|
70924
|
-
Math.min(this.selectedIndex, this.filteredItems.length - 1)
|
|
70925
|
-
);
|
|
71380
|
+
this.selectedIndex = Math.max(0, Math.min(this.selectedIndex, this.filteredRows.length - 1));
|
|
70926
71381
|
let startIndex = Math.max(
|
|
70927
71382
|
0,
|
|
70928
71383
|
Math.min(
|
|
70929
71384
|
this.selectedIndex - Math.floor(this.maxVisibleLines / 2),
|
|
70930
|
-
this.
|
|
71385
|
+
this.filteredRows.length - this.maxVisibleLines
|
|
70931
71386
|
)
|
|
70932
71387
|
);
|
|
70933
|
-
|
|
70934
|
-
startIndex + this.maxVisibleLines,
|
|
70935
|
-
this.filteredItems.length
|
|
70936
|
-
);
|
|
71388
|
+
const endIndex = Math.min(startIndex + this.maxVisibleLines, this.filteredRows.length);
|
|
70937
71389
|
if (endIndex - startIndex < this.maxVisibleLines && startIndex > 0) {
|
|
70938
71390
|
startIndex = Math.max(0, endIndex - this.maxVisibleLines);
|
|
70939
71391
|
}
|
|
70940
71392
|
for (let i = startIndex; i < endIndex; i++) {
|
|
70941
|
-
const
|
|
70942
|
-
const
|
|
70943
|
-
const
|
|
70944
|
-
const
|
|
70945
|
-
const
|
|
70946
|
-
|
|
70947
|
-
|
|
70948
|
-
|
|
70949
|
-
|
|
70950
|
-
|
|
70951
|
-
|
|
70952
|
-
|
|
70953
|
-
return null;
|
|
70954
|
-
};
|
|
70955
|
-
const originalNode = findOriginalNode(this.tree, item.node.id);
|
|
70956
|
-
const hasChildren = originalNode ? originalNode.children.length > 0 : false;
|
|
70957
|
-
const isExpanded = this.expandedNodes.has(item.node.id);
|
|
70958
|
-
const activeIndicator = item.node.isActive ? theme.fg("success", TREE_CHARS.active) : DIM + TREE_CHARS.inactive + RESET;
|
|
70959
|
-
const expandIndicator = hasChildren ? isExpanded ? theme.fg("dim", "\u25BC ") : theme.fg("dim", "\u25B6 ") : " ";
|
|
70960
|
-
const roleName = getRoleName(entry);
|
|
70961
|
-
const roleColored = getRoleColor(roleName);
|
|
70962
|
-
const content = extractContent(entry);
|
|
70963
|
-
const availableWidth = width - visibleLength(prefix) - visibleLength(activeIndicator) - visibleLength(expandIndicator) - visibleLength(roleColored) - 2;
|
|
70964
|
-
const truncatedContent = availableWidth > 0 ? truncateToWidth(content, availableWidth) : "";
|
|
70965
|
-
const lineContent = `${prefix}${activeIndicator}${expandIndicator}${roleColored}: ${truncatedContent}`;
|
|
70966
|
-
lines.push(createLine(lineContent, width, isSelected));
|
|
70967
|
-
}
|
|
70968
|
-
const visibleCount = endIndex - startIndex;
|
|
70969
|
-
for (let i = visibleCount; i < this.maxVisibleLines; i++) {
|
|
71393
|
+
const row = this.filteredRows[i];
|
|
71394
|
+
const activeIndicator = this.options.activePathSeqs.has(row.summary.seq) ? theme.fg("success", TREE_CHARS.active) : DIM + TREE_CHARS.inactive + RESET;
|
|
71395
|
+
const expandIndicator = row.inWindowChildren ? theme.fg("dim", this.collapsed.has(row.summary.id) ? "\u25B6 " : "\u25BC ") : row.hasChildren ? theme.fg("dim", "\xB7\xB7") : " ";
|
|
71396
|
+
const role = roleColor(roleName(row.summary));
|
|
71397
|
+
const indicatorWidth = visibleWidth(activeIndicator) + visibleWidth(expandIndicator) + visibleWidth(role) + 2;
|
|
71398
|
+
const prefixBudget = Math.max(0, Math.min(Math.floor(width * 0.35), width - indicatorWidth - MIN_BODY_WIDTH));
|
|
71399
|
+
const displayPrefix = clampPrefixForDisplay(row.prefix, prefixBudget);
|
|
71400
|
+
const availableWidth = Math.max(0, width - visibleWidth(displayPrefix) - indicatorWidth);
|
|
71401
|
+
const content = truncateToWidth(row.summary.preview ?? "", availableWidth);
|
|
71402
|
+
lines.push(createLine(`${displayPrefix}${activeIndicator}${expandIndicator}${role}: ${content}`, width, i === this.selectedIndex));
|
|
71403
|
+
}
|
|
71404
|
+
for (let i = endIndex - startIndex; i < this.maxVisibleLines; i++) {
|
|
70970
71405
|
lines.push(createLine("", width, false));
|
|
70971
71406
|
}
|
|
70972
|
-
const selectedItem = this.filteredItems[this.selectedIndex];
|
|
70973
|
-
const activePath = selectedItem?.node.isActive ? " [active]" : "";
|
|
70974
|
-
lines.push(
|
|
70975
|
-
createLine(
|
|
70976
|
-
` (${this.selectedIndex + 1}/${this.filteredItems.length})${this.filterMode === "user-only" ? " [user]" : ""}${activePath}`,
|
|
70977
|
-
width,
|
|
70978
|
-
false
|
|
70979
|
-
)
|
|
70980
|
-
);
|
|
70981
71407
|
}
|
|
71408
|
+
const selectedRow = this.filteredRows[this.selectedIndex];
|
|
71409
|
+
const activePath = selectedRow && this.options.activePathSeqs.has(selectedRow.summary.seq) ? " [active]" : "";
|
|
71410
|
+
lines.push(
|
|
71411
|
+
createLine(
|
|
71412
|
+
` (${selectedRow ? this.selectedIndex + 1 : 0}/${this.filteredRows.length})${this.filterMode === "user-only" ? " [user]" : ""}${activePath} \xB7 ${rangeLabel}`,
|
|
71413
|
+
width,
|
|
71414
|
+
false
|
|
71415
|
+
)
|
|
71416
|
+
);
|
|
70982
71417
|
while (lines.length < totalLines) {
|
|
70983
71418
|
lines.push(createLine("", width, false));
|
|
70984
71419
|
}
|
|
@@ -70987,51 +71422,24 @@ var TreeSelectorComponent = class {
|
|
|
70987
71422
|
handleInput(keyData) {
|
|
70988
71423
|
const kb = getEditorKeybindings();
|
|
70989
71424
|
if (kb.matches(keyData, "selectUp")) {
|
|
70990
|
-
this.
|
|
71425
|
+
this.moveUp();
|
|
70991
71426
|
} else if (kb.matches(keyData, "selectDown")) {
|
|
70992
|
-
this.
|
|
70993
|
-
|
|
70994
|
-
|
|
70995
|
-
|
|
70996
|
-
|
|
70997
|
-
this.selectedIndex = Math.min(
|
|
70998
|
-
this.filteredItems.length - 1,
|
|
70999
|
-
this.selectedIndex + this.maxVisibleLines
|
|
71000
|
-
);
|
|
71001
|
-
} else if (kb.matches(keyData, "cursorLeft")) {
|
|
71002
|
-
this.selectedIndex = Math.max(0, this.selectedIndex - this.maxVisibleLines);
|
|
71427
|
+
this.moveDown();
|
|
71428
|
+
} else if (kb.matches(keyData, "cursorRight") || kb.matches(keyData, "selectPageDown")) {
|
|
71429
|
+
this.pageNext();
|
|
71430
|
+
} else if (kb.matches(keyData, "cursorLeft") || kb.matches(keyData, "selectPageUp")) {
|
|
71431
|
+
this.pagePrev();
|
|
71003
71432
|
} else if (keyData === "e" || keyData === "E") {
|
|
71004
|
-
|
|
71005
|
-
if (selected) {
|
|
71006
|
-
const findOriginalNode = (nodes, id) => {
|
|
71007
|
-
for (const node of nodes) {
|
|
71008
|
-
if (node.id === id) return node;
|
|
71009
|
-
if (node.children.length > 0) {
|
|
71010
|
-
const found = findOriginalNode(node.children, id);
|
|
71011
|
-
if (found) return found;
|
|
71012
|
-
}
|
|
71013
|
-
}
|
|
71014
|
-
return null;
|
|
71015
|
-
};
|
|
71016
|
-
const originalNode = findOriginalNode(this.tree, selected.node.id);
|
|
71017
|
-
if (originalNode && originalNode.children.length > 0) {
|
|
71018
|
-
if (this.expandedNodes.has(selected.node.id)) {
|
|
71019
|
-
this.expandedNodes.delete(selected.node.id);
|
|
71020
|
-
} else {
|
|
71021
|
-
this.expandedNodes.add(selected.node.id);
|
|
71022
|
-
}
|
|
71023
|
-
this.refreshFlatItems();
|
|
71024
|
-
}
|
|
71025
|
-
}
|
|
71433
|
+
this.toggleCollapse();
|
|
71026
71434
|
} else if (kb.matches(keyData, "selectConfirm")) {
|
|
71027
|
-
const selected = this.
|
|
71435
|
+
const selected = this.filteredRows[this.selectedIndex];
|
|
71028
71436
|
if (selected && this.onSelect) {
|
|
71029
|
-
this.onSelect(selected.
|
|
71437
|
+
this.onSelect(selected.summary.id, "navigate");
|
|
71030
71438
|
}
|
|
71031
71439
|
} else if (keyData === "f" || keyData === "F") {
|
|
71032
|
-
const selected = this.
|
|
71440
|
+
const selected = this.filteredRows[this.selectedIndex];
|
|
71033
71441
|
if (selected && this.onSelect) {
|
|
71034
|
-
this.onSelect(selected.
|
|
71442
|
+
this.onSelect(selected.summary.id, "fork");
|
|
71035
71443
|
}
|
|
71036
71444
|
} else if (kb.matches(keyData, "selectCancel")) {
|
|
71037
71445
|
if (this.searchQuery) {
|
|
@@ -71040,12 +71448,15 @@ var TreeSelectorComponent = class {
|
|
|
71040
71448
|
} else {
|
|
71041
71449
|
this.onCancel?.();
|
|
71042
71450
|
}
|
|
71451
|
+
} else if (matchesKey(keyData, "tab")) {
|
|
71452
|
+
this.findNextMatch();
|
|
71043
71453
|
} else if (matchesKey(keyData, "ctrl+u")) {
|
|
71044
71454
|
this.filterMode = this.filterMode === "user-only" ? "all" : "user-only";
|
|
71045
71455
|
this.applyFilter();
|
|
71046
71456
|
} else if (kb.matches(keyData, "deleteCharBackward")) {
|
|
71047
71457
|
if (this.searchQuery.length > 0) {
|
|
71048
|
-
|
|
71458
|
+
const last = searchSegmenter.segment(this.searchQuery).containing(this.searchQuery.length - 1);
|
|
71459
|
+
this.searchQuery = this.searchQuery.slice(0, last?.index ?? 0);
|
|
71049
71460
|
this.applyFilter();
|
|
71050
71461
|
}
|
|
71051
71462
|
} else {
|
|
@@ -71060,10 +71471,10 @@ var TreeSelectorComponent = class {
|
|
|
71060
71471
|
}
|
|
71061
71472
|
}
|
|
71062
71473
|
invalidate() {
|
|
71063
|
-
this.
|
|
71474
|
+
this.rebuildRows();
|
|
71064
71475
|
}
|
|
71065
71476
|
getSelectedEntryId() {
|
|
71066
|
-
return this.
|
|
71477
|
+
return this.filteredRows[this.selectedIndex]?.summary.id ?? null;
|
|
71067
71478
|
}
|
|
71068
71479
|
};
|
|
71069
71480
|
|
|
@@ -71265,16 +71676,16 @@ var Diff = class {
|
|
|
71265
71676
|
}
|
|
71266
71677
|
}
|
|
71267
71678
|
}
|
|
71268
|
-
addToPath(
|
|
71269
|
-
const last =
|
|
71679
|
+
addToPath(path34, added, removed, oldPosInc, options) {
|
|
71680
|
+
const last = path34.lastComponent;
|
|
71270
71681
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
71271
71682
|
return {
|
|
71272
|
-
oldPos:
|
|
71683
|
+
oldPos: path34.oldPos + oldPosInc,
|
|
71273
71684
|
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
71274
71685
|
};
|
|
71275
71686
|
} else {
|
|
71276
71687
|
return {
|
|
71277
|
-
oldPos:
|
|
71688
|
+
oldPos: path34.oldPos + oldPosInc,
|
|
71278
71689
|
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
71279
71690
|
};
|
|
71280
71691
|
}
|
|
@@ -71722,13 +72133,13 @@ function formatSize2(bytes) {
|
|
|
71722
72133
|
}
|
|
71723
72134
|
var DEFAULT_MAX_BYTES = 102400;
|
|
71724
72135
|
var DEFAULT_MAX_LINES = 100;
|
|
71725
|
-
function shortenPath(
|
|
71726
|
-
if (typeof
|
|
72136
|
+
function shortenPath(path34) {
|
|
72137
|
+
if (typeof path34 !== "string") return "";
|
|
71727
72138
|
const home = os5.homedir();
|
|
71728
|
-
if (
|
|
71729
|
-
return `~${
|
|
72139
|
+
if (path34.startsWith(home)) {
|
|
72140
|
+
return `~${path34.slice(home.length)}`;
|
|
71730
72141
|
}
|
|
71731
|
-
return
|
|
72142
|
+
return path34;
|
|
71732
72143
|
}
|
|
71733
72144
|
function replaceTabs(text) {
|
|
71734
72145
|
return text.replace(/\t/g, " ");
|
|
@@ -71738,6 +72149,18 @@ function str(value) {
|
|
|
71738
72149
|
if (value == null) return "";
|
|
71739
72150
|
return null;
|
|
71740
72151
|
}
|
|
72152
|
+
function projectResultForDisplay(result) {
|
|
72153
|
+
const content = result.content;
|
|
72154
|
+
if (!Array.isArray(content) || !content.some((block) => typeof block?.data === "string" && block.data.length > 0)) {
|
|
72155
|
+
return result;
|
|
72156
|
+
}
|
|
72157
|
+
return {
|
|
72158
|
+
...result,
|
|
72159
|
+
content: content.map(
|
|
72160
|
+
(block) => typeof block?.data === "string" && block.data.length > 0 ? { ...block, data: "" } : block
|
|
72161
|
+
)
|
|
72162
|
+
};
|
|
72163
|
+
}
|
|
71741
72164
|
function partialStr(value, maxLen = 30) {
|
|
71742
72165
|
if (typeof value === "string") {
|
|
71743
72166
|
if (value.length === 0) return "...";
|
|
@@ -71772,7 +72195,7 @@ var ToolExecutionComponent = class extends Container {
|
|
|
71772
72195
|
this.updateDisplay();
|
|
71773
72196
|
}
|
|
71774
72197
|
updateResult(result, isPartial = false) {
|
|
71775
|
-
this.result = result;
|
|
72198
|
+
this.result = projectResultForDisplay(result);
|
|
71776
72199
|
this.isPartial = isPartial;
|
|
71777
72200
|
this.updateDisplay();
|
|
71778
72201
|
}
|
|
@@ -71811,14 +72234,14 @@ ${renderManageTodoListResult(this.result, { expanded: this.expanded }, theme)}`;
|
|
|
71811
72234
|
}
|
|
71812
72235
|
} else if (this.toolName === "read_file") {
|
|
71813
72236
|
const rawPath = str(this.args?.file_path ?? this.args?.path);
|
|
71814
|
-
const
|
|
72237
|
+
const path34 = rawPath !== null ? shortenPath(rawPath) : null;
|
|
71815
72238
|
const offset = typeof this.args?.offset === "number" ? this.args.offset : void 0;
|
|
71816
72239
|
const limit = typeof this.args?.limit === "number" ? this.args.limit : void 0;
|
|
71817
72240
|
let pathDisplay;
|
|
71818
|
-
if (
|
|
72241
|
+
if (path34 === null) {
|
|
71819
72242
|
pathDisplay = invalidArg;
|
|
71820
|
-
} else if (
|
|
71821
|
-
pathDisplay = theme.fg("accent",
|
|
72243
|
+
} else if (path34) {
|
|
72244
|
+
pathDisplay = theme.fg("accent", path34);
|
|
71822
72245
|
} else {
|
|
71823
72246
|
const partialPath = partialStr(this.args?.file_path ?? this.args?.path);
|
|
71824
72247
|
pathDisplay = theme.fg("toolOutput", partialPath);
|
|
@@ -71865,12 +72288,12 @@ ${renderManageTodoListResult(this.result, { expanded: this.expanded }, theme)}`;
|
|
|
71865
72288
|
} else if (this.toolName === "write_file") {
|
|
71866
72289
|
const rawPath = str(this.args?.file_path ?? this.args?.path);
|
|
71867
72290
|
const fileContent = str(this.args?.content);
|
|
71868
|
-
const
|
|
72291
|
+
const path34 = rawPath !== null ? shortenPath(rawPath) : null;
|
|
71869
72292
|
let pathDisplay;
|
|
71870
|
-
if (
|
|
72293
|
+
if (path34 === null) {
|
|
71871
72294
|
pathDisplay = invalidArg;
|
|
71872
|
-
} else if (
|
|
71873
|
-
pathDisplay = theme.fg("accent",
|
|
72295
|
+
} else if (path34) {
|
|
72296
|
+
pathDisplay = theme.fg("accent", path34);
|
|
71874
72297
|
} else {
|
|
71875
72298
|
const partialPath = partialStr(this.args?.file_path ?? this.args?.path);
|
|
71876
72299
|
pathDisplay = theme.fg("toolOutput", partialPath);
|
|
@@ -71907,12 +72330,12 @@ ${theme.fg("error", errorText)}`;
|
|
|
71907
72330
|
}
|
|
71908
72331
|
} else if (this.toolName === "edit_file") {
|
|
71909
72332
|
const rawPath = str(this.args?.file_path ?? this.args?.path);
|
|
71910
|
-
const
|
|
72333
|
+
const path34 = rawPath !== null ? shortenPath(rawPath) : null;
|
|
71911
72334
|
let pathDisplay;
|
|
71912
|
-
if (
|
|
72335
|
+
if (path34 === null) {
|
|
71913
72336
|
pathDisplay = invalidArg;
|
|
71914
|
-
} else if (
|
|
71915
|
-
pathDisplay = theme.fg("accent",
|
|
72337
|
+
} else if (path34) {
|
|
72338
|
+
pathDisplay = theme.fg("accent", path34);
|
|
71916
72339
|
} else {
|
|
71917
72340
|
const partialPath = partialStr(this.args?.file_path ?? this.args?.path);
|
|
71918
72341
|
pathDisplay = theme.fg("toolOutput", partialPath);
|
|
@@ -71937,7 +72360,7 @@ ${theme.fg("error", errorText)}`;
|
|
|
71937
72360
|
const diff = this.result.details.diff;
|
|
71938
72361
|
const firstChangedLine = this.result.details.firstChangedLine;
|
|
71939
72362
|
if (firstChangedLine) {
|
|
71940
|
-
text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent",
|
|
72363
|
+
text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent", path34 || rawPath)}${theme.fg("warning", `:${firstChangedLine}`)}`;
|
|
71941
72364
|
}
|
|
71942
72365
|
const lines = diff.split("\n");
|
|
71943
72366
|
const maxLines = this.expanded ? lines.length : 15;
|
|
@@ -71957,7 +72380,7 @@ ${theme.fg("error", errorText)}`;
|
|
|
71957
72380
|
const diff = generateEditDiff(oldText, newText, rawPath);
|
|
71958
72381
|
const firstChangedLine = findFirstChangedLine(oldText, newText);
|
|
71959
72382
|
if (firstChangedLine) {
|
|
71960
|
-
text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent",
|
|
72383
|
+
text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent", path34 || rawPath)}${theme.fg("warning", `:${firstChangedLine}`)}`;
|
|
71961
72384
|
}
|
|
71962
72385
|
const lines = diff.split("\n");
|
|
71963
72386
|
const maxLines = this.expanded ? lines.length : 15;
|
|
@@ -71976,9 +72399,9 @@ ${theme.fg("error", errorText)}`;
|
|
|
71976
72399
|
}
|
|
71977
72400
|
} else if (this.toolName === "list_dir") {
|
|
71978
72401
|
const rawPath = str(this.args?.path);
|
|
71979
|
-
const
|
|
72402
|
+
const path34 = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
71980
72403
|
const limit = this.args?.limit;
|
|
71981
|
-
text = `${theme.fg("toolTitle", theme.bold("list_dir"))} ${
|
|
72404
|
+
text = `${theme.fg("toolTitle", theme.bold("list_dir"))} ${path34 === null ? invalidArg : theme.fg("accent", path34)}`;
|
|
71982
72405
|
if (limit !== void 0) {
|
|
71983
72406
|
text += theme.fg("toolOutput", ` (limit ${limit})`);
|
|
71984
72407
|
}
|
|
@@ -72014,9 +72437,9 @@ ${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
|
|
|
72014
72437
|
} else if (this.toolName === "find_files") {
|
|
72015
72438
|
const pattern = str(this.args?.pattern);
|
|
72016
72439
|
const rawPath = str(this.args?.path);
|
|
72017
|
-
const
|
|
72440
|
+
const path34 = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
72018
72441
|
const limit = this.args?.limit;
|
|
72019
|
-
text = theme.fg("toolTitle", theme.bold("find_files")) + " " + (pattern === null ? invalidArg : theme.fg("accent", pattern || "")) + theme.fg("toolOutput", ` in ${
|
|
72442
|
+
text = theme.fg("toolTitle", theme.bold("find_files")) + " " + (pattern === null ? invalidArg : theme.fg("accent", pattern || "")) + theme.fg("toolOutput", ` in ${path34 === null ? invalidArg : path34}`);
|
|
72020
72443
|
if (limit !== void 0) {
|
|
72021
72444
|
text += theme.fg("toolOutput", ` (limit ${limit})`);
|
|
72022
72445
|
}
|
|
@@ -72052,10 +72475,10 @@ ${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
|
|
|
72052
72475
|
} else if (this.toolName === "grep_text") {
|
|
72053
72476
|
const pattern = str(this.args?.pattern);
|
|
72054
72477
|
const rawPath = str(this.args?.path);
|
|
72055
|
-
const
|
|
72478
|
+
const path34 = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
72056
72479
|
const glob = str(this.args?.glob);
|
|
72057
72480
|
const limit = this.args?.limit;
|
|
72058
|
-
text = theme.fg("toolTitle", theme.bold("grep_text")) + " " + (pattern === null ? invalidArg : theme.fg("accent", `/${pattern || ""}/`)) + theme.fg("toolOutput", ` in ${
|
|
72481
|
+
text = theme.fg("toolTitle", theme.bold("grep_text")) + " " + (pattern === null ? invalidArg : theme.fg("accent", `/${pattern || ""}/`)) + theme.fg("toolOutput", ` in ${path34 === null ? invalidArg : path34}`);
|
|
72059
72482
|
if (glob) {
|
|
72060
72483
|
text += theme.fg("toolOutput", ` (${glob})`);
|
|
72061
72484
|
}
|
|
@@ -72278,7 +72701,7 @@ async function handleResumeCommand(host) {
|
|
|
72278
72701
|
return { component: selector, focus: selector.getSelectList() };
|
|
72279
72702
|
});
|
|
72280
72703
|
}
|
|
72281
|
-
async function
|
|
72704
|
+
async function loadSession(host, sessionId) {
|
|
72282
72705
|
const beforeSwitch = await host.extensionRunner?.emitSessionBeforeSwitch({
|
|
72283
72706
|
type: "session:before_switch",
|
|
72284
72707
|
reason: "resume",
|
|
@@ -72475,29 +72898,31 @@ function setWaitingForUser(host, waiting) {
|
|
|
72475
72898
|
syncTitleActivity(host);
|
|
72476
72899
|
}
|
|
72477
72900
|
async function handleTreeCommand(host) {
|
|
72478
|
-
const
|
|
72479
|
-
|
|
72480
|
-
|
|
72481
|
-
host.showStatus(`No entries in current session (entries: ${entries.length})`);
|
|
72901
|
+
const head = host.sessionManager.getEntrySummariesPage({ limit: 1 });
|
|
72902
|
+
if (head.total === 0) {
|
|
72903
|
+
host.showStatus(`No entries in current session (entries: 0)`);
|
|
72482
72904
|
return;
|
|
72483
72905
|
}
|
|
72484
72906
|
host.showSelector((done) => {
|
|
72485
72907
|
const selector = new TreeSelectorComponent(
|
|
72486
|
-
|
|
72487
|
-
|
|
72488
|
-
|
|
72489
|
-
|
|
72490
|
-
|
|
72491
|
-
|
|
72492
|
-
|
|
72493
|
-
|
|
72908
|
+
{
|
|
72909
|
+
terminalHeight: host.ui.terminal.rows,
|
|
72910
|
+
activeEntryId: host.sessionManager.getActiveEntryId(),
|
|
72911
|
+
activePathSeqs: host.sessionManager.getActivePathSeqs(),
|
|
72912
|
+
totalEntries: head.total,
|
|
72913
|
+
fetchSummaries: (afterSeq, limit) => host.sessionManager.getEntrySummariesPage({ limit, afterSeq }),
|
|
72914
|
+
onSelect: async (entryId, action) => {
|
|
72915
|
+
done();
|
|
72916
|
+
if (action === "fork") {
|
|
72917
|
+
await host.forkAtEntry(entryId);
|
|
72918
|
+
} else {
|
|
72919
|
+
await host.navigateToEntry(entryId);
|
|
72920
|
+
}
|
|
72921
|
+
},
|
|
72922
|
+
onCancel: () => {
|
|
72923
|
+
done();
|
|
72494
72924
|
}
|
|
72495
|
-
}
|
|
72496
|
-
() => {
|
|
72497
|
-
done();
|
|
72498
|
-
},
|
|
72499
|
-
host.sessionManager.getActiveEntryId()
|
|
72500
|
-
// Start at active entry
|
|
72925
|
+
}
|
|
72501
72926
|
);
|
|
72502
72927
|
return { component: selector, focus: selector };
|
|
72503
72928
|
});
|
|
@@ -72514,8 +72939,8 @@ async function forkAtEntry(host, entryId) {
|
|
|
72514
72939
|
host.showError("Failed to branch at entry");
|
|
72515
72940
|
return;
|
|
72516
72941
|
}
|
|
72517
|
-
const
|
|
72518
|
-
const pathNames =
|
|
72942
|
+
const path34 = host.sessionManager.getPathSummaries(entryId);
|
|
72943
|
+
const pathNames = path34.map((summary) => summary.role || summary.type).join(" \u2192 ");
|
|
72519
72944
|
const messages = host.sessionManager.getMessages();
|
|
72520
72945
|
host.syncAgentFromActiveSession(messages);
|
|
72521
72946
|
await host.syncSessionScopedState(messages);
|
|
@@ -72528,7 +72953,7 @@ async function forkAtEntry(host, entryId) {
|
|
|
72528
72953
|
host.updatePendingMessagesDisplay();
|
|
72529
72954
|
host.renderMessageHistory(messages);
|
|
72530
72955
|
await host.sessionManager.save();
|
|
72531
|
-
host.showStatus(`Branched at: ${pathNames} (${
|
|
72956
|
+
host.showStatus(`Branched at: ${pathNames} (${path34.length} messages). Continue to add to this branch.`);
|
|
72532
72957
|
} catch (error) {
|
|
72533
72958
|
host.showError(
|
|
72534
72959
|
`Failed to branch: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -72556,10 +72981,10 @@ async function navigateToEntry(host, entryId) {
|
|
|
72556
72981
|
host.sessionManager.save().catch((err) => {
|
|
72557
72982
|
console.error("[Session] Save after navigation failed:", err);
|
|
72558
72983
|
});
|
|
72559
|
-
const
|
|
72560
|
-
const
|
|
72561
|
-
const role =
|
|
72562
|
-
host.showStatus(`Switched to branch: ${role} (${
|
|
72984
|
+
const path34 = host.sessionManager.getPathSummaries(entryId);
|
|
72985
|
+
const summary = host.sessionManager.getEntrySummary(entryId);
|
|
72986
|
+
const role = summary?.role || summary?.type || "entry";
|
|
72987
|
+
host.showStatus(`Switched to branch: ${role} (${path34.length} entries in path)`);
|
|
72563
72988
|
} catch (error) {
|
|
72564
72989
|
host.showError(
|
|
72565
72990
|
`Failed to navigate: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -72654,9 +73079,9 @@ async function handleForkCommand(host) {
|
|
|
72654
73079
|
}
|
|
72655
73080
|
|
|
72656
73081
|
// src/commands/interactive-skill-commands.ts
|
|
72657
|
-
import * as
|
|
73082
|
+
import * as fs24 from "fs";
|
|
72658
73083
|
import * as os7 from "os";
|
|
72659
|
-
import * as
|
|
73084
|
+
import * as path26 from "path";
|
|
72660
73085
|
|
|
72661
73086
|
// src/commands/subagent-command.ts
|
|
72662
73087
|
async function handleSubagentCommand(host, args) {
|
|
@@ -72793,9 +73218,9 @@ function handleSkillsCommand(host) {
|
|
|
72793
73218
|
});
|
|
72794
73219
|
}
|
|
72795
73220
|
function discoverSkills(host) {
|
|
72796
|
-
const builtinDir =
|
|
72797
|
-
const userDir =
|
|
72798
|
-
const projectDir =
|
|
73221
|
+
const builtinDir = path26.join(getBuiltinDir(), "skills");
|
|
73222
|
+
const userDir = path26.join(os7.homedir(), ".pie", "skills");
|
|
73223
|
+
const projectDir = path26.join(process.cwd(), ".pie", "skills");
|
|
72799
73224
|
return loadSkills({ dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: process.cwd() }) });
|
|
72800
73225
|
}
|
|
72801
73226
|
function listDiscoveredSkills(host) {
|
|
@@ -72927,7 +73352,7 @@ function expandSkillCommand(host, text) {
|
|
|
72927
73352
|
const skill = host.skills.find((s) => s.name === skillName);
|
|
72928
73353
|
if (!skill) return text;
|
|
72929
73354
|
try {
|
|
72930
|
-
const content =
|
|
73355
|
+
const content = fs24.readFileSync(skill.filePath, "utf-8");
|
|
72931
73356
|
const body = host.stripFrontmatter(content).trim();
|
|
72932
73357
|
const skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">
|
|
72933
73358
|
References are relative to ${skill.baseDir}.
|
|
@@ -72954,9 +73379,9 @@ async function handleSkillToggleCommand(host, args, enabled) {
|
|
|
72954
73379
|
host.showError(`Usage: /skills/${enabled ? "enable" : "disable"} <name>`);
|
|
72955
73380
|
return;
|
|
72956
73381
|
}
|
|
72957
|
-
const builtinDir =
|
|
72958
|
-
const userDir =
|
|
72959
|
-
const projectDir =
|
|
73382
|
+
const builtinDir = path26.join(getBuiltinDir(), "skills");
|
|
73383
|
+
const userDir = path26.join(os7.homedir(), ".pie", "skills");
|
|
73384
|
+
const projectDir = path26.join(process.cwd(), ".pie", "skills");
|
|
72960
73385
|
const discovered = loadSkills({ dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: process.cwd() }) }).skills;
|
|
72961
73386
|
if (!discovered.some((skill) => skill.name === name)) {
|
|
72962
73387
|
host.showError(`Skill not found: ${name}`);
|
|
@@ -73022,17 +73447,17 @@ async function handleSkillsCreate(host, args) {
|
|
|
73022
73447
|
if (!description) {
|
|
73023
73448
|
description = `Skill for ${name}`;
|
|
73024
73449
|
}
|
|
73025
|
-
const skillsDir =
|
|
73026
|
-
const skillDir =
|
|
73027
|
-
const skillFile =
|
|
73450
|
+
const skillsDir = path26.join(os7.homedir(), ".pie", "skills");
|
|
73451
|
+
const skillDir = path26.join(skillsDir, name);
|
|
73452
|
+
const skillFile = path26.join(skillDir, "SKILL.md");
|
|
73028
73453
|
debugLog2(`Creating at: ${skillFile}`);
|
|
73029
|
-
if (
|
|
73454
|
+
if (fs24.existsSync(skillDir)) {
|
|
73030
73455
|
host.showError(`Skill "${name}" already exists at ${skillDir}`);
|
|
73031
73456
|
return;
|
|
73032
73457
|
}
|
|
73033
|
-
|
|
73458
|
+
fs24.mkdirSync(skillDir, { recursive: true });
|
|
73034
73459
|
const template = createSkillTemplate(name, description);
|
|
73035
|
-
|
|
73460
|
+
fs24.writeFileSync(skillFile, template, "utf-8");
|
|
73036
73461
|
debugLog2("Successfully created skill");
|
|
73037
73462
|
host.chatContainer.addChild(new Spacer(1));
|
|
73038
73463
|
host.chatContainer.addChild(new Text(theme.fg("accent", `\u2713 Created skill: ${name}`), 1, 0));
|
|
@@ -73778,6 +74203,7 @@ function createExtensionContextForCommands(host) {
|
|
|
73778
74203
|
},
|
|
73779
74204
|
getRuntimeTools: () => host.agent.state.tools,
|
|
73780
74205
|
resolveModelClass: (modelClass) => host.options.modelRegistry.resolveModelClass(modelClass),
|
|
74206
|
+
resolveModelRef: (modelRef) => host.options.modelRegistry.resolveModelRef(modelRef),
|
|
73781
74207
|
getMessages: () => host.agent.state.messages,
|
|
73782
74208
|
getSessionMetadata: () => ({ ...host.sessionManager.getActiveSession()?.metadata ?? {} }),
|
|
73783
74209
|
setSessionMetadata: (key, value) => {
|
|
@@ -73968,8 +74394,7 @@ async function handleCompactCommand(host) {
|
|
|
73968
74394
|
host.showStatus("Nothing to compact yet");
|
|
73969
74395
|
return;
|
|
73970
74396
|
}
|
|
73971
|
-
const
|
|
73972
|
-
const firstKeptEntryId = findFirstKeptEntryId(pathEntries);
|
|
74397
|
+
const firstKeptEntryId = findFirstKeptEntrySummaryId(host.sessionManager.getActiveContextSummaries());
|
|
73973
74398
|
if (!firstKeptEntryId) {
|
|
73974
74399
|
host.showStatus("Need at least one real user message before compacting");
|
|
73975
74400
|
return;
|
|
@@ -74885,8 +75310,8 @@ function setupInteractiveEditorSubmitHandler(host) {
|
|
|
74885
75310
|
}
|
|
74886
75311
|
|
|
74887
75312
|
// src/input/interactive-file-pipeline.ts
|
|
74888
|
-
import * as
|
|
74889
|
-
import * as
|
|
75313
|
+
import * as fs27 from "fs";
|
|
75314
|
+
import * as path29 from "path";
|
|
74890
75315
|
|
|
74891
75316
|
// src/components/file-picker.ts
|
|
74892
75317
|
var FilePickerComponent = class extends Container {
|
|
@@ -75107,8 +75532,8 @@ var FilePickerComponent = class extends Container {
|
|
|
75107
75532
|
};
|
|
75108
75533
|
|
|
75109
75534
|
// src/files/commands/file-commands.ts
|
|
75110
|
-
import * as
|
|
75111
|
-
import * as
|
|
75535
|
+
import * as fs25 from "node:fs";
|
|
75536
|
+
import * as path27 from "node:path";
|
|
75112
75537
|
var FileCommands = class {
|
|
75113
75538
|
context;
|
|
75114
75539
|
constructor(context) {
|
|
@@ -75124,11 +75549,11 @@ var FileCommands = class {
|
|
|
75124
75549
|
return;
|
|
75125
75550
|
}
|
|
75126
75551
|
const filePath = resolvePath2(parsed.path);
|
|
75127
|
-
if (!
|
|
75552
|
+
if (!fs25.existsSync(filePath)) {
|
|
75128
75553
|
this.context.showError(`File not found: ${parsed.path}`);
|
|
75129
75554
|
return;
|
|
75130
75555
|
}
|
|
75131
|
-
this.context.showStatus(`Uploading ${
|
|
75556
|
+
this.context.showStatus(`Uploading ${path27.basename(filePath)}...`);
|
|
75132
75557
|
try {
|
|
75133
75558
|
const result = await this.context.fileManager.upload(filePath, {
|
|
75134
75559
|
purpose: parsed.purpose,
|
|
@@ -75163,7 +75588,7 @@ var FileCommands = class {
|
|
|
75163
75588
|
return;
|
|
75164
75589
|
}
|
|
75165
75590
|
const resolvedPath = resolvePath2(filePath);
|
|
75166
|
-
if (!
|
|
75591
|
+
if (!fs25.existsSync(resolvedPath)) {
|
|
75167
75592
|
this.context.showError(`File not found: ${filePath}`);
|
|
75168
75593
|
return;
|
|
75169
75594
|
}
|
|
@@ -75194,7 +75619,7 @@ var FileCommands = class {
|
|
|
75194
75619
|
return;
|
|
75195
75620
|
}
|
|
75196
75621
|
const resolvedPath = resolvePath2(parsed.path);
|
|
75197
|
-
if (!
|
|
75622
|
+
if (!fs25.existsSync(resolvedPath)) {
|
|
75198
75623
|
this.context.showError(`File not found: ${parsed.path}`);
|
|
75199
75624
|
return;
|
|
75200
75625
|
}
|
|
@@ -75672,8 +76097,8 @@ var FileStatusMonitor = class {
|
|
|
75672
76097
|
};
|
|
75673
76098
|
|
|
75674
76099
|
// src/files/mention/mention-handler.ts
|
|
75675
|
-
import * as
|
|
75676
|
-
import * as
|
|
76100
|
+
import * as fs26 from "node:fs";
|
|
76101
|
+
import * as path28 from "node:path";
|
|
75677
76102
|
var MentionHandler = class {
|
|
75678
76103
|
fileManager;
|
|
75679
76104
|
onShowPicker;
|
|
@@ -75728,7 +76153,7 @@ var MentionHandler = class {
|
|
|
75728
76153
|
navigateBrowseParent() {
|
|
75729
76154
|
const currentDir = this.getBrowserDirectory();
|
|
75730
76155
|
if (!currentDir) return;
|
|
75731
|
-
const parentDir =
|
|
76156
|
+
const parentDir = path28.dirname(currentDir);
|
|
75732
76157
|
if (parentDir === currentDir) return;
|
|
75733
76158
|
this.browsingDirectory = parentDir;
|
|
75734
76159
|
this.showMentionPicker("");
|
|
@@ -75748,7 +76173,7 @@ var MentionHandler = class {
|
|
|
75748
76173
|
if (option.type === "parent") {
|
|
75749
76174
|
const currentDir = this.getBrowserDirectory();
|
|
75750
76175
|
if (currentDir) {
|
|
75751
|
-
this.browsingDirectory =
|
|
76176
|
+
this.browsingDirectory = path28.dirname(currentDir);
|
|
75752
76177
|
this.showMentionPicker("");
|
|
75753
76178
|
this.isPickerVisible = true;
|
|
75754
76179
|
}
|
|
@@ -75888,7 +76313,7 @@ var MentionHandler = class {
|
|
|
75888
76313
|
id: part.content,
|
|
75889
76314
|
name: part.name || fileInfo.name,
|
|
75890
76315
|
mimeType: fileInfo.mimeType,
|
|
75891
|
-
ext:
|
|
76316
|
+
ext: path28.extname(part.name || fileInfo.name).toLowerCase(),
|
|
75892
76317
|
size: fileInfo.size,
|
|
75893
76318
|
source: fileInfo.platforms.length > 0 ? "session" : "local",
|
|
75894
76319
|
fileId: part.content,
|
|
@@ -76046,11 +76471,11 @@ var MentionHandler = class {
|
|
|
76046
76471
|
}
|
|
76047
76472
|
if (this.isPath(query)) {
|
|
76048
76473
|
const resolvedPath = resolvePath2(query);
|
|
76049
|
-
if (
|
|
76050
|
-
const stats =
|
|
76474
|
+
if (fs26.existsSync(resolvedPath)) {
|
|
76475
|
+
const stats = fs26.statSync(resolvedPath);
|
|
76051
76476
|
if (stats.isFile()) {
|
|
76052
76477
|
const type = FileCache.getFileTypeFromName(resolvedPath);
|
|
76053
|
-
const name =
|
|
76478
|
+
const name = path28.basename(resolvedPath);
|
|
76054
76479
|
if (!seenNames.has(name.toLowerCase())) {
|
|
76055
76480
|
options.push({
|
|
76056
76481
|
type: "upload",
|
|
@@ -76071,16 +76496,16 @@ var MentionHandler = class {
|
|
|
76071
76496
|
return void 0;
|
|
76072
76497
|
}
|
|
76073
76498
|
const queryPath = this.isPath(query) ? resolvePath2(query) : void 0;
|
|
76074
|
-
const filter = queryPath ?
|
|
76499
|
+
const filter = queryPath ? fs26.existsSync(queryPath) && fs26.statSync(queryPath).isDirectory() ? "" : path28.basename(queryPath) : query;
|
|
76075
76500
|
const entries = this.fileManager.listPathEntries(currentDir, filter);
|
|
76076
76501
|
const options = [];
|
|
76077
76502
|
const homeDir = process.env.HOME || "";
|
|
76078
76503
|
const displayDir = currentDir.startsWith(homeDir) ? `~${currentDir.slice(homeDir.length)}` : currentDir;
|
|
76079
|
-
if (
|
|
76504
|
+
if (path28.dirname(currentDir) !== currentDir) {
|
|
76080
76505
|
options.push({
|
|
76081
76506
|
type: "parent",
|
|
76082
76507
|
name: "..",
|
|
76083
|
-
path:
|
|
76508
|
+
path: path28.dirname(currentDir),
|
|
76084
76509
|
icon: "\u21A9",
|
|
76085
76510
|
meta: "Parent directory"
|
|
76086
76511
|
});
|
|
@@ -76112,10 +76537,10 @@ var MentionHandler = class {
|
|
|
76112
76537
|
getBrowserDirectory(query = this.currentQuery) {
|
|
76113
76538
|
if (this.isPath(query)) {
|
|
76114
76539
|
const resolvedPath = resolvePath2(query);
|
|
76115
|
-
if (
|
|
76540
|
+
if (fs26.existsSync(resolvedPath) && fs26.statSync(resolvedPath).isDirectory()) {
|
|
76116
76541
|
return resolvedPath;
|
|
76117
76542
|
}
|
|
76118
|
-
return
|
|
76543
|
+
return path28.dirname(resolvedPath);
|
|
76119
76544
|
}
|
|
76120
76545
|
return this.browsingDirectory;
|
|
76121
76546
|
}
|
|
@@ -76202,8 +76627,8 @@ async function initializeFileManager(host) {
|
|
|
76202
76627
|
sessionId,
|
|
76203
76628
|
platform: platform2,
|
|
76204
76629
|
apiKey: host.options.apiKey,
|
|
76205
|
-
baseDir:
|
|
76206
|
-
sessionsDir:
|
|
76630
|
+
baseDir: path29.join(host.options.configDir, "files"),
|
|
76631
|
+
sessionsDir: path29.join(host.options.configDir, "sessions")
|
|
76207
76632
|
});
|
|
76208
76633
|
switch (getFileManagerAdapterKind(platform2)) {
|
|
76209
76634
|
case "kimi":
|
|
@@ -76483,13 +76908,13 @@ function convertPreparedAttachmentItems(items) {
|
|
|
76483
76908
|
break;
|
|
76484
76909
|
case "image": {
|
|
76485
76910
|
if (!item.data && !item.path) return void 0;
|
|
76486
|
-
const data = item.data ??
|
|
76911
|
+
const data = item.data ?? fs27.readFileSync(item.path, "base64");
|
|
76487
76912
|
converted.push({ type: "image", data, mimeType: item.mimeType });
|
|
76488
76913
|
break;
|
|
76489
76914
|
}
|
|
76490
76915
|
case "video": {
|
|
76491
76916
|
if (!item.data && !item.path) return void 0;
|
|
76492
|
-
const data = item.data ??
|
|
76917
|
+
const data = item.data ?? fs27.readFileSync(item.path, "base64");
|
|
76493
76918
|
converted.push({ type: "video", data, mimeType: item.mimeType });
|
|
76494
76919
|
break;
|
|
76495
76920
|
}
|
|
@@ -77075,8 +77500,7 @@ async function createCliAutoCompactionResult(params) {
|
|
|
77075
77500
|
if (!activeEntryId) {
|
|
77076
77501
|
return { aborted: true };
|
|
77077
77502
|
}
|
|
77078
|
-
const
|
|
77079
|
-
const firstKeptEntryId = findFirstKeptEntryId(pathEntries);
|
|
77503
|
+
const firstKeptEntryId = findFirstKeptEntrySummaryId(params.context.sessionManager.getActiveContextSummaries());
|
|
77080
77504
|
if (!firstKeptEntryId) {
|
|
77081
77505
|
return { aborted: true };
|
|
77082
77506
|
}
|
|
@@ -77638,11 +78062,11 @@ var HierarchicalSelectorComponent = class extends Container {
|
|
|
77638
78062
|
// src/runtime/interactive-ui-helpers.ts
|
|
77639
78063
|
function showHierarchicalMenu(host, initialPath = []) {
|
|
77640
78064
|
const basePath = [...initialPath];
|
|
77641
|
-
const showAtPath = (
|
|
78065
|
+
const showAtPath = (path34) => {
|
|
77642
78066
|
host.showSelector((done) => {
|
|
77643
78067
|
const selector = new HierarchicalSelectorComponent({
|
|
77644
78068
|
tree: commandTree,
|
|
77645
|
-
path:
|
|
78069
|
+
path: path34,
|
|
77646
78070
|
basePath,
|
|
77647
78071
|
onNavigate: (newPath) => {
|
|
77648
78072
|
done();
|
|
@@ -77650,7 +78074,7 @@ function showHierarchicalMenu(host, initialPath = []) {
|
|
|
77650
78074
|
},
|
|
77651
78075
|
onSelect: async (selectedPath, node, searchArgs) => {
|
|
77652
78076
|
if (node.handler) {
|
|
77653
|
-
const args = searchArgs || (selectedPath.length >
|
|
78077
|
+
const args = searchArgs || (selectedPath.length > path34.length ? selectedPath.slice(path34.length).join(" ") : void 0);
|
|
77654
78078
|
const commandPath = "/" + selectedPath.join("/");
|
|
77655
78079
|
if (!args && host.isInteractiveCommand(commandPath)) {
|
|
77656
78080
|
done();
|
|
@@ -77904,6 +78328,18 @@ async function prepareAgentTurn(host, context) {
|
|
|
77904
78328
|
};
|
|
77905
78329
|
}
|
|
77906
78330
|
function createInteractiveAgentSessionController(host) {
|
|
78331
|
+
try {
|
|
78332
|
+
recoverInterruptedPublishes({
|
|
78333
|
+
sessionsDir: getSessionsDir(),
|
|
78334
|
+
warn: (message) => {
|
|
78335
|
+
console.warn(message);
|
|
78336
|
+
if (typeof host.appendWarningSummary === "function") {
|
|
78337
|
+
host.appendWarningSummary(message);
|
|
78338
|
+
}
|
|
78339
|
+
}
|
|
78340
|
+
});
|
|
78341
|
+
} catch {
|
|
78342
|
+
}
|
|
77907
78343
|
let retryElapsedTicker;
|
|
77908
78344
|
let retryElapsedStartedAt = 0;
|
|
77909
78345
|
const stopRetryElapsedTicker = () => {
|
|
@@ -77963,8 +78399,7 @@ function createInteractiveAgentSessionController(host) {
|
|
|
77963
78399
|
return { aborted: true };
|
|
77964
78400
|
}
|
|
77965
78401
|
if (beforeCompact?.summary) {
|
|
77966
|
-
const
|
|
77967
|
-
const firstKeptEntryId = activeEntryId ? findFirstKeptEntryId(context.sessionManager.getPathToEntry(activeEntryId)) : void 0;
|
|
78402
|
+
const firstKeptEntryId = findFirstKeptEntrySummaryId(context.sessionManager.getActiveContextSummaries());
|
|
77968
78403
|
if (!firstKeptEntryId) return { aborted: true };
|
|
77969
78404
|
return { summary: beforeCompact.summary, firstKeptEntryId };
|
|
77970
78405
|
}
|
|
@@ -78138,6 +78573,14 @@ function createInteractiveAgentSessionController(host) {
|
|
|
78138
78573
|
return;
|
|
78139
78574
|
}
|
|
78140
78575
|
host.resetFileObservationState();
|
|
78576
|
+
if (!event.result?.aborted) {
|
|
78577
|
+
host.streamingComponent = void 0;
|
|
78578
|
+
host.pendingTools.clear();
|
|
78579
|
+
host.chatContainer.clear();
|
|
78580
|
+
host.lastStatusSpacer = void 0;
|
|
78581
|
+
host.lastStatusText = void 0;
|
|
78582
|
+
host.renderMessageHistory(host.sessionManager.getMessages());
|
|
78583
|
+
}
|
|
78141
78584
|
const contextUsage = host.calculateContextUsage();
|
|
78142
78585
|
const contextWindow = host.options.model?.contextWindow ?? 0;
|
|
78143
78586
|
const contextPercent = contextWindow > 0 && contextUsage.tokens !== null ? contextUsage.tokens / contextWindow * 100 : 0;
|
|
@@ -79036,6 +79479,7 @@ async function loadInteractiveExtensions(host) {
|
|
|
79036
79479
|
fallbackReason: resolved.fallbackReason
|
|
79037
79480
|
};
|
|
79038
79481
|
},
|
|
79482
|
+
resolveModelRef: (modelRef) => host.options.modelRegistry.resolveModelRef(modelRef),
|
|
79039
79483
|
getMessages: () => host.agent.state.messages,
|
|
79040
79484
|
getSessionMetadata: () => ({ ...host.sessionManager.getActiveSession()?.metadata ?? {} }),
|
|
79041
79485
|
setSessionMetadata: (key, value) => {
|
|
@@ -79093,8 +79537,8 @@ async function loadInteractiveExtensions(host) {
|
|
|
79093
79537
|
host.extensionRunner.setUIContext(host.extensionUIContext);
|
|
79094
79538
|
await restoreExtensionProviderCredentials(host.options.modelRegistry);
|
|
79095
79539
|
if (process.env.PIE_VERBOSE) {
|
|
79096
|
-
for (const { path:
|
|
79097
|
-
console.error(`[Extension] Failed to load ${
|
|
79540
|
+
for (const { path: path34, error } of errors) {
|
|
79541
|
+
console.error(`[Extension] Failed to load ${path34}: ${error}`);
|
|
79098
79542
|
}
|
|
79099
79543
|
}
|
|
79100
79544
|
const extensionTools = filterEnabledTools(convertExtensionTools(extensions), host.options.settingsManager);
|
|
@@ -79464,8 +79908,8 @@ var InteractiveMode = class {
|
|
|
79464
79908
|
waitForAgentIdle() {
|
|
79465
79909
|
return this.agentSessionController.waitForIdle();
|
|
79466
79910
|
}
|
|
79467
|
-
replaceAgentMessagesAndMarkSynced(messages
|
|
79468
|
-
this.agentSessionController.replaceMessagesAndMarkSynced(messages
|
|
79911
|
+
replaceAgentMessagesAndMarkSynced(messages) {
|
|
79912
|
+
this.agentSessionController.replaceMessagesAndMarkSynced(messages);
|
|
79469
79913
|
this.lastSyncedMessageCount = this.agentSessionController.syncedMessageCount;
|
|
79470
79914
|
}
|
|
79471
79915
|
syncAgentFromActiveSession(messages) {
|
|
@@ -79493,7 +79937,7 @@ var InteractiveMode = class {
|
|
|
79493
79937
|
async init() {
|
|
79494
79938
|
const activeSession = this.sessionManager.getActiveSession();
|
|
79495
79939
|
this.thinkingLevel = resolveInitialThinkingLevel({ session: activeSession, settingsManager: this.options.settingsManager });
|
|
79496
|
-
const { Agent } = await import("./chunks/src-
|
|
79940
|
+
const { Agent } = await import("./chunks/src-SXUQ7OY6.js");
|
|
79497
79941
|
this.agent = new Agent({
|
|
79498
79942
|
initialState: {
|
|
79499
79943
|
systemPrompt: this.buildSystemPrompt(),
|
|
@@ -79603,9 +80047,9 @@ var InteractiveMode = class {
|
|
|
79603
80047
|
if (this.isProcessing) {
|
|
79604
80048
|
throw new Error("Cannot reload while a response is being processed. Wait for the turn to finish or abort it first.");
|
|
79605
80049
|
}
|
|
79606
|
-
const builtinDir =
|
|
79607
|
-
const userDir =
|
|
79608
|
-
const projectDir =
|
|
80050
|
+
const builtinDir = path30.join(getBuiltinDir(), "skills");
|
|
80051
|
+
const userDir = path30.join(os8.homedir(), ".pie", "skills");
|
|
80052
|
+
const projectDir = path30.join(this.options.cwd, ".pie", "skills");
|
|
79609
80053
|
const { skills, diagnostics } = loadSkills({
|
|
79610
80054
|
dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: this.options.cwd })
|
|
79611
80055
|
});
|
|
@@ -79767,7 +80211,7 @@ var InteractiveMode = class {
|
|
|
79767
80211
|
return handleResumeCommand(this);
|
|
79768
80212
|
}
|
|
79769
80213
|
async loadSession(sessionId) {
|
|
79770
|
-
return
|
|
80214
|
+
return loadSession(this, sessionId);
|
|
79771
80215
|
}
|
|
79772
80216
|
updateTerminalTitle() {
|
|
79773
80217
|
return updateTerminalTitle(this);
|
|
@@ -79908,8 +80352,8 @@ var InteractiveMode = class {
|
|
|
79908
80352
|
};
|
|
79909
80353
|
|
|
79910
80354
|
// src/app/runtime-composition.ts
|
|
79911
|
-
import { existsSync as
|
|
79912
|
-
import * as
|
|
80355
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync14 } from "fs";
|
|
80356
|
+
import * as path31 from "path";
|
|
79913
80357
|
var CliMissingApiKeyError = class extends Error {
|
|
79914
80358
|
constructor(message) {
|
|
79915
80359
|
super(message);
|
|
@@ -79930,13 +80374,13 @@ var CliSessionResumeError = class extends Error {
|
|
|
79930
80374
|
function getCliRuntimePaths() {
|
|
79931
80375
|
const configDir = getConfigDir();
|
|
79932
80376
|
const sessionsDir = getSessionsDir();
|
|
79933
|
-
const skillsDir =
|
|
79934
|
-
const builtinSkillsDir =
|
|
80377
|
+
const skillsDir = path31.join(configDir, "skills");
|
|
80378
|
+
const builtinSkillsDir = path31.join(getBuiltinDir(), "skills");
|
|
79935
80379
|
return { configDir, sessionsDir, skillsDir, builtinSkillsDir };
|
|
79936
80380
|
}
|
|
79937
80381
|
function ensureCliRuntimePaths(paths = getCliRuntimePaths()) {
|
|
79938
|
-
if (!
|
|
79939
|
-
|
|
80382
|
+
if (!existsSync19(paths.skillsDir)) {
|
|
80383
|
+
mkdirSync14(paths.skillsDir, { recursive: true });
|
|
79940
80384
|
}
|
|
79941
80385
|
return paths;
|
|
79942
80386
|
}
|
|
@@ -80051,7 +80495,7 @@ async function composeCliRuntime(params) {
|
|
|
80051
80495
|
fileLogger.log("cli", `Using API key for provider ${provider}`, {
|
|
80052
80496
|
keyPrefix: apiKey ? maskApiKey2(apiKey) : "none"
|
|
80053
80497
|
});
|
|
80054
|
-
const projectSkillsDir =
|
|
80498
|
+
const projectSkillsDir = path31.join(cwd, ".pie", "skills");
|
|
80055
80499
|
const { skills: discoveredSkills, diagnostics } = loadSkills({
|
|
80056
80500
|
dirs: buildSkillDirs({
|
|
80057
80501
|
builtinDir: paths.builtinSkillsDir,
|
|
@@ -80259,6 +80703,7 @@ async function loadPrintModeExtensions(params) {
|
|
|
80259
80703
|
})),
|
|
80260
80704
|
getRuntimeTools: () => params.getAgent()?.state.tools ?? [],
|
|
80261
80705
|
resolveModelClass: (modelClass) => params.modelRegistry.resolveModelClass(modelClass),
|
|
80706
|
+
resolveModelRef: (modelRef) => params.modelRegistry.resolveModelRef(modelRef),
|
|
80262
80707
|
getMessages: () => params.getAgent()?.state.messages ?? [],
|
|
80263
80708
|
getSessionMetadata: () => ({ ...params.sessionManager.getActiveSession()?.metadata ?? {} }),
|
|
80264
80709
|
setSessionMetadata: (key, value) => {
|
|
@@ -80326,7 +80771,7 @@ async function runPrintMode(params) {
|
|
|
80326
80771
|
`);
|
|
80327
80772
|
console.log("Assistant: ");
|
|
80328
80773
|
}
|
|
80329
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
80774
|
+
const { Agent: AgentClass } = await import("./chunks/src-SXUQ7OY6.js");
|
|
80330
80775
|
let agent;
|
|
80331
80776
|
const printModeExtensions = await loadPrintModeExtensions({
|
|
80332
80777
|
cwd: runtime.cwd,
|
|
@@ -80414,7 +80859,7 @@ async function runPrintMode(params) {
|
|
|
80414
80859
|
if (beforeCompact.cancel) return { aborted: true };
|
|
80415
80860
|
if (beforeCompact.summary) {
|
|
80416
80861
|
const activeEntryId = context.sessionManager.getActiveEntryId();
|
|
80417
|
-
const firstKeptEntryId = activeEntryId ?
|
|
80862
|
+
const firstKeptEntryId = activeEntryId ? findFirstKeptEntrySummaryId(context.sessionManager.getActiveContextSummaries()) : void 0;
|
|
80418
80863
|
if (!firstKeptEntryId) return { aborted: true };
|
|
80419
80864
|
return { summary: beforeCompact.summary, firstKeptEntryId };
|
|
80420
80865
|
}
|
|
@@ -80747,6 +81192,7 @@ async function loadJsonModeExtensions(params) {
|
|
|
80747
81192
|
})),
|
|
80748
81193
|
getRuntimeTools: () => params.getAgent()?.state.tools ?? [],
|
|
80749
81194
|
resolveModelClass: (modelClass) => params.runtime.modelRegistry.resolveModelClass(modelClass),
|
|
81195
|
+
resolveModelRef: (modelRef) => params.runtime.modelRegistry.resolveModelRef(modelRef),
|
|
80750
81196
|
getMessages: () => params.getAgent()?.state.messages ?? [],
|
|
80751
81197
|
getSessionMetadata: () => ({ ...params.runtime.sessionManager.getActiveSession()?.metadata ?? {} }),
|
|
80752
81198
|
setSessionMetadata: (key, value) => {
|
|
@@ -80804,6 +81250,7 @@ async function runJsonEventsMode(params) {
|
|
|
80804
81250
|
let thinkingLevelInitialized = false;
|
|
80805
81251
|
let defaultRuntime;
|
|
80806
81252
|
let defaultModelState;
|
|
81253
|
+
let publishRecoveryDone = false;
|
|
80807
81254
|
const completedSessionControlRequests = /* @__PURE__ */ new Map();
|
|
80808
81255
|
const completedSidechatRequests = /* @__PURE__ */ new Map();
|
|
80809
81256
|
const ensureRuntimeInFlight = /* @__PURE__ */ new Map();
|
|
@@ -80893,12 +81340,22 @@ async function runJsonEventsMode(params) {
|
|
|
80893
81340
|
metadata.rootEntryId = existing?.rootEntryId ?? rootEntryId;
|
|
80894
81341
|
return metadata;
|
|
80895
81342
|
}
|
|
80896
|
-
|
|
81343
|
+
function persistMockTurn(message, assistantText) {
|
|
80897
81344
|
const store = new FileSessionStore(getSessionsDir());
|
|
80898
|
-
const
|
|
81345
|
+
const targetSessionId = message.sessionId ?? sessionId;
|
|
81346
|
+
const status = store.headStatus(targetSessionId);
|
|
81347
|
+
if (status === "legacy") {
|
|
81348
|
+
throw new SessionControlError("session_unsupported_format", `Session uses an unsupported old format: ${targetSessionId}`);
|
|
81349
|
+
}
|
|
81350
|
+
if (status === "corrupt") {
|
|
81351
|
+
throw new SessionControlError("session_unrecoverable", `Session could not be recovered: ${targetSessionId}`);
|
|
81352
|
+
}
|
|
81353
|
+
const existing = store.readHead(targetSessionId);
|
|
81354
|
+
if (existing) store.createHead(targetSessionId, { name: void 0, createdAt: existing.metadata.createdAt });
|
|
80899
81355
|
const startedAt = activeTurn?.startedAt ?? Date.now();
|
|
80900
|
-
const
|
|
80901
|
-
const
|
|
81356
|
+
const baseSeq = existing?.committedSeq ?? store.readHead(targetSessionId)?.committedSeq ?? 0;
|
|
81357
|
+
const userEntryId = generateEntryId(baseSeq + 1);
|
|
81358
|
+
const assistantEntryId = generateEntryId(baseSeq + 2);
|
|
80902
81359
|
const parentId = existing?.metadata.activeEntryId ?? null;
|
|
80903
81360
|
const userEntry = {
|
|
80904
81361
|
id: userEntryId,
|
|
@@ -80936,10 +81393,13 @@ async function runJsonEventsMode(params) {
|
|
|
80936
81393
|
timestamp: assistantTimestamp,
|
|
80937
81394
|
message: assistantMessage
|
|
80938
81395
|
};
|
|
80939
|
-
|
|
80940
|
-
|
|
80941
|
-
|
|
80942
|
-
|
|
81396
|
+
if (!existing) {
|
|
81397
|
+
store.createHead(targetSessionId);
|
|
81398
|
+
}
|
|
81399
|
+
store.appendEntries(
|
|
81400
|
+
targetSessionId,
|
|
81401
|
+
[userEntry, assistantEntry],
|
|
81402
|
+
assistantEntryId,
|
|
80943
81403
|
persistedMockMetadata(existing?.metadata, assistantEntryId, existing?.metadata.rootEntryId ?? userEntryId, message.cwd)
|
|
80944
81404
|
);
|
|
80945
81405
|
return assistantEntryId;
|
|
@@ -80962,7 +81422,7 @@ async function runJsonEventsMode(params) {
|
|
|
80962
81422
|
};
|
|
80963
81423
|
}
|
|
80964
81424
|
function errorToFailureDetail(error) {
|
|
80965
|
-
if (error instanceof CliSessionResumeError) {
|
|
81425
|
+
if (error instanceof CliSessionResumeError || error instanceof SessionControlError) {
|
|
80966
81426
|
return {
|
|
80967
81427
|
message: error.message,
|
|
80968
81428
|
code: error.code,
|
|
@@ -80972,7 +81432,10 @@ async function runJsonEventsMode(params) {
|
|
|
80972
81432
|
return error instanceof Error ? error.message : String(error);
|
|
80973
81433
|
}
|
|
80974
81434
|
function sessionControlStore() {
|
|
80975
|
-
return new FileSessionStore(
|
|
81435
|
+
return new FileSessionStore(sessionControlSessionsDir());
|
|
81436
|
+
}
|
|
81437
|
+
function sessionControlSessionsDir() {
|
|
81438
|
+
return runtime?.paths.sessionsDir ?? getSessionsDir();
|
|
80976
81439
|
}
|
|
80977
81440
|
function invalidSessionControl(message) {
|
|
80978
81441
|
return new SessionControlError("invalid_request", message);
|
|
@@ -81081,6 +81544,7 @@ async function runJsonEventsMode(params) {
|
|
|
81081
81544
|
await saveRuntimeSessionForControl();
|
|
81082
81545
|
const result = await forkStoredSession({
|
|
81083
81546
|
store: sessionControlStore(),
|
|
81547
|
+
sessionsDir: sessionControlSessionsDir(),
|
|
81084
81548
|
sourceSessionId: controlSessionId,
|
|
81085
81549
|
sourceEntryId,
|
|
81086
81550
|
targetSessionId,
|
|
@@ -81168,7 +81632,7 @@ async function runJsonEventsMode(params) {
|
|
|
81168
81632
|
return;
|
|
81169
81633
|
}
|
|
81170
81634
|
const parent = agent;
|
|
81171
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
81635
|
+
const { Agent: AgentClass } = await import("./chunks/src-SXUQ7OY6.js");
|
|
81172
81636
|
const sideAgent = new AgentClass({
|
|
81173
81637
|
initialState: {
|
|
81174
81638
|
systemPrompt: parent.state.systemPrompt,
|
|
@@ -81495,6 +81959,16 @@ async function runJsonEventsMode(params) {
|
|
|
81495
81959
|
if (!runtime) {
|
|
81496
81960
|
throw new Error("JSON events mode requires a CLI runtime");
|
|
81497
81961
|
}
|
|
81962
|
+
if (!publishRecoveryDone) {
|
|
81963
|
+
publishRecoveryDone = true;
|
|
81964
|
+
try {
|
|
81965
|
+
recoverInterruptedPublishes({
|
|
81966
|
+
sessionsDir: runtime.paths.sessionsDir ?? getSessionsDir(),
|
|
81967
|
+
warn: (message) => console.warn(message)
|
|
81968
|
+
});
|
|
81969
|
+
} catch {
|
|
81970
|
+
}
|
|
81971
|
+
}
|
|
81498
81972
|
if (defaultRuntime !== runtime) {
|
|
81499
81973
|
defaultRuntime = runtime;
|
|
81500
81974
|
defaultModelState = configuredDefaultModelState(runtime);
|
|
@@ -81502,7 +81976,7 @@ async function runJsonEventsMode(params) {
|
|
|
81502
81976
|
if (runtime.initialModel.unconfigured || controller) {
|
|
81503
81977
|
return;
|
|
81504
81978
|
}
|
|
81505
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
81979
|
+
const { Agent: AgentClass } = await import("./chunks/src-SXUQ7OY6.js");
|
|
81506
81980
|
const jsonModeExtensions = await loadJsonModeExtensions({ runtime, getAgent: () => agent });
|
|
81507
81981
|
extensionRunner = jsonModeExtensions.runner;
|
|
81508
81982
|
const tools = [...runtime.tools, ...jsonModeExtensions.extensionTools];
|
|
@@ -81695,9 +82169,9 @@ async function runJsonEventsMode(params) {
|
|
|
81695
82169
|
}
|
|
81696
82170
|
display(params.mockResponse);
|
|
81697
82171
|
try {
|
|
81698
|
-
mockActiveEntryId =
|
|
82172
|
+
mockActiveEntryId = persistMockTurn(message, params.mockResponse);
|
|
81699
82173
|
} catch (error) {
|
|
81700
|
-
finalize("failed",
|
|
82174
|
+
finalize("failed", errorToFailureDetail(error));
|
|
81701
82175
|
if (activeTurn === turn) emitSettled(turn);
|
|
81702
82176
|
if (activeTurn === turn) activeTurn = null;
|
|
81703
82177
|
return;
|
|
@@ -81965,19 +82439,19 @@ async function runJsonEventsMode(params) {
|
|
|
81965
82439
|
}
|
|
81966
82440
|
|
|
81967
82441
|
// src/developer-instructions.ts
|
|
81968
|
-
import * as
|
|
81969
|
-
import * as
|
|
82442
|
+
import * as fs28 from "fs";
|
|
82443
|
+
import * as path32 from "path";
|
|
81970
82444
|
var MAX_DEVELOPER_INSTRUCTIONS_CHARS = 64e3;
|
|
81971
82445
|
function readTextFileBounded(filePath) {
|
|
81972
|
-
const resolved =
|
|
81973
|
-
const stat2 =
|
|
82446
|
+
const resolved = path32.resolve(filePath);
|
|
82447
|
+
const stat2 = fs28.statSync(resolved);
|
|
81974
82448
|
if (!stat2.isFile()) {
|
|
81975
82449
|
throw new Error(`Developer instructions file is not a regular file: ${filePath}`);
|
|
81976
82450
|
}
|
|
81977
82451
|
if (stat2.size > MAX_DEVELOPER_INSTRUCTIONS_CHARS * 4) {
|
|
81978
82452
|
throw new Error(`Developer instructions file is too large: ${filePath}`);
|
|
81979
82453
|
}
|
|
81980
|
-
return
|
|
82454
|
+
return fs28.readFileSync(resolved, "utf8");
|
|
81981
82455
|
}
|
|
81982
82456
|
function collectFlagValues(args, flag) {
|
|
81983
82457
|
const values = [];
|
|
@@ -82056,8 +82530,8 @@ var logError = (msg, err) => {
|
|
|
82056
82530
|
const logPath = getRuntimeLogPath();
|
|
82057
82531
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
82058
82532
|
const stack = err instanceof Error ? err.stack || "" : "";
|
|
82059
|
-
|
|
82060
|
-
|
|
82533
|
+
fs29.mkdirSync(path33.dirname(logPath), { recursive: true });
|
|
82534
|
+
fs29.appendFileSync(logPath, `[${timestamp}] ${msg}
|
|
82061
82535
|
${stack}
|
|
82062
82536
|
|
|
82063
82537
|
`);
|
|
@@ -82091,7 +82565,7 @@ async function runWithJsonEventsConsoleIsolation(fn) {
|
|
|
82091
82565
|
}
|
|
82092
82566
|
async function createCliTestStreamFnFromEnv() {
|
|
82093
82567
|
if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) return void 0;
|
|
82094
|
-
return (await import("./chunks/test-stream-
|
|
82568
|
+
return (await import("./chunks/test-stream-OD3B57AS.js")).createTestStreamFnFromSequenceEnv();
|
|
82095
82569
|
}
|
|
82096
82570
|
function resolveJsonEventsDetailFlag() {
|
|
82097
82571
|
for (let index = 0; index < process.argv.length; index += 1) {
|