@cydm/pie 2.3.0 → 2.4.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 +4 -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-FKUEIYFQ.js} +8212 -7366
- package/dist/chunks/{chunk-P3QPJXS7.js → chunk-XVUV3IM2.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 +1302 -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-XVUV3IM2.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-FKUEIYFQ.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"]);
|
|
@@ -55129,9 +55129,11 @@ function runCapabilitiesCommand(args) {
|
|
|
55129
55129
|
}
|
|
55130
55130
|
|
|
55131
55131
|
// src/commands/sessions.ts
|
|
55132
|
-
import
|
|
55132
|
+
import fs8 from "node:fs";
|
|
55133
55133
|
|
|
55134
55134
|
// src/session-control.ts
|
|
55135
|
+
import * as fs7 from "node:fs";
|
|
55136
|
+
import * as path7 from "node:path";
|
|
55135
55137
|
var SessionControlError = class extends Error {
|
|
55136
55138
|
constructor(code, message, recoverable = sessionControlErrorRecoverable(code)) {
|
|
55137
55139
|
super(message);
|
|
@@ -55145,27 +55147,70 @@ var SessionControlError = class extends Error {
|
|
|
55145
55147
|
function sessionControlErrorRecoverable(code) {
|
|
55146
55148
|
return code !== "session_unrecoverable" && code !== "session_mismatch";
|
|
55147
55149
|
}
|
|
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
|
-
);
|
|
55150
|
+
var FORK_BATCH_ENTRIES = 64;
|
|
55151
|
+
var FORK_BATCH_BYTES = 256 * 1024;
|
|
55152
|
+
var STAGING_SESSION_ID_PREFIX = "__pie-staging-";
|
|
55153
|
+
function stagingIdFor(targetSessionId) {
|
|
55154
|
+
return `${STAGING_SESSION_ID_PREFIX}${targetSessionId}-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
55156
55155
|
}
|
|
55157
|
-
|
|
55158
|
-
|
|
55159
|
-
|
|
55160
|
-
|
|
55156
|
+
var PUBLISH_JOURNAL_DIR = ".pie-publish-journal";
|
|
55157
|
+
function safeSessionDirName(sessionId) {
|
|
55158
|
+
return sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
55159
|
+
}
|
|
55160
|
+
function canonicalSessionDir(sessionsDir, sessionId) {
|
|
55161
|
+
const dir = path7.join(sessionsDir, safeSessionDirName(sessionId));
|
|
55162
|
+
try {
|
|
55163
|
+
if (!fs7.existsSync(dir)) return null;
|
|
55164
|
+
return fs7.realpathSync(dir);
|
|
55165
|
+
} catch {
|
|
55166
|
+
return null;
|
|
55161
55167
|
}
|
|
55168
|
+
}
|
|
55169
|
+
function publishJournalPath(sessionsDir, safeTargetId) {
|
|
55170
|
+
return path7.join(sessionsDir, PUBLISH_JOURNAL_DIR, `${safeTargetId}.json`);
|
|
55171
|
+
}
|
|
55172
|
+
function writePublishJournal(journalPath, record) {
|
|
55173
|
+
fs7.mkdirSync(path7.dirname(journalPath), { recursive: true });
|
|
55174
|
+
const tempPath = `${journalPath}.tmp`;
|
|
55175
|
+
fs7.writeFileSync(tempPath, JSON.stringify(record, void 0, " "));
|
|
55176
|
+
fs7.renameSync(tempPath, journalPath);
|
|
55177
|
+
}
|
|
55178
|
+
function clearPublishJournal(journalPath) {
|
|
55179
|
+
if (!journalPath) return;
|
|
55162
55180
|
try {
|
|
55163
|
-
|
|
55164
|
-
|
|
55165
|
-
|
|
55166
|
-
|
|
55167
|
-
|
|
55168
|
-
|
|
55181
|
+
fs7.rmSync(journalPath, { force: true });
|
|
55182
|
+
} catch {
|
|
55183
|
+
}
|
|
55184
|
+
}
|
|
55185
|
+
function toIoError(error) {
|
|
55186
|
+
if (error instanceof SessionControlError) return error;
|
|
55187
|
+
return new SessionControlError("session_io_error", error instanceof Error ? error.message : String(error));
|
|
55188
|
+
}
|
|
55189
|
+
function loadRequiredSessionHead(store, sessionId) {
|
|
55190
|
+
const status = store.headStatus(sessionId);
|
|
55191
|
+
if (status === "legacy") {
|
|
55192
|
+
throw new SessionControlError(
|
|
55193
|
+
"session_unsupported_format",
|
|
55194
|
+
`Session uses an unsupported old format: ${sessionId}`
|
|
55195
|
+
);
|
|
55196
|
+
}
|
|
55197
|
+
if (status === "corrupt") {
|
|
55198
|
+
throw new SessionControlError("session_unrecoverable", `Session could not be recovered: ${sessionId}`);
|
|
55199
|
+
}
|
|
55200
|
+
const head = store.readHead(sessionId);
|
|
55201
|
+
if (!head) {
|
|
55202
|
+
throw new SessionControlError("session_not_found", `Session not found: ${sessionId}`);
|
|
55203
|
+
}
|
|
55204
|
+
return head;
|
|
55205
|
+
}
|
|
55206
|
+
async function rewindStoredSession(params) {
|
|
55207
|
+
try {
|
|
55208
|
+
loadRequiredSessionHead(params.store, params.sessionId);
|
|
55209
|
+
if (params.store.getEntrySummary(params.sessionId, params.entryId) === null) {
|
|
55210
|
+
throw new SessionControlError("entry_not_found", `Entry not found: ${params.entryId}`);
|
|
55211
|
+
}
|
|
55212
|
+
params.store.setActiveEntry(params.sessionId, params.entryId);
|
|
55213
|
+
const metadata = params.store.getMetadata(params.sessionId);
|
|
55169
55214
|
if (!metadata) {
|
|
55170
55215
|
throw new SessionControlError("session_unrecoverable", `Session could not be recovered after rewind: ${params.sessionId}`, false);
|
|
55171
55216
|
}
|
|
@@ -55176,52 +55221,179 @@ async function rewindStoredSession(params) {
|
|
|
55176
55221
|
metadata
|
|
55177
55222
|
};
|
|
55178
55223
|
} catch (error) {
|
|
55179
|
-
|
|
55180
|
-
throw new SessionControlError("session_io_error", error instanceof Error ? error.message : String(error));
|
|
55224
|
+
throw toIoError(error);
|
|
55181
55225
|
}
|
|
55182
55226
|
}
|
|
55183
55227
|
async function forkStoredSession(params) {
|
|
55228
|
+
let stagingId;
|
|
55184
55229
|
try {
|
|
55230
|
+
const sanitizedTargetId = params.targetSessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
55231
|
+
if (sanitizedTargetId.startsWith(STAGING_SESSION_ID_PREFIX)) {
|
|
55232
|
+
throw new SessionControlError(
|
|
55233
|
+
"invalid_request",
|
|
55234
|
+
`Target session id starts with a reserved internal prefix: ${params.targetSessionId}`
|
|
55235
|
+
);
|
|
55236
|
+
}
|
|
55237
|
+
if (params.sourceSessionId.replace(/[^a-zA-Z0-9_-]/g, "_").toLowerCase() === sanitizedTargetId.toLowerCase()) {
|
|
55238
|
+
throw new SessionControlError(
|
|
55239
|
+
"invalid_request",
|
|
55240
|
+
"Fork source and target must be different sessions: " + params.sourceSessionId
|
|
55241
|
+
);
|
|
55242
|
+
}
|
|
55243
|
+
if (params.sessionsDir) {
|
|
55244
|
+
const canonicalSourceDir = canonicalSessionDir(params.sessionsDir, params.sourceSessionId);
|
|
55245
|
+
const canonicalTargetDir = canonicalSessionDir(params.sessionsDir, params.targetSessionId);
|
|
55246
|
+
if (canonicalSourceDir !== null && canonicalTargetDir !== null && canonicalSourceDir === canonicalTargetDir) {
|
|
55247
|
+
throw new SessionControlError(
|
|
55248
|
+
"invalid_request",
|
|
55249
|
+
`Fork source and target resolve to the same session directory: ${params.sourceSessionId} -> ${params.targetSessionId}`
|
|
55250
|
+
);
|
|
55251
|
+
}
|
|
55252
|
+
}
|
|
55185
55253
|
if (!params.force) {
|
|
55186
55254
|
const existingTarget = await maybeLoadExistingForkTarget(params);
|
|
55187
55255
|
if (existingTarget) return existingTarget;
|
|
55188
55256
|
}
|
|
55189
|
-
const source =
|
|
55190
|
-
const
|
|
55191
|
-
if (
|
|
55257
|
+
const source = loadRequiredSessionHead(params.store, params.sourceSessionId);
|
|
55258
|
+
const pathSummaries = params.store.getPathSummaries(params.sourceSessionId, params.sourceEntryId);
|
|
55259
|
+
if (pathSummaries.length === 0 || pathSummaries[pathSummaries.length - 1]?.id !== params.sourceEntryId) {
|
|
55192
55260
|
throw new SessionControlError("entry_not_found", `Entry not found: ${params.sourceEntryId}`);
|
|
55193
55261
|
}
|
|
55194
55262
|
const now = params.now ?? Date.now();
|
|
55263
|
+
stagingId = stagingIdFor(params.targetSessionId);
|
|
55264
|
+
params.store.createHead(stagingId, {
|
|
55265
|
+
name: params.name,
|
|
55266
|
+
createdAt: now
|
|
55267
|
+
});
|
|
55195
55268
|
const idMap = /* @__PURE__ */ new Map();
|
|
55196
|
-
|
|
55197
|
-
|
|
55198
|
-
|
|
55199
|
-
|
|
55200
|
-
|
|
55201
|
-
|
|
55202
|
-
|
|
55203
|
-
|
|
55204
|
-
|
|
55269
|
+
let seq = 1;
|
|
55270
|
+
let batch = [];
|
|
55271
|
+
let batchBytes = 0;
|
|
55272
|
+
let lastCopiedId = null;
|
|
55273
|
+
let firstCopiedId = null;
|
|
55274
|
+
const flushBatch = () => {
|
|
55275
|
+
if (batch.length === 0) return;
|
|
55276
|
+
params.store.appendEntries(stagingId, batch, null);
|
|
55277
|
+
batch = [];
|
|
55278
|
+
batchBytes = 0;
|
|
55279
|
+
};
|
|
55280
|
+
for (const summary of pathSummaries) {
|
|
55281
|
+
let entry = null;
|
|
55282
|
+
try {
|
|
55283
|
+
entry = params.store.readEntry(params.sourceSessionId, summary.id);
|
|
55284
|
+
} catch {
|
|
55285
|
+
entry = null;
|
|
55286
|
+
}
|
|
55287
|
+
if (!entry) {
|
|
55288
|
+
throw new SessionControlError(
|
|
55289
|
+
"session_unrecoverable",
|
|
55290
|
+
`Fork source entry is not readable: ${summary.id}`,
|
|
55291
|
+
false
|
|
55292
|
+
);
|
|
55293
|
+
}
|
|
55294
|
+
const copy = {
|
|
55295
|
+
...entry,
|
|
55296
|
+
id: generateEntryId(seq),
|
|
55297
|
+
parentId: lastCopiedId,
|
|
55205
55298
|
timestamp: entry.timestamp
|
|
55206
55299
|
};
|
|
55207
|
-
|
|
55208
|
-
|
|
55209
|
-
|
|
55210
|
-
|
|
55300
|
+
if (copy.compactionData) {
|
|
55301
|
+
const keptId = idMap.get(copy.compactionData.firstKeptEntryId);
|
|
55302
|
+
copy.compactionData = {
|
|
55303
|
+
...copy.compactionData,
|
|
55304
|
+
firstKeptEntryId: keptId ?? firstCopiedId ?? copy.id
|
|
55305
|
+
};
|
|
55306
|
+
}
|
|
55307
|
+
idMap.set(summary.id, copy.id);
|
|
55308
|
+
if (firstCopiedId === null) {
|
|
55309
|
+
firstCopiedId = copy.id;
|
|
55310
|
+
}
|
|
55311
|
+
const copyBytes = Buffer.byteLength(JSON.stringify(copy), "utf8");
|
|
55312
|
+
if (batch.length > 0 && batchBytes + copyBytes > FORK_BATCH_BYTES) flushBatch();
|
|
55313
|
+
batch.push(copy);
|
|
55314
|
+
batchBytes += copyBytes;
|
|
55315
|
+
lastCopiedId = copy.id;
|
|
55316
|
+
seq += 1;
|
|
55317
|
+
if (batch.length >= FORK_BATCH_ENTRIES || batchBytes >= FORK_BATCH_BYTES) {
|
|
55318
|
+
flushBatch();
|
|
55319
|
+
}
|
|
55320
|
+
}
|
|
55321
|
+
flushBatch();
|
|
55322
|
+
if (!lastCopiedId) {
|
|
55323
|
+
throw new SessionControlError("session_unrecoverable", `Fork source has no readable entries: ${params.sourceSessionId}`, false);
|
|
55211
55324
|
}
|
|
55212
|
-
|
|
55325
|
+
params.store.setActiveEntry(stagingId, lastCopiedId);
|
|
55326
|
+
params.store.updateMetadata(stagingId, {
|
|
55213
55327
|
name: params.name,
|
|
55214
55328
|
createdAt: now,
|
|
55215
|
-
updatedAt: now,
|
|
55216
|
-
activeEntryId,
|
|
55217
55329
|
cwd: params.cwd ?? source.metadata.cwd,
|
|
55218
55330
|
sourceSessionId: params.sourceSessionId,
|
|
55219
55331
|
sourceEntryId: params.sourceEntryId,
|
|
55220
55332
|
sourceActiveEntryId: source.metadata.activeEntryId ?? void 0,
|
|
55221
|
-
forkBaseEntryId:
|
|
55333
|
+
forkBaseEntryId: lastCopiedId,
|
|
55222
55334
|
...params.requestId ? { sessionControlRequestId: params.requestId } : {}
|
|
55223
55335
|
});
|
|
55224
|
-
const
|
|
55336
|
+
const backupId = `${params.targetSessionId}-previous-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
55337
|
+
const targetStatus = params.store.headStatus(params.targetSessionId);
|
|
55338
|
+
if (targetStatus === "legacy" || targetStatus === "corrupt") {
|
|
55339
|
+
loadRequiredSessionHead(params.store, params.targetSessionId);
|
|
55340
|
+
}
|
|
55341
|
+
const hadPreviousTarget = targetStatus === "ok";
|
|
55342
|
+
if (hadPreviousTarget && !params.force) {
|
|
55343
|
+
throw new SessionControlError("target_exists", `Target session already exists: ${params.targetSessionId}`);
|
|
55344
|
+
}
|
|
55345
|
+
const safeTargetId = safeSessionDirName(params.targetSessionId);
|
|
55346
|
+
const journalPath = params.sessionsDir ? publishJournalPath(params.sessionsDir, safeTargetId) : null;
|
|
55347
|
+
if (journalPath) {
|
|
55348
|
+
writePublishJournal(journalPath, {
|
|
55349
|
+
v: 1,
|
|
55350
|
+
targetId: safeTargetId,
|
|
55351
|
+
stagingId: safeSessionDirName(stagingId),
|
|
55352
|
+
backupDir: hadPreviousTarget ? safeSessionDirName(backupId) : null,
|
|
55353
|
+
writtenAt: Date.now()
|
|
55354
|
+
});
|
|
55355
|
+
}
|
|
55356
|
+
if (hadPreviousTarget) {
|
|
55357
|
+
try {
|
|
55358
|
+
params.store.moveSession(params.targetSessionId, backupId);
|
|
55359
|
+
} catch (error) {
|
|
55360
|
+
clearPublishJournal(journalPath);
|
|
55361
|
+
throw error;
|
|
55362
|
+
}
|
|
55363
|
+
}
|
|
55364
|
+
try {
|
|
55365
|
+
params.store.moveSession(stagingId, params.targetSessionId);
|
|
55366
|
+
} catch (error) {
|
|
55367
|
+
if (hadPreviousTarget) {
|
|
55368
|
+
try {
|
|
55369
|
+
if (params.store.headStatus(params.targetSessionId) !== "missing") {
|
|
55370
|
+
throw new Error("target path is occupied");
|
|
55371
|
+
}
|
|
55372
|
+
params.store.moveSession(backupId, params.targetSessionId);
|
|
55373
|
+
clearPublishJournal(journalPath);
|
|
55374
|
+
} catch (restoreError) {
|
|
55375
|
+
throw new SessionControlError(
|
|
55376
|
+
"session_io_error",
|
|
55377
|
+
`Fork publication failed; previous session is preserved as ${backupId}. Restore failed: ${String(restoreError)}`,
|
|
55378
|
+
false
|
|
55379
|
+
);
|
|
55380
|
+
}
|
|
55381
|
+
}
|
|
55382
|
+
clearPublishJournal(journalPath);
|
|
55383
|
+
throw error;
|
|
55384
|
+
}
|
|
55385
|
+
let backupDeleted = !hadPreviousTarget;
|
|
55386
|
+
if (hadPreviousTarget) {
|
|
55387
|
+
try {
|
|
55388
|
+
params.store.delete(backupId);
|
|
55389
|
+
backupDeleted = true;
|
|
55390
|
+
} catch {
|
|
55391
|
+
}
|
|
55392
|
+
}
|
|
55393
|
+
if (backupDeleted) {
|
|
55394
|
+
clearPublishJournal(journalPath);
|
|
55395
|
+
}
|
|
55396
|
+
const metadata = params.store.getMetadata(params.targetSessionId);
|
|
55225
55397
|
if (!metadata) {
|
|
55226
55398
|
throw new SessionControlError("session_unrecoverable", `Session could not be recovered after fork: ${params.targetSessionId}`, false);
|
|
55227
55399
|
}
|
|
@@ -55232,13 +55404,23 @@ async function forkStoredSession(params) {
|
|
|
55232
55404
|
sourceActiveEntryId: source.metadata.activeEntryId ?? null
|
|
55233
55405
|
});
|
|
55234
55406
|
} catch (error) {
|
|
55235
|
-
|
|
55236
|
-
|
|
55407
|
+
throw toIoError(error);
|
|
55408
|
+
} finally {
|
|
55409
|
+
if (stagingId) {
|
|
55410
|
+
try {
|
|
55411
|
+
params.store.delete(stagingId);
|
|
55412
|
+
} catch {
|
|
55413
|
+
}
|
|
55414
|
+
}
|
|
55237
55415
|
}
|
|
55238
55416
|
}
|
|
55239
55417
|
async function maybeLoadExistingForkTarget(params) {
|
|
55240
|
-
|
|
55241
|
-
|
|
55418
|
+
const status = params.store.headStatus(params.targetSessionId);
|
|
55419
|
+
if (status === "missing") return null;
|
|
55420
|
+
if (status === "legacy") {
|
|
55421
|
+
throw new SessionControlError("session_unsupported_format", `Target session uses an unsupported old format: ${params.targetSessionId}`);
|
|
55422
|
+
}
|
|
55423
|
+
const target = params.store.readHead(params.targetSessionId);
|
|
55242
55424
|
if (!target) {
|
|
55243
55425
|
throw new SessionControlError("session_unrecoverable", `Session could not be recovered: ${params.targetSessionId}`, false);
|
|
55244
55426
|
}
|
|
@@ -55269,20 +55451,93 @@ function buildForkResult(params) {
|
|
|
55269
55451
|
metadata: params.metadata
|
|
55270
55452
|
};
|
|
55271
55453
|
}
|
|
55272
|
-
function
|
|
55273
|
-
const
|
|
55274
|
-
const
|
|
55275
|
-
let
|
|
55276
|
-
|
|
55277
|
-
|
|
55278
|
-
|
|
55279
|
-
|
|
55280
|
-
current = entry.parentId;
|
|
55454
|
+
function recoverInterruptedPublishes(params) {
|
|
55455
|
+
const outcomes = [];
|
|
55456
|
+
const journalDir = path7.join(params.sessionsDir, PUBLISH_JOURNAL_DIR);
|
|
55457
|
+
let entries;
|
|
55458
|
+
try {
|
|
55459
|
+
entries = fs7.readdirSync(journalDir);
|
|
55460
|
+
} catch {
|
|
55461
|
+
return outcomes;
|
|
55281
55462
|
}
|
|
55282
|
-
|
|
55463
|
+
for (const entry of entries) {
|
|
55464
|
+
if (!entry.endsWith(".json")) continue;
|
|
55465
|
+
outcomes.push(recoverOnePublishJournal({
|
|
55466
|
+
sessionsDir: params.sessionsDir,
|
|
55467
|
+
journalPath: path7.join(journalDir, entry),
|
|
55468
|
+
warn: params.warn
|
|
55469
|
+
}));
|
|
55470
|
+
}
|
|
55471
|
+
return outcomes;
|
|
55283
55472
|
}
|
|
55284
|
-
function
|
|
55285
|
-
|
|
55473
|
+
function recoverOnePublishJournal(params) {
|
|
55474
|
+
const journalName = path7.basename(params.journalPath);
|
|
55475
|
+
const warn = (message) => {
|
|
55476
|
+
(params.warn ?? ((text) => console.warn(text)))(message);
|
|
55477
|
+
};
|
|
55478
|
+
let record;
|
|
55479
|
+
try {
|
|
55480
|
+
const parsed = JSON.parse(fs7.readFileSync(params.journalPath, "utf8"));
|
|
55481
|
+
const safeId = /^[a-zA-Z0-9_-]+$/;
|
|
55482
|
+
if (parsed?.v !== 1 || !safeId.test(parsed.targetId ?? "") || !safeId.test(parsed.stagingId ?? "") || !((parsed.backupDir ?? null) === null || safeId.test(parsed.backupDir))) {
|
|
55483
|
+
throw new Error("journal record has unexpected shape");
|
|
55484
|
+
}
|
|
55485
|
+
record = parsed;
|
|
55486
|
+
} catch (error) {
|
|
55487
|
+
const message = `[session-control] Unreadable publish journal ${journalName}; left in place for manual inspection: ${String(error)}`;
|
|
55488
|
+
warn(message);
|
|
55489
|
+
return { action: "unreadable-journal", journal: journalName, message };
|
|
55490
|
+
}
|
|
55491
|
+
const dirExists = (id) => {
|
|
55492
|
+
try {
|
|
55493
|
+
return fs7.statSync(path7.join(params.sessionsDir, id)).isDirectory();
|
|
55494
|
+
} catch {
|
|
55495
|
+
return false;
|
|
55496
|
+
}
|
|
55497
|
+
};
|
|
55498
|
+
const removeSessionDir = (id) => {
|
|
55499
|
+
fs7.rmSync(path7.join(params.sessionsDir, id), { recursive: true, force: true });
|
|
55500
|
+
};
|
|
55501
|
+
const removeJournal = () => {
|
|
55502
|
+
fs7.rmSync(params.journalPath, { force: true });
|
|
55503
|
+
};
|
|
55504
|
+
const targetExists = dirExists(record.targetId);
|
|
55505
|
+
const backupExists = record.backupDir ? dirExists(record.backupDir) : false;
|
|
55506
|
+
const stagingExists = dirExists(record.stagingId);
|
|
55507
|
+
try {
|
|
55508
|
+
if (targetExists && !stagingExists) {
|
|
55509
|
+
if (backupExists && record.backupDir) removeSessionDir(record.backupDir);
|
|
55510
|
+
removeJournal();
|
|
55511
|
+
return { action: "publish-completed", targetId: record.targetId };
|
|
55512
|
+
}
|
|
55513
|
+
if (!targetExists && backupExists && record.backupDir) {
|
|
55514
|
+
fs7.renameSync(
|
|
55515
|
+
path7.join(params.sessionsDir, record.backupDir),
|
|
55516
|
+
path7.join(params.sessionsDir, record.targetId)
|
|
55517
|
+
);
|
|
55518
|
+
removeJournal();
|
|
55519
|
+
if (stagingExists) {
|
|
55520
|
+
try {
|
|
55521
|
+
removeSessionDir(record.stagingId);
|
|
55522
|
+
} catch (error) {
|
|
55523
|
+
warn(`[session-control] Restored ${record.targetId} but could not remove its abandoned staging copy ${record.stagingId}: ${String(error)}`);
|
|
55524
|
+
}
|
|
55525
|
+
}
|
|
55526
|
+
return { action: "restored-previous-target", targetId: record.targetId };
|
|
55527
|
+
}
|
|
55528
|
+
if (!targetExists && !backupExists) {
|
|
55529
|
+
if (stagingExists) removeSessionDir(record.stagingId);
|
|
55530
|
+
removeJournal();
|
|
55531
|
+
return stagingExists ? { action: "discarded-incomplete-fork", targetId: record.targetId } : { action: "nothing-to-recover", targetId: record.targetId };
|
|
55532
|
+
}
|
|
55533
|
+
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`;
|
|
55534
|
+
warn(message);
|
|
55535
|
+
return { action: "ambiguous-preserved", targetId: record.targetId, message };
|
|
55536
|
+
} catch (error) {
|
|
55537
|
+
const message = `[session-control] Recovery of publish journal ${journalName} failed; state preserved for manual inspection: ${String(error)}`;
|
|
55538
|
+
warn(message);
|
|
55539
|
+
return { action: "ambiguous-preserved", targetId: record.targetId, message };
|
|
55540
|
+
}
|
|
55286
55541
|
}
|
|
55287
55542
|
|
|
55288
55543
|
// src/commands/sessions.ts
|
|
@@ -55339,6 +55594,7 @@ function toSessionCommandError(error, kind) {
|
|
|
55339
55594
|
if (error instanceof SessionControlError) {
|
|
55340
55595
|
const hints = {
|
|
55341
55596
|
session_not_found: "list sessions: pie sessions list --json",
|
|
55597
|
+
session_unsupported_format: "old-format sessions cannot be read by this version",
|
|
55342
55598
|
target_exists: "choose a new --target, or add --force to overwrite"
|
|
55343
55599
|
};
|
|
55344
55600
|
return new CommandError(kind, error.code, error.message, { hint: hints[error.code] });
|
|
@@ -55427,15 +55683,18 @@ async function readSession(parsed) {
|
|
|
55427
55683
|
throw new CommandError("sessions.read", "missing_positional", renderCommandUsage(SESSIONS_READ_SPEC), { usage: true });
|
|
55428
55684
|
}
|
|
55429
55685
|
const store = new FileSessionStore(getSessionsDir());
|
|
55430
|
-
const data =
|
|
55431
|
-
const events = activeTranscriptEvents(
|
|
55686
|
+
const data = loadSessionHead(store, sessionId, "sessions.read");
|
|
55687
|
+
const events = await activeTranscriptEvents(store, sessionId, data.metadata.activeEntryId);
|
|
55432
55688
|
const end = resolveBeforeCursor(events, before);
|
|
55433
55689
|
const start = Math.max(0, end - limit);
|
|
55434
55690
|
const page = events.slice(start, end);
|
|
55691
|
+
for (const event of page) {
|
|
55692
|
+
hydrateTranscriptEvent(store, sessionId, event);
|
|
55693
|
+
}
|
|
55435
55694
|
if (!json) {
|
|
55436
55695
|
console.log(`${data.metadata.id}: ${data.metadata.name}`);
|
|
55437
|
-
for (const
|
|
55438
|
-
console.log(`${
|
|
55696
|
+
for (const event of page) {
|
|
55697
|
+
console.log(`${event.logicalSeq} ${event.type}${event.role ? `:${event.role}` : ""} ${event.content ?? ""}`);
|
|
55439
55698
|
}
|
|
55440
55699
|
return;
|
|
55441
55700
|
}
|
|
@@ -55481,9 +55740,9 @@ async function renameSession(parsed) {
|
|
|
55481
55740
|
throw new CommandError("sessions.rename", "missing_positional", renderCommandUsage(SESSIONS_RENAME_SPEC), { usage: true });
|
|
55482
55741
|
}
|
|
55483
55742
|
const store = new FileSessionStore(getSessionsDir());
|
|
55484
|
-
|
|
55485
|
-
|
|
55486
|
-
const updated =
|
|
55743
|
+
loadSessionHead(store, sessionId, "sessions.rename");
|
|
55744
|
+
store.updateMetadata(sessionId, { name, nameSource: "manual", ...cwd ? { cwd } : {}, updatedAt: Date.now() });
|
|
55745
|
+
const updated = store.getMetadata(sessionId);
|
|
55487
55746
|
if (!updated) throw new CommandError("sessions.rename", "session_not_found", `Session not found after rename: ${sessionId}`);
|
|
55488
55747
|
if (json) {
|
|
55489
55748
|
printSuccessEnvelope("sessions.rename", { session: fullSessionRow(updated) });
|
|
@@ -55523,6 +55782,7 @@ async function forkSession(parsed) {
|
|
|
55523
55782
|
const store = new FileSessionStore(getSessionsDir());
|
|
55524
55783
|
const result = await forkStoredSession({
|
|
55525
55784
|
store,
|
|
55785
|
+
sessionsDir: getSessionsDir(),
|
|
55526
55786
|
sourceSessionId: sessionId,
|
|
55527
55787
|
sourceEntryId,
|
|
55528
55788
|
targetSessionId,
|
|
@@ -55542,10 +55802,19 @@ async function forkSession(parsed) {
|
|
|
55542
55802
|
}
|
|
55543
55803
|
console.log(`Forked ${sessionId} at ${sourceEntryId} into ${targetSessionId}.`);
|
|
55544
55804
|
}
|
|
55545
|
-
|
|
55546
|
-
const
|
|
55547
|
-
if (
|
|
55548
|
-
|
|
55805
|
+
function loadSessionHead(store, sessionId, kind) {
|
|
55806
|
+
const status = store.headStatus(sessionId);
|
|
55807
|
+
if (status === "legacy") {
|
|
55808
|
+
throw new CommandError(kind, "session_unsupported_format", `Session uses an unsupported old format: ${sessionId}`, {
|
|
55809
|
+
hint: "old-format sessions cannot be read by this version"
|
|
55810
|
+
});
|
|
55811
|
+
}
|
|
55812
|
+
if (status === "corrupt") {
|
|
55813
|
+
throw new CommandError(kind, "session_unrecoverable", `Session could not be recovered: ${sessionId}`);
|
|
55814
|
+
}
|
|
55815
|
+
const head = store.readHead(sessionId);
|
|
55816
|
+
if (!head) throw new CommandError(kind, "session_not_found", `Session not found: ${sessionId}`, { hint: "list sessions: pie sessions list --json" });
|
|
55817
|
+
return { metadata: head.metadata };
|
|
55549
55818
|
}
|
|
55550
55819
|
function fullSessionRow(metadata) {
|
|
55551
55820
|
return {
|
|
@@ -55599,31 +55868,30 @@ function cwdMatches(sessionCwd, requestedCwd) {
|
|
|
55599
55868
|
}
|
|
55600
55869
|
function realpathOrInput(value) {
|
|
55601
55870
|
try {
|
|
55602
|
-
return
|
|
55871
|
+
return fs8.realpathSync.native(value);
|
|
55603
55872
|
} catch {
|
|
55604
55873
|
return value;
|
|
55605
55874
|
}
|
|
55606
55875
|
}
|
|
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;
|
|
55876
|
+
async function activeTranscriptEvents(store, sessionId, activeEntryId) {
|
|
55625
55877
|
if (!activeEntryId) return [];
|
|
55626
|
-
|
|
55878
|
+
const summaries = store.getPathSummaries(sessionId, activeEntryId);
|
|
55879
|
+
return summaries.map((summary, index) => ({
|
|
55880
|
+
logicalSeq: index + 1,
|
|
55881
|
+
seq: summary.seq,
|
|
55882
|
+
entryId: summary.id,
|
|
55883
|
+
type: summary.type,
|
|
55884
|
+
timestamp: summary.timestamp,
|
|
55885
|
+
role: summary.role,
|
|
55886
|
+
content: summary.preview || void 0
|
|
55887
|
+
}));
|
|
55888
|
+
}
|
|
55889
|
+
function hydrateTranscriptEvent(store, sessionId, event) {
|
|
55890
|
+
const entry = store.readEntry(sessionId, event.entryId);
|
|
55891
|
+
if (!entry) return;
|
|
55892
|
+
event.turnId = isRecord2(entry.message) && typeof entry.message.turnId === "string" ? entry.message.turnId : void 0;
|
|
55893
|
+
event.content = textFromMessage(entry.message);
|
|
55894
|
+
event.message = entry.message ? cloneJson(entry.message) : void 0;
|
|
55627
55895
|
}
|
|
55628
55896
|
function resolveBeforeCursor(events, cursor) {
|
|
55629
55897
|
if (!cursor) return events.length;
|
|
@@ -55634,7 +55902,7 @@ function resolveBeforeCursor(events, cursor) {
|
|
|
55634
55902
|
const index = events.findIndex((event) => event.entryId === cursor);
|
|
55635
55903
|
return index >= 0 ? index : events.length;
|
|
55636
55904
|
}
|
|
55637
|
-
function
|
|
55905
|
+
function cloneJson(value) {
|
|
55638
55906
|
return JSON.parse(JSON.stringify(value));
|
|
55639
55907
|
}
|
|
55640
55908
|
function listCursorQueryKey(input) {
|
|
@@ -55671,9 +55939,9 @@ function isRecord2(value) {
|
|
|
55671
55939
|
}
|
|
55672
55940
|
|
|
55673
55941
|
// src/extensions/loader.ts
|
|
55674
|
-
import * as
|
|
55942
|
+
import * as fs9 from "node:fs";
|
|
55675
55943
|
import * as os2 from "os";
|
|
55676
|
-
import * as
|
|
55944
|
+
import * as path8 from "path";
|
|
55677
55945
|
import { pathToFileURL } from "node:url";
|
|
55678
55946
|
|
|
55679
55947
|
// src/command-tree.ts
|
|
@@ -55686,19 +55954,19 @@ var CommandTree = class {
|
|
|
55686
55954
|
* register(["session", "new"], { description, handler })
|
|
55687
55955
|
* register(["tools", "subagent", "spawn", "local"], { description, handler })
|
|
55688
55956
|
*/
|
|
55689
|
-
register(
|
|
55690
|
-
if (
|
|
55957
|
+
register(path34, info) {
|
|
55958
|
+
if (path34.length === 0) {
|
|
55691
55959
|
throw new Error("Command path cannot be empty");
|
|
55692
55960
|
}
|
|
55693
55961
|
let current = this.root;
|
|
55694
55962
|
const fullPath = [];
|
|
55695
|
-
for (let i = 0; i <
|
|
55696
|
-
const segment =
|
|
55963
|
+
for (let i = 0; i < path34.length; i++) {
|
|
55964
|
+
const segment = path34[i];
|
|
55697
55965
|
fullPath.push(segment);
|
|
55698
55966
|
if (!current.children) {
|
|
55699
55967
|
current.children = [];
|
|
55700
55968
|
}
|
|
55701
|
-
const isLast = i ===
|
|
55969
|
+
const isLast = i === path34.length - 1;
|
|
55702
55970
|
let node = current.children.find((n) => n.name === segment);
|
|
55703
55971
|
if (!node) {
|
|
55704
55972
|
node = {
|
|
@@ -55728,31 +55996,31 @@ var CommandTree = class {
|
|
|
55728
55996
|
/**
|
|
55729
55997
|
* Find a node by path
|
|
55730
55998
|
*/
|
|
55731
|
-
find(
|
|
55732
|
-
if (
|
|
55999
|
+
find(path34) {
|
|
56000
|
+
if (path34.length === 0) {
|
|
55733
56001
|
return this.root;
|
|
55734
56002
|
}
|
|
55735
|
-
const key =
|
|
56003
|
+
const key = path34.join("/");
|
|
55736
56004
|
return this.pathCache.get(key) || null;
|
|
55737
56005
|
}
|
|
55738
56006
|
/**
|
|
55739
56007
|
* Get children of a path
|
|
55740
56008
|
*/
|
|
55741
|
-
getChildren(
|
|
55742
|
-
const node = this.find(
|
|
56009
|
+
getChildren(path34) {
|
|
56010
|
+
const node = this.find(path34);
|
|
55743
56011
|
return (node?.children || []).filter((child) => !child.hidden);
|
|
55744
56012
|
}
|
|
55745
56013
|
/**
|
|
55746
56014
|
* Check if a path exists (as category or command)
|
|
55747
56015
|
*/
|
|
55748
|
-
exists(
|
|
55749
|
-
return this.find(
|
|
56016
|
+
exists(path34) {
|
|
56017
|
+
return this.find(path34) !== null;
|
|
55750
56018
|
}
|
|
55751
56019
|
/**
|
|
55752
56020
|
* Check if path is a category (has children)
|
|
55753
56021
|
*/
|
|
55754
|
-
isCategory(
|
|
55755
|
-
const node = this.find(
|
|
56022
|
+
isCategory(path34) {
|
|
56023
|
+
const node = this.find(path34);
|
|
55756
56024
|
return node?.isCategory || false;
|
|
55757
56025
|
}
|
|
55758
56026
|
/**
|
|
@@ -55831,8 +56099,8 @@ var CommandTree = class {
|
|
|
55831
56099
|
* Supports dot notation: "tools.subagent.spawn.local"
|
|
55832
56100
|
*/
|
|
55833
56101
|
registerFromPath(pathStr, info) {
|
|
55834
|
-
const
|
|
55835
|
-
this.register(
|
|
56102
|
+
const path34 = pathStr.split(/[./]/).filter(Boolean);
|
|
56103
|
+
this.register(path34, info);
|
|
55836
56104
|
}
|
|
55837
56105
|
};
|
|
55838
56106
|
var commandTree = new CommandTree();
|
|
@@ -55995,19 +56263,19 @@ function createExtension(extensionPath, resolvedPath, identity, source) {
|
|
|
55995
56263
|
}
|
|
55996
56264
|
function expandPath(p) {
|
|
55997
56265
|
if (p.startsWith("~/")) {
|
|
55998
|
-
return
|
|
56266
|
+
return path8.join(os2.homedir(), p.slice(2));
|
|
55999
56267
|
}
|
|
56000
56268
|
if (p.startsWith("~")) {
|
|
56001
|
-
return
|
|
56269
|
+
return path8.join(os2.homedir(), p.slice(1));
|
|
56002
56270
|
}
|
|
56003
56271
|
return p;
|
|
56004
56272
|
}
|
|
56005
56273
|
function resolvePath(extPath, cwd) {
|
|
56006
56274
|
const expanded = expandPath(extPath);
|
|
56007
|
-
if (
|
|
56275
|
+
if (path8.isAbsolute(expanded)) {
|
|
56008
56276
|
return expanded;
|
|
56009
56277
|
}
|
|
56010
|
-
return
|
|
56278
|
+
return path8.resolve(cwd, expanded);
|
|
56011
56279
|
}
|
|
56012
56280
|
async function loadExtensionModule(extensionPath) {
|
|
56013
56281
|
try {
|
|
@@ -56027,14 +56295,14 @@ function normalizeExtensionImportPath(extensionPath) {
|
|
|
56027
56295
|
if (/^[a-zA-Z]:[\\/]/.test(extensionPath)) {
|
|
56028
56296
|
return `file:///${extensionPath.replace(/\\/g, "/")}`;
|
|
56029
56297
|
}
|
|
56030
|
-
if (
|
|
56298
|
+
if (path8.isAbsolute(extensionPath)) {
|
|
56031
56299
|
return pathToFileURL(extensionPath).href;
|
|
56032
56300
|
}
|
|
56033
56301
|
return extensionPath;
|
|
56034
56302
|
}
|
|
56035
56303
|
async function loadExtension(extensionPath, cwd, uiContext, abortFn, isIdleFn, hasUI, actions, discovered) {
|
|
56036
56304
|
const resolvedPath = resolvePath(extensionPath, cwd);
|
|
56037
|
-
if (!
|
|
56305
|
+
if (!fs9.existsSync(resolvedPath)) {
|
|
56038
56306
|
return { extension: null, error: `Extension not found: ${extensionPath}` };
|
|
56039
56307
|
}
|
|
56040
56308
|
try {
|
|
@@ -56060,17 +56328,17 @@ async function loadExtension(extensionPath, cwd, uiContext, abortFn, isIdleFn, h
|
|
|
56060
56328
|
}
|
|
56061
56329
|
}
|
|
56062
56330
|
function discoverExtensionsInDir(dir, source) {
|
|
56063
|
-
if (!
|
|
56331
|
+
if (!fs9.existsSync(dir)) {
|
|
56064
56332
|
return [];
|
|
56065
56333
|
}
|
|
56066
56334
|
const discovered = [];
|
|
56067
56335
|
try {
|
|
56068
|
-
const entries =
|
|
56336
|
+
const entries = fs9.readdirSync(dir, { withFileTypes: true });
|
|
56069
56337
|
for (const entry of entries) {
|
|
56070
56338
|
if (entry.name.endsWith(".disabled")) {
|
|
56071
56339
|
continue;
|
|
56072
56340
|
}
|
|
56073
|
-
const entryPath =
|
|
56341
|
+
const entryPath = path8.join(dir, entry.name);
|
|
56074
56342
|
if (entry.isFile() && (entry.name.endsWith(".cjs") || entry.name.endsWith(".js") || entry.name.endsWith(".ts"))) {
|
|
56075
56343
|
discovered.push({
|
|
56076
56344
|
entryPath,
|
|
@@ -56080,13 +56348,13 @@ function discoverExtensionsInDir(dir, source) {
|
|
|
56080
56348
|
continue;
|
|
56081
56349
|
}
|
|
56082
56350
|
if (entry.isDirectory()) {
|
|
56083
|
-
const packageJsonPath =
|
|
56351
|
+
const packageJsonPath = path8.join(entryPath, "package.json");
|
|
56084
56352
|
let packageIdentity;
|
|
56085
56353
|
let packageDescription;
|
|
56086
56354
|
let packageMainPath;
|
|
56087
|
-
if (
|
|
56355
|
+
if (fs9.existsSync(packageJsonPath)) {
|
|
56088
56356
|
try {
|
|
56089
|
-
const pkg = JSON.parse(
|
|
56357
|
+
const pkg = JSON.parse(fs9.readFileSync(packageJsonPath, "utf-8"));
|
|
56090
56358
|
const manifest = pkg.pie && typeof pkg.pie === "object" && !Array.isArray(pkg.pie) ? pkg.pie : void 0;
|
|
56091
56359
|
packageIdentity = resolveExtensionIdentity({
|
|
56092
56360
|
pieName: typeof manifest?.name === "string" ? manifest.name : void 0,
|
|
@@ -56095,8 +56363,8 @@ function discoverExtensionsInDir(dir, source) {
|
|
|
56095
56363
|
});
|
|
56096
56364
|
packageDescription = typeof pkg.description === "string" ? pkg.description : void 0;
|
|
56097
56365
|
if (typeof manifest?.main === "string" && manifest.main.trim().length > 0) {
|
|
56098
|
-
const candidate =
|
|
56099
|
-
if (
|
|
56366
|
+
const candidate = path8.resolve(entryPath, manifest.main);
|
|
56367
|
+
if (fs9.existsSync(candidate)) {
|
|
56100
56368
|
packageMainPath = candidate;
|
|
56101
56369
|
}
|
|
56102
56370
|
}
|
|
@@ -56112,8 +56380,8 @@ function discoverExtensionsInDir(dir, source) {
|
|
|
56112
56380
|
});
|
|
56113
56381
|
continue;
|
|
56114
56382
|
}
|
|
56115
|
-
const indexCjs =
|
|
56116
|
-
if (
|
|
56383
|
+
const indexCjs = path8.join(entryPath, "index.cjs");
|
|
56384
|
+
if (fs9.existsSync(indexCjs)) {
|
|
56117
56385
|
discovered.push({
|
|
56118
56386
|
entryPath: indexCjs,
|
|
56119
56387
|
source,
|
|
@@ -56122,8 +56390,8 @@ function discoverExtensionsInDir(dir, source) {
|
|
|
56122
56390
|
});
|
|
56123
56391
|
continue;
|
|
56124
56392
|
}
|
|
56125
|
-
const indexJs =
|
|
56126
|
-
if (
|
|
56393
|
+
const indexJs = path8.join(entryPath, "index.js");
|
|
56394
|
+
if (fs9.existsSync(indexJs)) {
|
|
56127
56395
|
discovered.push({
|
|
56128
56396
|
entryPath: indexJs,
|
|
56129
56397
|
source,
|
|
@@ -56132,8 +56400,8 @@ function discoverExtensionsInDir(dir, source) {
|
|
|
56132
56400
|
});
|
|
56133
56401
|
continue;
|
|
56134
56402
|
}
|
|
56135
|
-
const indexTs =
|
|
56136
|
-
if (
|
|
56403
|
+
const indexTs = path8.join(entryPath, "index.ts");
|
|
56404
|
+
if (fs9.existsSync(indexTs)) {
|
|
56137
56405
|
discovered.push({
|
|
56138
56406
|
entryPath: indexTs,
|
|
56139
56407
|
source,
|
|
@@ -56154,21 +56422,21 @@ function collectDiscoveredExtensions(configuredPaths, cwd, options) {
|
|
|
56154
56422
|
const errors = [];
|
|
56155
56423
|
if (!options?.noExtensions) {
|
|
56156
56424
|
if (!options?.noBuiltinExtensions) {
|
|
56157
|
-
const builtinExtDir =
|
|
56425
|
+
const builtinExtDir = path8.join(getBuiltinDir(), "extensions");
|
|
56158
56426
|
discovered.push(...discoverExtensionsInDir(builtinExtDir, "builtin"));
|
|
56159
56427
|
}
|
|
56160
|
-
const globalExtDir =
|
|
56428
|
+
const globalExtDir = path8.join(os2.homedir(), ".pie", "extensions");
|
|
56161
56429
|
discovered.push(...discoverExtensionsInDir(globalExtDir, "global"));
|
|
56162
|
-
const localExtDir =
|
|
56430
|
+
const localExtDir = path8.join(cwd, ".pie", "extensions");
|
|
56163
56431
|
discovered.push(...discoverExtensionsInDir(localExtDir, "project"));
|
|
56164
56432
|
}
|
|
56165
56433
|
for (const p of configuredPaths) {
|
|
56166
56434
|
const resolved = resolvePath(p, cwd);
|
|
56167
|
-
if (!
|
|
56435
|
+
if (!fs9.existsSync(resolved)) {
|
|
56168
56436
|
errors.push({ path: p, error: `Extension path not found: ${p}` });
|
|
56169
56437
|
continue;
|
|
56170
56438
|
}
|
|
56171
|
-
if (!
|
|
56439
|
+
if (!fs9.statSync(resolved).isDirectory()) {
|
|
56172
56440
|
errors.push({ path: p, error: `Extension path must be a directory: ${p}` });
|
|
56173
56441
|
continue;
|
|
56174
56442
|
}
|
|
@@ -57023,8 +57291,8 @@ function wrapSingleLine(line, width) {
|
|
|
57023
57291
|
if (!line) {
|
|
57024
57292
|
return [""];
|
|
57025
57293
|
}
|
|
57026
|
-
const
|
|
57027
|
-
if (
|
|
57294
|
+
const visibleLength = visibleWidth(line);
|
|
57295
|
+
if (visibleLength <= width) {
|
|
57028
57296
|
return [line];
|
|
57029
57297
|
}
|
|
57030
57298
|
const wrapped = [];
|
|
@@ -58056,9 +58324,9 @@ var KillRing = class {
|
|
|
58056
58324
|
};
|
|
58057
58325
|
|
|
58058
58326
|
// ../../packages/tui/src/tui.ts
|
|
58059
|
-
import * as
|
|
58327
|
+
import * as fs10 from "node:fs";
|
|
58060
58328
|
import * as os3 from "node:os";
|
|
58061
|
-
import * as
|
|
58329
|
+
import * as path9 from "node:path";
|
|
58062
58330
|
|
|
58063
58331
|
// ../../packages/tui/src/terminal-image.ts
|
|
58064
58332
|
var cachedCapabilities = null;
|
|
@@ -58738,11 +59006,11 @@ var TUI = class extends Container {
|
|
|
58738
59006
|
const debugRedraw = process.env.PIE_DEBUG_REDRAW === "1";
|
|
58739
59007
|
const logRedraw = (reason) => {
|
|
58740
59008
|
if (!debugRedraw) return;
|
|
58741
|
-
const logPath =
|
|
58742
|
-
|
|
59009
|
+
const logPath = path9.join(os3.homedir(), ".pie", "logs", "pie-cli.log");
|
|
59010
|
+
fs10.mkdirSync(path9.dirname(logPath), { recursive: true });
|
|
58743
59011
|
const msg = `[${(/* @__PURE__ */ new Date()).toISOString()}] [DEBUG] [ui] fullRender: ${reason} (prev=${this.previousLines.length}, new=${newLines.length}, height=${height})
|
|
58744
59012
|
`;
|
|
58745
|
-
|
|
59013
|
+
fs10.appendFileSync(logPath, msg);
|
|
58746
59014
|
};
|
|
58747
59015
|
if (this.previousLines.length === 0 && !widthChanged) {
|
|
58748
59016
|
logRedraw("first render");
|
|
@@ -58835,7 +59103,7 @@ var TUI = class extends Container {
|
|
|
58835
59103
|
const line = newLines[i];
|
|
58836
59104
|
const isImage = isImageLine(line);
|
|
58837
59105
|
if (!isImage && visibleWidth(line) > width) {
|
|
58838
|
-
const crashLogPath =
|
|
59106
|
+
const crashLogPath = path9.join(os3.homedir(), ".pie", "pie-crash.log");
|
|
58839
59107
|
const crashData = [
|
|
58840
59108
|
`Crash at ${(/* @__PURE__ */ new Date()).toISOString()}`,
|
|
58841
59109
|
`Terminal width: ${width}`,
|
|
@@ -58845,8 +59113,8 @@ var TUI = class extends Container {
|
|
|
58845
59113
|
...newLines.map((l, idx) => `[${idx}] (w=${visibleWidth(l)}) ${l}`),
|
|
58846
59114
|
""
|
|
58847
59115
|
].join("\n");
|
|
58848
|
-
|
|
58849
|
-
|
|
59116
|
+
fs10.mkdirSync(path9.dirname(crashLogPath), { recursive: true });
|
|
59117
|
+
fs10.writeFileSync(crashLogPath, crashData);
|
|
58850
59118
|
this.stop();
|
|
58851
59119
|
const errorMsg = [
|
|
58852
59120
|
`Rendered line ${i} exceeds terminal width (${visibleWidth(line)} > ${width}).`,
|
|
@@ -58876,8 +59144,8 @@ var TUI = class extends Container {
|
|
|
58876
59144
|
buffer += "\x1B[?2026l";
|
|
58877
59145
|
if (process.env.PIE_TUI_DEBUG === "1") {
|
|
58878
59146
|
const debugDir = "/tmp/tui";
|
|
58879
|
-
|
|
58880
|
-
const debugPath =
|
|
59147
|
+
fs10.mkdirSync(debugDir, { recursive: true });
|
|
59148
|
+
const debugPath = path9.join(debugDir, `render-${Date.now()}-${Math.random().toString(36).slice(2)}.log`);
|
|
58881
59149
|
const debugData = [
|
|
58882
59150
|
`firstChanged: ${firstChanged}`,
|
|
58883
59151
|
`viewportTop: ${viewportTop}`,
|
|
@@ -58900,7 +59168,7 @@ var TUI = class extends Container {
|
|
|
58900
59168
|
"=== buffer ===",
|
|
58901
59169
|
JSON.stringify(buffer)
|
|
58902
59170
|
].join("\n");
|
|
58903
|
-
|
|
59171
|
+
fs10.writeFileSync(debugPath, debugData);
|
|
58904
59172
|
}
|
|
58905
59173
|
this.terminal.write(buffer);
|
|
58906
59174
|
this.cursorRow = Math.max(0, newLines.length - 1);
|
|
@@ -63189,7 +63457,7 @@ var StdinBuffer = class extends EventEmitter {
|
|
|
63189
63457
|
};
|
|
63190
63458
|
|
|
63191
63459
|
// ../../packages/tui/src/terminal.ts
|
|
63192
|
-
import * as
|
|
63460
|
+
import * as fs11 from "node:fs";
|
|
63193
63461
|
import koffi from "koffi";
|
|
63194
63462
|
var ProcessTerminal = class {
|
|
63195
63463
|
wasRaw = false;
|
|
@@ -63352,7 +63620,7 @@ var ProcessTerminal = class {
|
|
|
63352
63620
|
process.stdout.write(data);
|
|
63353
63621
|
if (this.writeLogPath) {
|
|
63354
63622
|
try {
|
|
63355
|
-
|
|
63623
|
+
fs11.appendFileSync(this.writeLogPath, data, { encoding: "utf8" });
|
|
63356
63624
|
} catch {
|
|
63357
63625
|
}
|
|
63358
63626
|
}
|
|
@@ -64197,8 +64465,8 @@ function restoreInteractiveSessionState(options) {
|
|
|
64197
64465
|
}
|
|
64198
64466
|
|
|
64199
64467
|
// src/keybindings.ts
|
|
64200
|
-
import { existsSync as
|
|
64201
|
-
import { join as
|
|
64468
|
+
import { existsSync as existsSync9, readFileSync as readFileSync8 } from "fs";
|
|
64469
|
+
import { join as join8 } from "path";
|
|
64202
64470
|
var DEFAULT_APP_KEYBINDINGS = {
|
|
64203
64471
|
interrupt: "escape",
|
|
64204
64472
|
clear: "ctrl+c",
|
|
@@ -64262,7 +64530,7 @@ var KeybindingsManager = class _KeybindingsManager {
|
|
|
64262
64530
|
* Create from config file and set up editor keybindings.
|
|
64263
64531
|
*/
|
|
64264
64532
|
static create(agentDir = getAgentDir()) {
|
|
64265
|
-
const configPath =
|
|
64533
|
+
const configPath = join8(agentDir, "keybindings.json");
|
|
64266
64534
|
const config = _KeybindingsManager.loadFromFile(configPath);
|
|
64267
64535
|
const manager = new _KeybindingsManager(config);
|
|
64268
64536
|
const editorConfig = {};
|
|
@@ -64280,10 +64548,10 @@ var KeybindingsManager = class _KeybindingsManager {
|
|
|
64280
64548
|
static inMemory(config = {}) {
|
|
64281
64549
|
return new _KeybindingsManager(config);
|
|
64282
64550
|
}
|
|
64283
|
-
static loadFromFile(
|
|
64284
|
-
if (!
|
|
64551
|
+
static loadFromFile(path34) {
|
|
64552
|
+
if (!existsSync9(path34)) return {};
|
|
64285
64553
|
try {
|
|
64286
|
-
return JSON.parse(
|
|
64554
|
+
return JSON.parse(readFileSync8(path34, "utf-8"));
|
|
64287
64555
|
} catch {
|
|
64288
64556
|
return {};
|
|
64289
64557
|
}
|
|
@@ -64332,19 +64600,19 @@ var KeybindingsManager = class _KeybindingsManager {
|
|
|
64332
64600
|
};
|
|
64333
64601
|
|
|
64334
64602
|
// src/project-knowledge.ts
|
|
64335
|
-
import
|
|
64336
|
-
import
|
|
64603
|
+
import fs12 from "node:fs";
|
|
64604
|
+
import path10 from "node:path";
|
|
64337
64605
|
function collectAncestorAgentsFiles(cwd) {
|
|
64338
|
-
const resolvedCwd =
|
|
64606
|
+
const resolvedCwd = path10.resolve(cwd || process.cwd());
|
|
64339
64607
|
const projectRoot = resolveCliProjectRoot(resolvedCwd);
|
|
64340
64608
|
const candidates = [];
|
|
64341
64609
|
let current = resolvedCwd;
|
|
64342
64610
|
while (true) {
|
|
64343
|
-
candidates.unshift(
|
|
64611
|
+
candidates.unshift(path10.join(current, AGENTS_CONTEXT_FILE_NAME));
|
|
64344
64612
|
if (current === projectRoot) {
|
|
64345
64613
|
break;
|
|
64346
64614
|
}
|
|
64347
|
-
const parent =
|
|
64615
|
+
const parent = path10.dirname(current);
|
|
64348
64616
|
if (parent === current) {
|
|
64349
64617
|
break;
|
|
64350
64618
|
}
|
|
@@ -64352,13 +64620,13 @@ function collectAncestorAgentsFiles(cwd) {
|
|
|
64352
64620
|
}
|
|
64353
64621
|
const files = [];
|
|
64354
64622
|
for (const candidate of candidates) {
|
|
64355
|
-
if (!
|
|
64623
|
+
if (!fs12.existsSync(candidate)) {
|
|
64356
64624
|
continue;
|
|
64357
64625
|
}
|
|
64358
64626
|
try {
|
|
64359
64627
|
files.push({
|
|
64360
|
-
path:
|
|
64361
|
-
content:
|
|
64628
|
+
path: path10.relative(resolvedCwd, candidate) || AGENTS_CONTEXT_FILE_NAME,
|
|
64629
|
+
content: fs12.readFileSync(candidate, "utf-8")
|
|
64362
64630
|
});
|
|
64363
64631
|
} catch {
|
|
64364
64632
|
}
|
|
@@ -64370,14 +64638,14 @@ function buildCliProjectContextSection(cwd) {
|
|
|
64370
64638
|
}
|
|
64371
64639
|
|
|
64372
64640
|
// src/file-access-context.ts
|
|
64373
|
-
import * as
|
|
64641
|
+
import * as path11 from "node:path";
|
|
64374
64642
|
function uniqueNormalizedPaths(paths) {
|
|
64375
64643
|
const seen = /* @__PURE__ */ new Set();
|
|
64376
64644
|
const result = [];
|
|
64377
64645
|
for (const entry of paths) {
|
|
64378
64646
|
const trimmed = String(entry || "").trim();
|
|
64379
64647
|
if (!trimmed) continue;
|
|
64380
|
-
const normalized =
|
|
64648
|
+
const normalized = path11.normalize(trimmed);
|
|
64381
64649
|
if (seen.has(normalized)) continue;
|
|
64382
64650
|
seen.add(normalized);
|
|
64383
64651
|
result.push(normalized);
|
|
@@ -64396,8 +64664,8 @@ function buildCliFileAccessOptions(params) {
|
|
|
64396
64664
|
}
|
|
64397
64665
|
|
|
64398
64666
|
// src/theme/theme.ts
|
|
64399
|
-
import * as
|
|
64400
|
-
import * as
|
|
64667
|
+
import * as fs13 from "node:fs";
|
|
64668
|
+
import * as path12 from "node:path";
|
|
64401
64669
|
|
|
64402
64670
|
// ../../node_modules/@sinclair/typebox/build/esm/compiler/compiler.mjs
|
|
64403
64671
|
var TypeCheck = class {
|
|
@@ -65284,11 +65552,11 @@ var BUILTIN_THEMES;
|
|
|
65284
65552
|
function getBuiltinThemes() {
|
|
65285
65553
|
if (!BUILTIN_THEMES) {
|
|
65286
65554
|
const themesDir = getThemesDir();
|
|
65287
|
-
const darkPath =
|
|
65288
|
-
const lightPath =
|
|
65555
|
+
const darkPath = path12.join(themesDir, "dark.json");
|
|
65556
|
+
const lightPath = path12.join(themesDir, "light.json");
|
|
65289
65557
|
BUILTIN_THEMES = {
|
|
65290
|
-
dark: JSON.parse(
|
|
65291
|
-
light: JSON.parse(
|
|
65558
|
+
dark: JSON.parse(fs13.readFileSync(darkPath, "utf-8")),
|
|
65559
|
+
light: JSON.parse(fs13.readFileSync(lightPath, "utf-8"))
|
|
65292
65560
|
};
|
|
65293
65561
|
}
|
|
65294
65562
|
return BUILTIN_THEMES;
|
|
@@ -65296,8 +65564,8 @@ function getBuiltinThemes() {
|
|
|
65296
65564
|
function getAvailableThemes() {
|
|
65297
65565
|
const themes = new Set(Object.keys(getBuiltinThemes()));
|
|
65298
65566
|
const customThemesDir = getCustomThemesDir();
|
|
65299
|
-
if (
|
|
65300
|
-
const files =
|
|
65567
|
+
if (fs13.existsSync(customThemesDir)) {
|
|
65568
|
+
const files = fs13.readdirSync(customThemesDir);
|
|
65301
65569
|
for (const file of files) {
|
|
65302
65570
|
if (file.endsWith(".json")) {
|
|
65303
65571
|
themes.add(file.slice(0, -5));
|
|
@@ -65358,18 +65626,18 @@ function loadThemeJson(name) {
|
|
|
65358
65626
|
}
|
|
65359
65627
|
const registeredTheme = registeredThemes.get(name);
|
|
65360
65628
|
if (registeredTheme?.sourcePath) {
|
|
65361
|
-
const content2 =
|
|
65629
|
+
const content2 = fs13.readFileSync(registeredTheme.sourcePath, "utf-8");
|
|
65362
65630
|
return parseThemeJsonContent(registeredTheme.sourcePath, content2);
|
|
65363
65631
|
}
|
|
65364
65632
|
if (registeredTheme) {
|
|
65365
65633
|
throw new Error(`Theme "${name}" does not have a source path for export`);
|
|
65366
65634
|
}
|
|
65367
65635
|
const customThemesDir = getCustomThemesDir();
|
|
65368
|
-
const themePath =
|
|
65369
|
-
if (!
|
|
65636
|
+
const themePath = path12.join(customThemesDir, `${name}.json`);
|
|
65637
|
+
if (!fs13.existsSync(themePath)) {
|
|
65370
65638
|
throw new Error(`Theme not found: ${name}`);
|
|
65371
65639
|
}
|
|
65372
|
-
const content =
|
|
65640
|
+
const content = fs13.readFileSync(themePath, "utf-8");
|
|
65373
65641
|
return parseThemeJsonContent(name, content);
|
|
65374
65642
|
}
|
|
65375
65643
|
function createTheme(themeJson, mode, sourcePath) {
|
|
@@ -65482,12 +65750,12 @@ function startThemeWatcher() {
|
|
|
65482
65750
|
return;
|
|
65483
65751
|
}
|
|
65484
65752
|
const customThemesDir = getCustomThemesDir();
|
|
65485
|
-
const themeFile =
|
|
65486
|
-
if (!
|
|
65753
|
+
const themeFile = path12.join(customThemesDir, `${currentThemeName}.json`);
|
|
65754
|
+
if (!fs13.existsSync(themeFile)) {
|
|
65487
65755
|
return;
|
|
65488
65756
|
}
|
|
65489
65757
|
try {
|
|
65490
|
-
themeWatcher =
|
|
65758
|
+
themeWatcher = fs13.watch(themeFile, (eventType) => {
|
|
65491
65759
|
if (eventType === "change") {
|
|
65492
65760
|
setTimeout(() => {
|
|
65493
65761
|
try {
|
|
@@ -65500,7 +65768,7 @@ function startThemeWatcher() {
|
|
|
65500
65768
|
}, 100);
|
|
65501
65769
|
} else if (eventType === "rename") {
|
|
65502
65770
|
setTimeout(() => {
|
|
65503
|
-
if (!
|
|
65771
|
+
if (!fs13.existsSync(themeFile)) {
|
|
65504
65772
|
currentThemeName = "dark";
|
|
65505
65773
|
setGlobalTheme(loadTheme("dark"));
|
|
65506
65774
|
if (themeWatcher) {
|
|
@@ -65681,9 +65949,9 @@ function getSettingsListTheme() {
|
|
|
65681
65949
|
|
|
65682
65950
|
// src/skills/loader.ts
|
|
65683
65951
|
var import_yaml = __toESM(require_dist2(), 1);
|
|
65684
|
-
import * as
|
|
65952
|
+
import * as fs14 from "fs";
|
|
65685
65953
|
import * as os4 from "os";
|
|
65686
|
-
import * as
|
|
65954
|
+
import * as path13 from "path";
|
|
65687
65955
|
function parseSkillDescription(content) {
|
|
65688
65956
|
content = content.replace(/^\uFEFF/, "").replace(/\r\n/g, "\n");
|
|
65689
65957
|
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---(?:\n|$)/);
|
|
@@ -65707,19 +65975,19 @@ function parseSkillDescription(content) {
|
|
|
65707
65975
|
}
|
|
65708
65976
|
var USER_CONTROLLED_SOURCES = /* @__PURE__ */ new Set(["user-agents", "user"]);
|
|
65709
65977
|
function pathIsInside(child, parent) {
|
|
65710
|
-
const relative3 =
|
|
65711
|
-
return relative3 !== "" && !relative3.startsWith(`..${
|
|
65978
|
+
const relative3 = path13.relative(parent, child);
|
|
65979
|
+
return relative3 !== "" && !relative3.startsWith(`..${path13.sep}`) && relative3 !== ".." && !path13.isAbsolute(relative3);
|
|
65712
65980
|
}
|
|
65713
65981
|
function resolveSkillSymlink(fullPath, dir, source) {
|
|
65714
65982
|
let target;
|
|
65715
65983
|
let stats;
|
|
65716
65984
|
try {
|
|
65717
|
-
target =
|
|
65718
|
-
stats =
|
|
65985
|
+
target = fs14.realpathSync(fullPath);
|
|
65986
|
+
stats = fs14.statSync(target);
|
|
65719
65987
|
} catch {
|
|
65720
65988
|
return { error: `broken skill symlink: ${fullPath}` };
|
|
65721
65989
|
}
|
|
65722
|
-
if (!USER_CONTROLLED_SOURCES.has(source) && !pathIsInside(target,
|
|
65990
|
+
if (!USER_CONTROLLED_SOURCES.has(source) && !pathIsInside(target, fs14.realpathSync(dir))) {
|
|
65723
65991
|
return { error: `skill symlink escapes the "${source}" layer (not loaded): ${fullPath} -> ${target}` };
|
|
65724
65992
|
}
|
|
65725
65993
|
return { target, isDirectory: stats.isDirectory(), isFile: stats.isFile() };
|
|
@@ -65727,13 +65995,13 @@ function resolveSkillSymlink(fullPath, dir, source) {
|
|
|
65727
65995
|
function loadSkillsFromDir(dir, source) {
|
|
65728
65996
|
const skills = [];
|
|
65729
65997
|
const diagnostics = [];
|
|
65730
|
-
if (!
|
|
65998
|
+
if (!fs14.existsSync(dir)) {
|
|
65731
65999
|
return { skills, diagnostics };
|
|
65732
66000
|
}
|
|
65733
|
-
const entries =
|
|
66001
|
+
const entries = fs14.readdirSync(dir, { withFileTypes: true });
|
|
65734
66002
|
for (const entry of entries) {
|
|
65735
66003
|
if (entry.name.startsWith(".")) continue;
|
|
65736
|
-
const fullPath =
|
|
66004
|
+
const fullPath = path13.join(dir, entry.name);
|
|
65737
66005
|
let entryPath = fullPath;
|
|
65738
66006
|
let entryIsDirectory = entry.isDirectory();
|
|
65739
66007
|
let entryIsFile = entry.isFile();
|
|
@@ -65748,10 +66016,10 @@ function loadSkillsFromDir(dir, source) {
|
|
|
65748
66016
|
entryIsFile = resolved.isFile;
|
|
65749
66017
|
}
|
|
65750
66018
|
if (entryIsDirectory) {
|
|
65751
|
-
const skillMdPath =
|
|
65752
|
-
if (
|
|
66019
|
+
const skillMdPath = path13.join(entryPath, "SKILL.md");
|
|
66020
|
+
if (fs14.existsSync(skillMdPath)) {
|
|
65753
66021
|
try {
|
|
65754
|
-
const content =
|
|
66022
|
+
const content = fs14.readFileSync(skillMdPath, "utf-8");
|
|
65755
66023
|
const description = parseSkillDescription(content);
|
|
65756
66024
|
skills.push({
|
|
65757
66025
|
name: entry.name,
|
|
@@ -65772,7 +66040,7 @@ function loadSkillsFromDir(dir, source) {
|
|
|
65772
66040
|
} else if (entryIsFile && entry.name.endsWith(".md")) {
|
|
65773
66041
|
const name = entry.name.slice(0, -3);
|
|
65774
66042
|
try {
|
|
65775
|
-
const content =
|
|
66043
|
+
const content = fs14.readFileSync(entryPath, "utf-8");
|
|
65776
66044
|
const description = parseSkillDescription(content);
|
|
65777
66045
|
skills.push({
|
|
65778
66046
|
name,
|
|
@@ -65780,7 +66048,7 @@ function loadSkillsFromDir(dir, source) {
|
|
|
65780
66048
|
content,
|
|
65781
66049
|
filePath: entryPath,
|
|
65782
66050
|
source,
|
|
65783
|
-
baseDir:
|
|
66051
|
+
baseDir: path13.dirname(entryPath)
|
|
65784
66052
|
});
|
|
65785
66053
|
} catch (e) {
|
|
65786
66054
|
diagnostics.push({
|
|
@@ -65794,18 +66062,18 @@ function loadSkillsFromDir(dir, source) {
|
|
|
65794
66062
|
return { skills, diagnostics };
|
|
65795
66063
|
}
|
|
65796
66064
|
function discoverAgentsSkillsDirs(cwd) {
|
|
65797
|
-
const resolvedCwd =
|
|
66065
|
+
const resolvedCwd = path13.resolve(cwd || process.cwd());
|
|
65798
66066
|
const projectRoot = resolveCliProjectRoot(resolvedCwd);
|
|
65799
66067
|
const projectAgentsDirs = [];
|
|
65800
66068
|
let current = projectRoot;
|
|
65801
66069
|
while (true) {
|
|
65802
|
-
projectAgentsDirs.push(
|
|
66070
|
+
projectAgentsDirs.push(path13.join(current, ".agents", "skills"));
|
|
65803
66071
|
if (current === resolvedCwd) break;
|
|
65804
|
-
const child =
|
|
66072
|
+
const child = path13.relative(current, resolvedCwd).split(path13.sep)[0];
|
|
65805
66073
|
if (!child) break;
|
|
65806
|
-
current =
|
|
66074
|
+
current = path13.join(current, child);
|
|
65807
66075
|
}
|
|
65808
|
-
return { userAgentsDir:
|
|
66076
|
+
return { userAgentsDir: path13.join(os4.homedir(), ".agents", "skills"), projectAgentsDirs };
|
|
65809
66077
|
}
|
|
65810
66078
|
function buildSkillDirs(options) {
|
|
65811
66079
|
const { userAgentsDir, projectAgentsDirs } = discoverAgentsSkillsDirs(options.cwd);
|
|
@@ -65976,11 +66244,11 @@ function validateSkillName(name) {
|
|
|
65976
66244
|
}
|
|
65977
66245
|
|
|
65978
66246
|
// src/interactive-mode.ts
|
|
65979
|
-
import * as
|
|
66247
|
+
import * as path30 from "path";
|
|
65980
66248
|
|
|
65981
66249
|
// src/capabilities/read-file-understanding.ts
|
|
65982
|
-
import * as
|
|
65983
|
-
import * as
|
|
66250
|
+
import * as path22 from "node:path";
|
|
66251
|
+
import * as fs22 from "node:fs/promises";
|
|
65984
66252
|
|
|
65985
66253
|
// src/core/provider-capabilities.ts
|
|
65986
66254
|
var PLATFORM_DISPLAY_NAMES = {
|
|
@@ -66006,8 +66274,8 @@ function getProviderDisplayName(platform2) {
|
|
|
66006
66274
|
}
|
|
66007
66275
|
|
|
66008
66276
|
// src/files/adapters/kimi-adapter.ts
|
|
66009
|
-
import * as
|
|
66010
|
-
import * as
|
|
66277
|
+
import * as fs15 from "node:fs";
|
|
66278
|
+
import * as path14 from "node:path";
|
|
66011
66279
|
|
|
66012
66280
|
// src/files/errors.ts
|
|
66013
66281
|
var FileErrorMessages = {
|
|
@@ -66144,17 +66412,17 @@ var KimiFileAdapter = class {
|
|
|
66144
66412
|
// Upload
|
|
66145
66413
|
// ============================================================================
|
|
66146
66414
|
async upload(filePath, options = {}) {
|
|
66147
|
-
const fileName = options.sourceName ||
|
|
66415
|
+
const fileName = options.sourceName || path14.basename(filePath);
|
|
66148
66416
|
const mimeType = options.mimeType || this.guessMimeType(fileName);
|
|
66149
66417
|
const purpose = this.detectPurpose(filePath, options.purpose, mimeType);
|
|
66150
|
-
const stats =
|
|
66418
|
+
const stats = fs15.statSync(filePath);
|
|
66151
66419
|
if (stats.size > this.capabilities.maxFileSize) {
|
|
66152
66420
|
throw new FileManagerError(
|
|
66153
66421
|
"FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
|
|
66154
66422
|
`File size ${(stats.size / 1024 / 1024).toFixed(1)}MB exceeds Kimi limit of 100MB`
|
|
66155
66423
|
);
|
|
66156
66424
|
}
|
|
66157
|
-
const fileBuffer =
|
|
66425
|
+
const fileBuffer = fs15.readFileSync(filePath);
|
|
66158
66426
|
const file = new File([fileBuffer], fileName, { type: mimeType });
|
|
66159
66427
|
const formData = new FormData();
|
|
66160
66428
|
formData.append("file", file);
|
|
@@ -66206,7 +66474,7 @@ var KimiFileAdapter = class {
|
|
|
66206
66474
|
return "file-extract";
|
|
66207
66475
|
}
|
|
66208
66476
|
guessMimeType(filename) {
|
|
66209
|
-
const ext =
|
|
66477
|
+
const ext = path14.extname(filename).toLowerCase();
|
|
66210
66478
|
switch (ext) {
|
|
66211
66479
|
case ".jpg":
|
|
66212
66480
|
case ".jpeg":
|
|
@@ -66368,8 +66636,8 @@ var KimiFileAdapter = class {
|
|
|
66368
66636
|
};
|
|
66369
66637
|
|
|
66370
66638
|
// src/files/adapters/gemini-adapter.ts
|
|
66371
|
-
import * as
|
|
66372
|
-
import * as
|
|
66639
|
+
import * as fs16 from "node:fs";
|
|
66640
|
+
import * as path15 from "node:path";
|
|
66373
66641
|
import { Readable } from "node:stream";
|
|
66374
66642
|
var GeminiFileAdapter = class {
|
|
66375
66643
|
platform = "gemini";
|
|
@@ -66426,7 +66694,7 @@ var GeminiFileAdapter = class {
|
|
|
66426
66694
|
// Upload
|
|
66427
66695
|
// ============================================================================
|
|
66428
66696
|
async upload(filePath, options = {}) {
|
|
66429
|
-
const stats =
|
|
66697
|
+
const stats = fs16.statSync(filePath);
|
|
66430
66698
|
if (stats.size > this.capabilities.maxFileSize) {
|
|
66431
66699
|
throw new FileManagerError(
|
|
66432
66700
|
"FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
|
|
@@ -66434,7 +66702,7 @@ var GeminiFileAdapter = class {
|
|
|
66434
66702
|
);
|
|
66435
66703
|
}
|
|
66436
66704
|
const mimeType = options.mimeType || this.guessMimeType(filePath);
|
|
66437
|
-
const displayName = options.sourceName ||
|
|
66705
|
+
const displayName = options.sourceName || path15.basename(filePath);
|
|
66438
66706
|
const startResponse = await fetch(
|
|
66439
66707
|
`${this.baseUrl}/upload/v1beta/files?key=${this.apiKey}`,
|
|
66440
66708
|
{
|
|
@@ -66465,7 +66733,7 @@ var GeminiFileAdapter = class {
|
|
|
66465
66733
|
"No upload URL received"
|
|
66466
66734
|
);
|
|
66467
66735
|
}
|
|
66468
|
-
const fileStream = Readable.toWeb(
|
|
66736
|
+
const fileStream = Readable.toWeb(fs16.createReadStream(filePath));
|
|
66469
66737
|
const uploadResponse = await fetch(uploadUrl, {
|
|
66470
66738
|
method: "POST",
|
|
66471
66739
|
headers: {
|
|
@@ -66669,8 +66937,8 @@ var GeminiFileAdapter = class {
|
|
|
66669
66937
|
};
|
|
66670
66938
|
|
|
66671
66939
|
// src/files/adapters/openai-compatible-files-adapter.ts
|
|
66672
|
-
import * as
|
|
66673
|
-
import * as
|
|
66940
|
+
import * as fs17 from "node:fs";
|
|
66941
|
+
import * as path16 from "node:path";
|
|
66674
66942
|
var OpenAICompatibleFilesAdapter = class {
|
|
66675
66943
|
constructor(apiKey, baseUrl, extraHeaders = {}) {
|
|
66676
66944
|
this.apiKey = apiKey;
|
|
@@ -66696,16 +66964,16 @@ var OpenAICompatibleFilesAdapter = class {
|
|
|
66696
66964
|
]
|
|
66697
66965
|
};
|
|
66698
66966
|
async upload(filePath, options = {}) {
|
|
66699
|
-
const fileName = options.sourceName ||
|
|
66967
|
+
const fileName = options.sourceName || path16.basename(filePath);
|
|
66700
66968
|
const mimeType = options.mimeType || guessMimeType(fileName);
|
|
66701
|
-
const stats =
|
|
66969
|
+
const stats = fs17.statSync(filePath);
|
|
66702
66970
|
if (stats.size > this.capabilities.maxFileSize) {
|
|
66703
66971
|
throw new FileManagerError(
|
|
66704
66972
|
"FILE_TOO_LARGE" /* FILE_TOO_LARGE */,
|
|
66705
66973
|
`File size ${(stats.size / 1024 / 1024).toFixed(1)}MB exceeds OpenAI-compatible Files limit of ${this.capabilities.maxFileSize / 1024 / 1024}MB`
|
|
66706
66974
|
);
|
|
66707
66975
|
}
|
|
66708
|
-
const file = new File([
|
|
66976
|
+
const file = new File([fs17.readFileSync(filePath)], fileName, { type: mimeType });
|
|
66709
66977
|
const formData = new FormData();
|
|
66710
66978
|
formData.append("file", file);
|
|
66711
66979
|
formData.append("purpose", options.purpose && options.purpose !== "auto" ? options.purpose : "file-extract");
|
|
@@ -66822,7 +67090,7 @@ function extractContentText(raw) {
|
|
|
66822
67090
|
return raw;
|
|
66823
67091
|
}
|
|
66824
67092
|
function guessMimeType(filename) {
|
|
66825
|
-
const ext =
|
|
67093
|
+
const ext = path16.extname(filename).toLowerCase();
|
|
66826
67094
|
switch (ext) {
|
|
66827
67095
|
case ".pdf":
|
|
66828
67096
|
return "application/pdf";
|
|
@@ -66838,13 +67106,13 @@ function guessMimeType(filename) {
|
|
|
66838
67106
|
}
|
|
66839
67107
|
|
|
66840
67108
|
// src/files/file-manager.ts
|
|
66841
|
-
import * as
|
|
66842
|
-
import * as
|
|
67109
|
+
import * as fs21 from "node:fs";
|
|
67110
|
+
import * as path21 from "node:path";
|
|
66843
67111
|
import * as crypto2 from "node:crypto";
|
|
66844
67112
|
|
|
66845
67113
|
// src/files/file-cache.ts
|
|
66846
|
-
import * as
|
|
66847
|
-
import * as
|
|
67114
|
+
import * as fs18 from "node:fs";
|
|
67115
|
+
import * as path18 from "node:path";
|
|
66848
67116
|
import * as crypto from "node:crypto";
|
|
66849
67117
|
|
|
66850
67118
|
// src/files/logger.ts
|
|
@@ -66939,7 +67207,7 @@ var DEFAULT_PIC_OPTIONS = {
|
|
|
66939
67207
|
};
|
|
66940
67208
|
|
|
66941
67209
|
// src/files/utils.ts
|
|
66942
|
-
import * as
|
|
67210
|
+
import * as path17 from "node:path";
|
|
66943
67211
|
import { homedir as homedir5 } from "node:os";
|
|
66944
67212
|
var WINDOWS_ABSOLUTE_PATH_RE = /^(?:[a-zA-Z]:[\\/]|[\\/]{2}[^\\/]+[\\/][^\\/]+)/;
|
|
66945
67213
|
function isWindowsAbsolutePath(filePath) {
|
|
@@ -66960,13 +67228,13 @@ function formatBytes(bytes) {
|
|
|
66960
67228
|
}
|
|
66961
67229
|
function resolvePath2(inputPath) {
|
|
66962
67230
|
if (inputPath.startsWith("~")) {
|
|
66963
|
-
return
|
|
67231
|
+
return path17.join(getHomeDirectory(), inputPath.slice(1));
|
|
66964
67232
|
}
|
|
66965
67233
|
if (isWindowsAbsolutePath(inputPath)) {
|
|
66966
67234
|
return inputPath;
|
|
66967
67235
|
}
|
|
66968
|
-
if (!
|
|
66969
|
-
return
|
|
67236
|
+
if (!path17.isAbsolute(inputPath)) {
|
|
67237
|
+
return path17.resolve(process.cwd(), inputPath);
|
|
66970
67238
|
}
|
|
66971
67239
|
return inputPath;
|
|
66972
67240
|
}
|
|
@@ -66994,8 +67262,8 @@ var FileCache = class _FileCache {
|
|
|
66994
67262
|
maxEntries;
|
|
66995
67263
|
constructor(baseDir, maxEntries = DEFAULT_MAX_CACHE_ENTRIES) {
|
|
66996
67264
|
this.baseDir = baseDir;
|
|
66997
|
-
this.dataDir =
|
|
66998
|
-
this.indexPath =
|
|
67265
|
+
this.dataDir = path18.join(baseDir, "data");
|
|
67266
|
+
this.indexPath = path18.join(baseDir, "index.json");
|
|
66999
67267
|
this.maxEntries = maxEntries;
|
|
67000
67268
|
this.index = this.loadIndex();
|
|
67001
67269
|
this.ensureDirectories();
|
|
@@ -67004,22 +67272,22 @@ var FileCache = class _FileCache {
|
|
|
67004
67272
|
// Directory Management
|
|
67005
67273
|
// ============================================================================
|
|
67006
67274
|
ensureDirectories() {
|
|
67007
|
-
if (!
|
|
67008
|
-
|
|
67275
|
+
if (!fs18.existsSync(this.baseDir)) {
|
|
67276
|
+
fs18.mkdirSync(this.baseDir, { recursive: true });
|
|
67009
67277
|
}
|
|
67010
|
-
if (!
|
|
67011
|
-
|
|
67278
|
+
if (!fs18.existsSync(this.dataDir)) {
|
|
67279
|
+
fs18.mkdirSync(this.dataDir, { recursive: true });
|
|
67012
67280
|
}
|
|
67013
67281
|
}
|
|
67014
67282
|
// ============================================================================
|
|
67015
67283
|
// Index Management
|
|
67016
67284
|
// ============================================================================
|
|
67017
67285
|
loadIndex() {
|
|
67018
|
-
if (!
|
|
67286
|
+
if (!fs18.existsSync(this.indexPath)) {
|
|
67019
67287
|
return { version: CACHE_VERSION, files: {}, pathHints: {} };
|
|
67020
67288
|
}
|
|
67021
67289
|
try {
|
|
67022
|
-
const data = JSON.parse(
|
|
67290
|
+
const data = JSON.parse(fs18.readFileSync(this.indexPath, "utf-8"));
|
|
67023
67291
|
if (data.version !== CACHE_VERSION) {
|
|
67024
67292
|
cacheLogger.warn(`Index version mismatch: ${data.version} vs ${CACHE_VERSION}`);
|
|
67025
67293
|
}
|
|
@@ -67035,7 +67303,7 @@ var FileCache = class _FileCache {
|
|
|
67035
67303
|
}
|
|
67036
67304
|
saveIndex() {
|
|
67037
67305
|
try {
|
|
67038
|
-
|
|
67306
|
+
fs18.writeFileSync(this.indexPath, JSON.stringify(this.index, null, 2));
|
|
67039
67307
|
} catch (err) {
|
|
67040
67308
|
cacheLogger.error(" Failed to save index:", err);
|
|
67041
67309
|
throw err;
|
|
@@ -67047,7 +67315,7 @@ var FileCache = class _FileCache {
|
|
|
67047
67315
|
async computeHash(filePath) {
|
|
67048
67316
|
return new Promise((resolve7, reject) => {
|
|
67049
67317
|
const hash = crypto.createHash("sha256");
|
|
67050
|
-
const stream =
|
|
67318
|
+
const stream = fs18.createReadStream(filePath);
|
|
67051
67319
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
67052
67320
|
stream.on("end", () => resolve7(hash.digest("hex")));
|
|
67053
67321
|
stream.on("error", reject);
|
|
@@ -67061,25 +67329,25 @@ var FileCache = class _FileCache {
|
|
|
67061
67329
|
// ============================================================================
|
|
67062
67330
|
getStoragePath(hash) {
|
|
67063
67331
|
const subdir = hash.slice(0, 2);
|
|
67064
|
-
const fullDir =
|
|
67065
|
-
if (!
|
|
67066
|
-
|
|
67332
|
+
const fullDir = path18.join(this.dataDir, subdir);
|
|
67333
|
+
if (!fs18.existsSync(fullDir)) {
|
|
67334
|
+
fs18.mkdirSync(fullDir, { recursive: true });
|
|
67067
67335
|
}
|
|
67068
|
-
return
|
|
67336
|
+
return path18.join(fullDir, hash);
|
|
67069
67337
|
}
|
|
67070
67338
|
getStorageRelativePath(hash) {
|
|
67071
67339
|
const subdir = hash.slice(0, 2);
|
|
67072
|
-
return
|
|
67340
|
+
return path18.join(subdir, hash);
|
|
67073
67341
|
}
|
|
67074
67342
|
async storeFile(sourcePath, name, mimeType) {
|
|
67075
67343
|
const hash = await this.computeHash(sourcePath);
|
|
67076
67344
|
const storagePath = this.getStoragePath(hash);
|
|
67077
67345
|
this.rememberPathHint(sourcePath, hash, name);
|
|
67078
|
-
if (
|
|
67346
|
+
if (fs18.existsSync(storagePath)) {
|
|
67079
67347
|
return { hash, localPath: storagePath };
|
|
67080
67348
|
}
|
|
67081
|
-
|
|
67082
|
-
const stat2 =
|
|
67349
|
+
fs18.copyFileSync(sourcePath, storagePath);
|
|
67350
|
+
const stat2 = fs18.statSync(storagePath);
|
|
67083
67351
|
this.index.files[hash] = {
|
|
67084
67352
|
hash,
|
|
67085
67353
|
name,
|
|
@@ -67096,10 +67364,10 @@ var FileCache = class _FileCache {
|
|
|
67096
67364
|
async storeBuffer(data, name, mimeType) {
|
|
67097
67365
|
const hash = this.computeHashSync(data);
|
|
67098
67366
|
const storagePath = this.getStoragePath(hash);
|
|
67099
|
-
if (
|
|
67367
|
+
if (fs18.existsSync(storagePath)) {
|
|
67100
67368
|
return { hash, localPath: storagePath };
|
|
67101
67369
|
}
|
|
67102
|
-
|
|
67370
|
+
fs18.writeFileSync(storagePath, data);
|
|
67103
67371
|
this.index.files[hash] = {
|
|
67104
67372
|
hash,
|
|
67105
67373
|
name,
|
|
@@ -67131,7 +67399,7 @@ var FileCache = class _FileCache {
|
|
|
67131
67399
|
getLocalPath(hash) {
|
|
67132
67400
|
const entry = this.index.files[hash];
|
|
67133
67401
|
if (!entry) return void 0;
|
|
67134
|
-
return
|
|
67402
|
+
return path18.join(this.dataDir, entry.localPath);
|
|
67135
67403
|
}
|
|
67136
67404
|
exists(hash) {
|
|
67137
67405
|
return hash in this.index.files;
|
|
@@ -67171,7 +67439,7 @@ var FileCache = class _FileCache {
|
|
|
67171
67439
|
getPathHint(filePath) {
|
|
67172
67440
|
try {
|
|
67173
67441
|
const resolvedPath = this.getResolvedHintPath(filePath);
|
|
67174
|
-
const stat2 =
|
|
67442
|
+
const stat2 = fs18.statSync(resolvedPath);
|
|
67175
67443
|
if (!stat2.isFile()) return void 0;
|
|
67176
67444
|
const normalizedMtimeMs = this.normalizeHintMtimeMs(stat2.mtimeMs);
|
|
67177
67445
|
const key = this.getPathHintKey(resolvedPath);
|
|
@@ -67201,7 +67469,7 @@ var FileCache = class _FileCache {
|
|
|
67201
67469
|
rememberPathHint(filePath, hash, name) {
|
|
67202
67470
|
try {
|
|
67203
67471
|
const resolvedPath = this.getResolvedHintPath(filePath);
|
|
67204
|
-
const stat2 =
|
|
67472
|
+
const stat2 = fs18.statSync(resolvedPath);
|
|
67205
67473
|
if (!stat2.isFile()) return;
|
|
67206
67474
|
const entry = this.index.files[hash];
|
|
67207
67475
|
const normalizedMtimeMs = this.normalizeHintMtimeMs(stat2.mtimeMs);
|
|
@@ -67211,7 +67479,7 @@ var FileCache = class _FileCache {
|
|
|
67211
67479
|
this.index.pathHints[this.getPathHintKey(resolvedPath)] = {
|
|
67212
67480
|
path: resolvedPath,
|
|
67213
67481
|
hash,
|
|
67214
|
-
name: name || entry?.name ||
|
|
67482
|
+
name: name || entry?.name || path18.basename(resolvedPath),
|
|
67215
67483
|
size: stat2.size,
|
|
67216
67484
|
mtimeMs: normalizedMtimeMs,
|
|
67217
67485
|
lastSeenAt: Date.now(),
|
|
@@ -67259,9 +67527,9 @@ var FileCache = class _FileCache {
|
|
|
67259
67527
|
deleteEntry(hash, entry) {
|
|
67260
67528
|
entry = entry || this.index.files[hash];
|
|
67261
67529
|
if (!entry) return;
|
|
67262
|
-
const localPath =
|
|
67263
|
-
if (
|
|
67264
|
-
|
|
67530
|
+
const localPath = path18.join(this.dataDir, entry.localPath);
|
|
67531
|
+
if (fs18.existsSync(localPath)) {
|
|
67532
|
+
fs18.unlinkSync(localPath);
|
|
67265
67533
|
}
|
|
67266
67534
|
delete this.index.files[hash];
|
|
67267
67535
|
if (this.index.pathHints) {
|
|
@@ -67275,9 +67543,9 @@ var FileCache = class _FileCache {
|
|
|
67275
67543
|
}
|
|
67276
67544
|
clear() {
|
|
67277
67545
|
for (const entry of Object.values(this.index.files)) {
|
|
67278
|
-
const localPath =
|
|
67279
|
-
if (
|
|
67280
|
-
|
|
67546
|
+
const localPath = path18.join(this.dataDir, entry.localPath);
|
|
67547
|
+
if (fs18.existsSync(localPath)) {
|
|
67548
|
+
fs18.unlinkSync(localPath);
|
|
67281
67549
|
}
|
|
67282
67550
|
}
|
|
67283
67551
|
this.index = { version: CACHE_VERSION, files: {}, pathHints: {} };
|
|
@@ -67330,11 +67598,11 @@ var FileCache = class _FileCache {
|
|
|
67330
67598
|
};
|
|
67331
67599
|
}
|
|
67332
67600
|
static getMimeType(fileName) {
|
|
67333
|
-
const ext =
|
|
67601
|
+
const ext = path18.extname(fileName).toLowerCase();
|
|
67334
67602
|
return MIME_TYPES[ext] || "application/octet-stream";
|
|
67335
67603
|
}
|
|
67336
67604
|
static getFileTypeFromName(fileName) {
|
|
67337
|
-
const baseName =
|
|
67605
|
+
const baseName = path18.basename(fileName);
|
|
67338
67606
|
if (!baseName || baseName.startsWith(".")) {
|
|
67339
67607
|
return void 0;
|
|
67340
67608
|
}
|
|
@@ -67365,7 +67633,7 @@ var FileCache = class _FileCache {
|
|
|
67365
67633
|
getResolvedHintPath(filePath) {
|
|
67366
67634
|
const resolvedPath = resolvePath2(filePath);
|
|
67367
67635
|
try {
|
|
67368
|
-
return
|
|
67636
|
+
return fs18.realpathSync.native ? fs18.realpathSync.native(resolvedPath) : fs18.realpathSync(resolvedPath);
|
|
67369
67637
|
} catch {
|
|
67370
67638
|
return resolvedPath;
|
|
67371
67639
|
}
|
|
@@ -67373,8 +67641,8 @@ var FileCache = class _FileCache {
|
|
|
67373
67641
|
};
|
|
67374
67642
|
|
|
67375
67643
|
// src/files/session-file-manager.ts
|
|
67376
|
-
import * as
|
|
67377
|
-
import * as
|
|
67644
|
+
import * as fs19 from "node:fs";
|
|
67645
|
+
import * as path19 from "node:path";
|
|
67378
67646
|
var INITIAL_REFRESH_BACKOFF_MS = 6e4;
|
|
67379
67647
|
var MAX_REFRESH_BACKOFF_MS = 60 * 60 * 1e3;
|
|
67380
67648
|
var SessionFileManager = class {
|
|
@@ -67388,7 +67656,7 @@ var SessionFileManager = class {
|
|
|
67388
67656
|
constructor(sessionId, sessionsDir, fileCache, authFingerprint) {
|
|
67389
67657
|
this.sessionId = sessionId;
|
|
67390
67658
|
this.sessionsDir = sessionsDir;
|
|
67391
|
-
this.statePath =
|
|
67659
|
+
this.statePath = path19.join(this.sessionsDir, `${sessionId}-files.json`);
|
|
67392
67660
|
this.fileCache = fileCache;
|
|
67393
67661
|
this.authFingerprint = authFingerprint;
|
|
67394
67662
|
this.state = this.loadState();
|
|
@@ -67398,15 +67666,15 @@ var SessionFileManager = class {
|
|
|
67398
67666
|
// Directory Management
|
|
67399
67667
|
// ============================================================================
|
|
67400
67668
|
ensureDirectories() {
|
|
67401
|
-
if (!
|
|
67402
|
-
|
|
67669
|
+
if (!fs19.existsSync(this.sessionsDir)) {
|
|
67670
|
+
fs19.mkdirSync(this.sessionsDir, { recursive: true });
|
|
67403
67671
|
}
|
|
67404
67672
|
}
|
|
67405
67673
|
// ============================================================================
|
|
67406
67674
|
// State Management
|
|
67407
67675
|
// ============================================================================
|
|
67408
67676
|
loadState() {
|
|
67409
|
-
if (!
|
|
67677
|
+
if (!fs19.existsSync(this.statePath)) {
|
|
67410
67678
|
return {
|
|
67411
67679
|
sessionId: this.sessionId,
|
|
67412
67680
|
lastSyncedAt: 0,
|
|
@@ -67414,7 +67682,7 @@ var SessionFileManager = class {
|
|
|
67414
67682
|
};
|
|
67415
67683
|
}
|
|
67416
67684
|
try {
|
|
67417
|
-
return JSON.parse(
|
|
67685
|
+
return JSON.parse(fs19.readFileSync(this.statePath, "utf-8"));
|
|
67418
67686
|
} catch (err) {
|
|
67419
67687
|
sessionLogger.error(" Failed to load state:", err);
|
|
67420
67688
|
return {
|
|
@@ -67427,12 +67695,12 @@ var SessionFileManager = class {
|
|
|
67427
67695
|
saveState() {
|
|
67428
67696
|
try {
|
|
67429
67697
|
if (Object.keys(this.state.files).length === 0) {
|
|
67430
|
-
if (
|
|
67431
|
-
|
|
67698
|
+
if (fs19.existsSync(this.statePath)) {
|
|
67699
|
+
fs19.unlinkSync(this.statePath);
|
|
67432
67700
|
}
|
|
67433
67701
|
return;
|
|
67434
67702
|
}
|
|
67435
|
-
|
|
67703
|
+
fs19.writeFileSync(this.statePath, JSON.stringify(this.state, null, 2));
|
|
67436
67704
|
} catch (err) {
|
|
67437
67705
|
sessionLogger.error(" Failed to save state:", err);
|
|
67438
67706
|
}
|
|
@@ -67578,7 +67846,7 @@ var SessionFileManager = class {
|
|
|
67578
67846
|
return { success: false, coolingDown: true };
|
|
67579
67847
|
}
|
|
67580
67848
|
const localPath = this.fileCache.getLocalPath(entry.hash);
|
|
67581
|
-
if (!localPath || !
|
|
67849
|
+
if (!localPath || !fs19.existsSync(localPath)) {
|
|
67582
67850
|
sessionLogger.warn(`Local file not found for ${fileId}`);
|
|
67583
67851
|
entry.status = "expired";
|
|
67584
67852
|
entry.error = "Local file missing";
|
|
@@ -67729,15 +67997,15 @@ var SessionFileManager = class {
|
|
|
67729
67997
|
// Static Utilities
|
|
67730
67998
|
// ============================================================================
|
|
67731
67999
|
static cleanupOldSessions(sessionsDir, maxAge = 30 * 24 * 60 * 60 * 1e3) {
|
|
67732
|
-
if (!
|
|
68000
|
+
if (!fs19.existsSync(sessionsDir)) return;
|
|
67733
68001
|
const now = Date.now();
|
|
67734
|
-
const files =
|
|
68002
|
+
const files = fs19.readdirSync(sessionsDir);
|
|
67735
68003
|
for (const file of files) {
|
|
67736
68004
|
if (!file.endsWith(".json")) continue;
|
|
67737
|
-
const filePath =
|
|
67738
|
-
const stat2 =
|
|
68005
|
+
const filePath = path19.join(sessionsDir, file);
|
|
68006
|
+
const stat2 = fs19.statSync(filePath);
|
|
67739
68007
|
if (now - stat2.mtime.getTime() > maxAge) {
|
|
67740
|
-
|
|
68008
|
+
fs19.unlinkSync(filePath);
|
|
67741
68009
|
sessionLogger.debug(`Cleaned up old session: ${file}`);
|
|
67742
68010
|
}
|
|
67743
68011
|
}
|
|
@@ -67745,8 +68013,8 @@ var SessionFileManager = class {
|
|
|
67745
68013
|
};
|
|
67746
68014
|
|
|
67747
68015
|
// src/files/ffmpeg-processor.ts
|
|
67748
|
-
import * as
|
|
67749
|
-
import * as
|
|
68016
|
+
import * as fs20 from "node:fs";
|
|
68017
|
+
import * as path20 from "node:path";
|
|
67750
68018
|
import { spawn } from "node:child_process";
|
|
67751
68019
|
var FFmpegProcessor = class {
|
|
67752
68020
|
ffmpegPath = "ffmpeg";
|
|
@@ -67850,7 +68118,7 @@ var FFmpegProcessor = class {
|
|
|
67850
68118
|
}
|
|
67851
68119
|
async compressVideo(inputPath, outputDir, info, opts, onProgress) {
|
|
67852
68120
|
const outputName = `compressed_${Date.now()}.mp4`;
|
|
67853
|
-
const outputPath =
|
|
68121
|
+
const outputPath = path20.join(outputDir, outputName);
|
|
67854
68122
|
const adaptiveParams = this.calculateAdaptiveParams(info.duration, opts);
|
|
67855
68123
|
const args = [
|
|
67856
68124
|
"-i",
|
|
@@ -67881,7 +68149,7 @@ var FFmpegProcessor = class {
|
|
|
67881
68149
|
onProgress?.(percent);
|
|
67882
68150
|
}
|
|
67883
68151
|
});
|
|
67884
|
-
const outputStat =
|
|
68152
|
+
const outputStat = fs20.statSync(outputPath);
|
|
67885
68153
|
return {
|
|
67886
68154
|
type: "video",
|
|
67887
68155
|
output: outputPath,
|
|
@@ -67912,9 +68180,9 @@ var FFmpegProcessor = class {
|
|
|
67912
68180
|
}
|
|
67913
68181
|
async extractKeyframes(inputPath, outputDir, info, opts, onProgress) {
|
|
67914
68182
|
const interval = Math.floor(info.duration / opts.keyframeCount);
|
|
67915
|
-
const framesDir =
|
|
67916
|
-
|
|
67917
|
-
const outputPattern =
|
|
68183
|
+
const framesDir = path20.join(outputDir, `keyframes_${Date.now()}`);
|
|
68184
|
+
fs20.mkdirSync(framesDir, { recursive: true });
|
|
68185
|
+
const outputPattern = path20.join(framesDir, "frame_%03d.jpg");
|
|
67918
68186
|
const args = [
|
|
67919
68187
|
"-i",
|
|
67920
68188
|
inputPath,
|
|
@@ -67932,10 +68200,10 @@ var FFmpegProcessor = class {
|
|
|
67932
68200
|
onProgress?.(percent);
|
|
67933
68201
|
}
|
|
67934
68202
|
});
|
|
67935
|
-
let frames =
|
|
68203
|
+
let frames = fs20.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path20.join(framesDir, f));
|
|
67936
68204
|
if (frames.length < opts.keyframeCount / 2) {
|
|
67937
|
-
|
|
67938
|
-
|
|
68205
|
+
fs20.rmSync(framesDir, { recursive: true, force: true });
|
|
68206
|
+
fs20.mkdirSync(framesDir, { recursive: true });
|
|
67939
68207
|
const uniformArgs = [
|
|
67940
68208
|
"-i",
|
|
67941
68209
|
inputPath,
|
|
@@ -67951,10 +68219,10 @@ var FFmpegProcessor = class {
|
|
|
67951
68219
|
onProgress?.(percent);
|
|
67952
68220
|
}
|
|
67953
68221
|
});
|
|
67954
|
-
frames =
|
|
68222
|
+
frames = fs20.readdirSync(framesDir).filter((f) => f.endsWith(".jpg")).sort().map((f) => path20.join(framesDir, f));
|
|
67955
68223
|
}
|
|
67956
68224
|
const totalOutputSize = frames.reduce(
|
|
67957
|
-
(sum, f) => sum +
|
|
68225
|
+
(sum, f) => sum + fs20.statSync(f).size,
|
|
67958
68226
|
0
|
|
67959
68227
|
);
|
|
67960
68228
|
return {
|
|
@@ -67975,7 +68243,7 @@ var FFmpegProcessor = class {
|
|
|
67975
68243
|
const opts = { ...DEFAULT_PIC_OPTIONS, ...options };
|
|
67976
68244
|
const ext = opts.format === "webp" ? ".webp" : ".jpg";
|
|
67977
68245
|
const outputName = `optimized_${Date.now()}${ext}`;
|
|
67978
|
-
const outputPath =
|
|
68246
|
+
const outputPath = path20.join(outputDir, outputName);
|
|
67979
68247
|
const args = [
|
|
67980
68248
|
"-i",
|
|
67981
68249
|
inputPath,
|
|
@@ -68150,8 +68418,8 @@ var DIRECTORY_LISTING_TTL_MS = 1500;
|
|
|
68150
68418
|
var FileManager = class {
|
|
68151
68419
|
constructor(options) {
|
|
68152
68420
|
this.options = options;
|
|
68153
|
-
const baseDir = options.baseDir ||
|
|
68154
|
-
const sessionsDir = options.sessionsDir ||
|
|
68421
|
+
const baseDir = options.baseDir || path21.join(process.env.HOME || ".", ".pie", "files");
|
|
68422
|
+
const sessionsDir = options.sessionsDir || path21.join(process.env.HOME || ".", ".pie", "sessions");
|
|
68155
68423
|
this.fileCache = new FileCache(baseDir);
|
|
68156
68424
|
this.authFingerprint = options.apiKey ? this.buildAuthFingerprint(options.apiKey) : void 0;
|
|
68157
68425
|
this.sessionManager = new SessionFileManager(
|
|
@@ -68162,7 +68430,7 @@ var FileManager = class {
|
|
|
68162
68430
|
);
|
|
68163
68431
|
this.ffmpeg = new FFmpegProcessor(options.ffmpegPath);
|
|
68164
68432
|
this.platform = normalizeFileManagerPlatform(options.platform);
|
|
68165
|
-
this.tempDir =
|
|
68433
|
+
this.tempDir = path21.join(baseDir, "temp");
|
|
68166
68434
|
this.ensureDirectories();
|
|
68167
68435
|
}
|
|
68168
68436
|
options;
|
|
@@ -68174,8 +68442,8 @@ var FileManager = class {
|
|
|
68174
68442
|
directoryListingCache = /* @__PURE__ */ new Map();
|
|
68175
68443
|
authFingerprint;
|
|
68176
68444
|
ensureDirectories() {
|
|
68177
|
-
if (!
|
|
68178
|
-
|
|
68445
|
+
if (!fs21.existsSync(this.tempDir)) {
|
|
68446
|
+
fs21.mkdirSync(this.tempDir, { recursive: true });
|
|
68179
68447
|
}
|
|
68180
68448
|
}
|
|
68181
68449
|
// ============================================================================
|
|
@@ -68209,8 +68477,8 @@ var FileManager = class {
|
|
|
68209
68477
|
// ============================================================================
|
|
68210
68478
|
async stageLocal(filePath, options = {}) {
|
|
68211
68479
|
const resolvedPath = resolvePath2(filePath);
|
|
68212
|
-
const sourceName = options.sourceName ||
|
|
68213
|
-
if (!
|
|
68480
|
+
const sourceName = options.sourceName || path21.basename(resolvedPath);
|
|
68481
|
+
if (!fs21.existsSync(resolvedPath)) {
|
|
68214
68482
|
throw new FileManagerError(
|
|
68215
68483
|
"LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
|
|
68216
68484
|
`File not found: ${filePath}`
|
|
@@ -68225,7 +68493,7 @@ var FileManager = class {
|
|
|
68225
68493
|
this.fileCache.rememberPathHint(resolvedPath, hash, sourceName);
|
|
68226
68494
|
this.invalidateDirectoryListingCacheForPath(resolvedPath);
|
|
68227
68495
|
const entry = this.fileCache.getByHash(hash);
|
|
68228
|
-
const size = entry?.size ??
|
|
68496
|
+
const size = entry?.size ?? fs21.statSync(resolvedPath).size;
|
|
68229
68497
|
return {
|
|
68230
68498
|
success: true,
|
|
68231
68499
|
hash,
|
|
@@ -68239,8 +68507,8 @@ var FileManager = class {
|
|
|
68239
68507
|
}
|
|
68240
68508
|
async upload(filePath, options = {}) {
|
|
68241
68509
|
const resolvedPath = resolvePath2(filePath);
|
|
68242
|
-
const sourceName = options.sourceName ||
|
|
68243
|
-
if (!
|
|
68510
|
+
const sourceName = options.sourceName || path21.basename(resolvedPath);
|
|
68511
|
+
if (!fs21.existsSync(resolvedPath)) {
|
|
68244
68512
|
throw new FileManagerError(
|
|
68245
68513
|
"LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
|
|
68246
68514
|
`File not found: ${filePath}`
|
|
@@ -68321,7 +68589,7 @@ var FileManager = class {
|
|
|
68321
68589
|
// ============================================================================
|
|
68322
68590
|
async uploadPic(filePath, options = {}) {
|
|
68323
68591
|
const resolvedPath = resolvePath2(filePath);
|
|
68324
|
-
if (!
|
|
68592
|
+
if (!fs21.existsSync(resolvedPath)) {
|
|
68325
68593
|
throw new FileManagerError(
|
|
68326
68594
|
"LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
|
|
68327
68595
|
`File not found: ${filePath}`
|
|
@@ -68329,7 +68597,7 @@ var FileManager = class {
|
|
|
68329
68597
|
}
|
|
68330
68598
|
const cachedResult = await this.tryReuseCachedSourceUpload(
|
|
68331
68599
|
resolvedPath,
|
|
68332
|
-
options.sourceName ||
|
|
68600
|
+
options.sourceName || path21.basename(resolvedPath),
|
|
68333
68601
|
options.platform || this.platform
|
|
68334
68602
|
);
|
|
68335
68603
|
if (cachedResult) {
|
|
@@ -68346,12 +68614,12 @@ var FileManager = class {
|
|
|
68346
68614
|
const result = await this.upload(optimizedPath, {
|
|
68347
68615
|
...options,
|
|
68348
68616
|
purpose: "image",
|
|
68349
|
-
sourceName:
|
|
68617
|
+
sourceName: path21.basename(resolvedPath)
|
|
68350
68618
|
});
|
|
68351
|
-
this.fileCache.rememberPathHint(resolvedPath, result.hash,
|
|
68619
|
+
this.fileCache.rememberPathHint(resolvedPath, result.hash, path21.basename(resolvedPath));
|
|
68352
68620
|
this.invalidateDirectoryListingCacheForPath(resolvedPath);
|
|
68353
68621
|
try {
|
|
68354
|
-
|
|
68622
|
+
fs21.unlinkSync(optimizedPath);
|
|
68355
68623
|
} catch {
|
|
68356
68624
|
}
|
|
68357
68625
|
return result;
|
|
@@ -68361,7 +68629,7 @@ var FileManager = class {
|
|
|
68361
68629
|
// ============================================================================
|
|
68362
68630
|
async uploadVideo(filePath, options = {}) {
|
|
68363
68631
|
const resolvedPath = resolvePath2(filePath);
|
|
68364
|
-
if (!
|
|
68632
|
+
if (!fs21.existsSync(resolvedPath)) {
|
|
68365
68633
|
throw new FileManagerError(
|
|
68366
68634
|
"LOCAL_FILE_MISSING" /* LOCAL_FILE_MISSING */,
|
|
68367
68635
|
`File not found: ${filePath}`
|
|
@@ -68369,7 +68637,7 @@ var FileManager = class {
|
|
|
68369
68637
|
}
|
|
68370
68638
|
const cachedResult = await this.tryReuseCachedSourceUpload(
|
|
68371
68639
|
resolvedPath,
|
|
68372
|
-
options.sourceName ||
|
|
68640
|
+
options.sourceName || path21.basename(resolvedPath),
|
|
68373
68641
|
options.platform || this.platform
|
|
68374
68642
|
);
|
|
68375
68643
|
if (cachedResult) {
|
|
@@ -68419,9 +68687,9 @@ var FileManager = class {
|
|
|
68419
68687
|
result = await this.upload(preprocessResult.output, {
|
|
68420
68688
|
...options,
|
|
68421
68689
|
purpose: "video",
|
|
68422
|
-
sourceName:
|
|
68690
|
+
sourceName: path21.basename(resolvedPath)
|
|
68423
68691
|
});
|
|
68424
|
-
this.fileCache.rememberPathHint(resolvedPath, result.hash,
|
|
68692
|
+
this.fileCache.rememberPathHint(resolvedPath, result.hash, path21.basename(resolvedPath));
|
|
68425
68693
|
this.invalidateDirectoryListingCacheForPath(resolvedPath);
|
|
68426
68694
|
} else {
|
|
68427
68695
|
throw new FileManagerError(
|
|
@@ -68713,7 +68981,7 @@ var FileManager = class {
|
|
|
68713
68981
|
* Detect purpose from file path based on extension
|
|
68714
68982
|
*/
|
|
68715
68983
|
detectPurpose(filePath) {
|
|
68716
|
-
const ext =
|
|
68984
|
+
const ext = path21.extname(filePath).toLowerCase();
|
|
68717
68985
|
switch (ext) {
|
|
68718
68986
|
case ".mp4":
|
|
68719
68987
|
case ".mov":
|
|
@@ -68755,13 +69023,13 @@ var FileManager = class {
|
|
|
68755
69023
|
cleanupTempFiles(output) {
|
|
68756
69024
|
try {
|
|
68757
69025
|
if (typeof output === "string") {
|
|
68758
|
-
if (
|
|
68759
|
-
|
|
69026
|
+
if (fs21.existsSync(output)) {
|
|
69027
|
+
fs21.unlinkSync(output);
|
|
68760
69028
|
}
|
|
68761
69029
|
} else {
|
|
68762
69030
|
for (const file of output) {
|
|
68763
|
-
if (
|
|
68764
|
-
|
|
69031
|
+
if (fs21.existsSync(file)) {
|
|
69032
|
+
fs21.unlinkSync(file);
|
|
68765
69033
|
}
|
|
68766
69034
|
}
|
|
68767
69035
|
}
|
|
@@ -68793,7 +69061,7 @@ var FileManager = class {
|
|
|
68793
69061
|
}];
|
|
68794
69062
|
}
|
|
68795
69063
|
const localPath = this.fileCache.getLocalPath(entry.hash);
|
|
68796
|
-
if (localPath &&
|
|
69064
|
+
if (localPath && fs21.existsSync(localPath)) {
|
|
68797
69065
|
return [{
|
|
68798
69066
|
fileId,
|
|
68799
69067
|
name: cacheEntry.name,
|
|
@@ -68890,12 +69158,12 @@ var FileManager = class {
|
|
|
68890
69158
|
directories: []
|
|
68891
69159
|
};
|
|
68892
69160
|
try {
|
|
68893
|
-
const entries =
|
|
69161
|
+
const entries = fs21.readdirSync(resolvedDir, { withFileTypes: true });
|
|
68894
69162
|
for (const entry of entries) {
|
|
68895
69163
|
if (!entry.name || entry.name.startsWith(".")) {
|
|
68896
69164
|
continue;
|
|
68897
69165
|
}
|
|
68898
|
-
const fullPath =
|
|
69166
|
+
const fullPath = path21.join(resolvedDir, entry.name);
|
|
68899
69167
|
if (entry.isDirectory()) {
|
|
68900
69168
|
listing.directories.push({ name: entry.name, path: fullPath });
|
|
68901
69169
|
continue;
|
|
@@ -68904,7 +69172,7 @@ var FileManager = class {
|
|
|
68904
69172
|
let isFile = entry.isFile();
|
|
68905
69173
|
if (entry.isSymbolicLink()) {
|
|
68906
69174
|
try {
|
|
68907
|
-
const targetStat =
|
|
69175
|
+
const targetStat = fs21.statSync(fullPath);
|
|
68908
69176
|
isDirectory = targetStat.isDirectory();
|
|
68909
69177
|
isFile = targetStat.isFile();
|
|
68910
69178
|
} catch {
|
|
@@ -68922,7 +69190,7 @@ var FileManager = class {
|
|
|
68922
69190
|
if (!type) {
|
|
68923
69191
|
continue;
|
|
68924
69192
|
}
|
|
68925
|
-
const stat2 =
|
|
69193
|
+
const stat2 = fs21.statSync(fullPath);
|
|
68926
69194
|
listing.files.push({
|
|
68927
69195
|
name: entry.name,
|
|
68928
69196
|
path: fullPath,
|
|
@@ -68936,7 +69204,7 @@ var FileManager = class {
|
|
|
68936
69204
|
return listing;
|
|
68937
69205
|
}
|
|
68938
69206
|
invalidateDirectoryListingCacheForPath(filePath) {
|
|
68939
|
-
this.directoryListingCache.delete(
|
|
69207
|
+
this.directoryListingCache.delete(path21.dirname(resolvePath2(filePath)));
|
|
68940
69208
|
}
|
|
68941
69209
|
buildAuthFingerprint(apiKey) {
|
|
68942
69210
|
return crypto2.createHash("sha256").update(apiKey).digest("hex").slice(0, 16);
|
|
@@ -68985,8 +69253,8 @@ function createFileManagerForModel(params) {
|
|
|
68985
69253
|
sessionId: params.sessionId,
|
|
68986
69254
|
platform: platform2,
|
|
68987
69255
|
apiKey: params.apiKey,
|
|
68988
|
-
baseDir:
|
|
68989
|
-
sessionsDir:
|
|
69256
|
+
baseDir: path22.join(params.configDir, "files"),
|
|
69257
|
+
sessionsDir: path22.join(params.configDir, "sessions")
|
|
68990
69258
|
});
|
|
68991
69259
|
switch (getFileManagerAdapterKind(platform2)) {
|
|
68992
69260
|
case "kimi":
|
|
@@ -69021,15 +69289,15 @@ function isInlineMediaRequest(request) {
|
|
|
69021
69289
|
return request.kind === "image" || request.kind === "video";
|
|
69022
69290
|
}
|
|
69023
69291
|
async function prepareInlineMediaContent(params) {
|
|
69024
|
-
const stat2 = await
|
|
69292
|
+
const stat2 = await fs22.stat(params.request.absolutePath);
|
|
69025
69293
|
const limitMb = getCapabilityLimitMb(params.model, params.request.kind);
|
|
69026
69294
|
const limitBytes = limitMb * 1024 * 1024;
|
|
69027
69295
|
if (stat2.size > limitBytes) {
|
|
69028
69296
|
throw new Error(
|
|
69029
|
-
`${params.request.kind} understanding for ${params.model.provider}/${params.model.id} supports inline files up to ${limitMb}MB; ${
|
|
69297
|
+
`${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
69298
|
);
|
|
69031
69299
|
}
|
|
69032
|
-
const data = await
|
|
69300
|
+
const data = await fs22.readFile(params.request.absolutePath, "base64");
|
|
69033
69301
|
const content = params.request.kind === "video" ? [{ type: "video", data, mimeType: params.request.mimeType }] : [{ type: "image", data, mimeType: params.request.mimeType }];
|
|
69034
69302
|
return {
|
|
69035
69303
|
content,
|
|
@@ -69065,7 +69333,7 @@ async function prepareFileContent(configDir, params) {
|
|
|
69065
69333
|
});
|
|
69066
69334
|
if (params.request.kind === "document") {
|
|
69067
69335
|
const upload2 = await manager.upload(params.request.absolutePath, {
|
|
69068
|
-
sourceName:
|
|
69336
|
+
sourceName: path22.basename(params.request.displayPath),
|
|
69069
69337
|
purpose: "file-extract"
|
|
69070
69338
|
});
|
|
69071
69339
|
await waitForReady({ manager, fileId: upload2.fileId, timeoutMs: 12e4, signal: params.request.signal });
|
|
@@ -69088,8 +69356,8 @@ async function prepareFileContent(configDir, params) {
|
|
|
69088
69356
|
}
|
|
69089
69357
|
};
|
|
69090
69358
|
}
|
|
69091
|
-
const upload = params.request.kind === "video" ? await manager.uploadVideo(params.request.absolutePath, { sourceName:
|
|
69092
|
-
sourceName:
|
|
69359
|
+
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, {
|
|
69360
|
+
sourceName: path22.basename(params.request.displayPath),
|
|
69093
69361
|
purpose: params.request.kind === "image" ? "image" : "file-extract"
|
|
69094
69362
|
});
|
|
69095
69363
|
if (params.request.kind !== "video") {
|
|
@@ -69510,22 +69778,22 @@ var ExecutionStateManager = class {
|
|
|
69510
69778
|
};
|
|
69511
69779
|
|
|
69512
69780
|
// src/session-trace.ts
|
|
69513
|
-
import * as
|
|
69514
|
-
import * as
|
|
69781
|
+
import * as fs23 from "node:fs";
|
|
69782
|
+
import * as path23 from "node:path";
|
|
69515
69783
|
function saveTraceFileBestEffort(tracePath, content) {
|
|
69516
69784
|
const tempPath = `${tracePath}.${process.pid}.${Date.now()}.tmp`;
|
|
69517
69785
|
try {
|
|
69518
|
-
|
|
69786
|
+
fs23.writeFileSync(tempPath, content, "utf8");
|
|
69519
69787
|
try {
|
|
69520
|
-
|
|
69788
|
+
fs23.renameSync(tempPath, tracePath);
|
|
69521
69789
|
return;
|
|
69522
69790
|
} catch {
|
|
69523
69791
|
try {
|
|
69524
|
-
|
|
69792
|
+
fs23.copyFileSync(tempPath, tracePath);
|
|
69525
69793
|
} catch {
|
|
69526
69794
|
} finally {
|
|
69527
69795
|
try {
|
|
69528
|
-
|
|
69796
|
+
fs23.unlinkSync(tempPath);
|
|
69529
69797
|
} catch {
|
|
69530
69798
|
}
|
|
69531
69799
|
}
|
|
@@ -69538,16 +69806,16 @@ var SessionTraceWriter = class extends SessionTraceSnapshotWriter {
|
|
|
69538
69806
|
super({
|
|
69539
69807
|
getSessionId: () => sessionManager.getActiveSessionId(),
|
|
69540
69808
|
loadTrace: (sessionId) => {
|
|
69541
|
-
const tracePath =
|
|
69542
|
-
if (!
|
|
69809
|
+
const tracePath = path23.join(sessionsDir, `${sessionId}.trace.json`);
|
|
69810
|
+
if (!fs23.existsSync(tracePath)) return null;
|
|
69543
69811
|
try {
|
|
69544
|
-
return JSON.parse(
|
|
69812
|
+
return JSON.parse(fs23.readFileSync(tracePath, "utf8"));
|
|
69545
69813
|
} catch {
|
|
69546
69814
|
return null;
|
|
69547
69815
|
}
|
|
69548
69816
|
},
|
|
69549
69817
|
saveTrace: (trace) => {
|
|
69550
|
-
const tracePath =
|
|
69818
|
+
const tracePath = path23.join(sessionsDir, `${trace.sessionId}.trace.json`);
|
|
69551
69819
|
saveTraceFileBestEffort(tracePath, JSON.stringify(trace, null, 2));
|
|
69552
69820
|
}
|
|
69553
69821
|
});
|
|
@@ -69837,7 +70105,7 @@ function normalizeSessionTitle(raw) {
|
|
|
69837
70105
|
}
|
|
69838
70106
|
|
|
69839
70107
|
// src/components/extension-selector.ts
|
|
69840
|
-
import * as
|
|
70108
|
+
import * as path24 from "node:path";
|
|
69841
70109
|
var ExtensionSelectorComponent = class extends Container {
|
|
69842
70110
|
selectList;
|
|
69843
70111
|
shortcuts;
|
|
@@ -69893,8 +70161,8 @@ function selectRuntimeExtensionWinners(infos) {
|
|
|
69893
70161
|
return reversed.reverse();
|
|
69894
70162
|
}
|
|
69895
70163
|
function unidentifiedLabel(info) {
|
|
69896
|
-
const parentName =
|
|
69897
|
-
const fileName =
|
|
70164
|
+
const parentName = path24.basename(path24.dirname(info.entryPath));
|
|
70165
|
+
const fileName = path24.basename(info.entryPath);
|
|
69898
70166
|
return `(unidentified) ${parentName || fileName}`;
|
|
69899
70167
|
}
|
|
69900
70168
|
var ExtensionEnablementSelectorComponent = class extends Container {
|
|
@@ -70442,7 +70710,7 @@ async function handleDebugPackageCommand(host) {
|
|
|
70442
70710
|
import * as os6 from "os";
|
|
70443
70711
|
|
|
70444
70712
|
// src/components/session-selector.ts
|
|
70445
|
-
import * as
|
|
70713
|
+
import * as path25 from "node:path";
|
|
70446
70714
|
function formatDate(timestamp) {
|
|
70447
70715
|
const date = new Date(timestamp);
|
|
70448
70716
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -70473,7 +70741,7 @@ function getPathFlavor(value, peer) {
|
|
|
70473
70741
|
return "posix";
|
|
70474
70742
|
}
|
|
70475
70743
|
function getPathApi(flavor) {
|
|
70476
|
-
return flavor === "windows" ?
|
|
70744
|
+
return flavor === "windows" ? path25.win32 : path25.posix;
|
|
70477
70745
|
}
|
|
70478
70746
|
function normalizeForComparison(value, flavor) {
|
|
70479
70747
|
const pathApi = getPathApi(flavor);
|
|
@@ -70630,102 +70898,37 @@ var SessionSelectorComponent = class extends Container {
|
|
|
70630
70898
|
var RESET = "\x1B[0m";
|
|
70631
70899
|
var INVERSE = "\x1B[7m";
|
|
70632
70900
|
var DIM = "\x1B[2m";
|
|
70633
|
-
|
|
70634
|
-
return visibleWidth(str2);
|
|
70635
|
-
}
|
|
70901
|
+
var searchSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
70636
70902
|
var TREE_CHARS = {
|
|
70637
70903
|
branch: "\u251C\u2500\u2500 ",
|
|
70638
70904
|
corner: "\u2514\u2500\u2500 ",
|
|
70639
70905
|
pipe: "\u2502 ",
|
|
70640
70906
|
space: " ",
|
|
70641
70907
|
active: "\u25CF ",
|
|
70642
|
-
inactive: "\u25CB "
|
|
70908
|
+
inactive: "\u25CB ",
|
|
70909
|
+
/** Marks rows whose full ancestry is not visible in the window. */
|
|
70910
|
+
hiddenAncestry: "\u2026"
|
|
70643
70911
|
};
|
|
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) {
|
|
70912
|
+
var MIN_PAGE_SIZE = 48;
|
|
70913
|
+
var MAX_PAGE_SIZE = 256;
|
|
70914
|
+
var SEGMENT_WIDTH = 4;
|
|
70915
|
+
var MIN_BODY_WIDTH = 12;
|
|
70916
|
+
var PREFIX_DEPTH_ABS_CAP = 24;
|
|
70917
|
+
var SEARCH_SCAN_PAGE_LIMIT = 16;
|
|
70918
|
+
var COLLAPSED_CAP = 256;
|
|
70919
|
+
function roleName(summary) {
|
|
70920
|
+
if (summary.type === "fork") return "fork";
|
|
70921
|
+
if (summary.type === "compaction") return "compact";
|
|
70922
|
+
if (summary.type === "custom") return "custom";
|
|
70923
|
+
return summary.role ?? "entry";
|
|
70924
|
+
}
|
|
70925
|
+
function roleColor(role) {
|
|
70724
70926
|
switch (role) {
|
|
70725
70927
|
case "user":
|
|
70726
70928
|
return theme.fg("accent", role);
|
|
70727
70929
|
case "assistant":
|
|
70728
70930
|
return theme.fg("text", role);
|
|
70931
|
+
case "toolResult":
|
|
70729
70932
|
case "tool":
|
|
70730
70933
|
return theme.fg("dim", role);
|
|
70731
70934
|
case "fork":
|
|
@@ -70736,57 +70939,47 @@ function getRoleColor(role) {
|
|
|
70736
70939
|
return theme.fg("muted", role);
|
|
70737
70940
|
}
|
|
70738
70941
|
}
|
|
70942
|
+
function seqFromEntryId(entryId) {
|
|
70943
|
+
if (!entryId) return null;
|
|
70944
|
+
const match = /^e(\d+)-/.exec(entryId);
|
|
70945
|
+
if (!match) return null;
|
|
70946
|
+
const seq = Number(match[1]);
|
|
70947
|
+
return Number.isInteger(seq) && seq > 0 ? seq : null;
|
|
70948
|
+
}
|
|
70739
70949
|
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);
|
|
70950
|
+
const normalized = content.replace(/[\r\n]+/g, " ");
|
|
70951
|
+
const body = isSelected ? INVERSE + normalized : normalized;
|
|
70952
|
+
return truncateToWidth(body + RESET, width, "...", true);
|
|
70753
70953
|
}
|
|
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;
|
|
70954
|
+
function clampPrefixForDisplay(prefix, budget) {
|
|
70955
|
+
if (budget <= 0) return "";
|
|
70956
|
+
if (prefix.length <= budget) return prefix;
|
|
70957
|
+
const keep = Math.floor((budget - 1) / SEGMENT_WIDTH) * SEGMENT_WIDTH;
|
|
70958
|
+
return TREE_CHARS.hiddenAncestry + (keep > 0 ? prefix.slice(-keep) : "");
|
|
70779
70959
|
}
|
|
70780
70960
|
var TreeSelectorComponent = class {
|
|
70781
|
-
|
|
70782
|
-
|
|
70783
|
-
|
|
70961
|
+
options;
|
|
70962
|
+
/** The single resident window of headers (bounded by pageSize). */
|
|
70963
|
+
pageSummaries = [];
|
|
70964
|
+
totalEntries;
|
|
70965
|
+
hasPrev = false;
|
|
70966
|
+
hasNext = false;
|
|
70967
|
+
rows = [];
|
|
70968
|
+
filteredRows = [];
|
|
70784
70969
|
selectedIndex = 0;
|
|
70785
70970
|
maxVisibleLines;
|
|
70971
|
+
pageSizeValue;
|
|
70972
|
+
prefixDepthCap;
|
|
70786
70973
|
filterMode = "all";
|
|
70787
70974
|
searchQuery = "";
|
|
70788
|
-
|
|
70789
|
-
|
|
70975
|
+
statusMessage = null;
|
|
70976
|
+
collapsed = /* @__PURE__ */ new Map();
|
|
70977
|
+
// Bounded-memory instrumentation (tests/telemetry).
|
|
70978
|
+
maxResidentHeadersSeen = 0;
|
|
70979
|
+
maxPrefixCharsSeen = 0;
|
|
70980
|
+
currentTotalPrefixChars = 0;
|
|
70981
|
+
fetchCallCount = 0;
|
|
70982
|
+
headersFetchedTotal = 0;
|
|
70790
70983
|
onSelect;
|
|
70791
70984
|
onCancel;
|
|
70792
70985
|
_focused = false;
|
|
@@ -70796,189 +70989,387 @@ var TreeSelectorComponent = class {
|
|
|
70796
70989
|
set focused(value) {
|
|
70797
70990
|
this._focused = value;
|
|
70798
70991
|
}
|
|
70799
|
-
constructor(
|
|
70800
|
-
this.
|
|
70801
|
-
this.
|
|
70802
|
-
this.
|
|
70803
|
-
this.
|
|
70804
|
-
this.
|
|
70805
|
-
this.
|
|
70806
|
-
|
|
70807
|
-
|
|
70808
|
-
|
|
70809
|
-
|
|
70810
|
-
|
|
70811
|
-
|
|
70992
|
+
constructor(options) {
|
|
70993
|
+
this.options = options;
|
|
70994
|
+
this.totalEntries = options.totalEntries;
|
|
70995
|
+
this.maxVisibleLines = Math.max(15, Math.floor(options.terminalHeight * 0.6));
|
|
70996
|
+
this.pageSizeValue = Math.max(MIN_PAGE_SIZE, Math.min(MAX_PAGE_SIZE, this.maxVisibleLines * 3));
|
|
70997
|
+
this.prefixDepthCap = Math.max(3, Math.min(PREFIX_DEPTH_ABS_CAP, this.maxVisibleLines));
|
|
70998
|
+
this.onSelect = options.onSelect;
|
|
70999
|
+
this.onCancel = options.onCancel;
|
|
71000
|
+
if (options.totalEntries === 0) {
|
|
71001
|
+
setTimeout(() => options.onCancel(), 100);
|
|
71002
|
+
return;
|
|
71003
|
+
}
|
|
71004
|
+
const activeSeq = this.resolveActiveSeq() ?? options.totalEntries;
|
|
71005
|
+
const afterSeq = Math.max(0, activeSeq - Math.floor(this.pageSizeValue / 2));
|
|
71006
|
+
this.loadWindow(afterSeq);
|
|
71007
|
+
this.selectNearestSeq(activeSeq);
|
|
71008
|
+
}
|
|
71009
|
+
/**
|
|
71010
|
+
* Locate the active entry without loading bodies: prefer the commit
|
|
71011
|
+
* sequence encoded in the entry id, then the deepest active-path seq
|
|
71012
|
+
* (children always commit after parents, so the max is the active leaf).
|
|
71013
|
+
*/
|
|
71014
|
+
resolveActiveSeq() {
|
|
71015
|
+
const fromId = seqFromEntryId(this.options.activeEntryId);
|
|
71016
|
+
if (fromId !== null) return fromId;
|
|
71017
|
+
let deepest = 0;
|
|
71018
|
+
for (const seq of this.options.activePathSeqs) {
|
|
71019
|
+
if (seq > deepest) deepest = seq;
|
|
71020
|
+
}
|
|
71021
|
+
return deepest > 0 ? deepest : null;
|
|
71022
|
+
}
|
|
71023
|
+
/** Select the row whose seq equals `target`, else the nearest earlier row. */
|
|
71024
|
+
selectNearestSeq(target) {
|
|
71025
|
+
let chosen = -1;
|
|
71026
|
+
for (let i = 0; i < this.filteredRows.length; i++) {
|
|
71027
|
+
const seq = this.filteredRows[i].summary.seq;
|
|
71028
|
+
if (seq === target) {
|
|
71029
|
+
chosen = i;
|
|
71030
|
+
break;
|
|
70812
71031
|
}
|
|
70813
|
-
|
|
70814
|
-
this.selectedIndex = this.flatItems.length - 1;
|
|
71032
|
+
if (seq < target) chosen = i;
|
|
70815
71033
|
}
|
|
70816
|
-
|
|
70817
|
-
|
|
71034
|
+
this.selectedIndex = chosen === -1 ? 0 : chosen;
|
|
71035
|
+
}
|
|
71036
|
+
/** Current resident header count (tests/telemetry; one window only). */
|
|
71037
|
+
get loadedCount() {
|
|
71038
|
+
return this.pageSummaries.length;
|
|
71039
|
+
}
|
|
71040
|
+
/** High-water mark of resident headers across the component lifetime. */
|
|
71041
|
+
get maxResidentHeaders() {
|
|
71042
|
+
return this.maxResidentHeadersSeen;
|
|
71043
|
+
}
|
|
71044
|
+
/** High-water mark of per-row prefix characters. */
|
|
71045
|
+
get maxPrefixChars() {
|
|
71046
|
+
return this.maxPrefixCharsSeen;
|
|
71047
|
+
}
|
|
71048
|
+
/** Sum of prefix characters across the current rows. */
|
|
71049
|
+
get totalPrefixChars() {
|
|
71050
|
+
return this.currentTotalPrefixChars;
|
|
71051
|
+
}
|
|
71052
|
+
/** Configured header window size. */
|
|
71053
|
+
get pageSize() {
|
|
71054
|
+
return this.pageSizeValue;
|
|
71055
|
+
}
|
|
71056
|
+
/** Number of fetchSummaries calls issued. */
|
|
71057
|
+
get fetchCount() {
|
|
71058
|
+
return this.fetchCallCount;
|
|
71059
|
+
}
|
|
71060
|
+
/** Cumulative headers returned by fetchSummaries (all pages ever fetched). */
|
|
71061
|
+
get headersFetched() {
|
|
71062
|
+
return this.headersFetchedTotal;
|
|
71063
|
+
}
|
|
71064
|
+
/** Current collapsed-id count (bounded by COLLAPSED_CAP). */
|
|
71065
|
+
get collapsedCount() {
|
|
71066
|
+
return this.collapsed.size;
|
|
71067
|
+
}
|
|
71068
|
+
/** Seq of the selected row, or null when nothing is selected. */
|
|
71069
|
+
get selectedSeq() {
|
|
71070
|
+
return this.filteredRows[this.selectedIndex]?.summary.seq ?? null;
|
|
71071
|
+
}
|
|
71072
|
+
/** First and last seq of the resident window, or null when empty. */
|
|
71073
|
+
get windowSeqRange() {
|
|
71074
|
+
if (this.pageSummaries.length === 0) return null;
|
|
71075
|
+
return [this.pageSummaries[0].seq, this.pageSummaries[this.pageSummaries.length - 1].seq];
|
|
71076
|
+
}
|
|
71077
|
+
/**
|
|
71078
|
+
* Fetch one window of headers and adopt it as the single resident page.
|
|
71079
|
+
* The previous window is replaced (not merged), keeping residency at
|
|
71080
|
+
* O(pageSize). `upperExclusiveSeq` trims overlap when paging backward;
|
|
71081
|
+
* entries trimmed away still count toward hasNext so the forward
|
|
71082
|
+
* direction never strands a short history behind a backward page.
|
|
71083
|
+
* Returns false when the fetch adopted nothing (boundary/gap).
|
|
71084
|
+
*/
|
|
71085
|
+
fetchWindow(afterSeq, upperExclusiveSeq) {
|
|
71086
|
+
const page = this.options.fetchSummaries(afterSeq > 0 ? afterSeq : void 0, this.pageSizeValue);
|
|
71087
|
+
this.fetchCallCount++;
|
|
71088
|
+
this.headersFetchedTotal += page.summaries.length;
|
|
71089
|
+
let summaries = page.summaries.length > this.pageSizeValue ? page.summaries.slice(0, this.pageSizeValue) : page.summaries;
|
|
71090
|
+
let trimmedAway = 0;
|
|
71091
|
+
if (upperExclusiveSeq !== null) {
|
|
71092
|
+
const kept = summaries.filter((summary) => summary.seq < upperExclusiveSeq);
|
|
71093
|
+
trimmedAway = summaries.length - kept.length;
|
|
71094
|
+
summaries = kept;
|
|
71095
|
+
}
|
|
71096
|
+
this.hasNext = page.hasMore || trimmedAway > 0;
|
|
71097
|
+
this.totalEntries = page.total;
|
|
71098
|
+
if (summaries.length === 0) {
|
|
71099
|
+
return false;
|
|
70818
71100
|
}
|
|
71101
|
+
this.pageSummaries = summaries;
|
|
71102
|
+
this.maxResidentHeadersSeen = Math.max(this.maxResidentHeadersSeen, this.pageSummaries.length);
|
|
71103
|
+
this.hasPrev = summaries[0].seq > 1;
|
|
71104
|
+
this.rebuildRows();
|
|
71105
|
+
return true;
|
|
70819
71106
|
}
|
|
70820
|
-
|
|
70821
|
-
|
|
70822
|
-
|
|
70823
|
-
|
|
70824
|
-
|
|
70825
|
-
|
|
70826
|
-
|
|
71107
|
+
loadWindow(afterSeq) {
|
|
71108
|
+
this.fetchWindow(afterSeq, null);
|
|
71109
|
+
}
|
|
71110
|
+
/**
|
|
71111
|
+
* Load the window immediately before the current one. Backs off (up to a
|
|
71112
|
+
* few attempts) around seq gaps, then reports the oldest boundary.
|
|
71113
|
+
*/
|
|
71114
|
+
goToPreviousPage() {
|
|
71115
|
+
if (this.pageSummaries.length === 0 || !this.hasPrev) return false;
|
|
71116
|
+
const firstSeq = this.pageSummaries[0].seq;
|
|
71117
|
+
let back = Math.max(0, firstSeq - 1 - this.pageSizeValue);
|
|
71118
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
71119
|
+
if (this.fetchWindow(back, firstSeq)) {
|
|
71120
|
+
this.selectedIndex = Math.max(0, this.filteredRows.length - 1);
|
|
71121
|
+
return true;
|
|
70827
71122
|
}
|
|
70828
|
-
|
|
70829
|
-
|
|
71123
|
+
if (back === 0) break;
|
|
71124
|
+
back = Math.max(0, back - this.pageSizeValue);
|
|
71125
|
+
}
|
|
71126
|
+
this.hasPrev = false;
|
|
71127
|
+
return false;
|
|
70830
71128
|
}
|
|
70831
|
-
|
|
70832
|
-
|
|
70833
|
-
|
|
70834
|
-
|
|
70835
|
-
|
|
70836
|
-
|
|
70837
|
-
|
|
71129
|
+
/** Load the window immediately after the current one. */
|
|
71130
|
+
goToNextPage() {
|
|
71131
|
+
if (this.pageSummaries.length === 0 || !this.hasNext) return false;
|
|
71132
|
+
const lastSeq = this.pageSummaries[this.pageSummaries.length - 1].seq;
|
|
71133
|
+
let anchor = lastSeq;
|
|
71134
|
+
for (let attempt = 0; attempt < 4; attempt++) {
|
|
71135
|
+
if (this.fetchWindow(anchor, null)) {
|
|
71136
|
+
this.selectedIndex = 0;
|
|
71137
|
+
return true;
|
|
70838
71138
|
}
|
|
70839
|
-
|
|
70840
|
-
|
|
70841
|
-
|
|
70842
|
-
|
|
70843
|
-
|
|
70844
|
-
|
|
70845
|
-
|
|
70846
|
-
|
|
70847
|
-
|
|
70848
|
-
|
|
70849
|
-
|
|
70850
|
-
|
|
70851
|
-
|
|
70852
|
-
const
|
|
70853
|
-
|
|
71139
|
+
if (!this.hasNext) break;
|
|
71140
|
+
anchor += this.pageSizeValue;
|
|
71141
|
+
}
|
|
71142
|
+
return false;
|
|
71143
|
+
}
|
|
71144
|
+
/**
|
|
71145
|
+
* Iteratively flatten the resident window. Parents always commit before
|
|
71146
|
+
* children, so one forward pass resolves in-window ancestry; an explicit
|
|
71147
|
+
* stack (no recursion) emits DFS rows whose prefixes are capped to
|
|
71148
|
+
* prefixDepthCap segments, so prefix memory stays O(rows).
|
|
71149
|
+
*/
|
|
71150
|
+
rebuildRows() {
|
|
71151
|
+
const count = this.pageSummaries.length;
|
|
71152
|
+
const seqToIndex = /* @__PURE__ */ new Map();
|
|
71153
|
+
const depth = new Int32Array(count);
|
|
71154
|
+
const parentIndex = new Int32Array(count).fill(-1);
|
|
71155
|
+
const childLists = new Array(count);
|
|
71156
|
+
for (let i = 0; i < count; i++) {
|
|
71157
|
+
const summary = this.pageSummaries[i];
|
|
71158
|
+
seqToIndex.set(summary.seq, i);
|
|
71159
|
+
const parent = summary.parentSeq === null ? -1 : seqToIndex.get(summary.parentSeq) ?? -1;
|
|
71160
|
+
if (parent >= 0) {
|
|
71161
|
+
depth[i] = depth[parent] + 1;
|
|
71162
|
+
parentIndex[i] = parent;
|
|
71163
|
+
const bucket = childLists[parent];
|
|
71164
|
+
if (bucket) bucket.push(i);
|
|
71165
|
+
else childLists[parent] = [i];
|
|
71166
|
+
}
|
|
71167
|
+
}
|
|
71168
|
+
const capChars = this.prefixDepthCap * SEGMENT_WIDTH;
|
|
71169
|
+
const capSegments = (segments) => segments.length > capChars ? segments.slice(segments.length - capChars) : segments;
|
|
71170
|
+
const roots = [];
|
|
71171
|
+
for (let i = 0; i < count; i++) {
|
|
71172
|
+
if (parentIndex[i] === -1) roots.push(i);
|
|
71173
|
+
}
|
|
71174
|
+
const rows = [];
|
|
71175
|
+
const stack = [];
|
|
71176
|
+
for (let i = roots.length - 1; i >= 0; i--) {
|
|
71177
|
+
stack.push({ index: roots[i], base: "", isLast: i === roots.length - 1 });
|
|
71178
|
+
}
|
|
71179
|
+
while (stack.length > 0) {
|
|
71180
|
+
const item = stack.pop();
|
|
71181
|
+
const summary = this.pageSummaries[item.index];
|
|
71182
|
+
const rowDepth = depth[item.index];
|
|
71183
|
+
const connector = rowDepth === 0 ? "" : item.isLast ? TREE_CHARS.corner : TREE_CHARS.branch;
|
|
71184
|
+
const segments = capSegments(item.base + connector);
|
|
71185
|
+
const ancestryHidden = rowDepth > this.prefixDepthCap || summary.parentSeq !== null && parentIndex[item.index] === -1;
|
|
71186
|
+
const prefix = ancestryHidden ? TREE_CHARS.hiddenAncestry + segments : segments;
|
|
71187
|
+
rows.push({
|
|
71188
|
+
summary,
|
|
71189
|
+
prefix,
|
|
71190
|
+
hasChildren: summary.childCount > 0,
|
|
71191
|
+
inWindowChildren: childLists[item.index] !== void 0
|
|
71192
|
+
});
|
|
71193
|
+
if (prefix.length > this.maxPrefixCharsSeen) this.maxPrefixCharsSeen = prefix.length;
|
|
71194
|
+
if (this.collapsed.has(summary.id)) continue;
|
|
71195
|
+
const children = childLists[item.index];
|
|
71196
|
+
if (children === void 0) continue;
|
|
71197
|
+
const childBase = capSegments(item.base + (item.isLast ? TREE_CHARS.space : TREE_CHARS.pipe));
|
|
71198
|
+
for (let i = children.length - 1; i >= 0; i--) {
|
|
71199
|
+
stack.push({ index: children[i], base: childBase, isLast: i === children.length - 1 });
|
|
71200
|
+
}
|
|
71201
|
+
}
|
|
71202
|
+
this.rows = rows;
|
|
71203
|
+
let totalPrefix = 0;
|
|
71204
|
+
for (const row of rows) totalPrefix += row.prefix.length;
|
|
71205
|
+
this.currentTotalPrefixChars = totalPrefix;
|
|
70854
71206
|
this.applyFilter();
|
|
70855
71207
|
}
|
|
70856
71208
|
applyFilter() {
|
|
70857
71209
|
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") {
|
|
71210
|
+
this.filteredRows = this.rows;
|
|
71211
|
+
} else {
|
|
71212
|
+
const tokens = this.searchQuery.toLowerCase().split(/\s+/).filter(Boolean);
|
|
71213
|
+
this.filteredRows = this.rows.filter((row) => {
|
|
71214
|
+
if (this.filterMode === "user-only" && (row.summary.type !== "message" || row.summary.role !== "user")) {
|
|
70866
71215
|
return false;
|
|
70867
71216
|
}
|
|
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
|
-
);
|
|
71217
|
+
if (tokens.length === 0) return true;
|
|
71218
|
+
const text = `${row.summary.preview ?? ""} ${roleName(row.summary)} ${row.summary.customType ?? ""} ${row.summary.label ?? ""} ${row.summary.seq}`.toLowerCase();
|
|
71219
|
+
return tokens.every((token) => text.includes(token));
|
|
71220
|
+
});
|
|
71221
|
+
}
|
|
71222
|
+
this.selectedIndex = Math.max(0, Math.min(this.selectedIndex, this.filteredRows.length - 1));
|
|
70882
71223
|
}
|
|
70883
|
-
|
|
70884
|
-
|
|
70885
|
-
|
|
70886
|
-
|
|
70887
|
-
|
|
70888
|
-
|
|
70889
|
-
|
|
71224
|
+
moveUp() {
|
|
71225
|
+
if (this.selectedIndex > 0) {
|
|
71226
|
+
this.selectedIndex--;
|
|
71227
|
+
this.statusMessage = null;
|
|
71228
|
+
return;
|
|
71229
|
+
}
|
|
71230
|
+
if (this.goToPreviousPage()) {
|
|
71231
|
+
this.statusMessage = null;
|
|
71232
|
+
return;
|
|
71233
|
+
}
|
|
71234
|
+
this.selectedIndex = 0;
|
|
71235
|
+
this.statusMessage = "at oldest entry";
|
|
71236
|
+
}
|
|
71237
|
+
moveDown() {
|
|
71238
|
+
if (this.selectedIndex < this.filteredRows.length - 1) {
|
|
71239
|
+
this.selectedIndex++;
|
|
71240
|
+
this.statusMessage = null;
|
|
71241
|
+
return;
|
|
71242
|
+
}
|
|
71243
|
+
if (this.goToNextPage()) {
|
|
71244
|
+
this.statusMessage = null;
|
|
71245
|
+
return;
|
|
71246
|
+
}
|
|
71247
|
+
this.statusMessage = this.filteredRows.length === 0 && this.searchQuery ? "no matches on this page - tab scans ahead" : "at latest entry";
|
|
71248
|
+
}
|
|
71249
|
+
pageNext() {
|
|
71250
|
+
if (this.goToNextPage()) {
|
|
71251
|
+
this.statusMessage = null;
|
|
71252
|
+
} else {
|
|
71253
|
+
this.statusMessage = this.pageSummaries.length === 0 ? "no entries" : "latest page";
|
|
71254
|
+
}
|
|
71255
|
+
}
|
|
71256
|
+
pagePrev() {
|
|
71257
|
+
if (this.goToPreviousPage()) {
|
|
71258
|
+
this.statusMessage = null;
|
|
71259
|
+
} else {
|
|
71260
|
+
this.statusMessage = this.pageSummaries.length === 0 ? "no entries" : "oldest page";
|
|
71261
|
+
}
|
|
71262
|
+
}
|
|
71263
|
+
/**
|
|
71264
|
+
* Bounded "next match": step to the next in-page match, otherwise scan
|
|
71265
|
+
* forward at most SEARCH_SCAN_PAGE_LIMIT pages per press. Never scans
|
|
71266
|
+
* the whole history eagerly and never accumulates fetched pages.
|
|
71267
|
+
*/
|
|
71268
|
+
findNextMatch() {
|
|
71269
|
+
if (!this.searchQuery && this.filterMode === "all") {
|
|
71270
|
+
this.pageNext();
|
|
71271
|
+
return;
|
|
71272
|
+
}
|
|
71273
|
+
if (this.filteredRows.length > 1 && this.selectedIndex < this.filteredRows.length - 1) {
|
|
71274
|
+
this.selectedIndex++;
|
|
71275
|
+
this.statusMessage = null;
|
|
71276
|
+
return;
|
|
71277
|
+
}
|
|
71278
|
+
let scanned = 0;
|
|
71279
|
+
while (this.hasNext && scanned < SEARCH_SCAN_PAGE_LIMIT) {
|
|
71280
|
+
if (!this.goToNextPage()) break;
|
|
71281
|
+
scanned++;
|
|
71282
|
+
if (this.filteredRows.length > 0) {
|
|
71283
|
+
this.selectedIndex = 0;
|
|
71284
|
+
this.statusMessage = scanned === 1 ? "match on next page" : `match ${scanned} pages ahead`;
|
|
71285
|
+
return;
|
|
71286
|
+
}
|
|
71287
|
+
}
|
|
71288
|
+
if (!this.hasNext) {
|
|
71289
|
+
this.statusMessage = "no more matches - end of history";
|
|
70890
71290
|
} else {
|
|
70891
|
-
|
|
71291
|
+
this.statusMessage = `no matches in next ${scanned} pages - tab to continue`;
|
|
70892
71292
|
}
|
|
70893
|
-
|
|
70894
|
-
|
|
71293
|
+
}
|
|
71294
|
+
toggleCollapse() {
|
|
71295
|
+
const selected = this.filteredRows[this.selectedIndex];
|
|
71296
|
+
if (!selected) return;
|
|
71297
|
+
if (this.collapsed.has(selected.summary.id)) {
|
|
71298
|
+
this.collapsed.delete(selected.summary.id);
|
|
71299
|
+
} else {
|
|
71300
|
+
if (this.collapsed.size >= COLLAPSED_CAP) {
|
|
71301
|
+
const oldest = this.collapsed.keys().next().value;
|
|
71302
|
+
if (oldest !== void 0) this.collapsed.delete(oldest);
|
|
71303
|
+
}
|
|
71304
|
+
this.collapsed.set(selected.summary.id, true);
|
|
70895
71305
|
}
|
|
70896
|
-
|
|
71306
|
+
this.rebuildRows();
|
|
70897
71307
|
}
|
|
70898
71308
|
render(width) {
|
|
70899
71309
|
const lines = [];
|
|
70900
71310
|
const totalLines = this.maxVisibleLines + 5;
|
|
71311
|
+
const range = this.windowSeqRange;
|
|
71312
|
+
const rangeLabel = range === null ? "empty" : `seqs ${range[0]}-${range[1]} of ${this.totalEntries}`;
|
|
70901
71313
|
lines.push(createLine(" Conversation Tree", width, false));
|
|
70902
71314
|
lines.push(
|
|
70903
71315
|
createLine(
|
|
70904
|
-
" \u2191\u2193:move \u2190\u2192:page e:
|
|
71316
|
+
" \u2191\u2193:move \u2190\u2192:page e:collapse tab:next match F:fork Enter:navigate Esc:cancel",
|
|
70905
71317
|
width,
|
|
70906
71318
|
false
|
|
70907
71319
|
)
|
|
70908
71320
|
);
|
|
70909
71321
|
lines.push(
|
|
70910
71322
|
createLine(
|
|
70911
|
-
this.searchQuery ? ` Search: ${this.searchQuery}` :
|
|
71323
|
+
this.searchQuery ? ` Search: ${this.searchQuery} (${this.filteredRows.length} on this page, tab:next match)` : ` Type to search (${rangeLabel})`,
|
|
70912
71324
|
width,
|
|
70913
71325
|
false
|
|
70914
71326
|
)
|
|
70915
71327
|
);
|
|
70916
|
-
lines.push(createLine("", width, false));
|
|
70917
|
-
if (this.
|
|
70918
|
-
|
|
71328
|
+
lines.push(createLine(this.statusMessage ? ` ${this.statusMessage}` : "", width, false));
|
|
71329
|
+
if (this.filteredRows.length === 0) {
|
|
71330
|
+
const notice = this.searchQuery || this.filterMode === "user-only" ? " (no matching entries on this page)" : " (no entries)";
|
|
71331
|
+
lines.push(createLine(notice, width, false));
|
|
71332
|
+
for (let i = 1; i < this.maxVisibleLines; i++) {
|
|
70919
71333
|
lines.push(createLine("", width, false));
|
|
70920
71334
|
}
|
|
70921
71335
|
} else {
|
|
70922
|
-
this.selectedIndex = Math.max(
|
|
70923
|
-
0,
|
|
70924
|
-
Math.min(this.selectedIndex, this.filteredItems.length - 1)
|
|
70925
|
-
);
|
|
71336
|
+
this.selectedIndex = Math.max(0, Math.min(this.selectedIndex, this.filteredRows.length - 1));
|
|
70926
71337
|
let startIndex = Math.max(
|
|
70927
71338
|
0,
|
|
70928
71339
|
Math.min(
|
|
70929
71340
|
this.selectedIndex - Math.floor(this.maxVisibleLines / 2),
|
|
70930
|
-
this.
|
|
71341
|
+
this.filteredRows.length - this.maxVisibleLines
|
|
70931
71342
|
)
|
|
70932
71343
|
);
|
|
70933
|
-
|
|
70934
|
-
startIndex + this.maxVisibleLines,
|
|
70935
|
-
this.filteredItems.length
|
|
70936
|
-
);
|
|
71344
|
+
const endIndex = Math.min(startIndex + this.maxVisibleLines, this.filteredRows.length);
|
|
70937
71345
|
if (endIndex - startIndex < this.maxVisibleLines && startIndex > 0) {
|
|
70938
71346
|
startIndex = Math.max(0, endIndex - this.maxVisibleLines);
|
|
70939
71347
|
}
|
|
70940
71348
|
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++) {
|
|
71349
|
+
const row = this.filteredRows[i];
|
|
71350
|
+
const activeIndicator = this.options.activePathSeqs.has(row.summary.seq) ? theme.fg("success", TREE_CHARS.active) : DIM + TREE_CHARS.inactive + RESET;
|
|
71351
|
+
const expandIndicator = row.inWindowChildren ? theme.fg("dim", this.collapsed.has(row.summary.id) ? "\u25B6 " : "\u25BC ") : row.hasChildren ? theme.fg("dim", "\xB7\xB7") : " ";
|
|
71352
|
+
const role = roleColor(roleName(row.summary));
|
|
71353
|
+
const indicatorWidth = visibleWidth(activeIndicator) + visibleWidth(expandIndicator) + visibleWidth(role) + 2;
|
|
71354
|
+
const prefixBudget = Math.max(0, Math.min(Math.floor(width * 0.35), width - indicatorWidth - MIN_BODY_WIDTH));
|
|
71355
|
+
const displayPrefix = clampPrefixForDisplay(row.prefix, prefixBudget);
|
|
71356
|
+
const availableWidth = Math.max(0, width - visibleWidth(displayPrefix) - indicatorWidth);
|
|
71357
|
+
const content = truncateToWidth(row.summary.preview ?? "", availableWidth);
|
|
71358
|
+
lines.push(createLine(`${displayPrefix}${activeIndicator}${expandIndicator}${role}: ${content}`, width, i === this.selectedIndex));
|
|
71359
|
+
}
|
|
71360
|
+
for (let i = endIndex - startIndex; i < this.maxVisibleLines; i++) {
|
|
70970
71361
|
lines.push(createLine("", width, false));
|
|
70971
71362
|
}
|
|
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
71363
|
}
|
|
71364
|
+
const selectedRow = this.filteredRows[this.selectedIndex];
|
|
71365
|
+
const activePath = selectedRow && this.options.activePathSeqs.has(selectedRow.summary.seq) ? " [active]" : "";
|
|
71366
|
+
lines.push(
|
|
71367
|
+
createLine(
|
|
71368
|
+
` (${selectedRow ? this.selectedIndex + 1 : 0}/${this.filteredRows.length})${this.filterMode === "user-only" ? " [user]" : ""}${activePath} \xB7 ${rangeLabel}`,
|
|
71369
|
+
width,
|
|
71370
|
+
false
|
|
71371
|
+
)
|
|
71372
|
+
);
|
|
70982
71373
|
while (lines.length < totalLines) {
|
|
70983
71374
|
lines.push(createLine("", width, false));
|
|
70984
71375
|
}
|
|
@@ -70987,51 +71378,24 @@ var TreeSelectorComponent = class {
|
|
|
70987
71378
|
handleInput(keyData) {
|
|
70988
71379
|
const kb = getEditorKeybindings();
|
|
70989
71380
|
if (kb.matches(keyData, "selectUp")) {
|
|
70990
|
-
this.
|
|
71381
|
+
this.moveUp();
|
|
70991
71382
|
} 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);
|
|
71383
|
+
this.moveDown();
|
|
71384
|
+
} else if (kb.matches(keyData, "cursorRight") || kb.matches(keyData, "selectPageDown")) {
|
|
71385
|
+
this.pageNext();
|
|
71386
|
+
} else if (kb.matches(keyData, "cursorLeft") || kb.matches(keyData, "selectPageUp")) {
|
|
71387
|
+
this.pagePrev();
|
|
71003
71388
|
} 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
|
-
}
|
|
71389
|
+
this.toggleCollapse();
|
|
71026
71390
|
} else if (kb.matches(keyData, "selectConfirm")) {
|
|
71027
|
-
const selected = this.
|
|
71391
|
+
const selected = this.filteredRows[this.selectedIndex];
|
|
71028
71392
|
if (selected && this.onSelect) {
|
|
71029
|
-
this.onSelect(selected.
|
|
71393
|
+
this.onSelect(selected.summary.id, "navigate");
|
|
71030
71394
|
}
|
|
71031
71395
|
} else if (keyData === "f" || keyData === "F") {
|
|
71032
|
-
const selected = this.
|
|
71396
|
+
const selected = this.filteredRows[this.selectedIndex];
|
|
71033
71397
|
if (selected && this.onSelect) {
|
|
71034
|
-
this.onSelect(selected.
|
|
71398
|
+
this.onSelect(selected.summary.id, "fork");
|
|
71035
71399
|
}
|
|
71036
71400
|
} else if (kb.matches(keyData, "selectCancel")) {
|
|
71037
71401
|
if (this.searchQuery) {
|
|
@@ -71040,12 +71404,15 @@ var TreeSelectorComponent = class {
|
|
|
71040
71404
|
} else {
|
|
71041
71405
|
this.onCancel?.();
|
|
71042
71406
|
}
|
|
71407
|
+
} else if (matchesKey(keyData, "tab")) {
|
|
71408
|
+
this.findNextMatch();
|
|
71043
71409
|
} else if (matchesKey(keyData, "ctrl+u")) {
|
|
71044
71410
|
this.filterMode = this.filterMode === "user-only" ? "all" : "user-only";
|
|
71045
71411
|
this.applyFilter();
|
|
71046
71412
|
} else if (kb.matches(keyData, "deleteCharBackward")) {
|
|
71047
71413
|
if (this.searchQuery.length > 0) {
|
|
71048
|
-
|
|
71414
|
+
const last = searchSegmenter.segment(this.searchQuery).containing(this.searchQuery.length - 1);
|
|
71415
|
+
this.searchQuery = this.searchQuery.slice(0, last?.index ?? 0);
|
|
71049
71416
|
this.applyFilter();
|
|
71050
71417
|
}
|
|
71051
71418
|
} else {
|
|
@@ -71060,10 +71427,10 @@ var TreeSelectorComponent = class {
|
|
|
71060
71427
|
}
|
|
71061
71428
|
}
|
|
71062
71429
|
invalidate() {
|
|
71063
|
-
this.
|
|
71430
|
+
this.rebuildRows();
|
|
71064
71431
|
}
|
|
71065
71432
|
getSelectedEntryId() {
|
|
71066
|
-
return this.
|
|
71433
|
+
return this.filteredRows[this.selectedIndex]?.summary.id ?? null;
|
|
71067
71434
|
}
|
|
71068
71435
|
};
|
|
71069
71436
|
|
|
@@ -71265,16 +71632,16 @@ var Diff = class {
|
|
|
71265
71632
|
}
|
|
71266
71633
|
}
|
|
71267
71634
|
}
|
|
71268
|
-
addToPath(
|
|
71269
|
-
const last =
|
|
71635
|
+
addToPath(path34, added, removed, oldPosInc, options) {
|
|
71636
|
+
const last = path34.lastComponent;
|
|
71270
71637
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
71271
71638
|
return {
|
|
71272
|
-
oldPos:
|
|
71639
|
+
oldPos: path34.oldPos + oldPosInc,
|
|
71273
71640
|
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
71274
71641
|
};
|
|
71275
71642
|
} else {
|
|
71276
71643
|
return {
|
|
71277
|
-
oldPos:
|
|
71644
|
+
oldPos: path34.oldPos + oldPosInc,
|
|
71278
71645
|
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
71279
71646
|
};
|
|
71280
71647
|
}
|
|
@@ -71722,13 +72089,13 @@ function formatSize2(bytes) {
|
|
|
71722
72089
|
}
|
|
71723
72090
|
var DEFAULT_MAX_BYTES = 102400;
|
|
71724
72091
|
var DEFAULT_MAX_LINES = 100;
|
|
71725
|
-
function shortenPath(
|
|
71726
|
-
if (typeof
|
|
72092
|
+
function shortenPath(path34) {
|
|
72093
|
+
if (typeof path34 !== "string") return "";
|
|
71727
72094
|
const home = os5.homedir();
|
|
71728
|
-
if (
|
|
71729
|
-
return `~${
|
|
72095
|
+
if (path34.startsWith(home)) {
|
|
72096
|
+
return `~${path34.slice(home.length)}`;
|
|
71730
72097
|
}
|
|
71731
|
-
return
|
|
72098
|
+
return path34;
|
|
71732
72099
|
}
|
|
71733
72100
|
function replaceTabs(text) {
|
|
71734
72101
|
return text.replace(/\t/g, " ");
|
|
@@ -71738,6 +72105,18 @@ function str(value) {
|
|
|
71738
72105
|
if (value == null) return "";
|
|
71739
72106
|
return null;
|
|
71740
72107
|
}
|
|
72108
|
+
function projectResultForDisplay(result) {
|
|
72109
|
+
const content = result.content;
|
|
72110
|
+
if (!Array.isArray(content) || !content.some((block) => typeof block?.data === "string" && block.data.length > 0)) {
|
|
72111
|
+
return result;
|
|
72112
|
+
}
|
|
72113
|
+
return {
|
|
72114
|
+
...result,
|
|
72115
|
+
content: content.map(
|
|
72116
|
+
(block) => typeof block?.data === "string" && block.data.length > 0 ? { ...block, data: "" } : block
|
|
72117
|
+
)
|
|
72118
|
+
};
|
|
72119
|
+
}
|
|
71741
72120
|
function partialStr(value, maxLen = 30) {
|
|
71742
72121
|
if (typeof value === "string") {
|
|
71743
72122
|
if (value.length === 0) return "...";
|
|
@@ -71772,7 +72151,7 @@ var ToolExecutionComponent = class extends Container {
|
|
|
71772
72151
|
this.updateDisplay();
|
|
71773
72152
|
}
|
|
71774
72153
|
updateResult(result, isPartial = false) {
|
|
71775
|
-
this.result = result;
|
|
72154
|
+
this.result = projectResultForDisplay(result);
|
|
71776
72155
|
this.isPartial = isPartial;
|
|
71777
72156
|
this.updateDisplay();
|
|
71778
72157
|
}
|
|
@@ -71811,14 +72190,14 @@ ${renderManageTodoListResult(this.result, { expanded: this.expanded }, theme)}`;
|
|
|
71811
72190
|
}
|
|
71812
72191
|
} else if (this.toolName === "read_file") {
|
|
71813
72192
|
const rawPath = str(this.args?.file_path ?? this.args?.path);
|
|
71814
|
-
const
|
|
72193
|
+
const path34 = rawPath !== null ? shortenPath(rawPath) : null;
|
|
71815
72194
|
const offset = typeof this.args?.offset === "number" ? this.args.offset : void 0;
|
|
71816
72195
|
const limit = typeof this.args?.limit === "number" ? this.args.limit : void 0;
|
|
71817
72196
|
let pathDisplay;
|
|
71818
|
-
if (
|
|
72197
|
+
if (path34 === null) {
|
|
71819
72198
|
pathDisplay = invalidArg;
|
|
71820
|
-
} else if (
|
|
71821
|
-
pathDisplay = theme.fg("accent",
|
|
72199
|
+
} else if (path34) {
|
|
72200
|
+
pathDisplay = theme.fg("accent", path34);
|
|
71822
72201
|
} else {
|
|
71823
72202
|
const partialPath = partialStr(this.args?.file_path ?? this.args?.path);
|
|
71824
72203
|
pathDisplay = theme.fg("toolOutput", partialPath);
|
|
@@ -71865,12 +72244,12 @@ ${renderManageTodoListResult(this.result, { expanded: this.expanded }, theme)}`;
|
|
|
71865
72244
|
} else if (this.toolName === "write_file") {
|
|
71866
72245
|
const rawPath = str(this.args?.file_path ?? this.args?.path);
|
|
71867
72246
|
const fileContent = str(this.args?.content);
|
|
71868
|
-
const
|
|
72247
|
+
const path34 = rawPath !== null ? shortenPath(rawPath) : null;
|
|
71869
72248
|
let pathDisplay;
|
|
71870
|
-
if (
|
|
72249
|
+
if (path34 === null) {
|
|
71871
72250
|
pathDisplay = invalidArg;
|
|
71872
|
-
} else if (
|
|
71873
|
-
pathDisplay = theme.fg("accent",
|
|
72251
|
+
} else if (path34) {
|
|
72252
|
+
pathDisplay = theme.fg("accent", path34);
|
|
71874
72253
|
} else {
|
|
71875
72254
|
const partialPath = partialStr(this.args?.file_path ?? this.args?.path);
|
|
71876
72255
|
pathDisplay = theme.fg("toolOutput", partialPath);
|
|
@@ -71907,12 +72286,12 @@ ${theme.fg("error", errorText)}`;
|
|
|
71907
72286
|
}
|
|
71908
72287
|
} else if (this.toolName === "edit_file") {
|
|
71909
72288
|
const rawPath = str(this.args?.file_path ?? this.args?.path);
|
|
71910
|
-
const
|
|
72289
|
+
const path34 = rawPath !== null ? shortenPath(rawPath) : null;
|
|
71911
72290
|
let pathDisplay;
|
|
71912
|
-
if (
|
|
72291
|
+
if (path34 === null) {
|
|
71913
72292
|
pathDisplay = invalidArg;
|
|
71914
|
-
} else if (
|
|
71915
|
-
pathDisplay = theme.fg("accent",
|
|
72293
|
+
} else if (path34) {
|
|
72294
|
+
pathDisplay = theme.fg("accent", path34);
|
|
71916
72295
|
} else {
|
|
71917
72296
|
const partialPath = partialStr(this.args?.file_path ?? this.args?.path);
|
|
71918
72297
|
pathDisplay = theme.fg("toolOutput", partialPath);
|
|
@@ -71937,7 +72316,7 @@ ${theme.fg("error", errorText)}`;
|
|
|
71937
72316
|
const diff = this.result.details.diff;
|
|
71938
72317
|
const firstChangedLine = this.result.details.firstChangedLine;
|
|
71939
72318
|
if (firstChangedLine) {
|
|
71940
|
-
text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent",
|
|
72319
|
+
text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent", path34 || rawPath)}${theme.fg("warning", `:${firstChangedLine}`)}`;
|
|
71941
72320
|
}
|
|
71942
72321
|
const lines = diff.split("\n");
|
|
71943
72322
|
const maxLines = this.expanded ? lines.length : 15;
|
|
@@ -71957,7 +72336,7 @@ ${theme.fg("error", errorText)}`;
|
|
|
71957
72336
|
const diff = generateEditDiff(oldText, newText, rawPath);
|
|
71958
72337
|
const firstChangedLine = findFirstChangedLine(oldText, newText);
|
|
71959
72338
|
if (firstChangedLine) {
|
|
71960
|
-
text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent",
|
|
72339
|
+
text = `${theme.fg("toolTitle", theme.bold("edit_file"))} ${theme.fg("accent", path34 || rawPath)}${theme.fg("warning", `:${firstChangedLine}`)}`;
|
|
71961
72340
|
}
|
|
71962
72341
|
const lines = diff.split("\n");
|
|
71963
72342
|
const maxLines = this.expanded ? lines.length : 15;
|
|
@@ -71976,9 +72355,9 @@ ${theme.fg("error", errorText)}`;
|
|
|
71976
72355
|
}
|
|
71977
72356
|
} else if (this.toolName === "list_dir") {
|
|
71978
72357
|
const rawPath = str(this.args?.path);
|
|
71979
|
-
const
|
|
72358
|
+
const path34 = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
71980
72359
|
const limit = this.args?.limit;
|
|
71981
|
-
text = `${theme.fg("toolTitle", theme.bold("list_dir"))} ${
|
|
72360
|
+
text = `${theme.fg("toolTitle", theme.bold("list_dir"))} ${path34 === null ? invalidArg : theme.fg("accent", path34)}`;
|
|
71982
72361
|
if (limit !== void 0) {
|
|
71983
72362
|
text += theme.fg("toolOutput", ` (limit ${limit})`);
|
|
71984
72363
|
}
|
|
@@ -72014,9 +72393,9 @@ ${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
|
|
|
72014
72393
|
} else if (this.toolName === "find_files") {
|
|
72015
72394
|
const pattern = str(this.args?.pattern);
|
|
72016
72395
|
const rawPath = str(this.args?.path);
|
|
72017
|
-
const
|
|
72396
|
+
const path34 = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
72018
72397
|
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 ${
|
|
72398
|
+
text = theme.fg("toolTitle", theme.bold("find_files")) + " " + (pattern === null ? invalidArg : theme.fg("accent", pattern || "")) + theme.fg("toolOutput", ` in ${path34 === null ? invalidArg : path34}`);
|
|
72020
72399
|
if (limit !== void 0) {
|
|
72021
72400
|
text += theme.fg("toolOutput", ` (limit ${limit})`);
|
|
72022
72401
|
}
|
|
@@ -72052,10 +72431,10 @@ ${theme.fg("warning", `[Truncated: ${warnings.join(", ")}]`)}`;
|
|
|
72052
72431
|
} else if (this.toolName === "grep_text") {
|
|
72053
72432
|
const pattern = str(this.args?.pattern);
|
|
72054
72433
|
const rawPath = str(this.args?.path);
|
|
72055
|
-
const
|
|
72434
|
+
const path34 = rawPath !== null ? shortenPath(rawPath || ".") : null;
|
|
72056
72435
|
const glob = str(this.args?.glob);
|
|
72057
72436
|
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 ${
|
|
72437
|
+
text = theme.fg("toolTitle", theme.bold("grep_text")) + " " + (pattern === null ? invalidArg : theme.fg("accent", `/${pattern || ""}/`)) + theme.fg("toolOutput", ` in ${path34 === null ? invalidArg : path34}`);
|
|
72059
72438
|
if (glob) {
|
|
72060
72439
|
text += theme.fg("toolOutput", ` (${glob})`);
|
|
72061
72440
|
}
|
|
@@ -72278,7 +72657,7 @@ async function handleResumeCommand(host) {
|
|
|
72278
72657
|
return { component: selector, focus: selector.getSelectList() };
|
|
72279
72658
|
});
|
|
72280
72659
|
}
|
|
72281
|
-
async function
|
|
72660
|
+
async function loadSession(host, sessionId) {
|
|
72282
72661
|
const beforeSwitch = await host.extensionRunner?.emitSessionBeforeSwitch({
|
|
72283
72662
|
type: "session:before_switch",
|
|
72284
72663
|
reason: "resume",
|
|
@@ -72475,29 +72854,31 @@ function setWaitingForUser(host, waiting) {
|
|
|
72475
72854
|
syncTitleActivity(host);
|
|
72476
72855
|
}
|
|
72477
72856
|
async function handleTreeCommand(host) {
|
|
72478
|
-
const
|
|
72479
|
-
|
|
72480
|
-
|
|
72481
|
-
host.showStatus(`No entries in current session (entries: ${entries.length})`);
|
|
72857
|
+
const head = host.sessionManager.getEntrySummariesPage({ limit: 1 });
|
|
72858
|
+
if (head.total === 0) {
|
|
72859
|
+
host.showStatus(`No entries in current session (entries: 0)`);
|
|
72482
72860
|
return;
|
|
72483
72861
|
}
|
|
72484
72862
|
host.showSelector((done) => {
|
|
72485
72863
|
const selector = new TreeSelectorComponent(
|
|
72486
|
-
|
|
72487
|
-
|
|
72488
|
-
|
|
72489
|
-
|
|
72490
|
-
|
|
72491
|
-
|
|
72492
|
-
|
|
72493
|
-
|
|
72864
|
+
{
|
|
72865
|
+
terminalHeight: host.ui.terminal.rows,
|
|
72866
|
+
activeEntryId: host.sessionManager.getActiveEntryId(),
|
|
72867
|
+
activePathSeqs: host.sessionManager.getActivePathSeqs(),
|
|
72868
|
+
totalEntries: head.total,
|
|
72869
|
+
fetchSummaries: (afterSeq, limit) => host.sessionManager.getEntrySummariesPage({ limit, afterSeq }),
|
|
72870
|
+
onSelect: async (entryId, action) => {
|
|
72871
|
+
done();
|
|
72872
|
+
if (action === "fork") {
|
|
72873
|
+
await host.forkAtEntry(entryId);
|
|
72874
|
+
} else {
|
|
72875
|
+
await host.navigateToEntry(entryId);
|
|
72876
|
+
}
|
|
72877
|
+
},
|
|
72878
|
+
onCancel: () => {
|
|
72879
|
+
done();
|
|
72494
72880
|
}
|
|
72495
|
-
}
|
|
72496
|
-
() => {
|
|
72497
|
-
done();
|
|
72498
|
-
},
|
|
72499
|
-
host.sessionManager.getActiveEntryId()
|
|
72500
|
-
// Start at active entry
|
|
72881
|
+
}
|
|
72501
72882
|
);
|
|
72502
72883
|
return { component: selector, focus: selector };
|
|
72503
72884
|
});
|
|
@@ -72514,8 +72895,8 @@ async function forkAtEntry(host, entryId) {
|
|
|
72514
72895
|
host.showError("Failed to branch at entry");
|
|
72515
72896
|
return;
|
|
72516
72897
|
}
|
|
72517
|
-
const
|
|
72518
|
-
const pathNames =
|
|
72898
|
+
const path34 = host.sessionManager.getPathSummaries(entryId);
|
|
72899
|
+
const pathNames = path34.map((summary) => summary.role || summary.type).join(" \u2192 ");
|
|
72519
72900
|
const messages = host.sessionManager.getMessages();
|
|
72520
72901
|
host.syncAgentFromActiveSession(messages);
|
|
72521
72902
|
await host.syncSessionScopedState(messages);
|
|
@@ -72528,7 +72909,7 @@ async function forkAtEntry(host, entryId) {
|
|
|
72528
72909
|
host.updatePendingMessagesDisplay();
|
|
72529
72910
|
host.renderMessageHistory(messages);
|
|
72530
72911
|
await host.sessionManager.save();
|
|
72531
|
-
host.showStatus(`Branched at: ${pathNames} (${
|
|
72912
|
+
host.showStatus(`Branched at: ${pathNames} (${path34.length} messages). Continue to add to this branch.`);
|
|
72532
72913
|
} catch (error) {
|
|
72533
72914
|
host.showError(
|
|
72534
72915
|
`Failed to branch: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -72556,10 +72937,10 @@ async function navigateToEntry(host, entryId) {
|
|
|
72556
72937
|
host.sessionManager.save().catch((err) => {
|
|
72557
72938
|
console.error("[Session] Save after navigation failed:", err);
|
|
72558
72939
|
});
|
|
72559
|
-
const
|
|
72560
|
-
const
|
|
72561
|
-
const role =
|
|
72562
|
-
host.showStatus(`Switched to branch: ${role} (${
|
|
72940
|
+
const path34 = host.sessionManager.getPathSummaries(entryId);
|
|
72941
|
+
const summary = host.sessionManager.getEntrySummary(entryId);
|
|
72942
|
+
const role = summary?.role || summary?.type || "entry";
|
|
72943
|
+
host.showStatus(`Switched to branch: ${role} (${path34.length} entries in path)`);
|
|
72563
72944
|
} catch (error) {
|
|
72564
72945
|
host.showError(
|
|
72565
72946
|
`Failed to navigate: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -72654,9 +73035,9 @@ async function handleForkCommand(host) {
|
|
|
72654
73035
|
}
|
|
72655
73036
|
|
|
72656
73037
|
// src/commands/interactive-skill-commands.ts
|
|
72657
|
-
import * as
|
|
73038
|
+
import * as fs24 from "fs";
|
|
72658
73039
|
import * as os7 from "os";
|
|
72659
|
-
import * as
|
|
73040
|
+
import * as path26 from "path";
|
|
72660
73041
|
|
|
72661
73042
|
// src/commands/subagent-command.ts
|
|
72662
73043
|
async function handleSubagentCommand(host, args) {
|
|
@@ -72793,9 +73174,9 @@ function handleSkillsCommand(host) {
|
|
|
72793
73174
|
});
|
|
72794
73175
|
}
|
|
72795
73176
|
function discoverSkills(host) {
|
|
72796
|
-
const builtinDir =
|
|
72797
|
-
const userDir =
|
|
72798
|
-
const projectDir =
|
|
73177
|
+
const builtinDir = path26.join(getBuiltinDir(), "skills");
|
|
73178
|
+
const userDir = path26.join(os7.homedir(), ".pie", "skills");
|
|
73179
|
+
const projectDir = path26.join(process.cwd(), ".pie", "skills");
|
|
72799
73180
|
return loadSkills({ dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: process.cwd() }) });
|
|
72800
73181
|
}
|
|
72801
73182
|
function listDiscoveredSkills(host) {
|
|
@@ -72927,7 +73308,7 @@ function expandSkillCommand(host, text) {
|
|
|
72927
73308
|
const skill = host.skills.find((s) => s.name === skillName);
|
|
72928
73309
|
if (!skill) return text;
|
|
72929
73310
|
try {
|
|
72930
|
-
const content =
|
|
73311
|
+
const content = fs24.readFileSync(skill.filePath, "utf-8");
|
|
72931
73312
|
const body = host.stripFrontmatter(content).trim();
|
|
72932
73313
|
const skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">
|
|
72933
73314
|
References are relative to ${skill.baseDir}.
|
|
@@ -72954,9 +73335,9 @@ async function handleSkillToggleCommand(host, args, enabled) {
|
|
|
72954
73335
|
host.showError(`Usage: /skills/${enabled ? "enable" : "disable"} <name>`);
|
|
72955
73336
|
return;
|
|
72956
73337
|
}
|
|
72957
|
-
const builtinDir =
|
|
72958
|
-
const userDir =
|
|
72959
|
-
const projectDir =
|
|
73338
|
+
const builtinDir = path26.join(getBuiltinDir(), "skills");
|
|
73339
|
+
const userDir = path26.join(os7.homedir(), ".pie", "skills");
|
|
73340
|
+
const projectDir = path26.join(process.cwd(), ".pie", "skills");
|
|
72960
73341
|
const discovered = loadSkills({ dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: process.cwd() }) }).skills;
|
|
72961
73342
|
if (!discovered.some((skill) => skill.name === name)) {
|
|
72962
73343
|
host.showError(`Skill not found: ${name}`);
|
|
@@ -73022,17 +73403,17 @@ async function handleSkillsCreate(host, args) {
|
|
|
73022
73403
|
if (!description) {
|
|
73023
73404
|
description = `Skill for ${name}`;
|
|
73024
73405
|
}
|
|
73025
|
-
const skillsDir =
|
|
73026
|
-
const skillDir =
|
|
73027
|
-
const skillFile =
|
|
73406
|
+
const skillsDir = path26.join(os7.homedir(), ".pie", "skills");
|
|
73407
|
+
const skillDir = path26.join(skillsDir, name);
|
|
73408
|
+
const skillFile = path26.join(skillDir, "SKILL.md");
|
|
73028
73409
|
debugLog2(`Creating at: ${skillFile}`);
|
|
73029
|
-
if (
|
|
73410
|
+
if (fs24.existsSync(skillDir)) {
|
|
73030
73411
|
host.showError(`Skill "${name}" already exists at ${skillDir}`);
|
|
73031
73412
|
return;
|
|
73032
73413
|
}
|
|
73033
|
-
|
|
73414
|
+
fs24.mkdirSync(skillDir, { recursive: true });
|
|
73034
73415
|
const template = createSkillTemplate(name, description);
|
|
73035
|
-
|
|
73416
|
+
fs24.writeFileSync(skillFile, template, "utf-8");
|
|
73036
73417
|
debugLog2("Successfully created skill");
|
|
73037
73418
|
host.chatContainer.addChild(new Spacer(1));
|
|
73038
73419
|
host.chatContainer.addChild(new Text(theme.fg("accent", `\u2713 Created skill: ${name}`), 1, 0));
|
|
@@ -73968,8 +74349,7 @@ async function handleCompactCommand(host) {
|
|
|
73968
74349
|
host.showStatus("Nothing to compact yet");
|
|
73969
74350
|
return;
|
|
73970
74351
|
}
|
|
73971
|
-
const
|
|
73972
|
-
const firstKeptEntryId = findFirstKeptEntryId(pathEntries);
|
|
74352
|
+
const firstKeptEntryId = findFirstKeptEntrySummaryId(host.sessionManager.getActiveContextSummaries());
|
|
73973
74353
|
if (!firstKeptEntryId) {
|
|
73974
74354
|
host.showStatus("Need at least one real user message before compacting");
|
|
73975
74355
|
return;
|
|
@@ -74885,8 +75265,8 @@ function setupInteractiveEditorSubmitHandler(host) {
|
|
|
74885
75265
|
}
|
|
74886
75266
|
|
|
74887
75267
|
// src/input/interactive-file-pipeline.ts
|
|
74888
|
-
import * as
|
|
74889
|
-
import * as
|
|
75268
|
+
import * as fs27 from "fs";
|
|
75269
|
+
import * as path29 from "path";
|
|
74890
75270
|
|
|
74891
75271
|
// src/components/file-picker.ts
|
|
74892
75272
|
var FilePickerComponent = class extends Container {
|
|
@@ -75107,8 +75487,8 @@ var FilePickerComponent = class extends Container {
|
|
|
75107
75487
|
};
|
|
75108
75488
|
|
|
75109
75489
|
// src/files/commands/file-commands.ts
|
|
75110
|
-
import * as
|
|
75111
|
-
import * as
|
|
75490
|
+
import * as fs25 from "node:fs";
|
|
75491
|
+
import * as path27 from "node:path";
|
|
75112
75492
|
var FileCommands = class {
|
|
75113
75493
|
context;
|
|
75114
75494
|
constructor(context) {
|
|
@@ -75124,11 +75504,11 @@ var FileCommands = class {
|
|
|
75124
75504
|
return;
|
|
75125
75505
|
}
|
|
75126
75506
|
const filePath = resolvePath2(parsed.path);
|
|
75127
|
-
if (!
|
|
75507
|
+
if (!fs25.existsSync(filePath)) {
|
|
75128
75508
|
this.context.showError(`File not found: ${parsed.path}`);
|
|
75129
75509
|
return;
|
|
75130
75510
|
}
|
|
75131
|
-
this.context.showStatus(`Uploading ${
|
|
75511
|
+
this.context.showStatus(`Uploading ${path27.basename(filePath)}...`);
|
|
75132
75512
|
try {
|
|
75133
75513
|
const result = await this.context.fileManager.upload(filePath, {
|
|
75134
75514
|
purpose: parsed.purpose,
|
|
@@ -75163,7 +75543,7 @@ var FileCommands = class {
|
|
|
75163
75543
|
return;
|
|
75164
75544
|
}
|
|
75165
75545
|
const resolvedPath = resolvePath2(filePath);
|
|
75166
|
-
if (!
|
|
75546
|
+
if (!fs25.existsSync(resolvedPath)) {
|
|
75167
75547
|
this.context.showError(`File not found: ${filePath}`);
|
|
75168
75548
|
return;
|
|
75169
75549
|
}
|
|
@@ -75194,7 +75574,7 @@ var FileCommands = class {
|
|
|
75194
75574
|
return;
|
|
75195
75575
|
}
|
|
75196
75576
|
const resolvedPath = resolvePath2(parsed.path);
|
|
75197
|
-
if (!
|
|
75577
|
+
if (!fs25.existsSync(resolvedPath)) {
|
|
75198
75578
|
this.context.showError(`File not found: ${parsed.path}`);
|
|
75199
75579
|
return;
|
|
75200
75580
|
}
|
|
@@ -75672,8 +76052,8 @@ var FileStatusMonitor = class {
|
|
|
75672
76052
|
};
|
|
75673
76053
|
|
|
75674
76054
|
// src/files/mention/mention-handler.ts
|
|
75675
|
-
import * as
|
|
75676
|
-
import * as
|
|
76055
|
+
import * as fs26 from "node:fs";
|
|
76056
|
+
import * as path28 from "node:path";
|
|
75677
76057
|
var MentionHandler = class {
|
|
75678
76058
|
fileManager;
|
|
75679
76059
|
onShowPicker;
|
|
@@ -75728,7 +76108,7 @@ var MentionHandler = class {
|
|
|
75728
76108
|
navigateBrowseParent() {
|
|
75729
76109
|
const currentDir = this.getBrowserDirectory();
|
|
75730
76110
|
if (!currentDir) return;
|
|
75731
|
-
const parentDir =
|
|
76111
|
+
const parentDir = path28.dirname(currentDir);
|
|
75732
76112
|
if (parentDir === currentDir) return;
|
|
75733
76113
|
this.browsingDirectory = parentDir;
|
|
75734
76114
|
this.showMentionPicker("");
|
|
@@ -75748,7 +76128,7 @@ var MentionHandler = class {
|
|
|
75748
76128
|
if (option.type === "parent") {
|
|
75749
76129
|
const currentDir = this.getBrowserDirectory();
|
|
75750
76130
|
if (currentDir) {
|
|
75751
|
-
this.browsingDirectory =
|
|
76131
|
+
this.browsingDirectory = path28.dirname(currentDir);
|
|
75752
76132
|
this.showMentionPicker("");
|
|
75753
76133
|
this.isPickerVisible = true;
|
|
75754
76134
|
}
|
|
@@ -75888,7 +76268,7 @@ var MentionHandler = class {
|
|
|
75888
76268
|
id: part.content,
|
|
75889
76269
|
name: part.name || fileInfo.name,
|
|
75890
76270
|
mimeType: fileInfo.mimeType,
|
|
75891
|
-
ext:
|
|
76271
|
+
ext: path28.extname(part.name || fileInfo.name).toLowerCase(),
|
|
75892
76272
|
size: fileInfo.size,
|
|
75893
76273
|
source: fileInfo.platforms.length > 0 ? "session" : "local",
|
|
75894
76274
|
fileId: part.content,
|
|
@@ -76046,11 +76426,11 @@ var MentionHandler = class {
|
|
|
76046
76426
|
}
|
|
76047
76427
|
if (this.isPath(query)) {
|
|
76048
76428
|
const resolvedPath = resolvePath2(query);
|
|
76049
|
-
if (
|
|
76050
|
-
const stats =
|
|
76429
|
+
if (fs26.existsSync(resolvedPath)) {
|
|
76430
|
+
const stats = fs26.statSync(resolvedPath);
|
|
76051
76431
|
if (stats.isFile()) {
|
|
76052
76432
|
const type = FileCache.getFileTypeFromName(resolvedPath);
|
|
76053
|
-
const name =
|
|
76433
|
+
const name = path28.basename(resolvedPath);
|
|
76054
76434
|
if (!seenNames.has(name.toLowerCase())) {
|
|
76055
76435
|
options.push({
|
|
76056
76436
|
type: "upload",
|
|
@@ -76071,16 +76451,16 @@ var MentionHandler = class {
|
|
|
76071
76451
|
return void 0;
|
|
76072
76452
|
}
|
|
76073
76453
|
const queryPath = this.isPath(query) ? resolvePath2(query) : void 0;
|
|
76074
|
-
const filter = queryPath ?
|
|
76454
|
+
const filter = queryPath ? fs26.existsSync(queryPath) && fs26.statSync(queryPath).isDirectory() ? "" : path28.basename(queryPath) : query;
|
|
76075
76455
|
const entries = this.fileManager.listPathEntries(currentDir, filter);
|
|
76076
76456
|
const options = [];
|
|
76077
76457
|
const homeDir = process.env.HOME || "";
|
|
76078
76458
|
const displayDir = currentDir.startsWith(homeDir) ? `~${currentDir.slice(homeDir.length)}` : currentDir;
|
|
76079
|
-
if (
|
|
76459
|
+
if (path28.dirname(currentDir) !== currentDir) {
|
|
76080
76460
|
options.push({
|
|
76081
76461
|
type: "parent",
|
|
76082
76462
|
name: "..",
|
|
76083
|
-
path:
|
|
76463
|
+
path: path28.dirname(currentDir),
|
|
76084
76464
|
icon: "\u21A9",
|
|
76085
76465
|
meta: "Parent directory"
|
|
76086
76466
|
});
|
|
@@ -76112,10 +76492,10 @@ var MentionHandler = class {
|
|
|
76112
76492
|
getBrowserDirectory(query = this.currentQuery) {
|
|
76113
76493
|
if (this.isPath(query)) {
|
|
76114
76494
|
const resolvedPath = resolvePath2(query);
|
|
76115
|
-
if (
|
|
76495
|
+
if (fs26.existsSync(resolvedPath) && fs26.statSync(resolvedPath).isDirectory()) {
|
|
76116
76496
|
return resolvedPath;
|
|
76117
76497
|
}
|
|
76118
|
-
return
|
|
76498
|
+
return path28.dirname(resolvedPath);
|
|
76119
76499
|
}
|
|
76120
76500
|
return this.browsingDirectory;
|
|
76121
76501
|
}
|
|
@@ -76202,8 +76582,8 @@ async function initializeFileManager(host) {
|
|
|
76202
76582
|
sessionId,
|
|
76203
76583
|
platform: platform2,
|
|
76204
76584
|
apiKey: host.options.apiKey,
|
|
76205
|
-
baseDir:
|
|
76206
|
-
sessionsDir:
|
|
76585
|
+
baseDir: path29.join(host.options.configDir, "files"),
|
|
76586
|
+
sessionsDir: path29.join(host.options.configDir, "sessions")
|
|
76207
76587
|
});
|
|
76208
76588
|
switch (getFileManagerAdapterKind(platform2)) {
|
|
76209
76589
|
case "kimi":
|
|
@@ -76483,13 +76863,13 @@ function convertPreparedAttachmentItems(items) {
|
|
|
76483
76863
|
break;
|
|
76484
76864
|
case "image": {
|
|
76485
76865
|
if (!item.data && !item.path) return void 0;
|
|
76486
|
-
const data = item.data ??
|
|
76866
|
+
const data = item.data ?? fs27.readFileSync(item.path, "base64");
|
|
76487
76867
|
converted.push({ type: "image", data, mimeType: item.mimeType });
|
|
76488
76868
|
break;
|
|
76489
76869
|
}
|
|
76490
76870
|
case "video": {
|
|
76491
76871
|
if (!item.data && !item.path) return void 0;
|
|
76492
|
-
const data = item.data ??
|
|
76872
|
+
const data = item.data ?? fs27.readFileSync(item.path, "base64");
|
|
76493
76873
|
converted.push({ type: "video", data, mimeType: item.mimeType });
|
|
76494
76874
|
break;
|
|
76495
76875
|
}
|
|
@@ -77075,8 +77455,7 @@ async function createCliAutoCompactionResult(params) {
|
|
|
77075
77455
|
if (!activeEntryId) {
|
|
77076
77456
|
return { aborted: true };
|
|
77077
77457
|
}
|
|
77078
|
-
const
|
|
77079
|
-
const firstKeptEntryId = findFirstKeptEntryId(pathEntries);
|
|
77458
|
+
const firstKeptEntryId = findFirstKeptEntrySummaryId(params.context.sessionManager.getActiveContextSummaries());
|
|
77080
77459
|
if (!firstKeptEntryId) {
|
|
77081
77460
|
return { aborted: true };
|
|
77082
77461
|
}
|
|
@@ -77638,11 +78017,11 @@ var HierarchicalSelectorComponent = class extends Container {
|
|
|
77638
78017
|
// src/runtime/interactive-ui-helpers.ts
|
|
77639
78018
|
function showHierarchicalMenu(host, initialPath = []) {
|
|
77640
78019
|
const basePath = [...initialPath];
|
|
77641
|
-
const showAtPath = (
|
|
78020
|
+
const showAtPath = (path34) => {
|
|
77642
78021
|
host.showSelector((done) => {
|
|
77643
78022
|
const selector = new HierarchicalSelectorComponent({
|
|
77644
78023
|
tree: commandTree,
|
|
77645
|
-
path:
|
|
78024
|
+
path: path34,
|
|
77646
78025
|
basePath,
|
|
77647
78026
|
onNavigate: (newPath) => {
|
|
77648
78027
|
done();
|
|
@@ -77650,7 +78029,7 @@ function showHierarchicalMenu(host, initialPath = []) {
|
|
|
77650
78029
|
},
|
|
77651
78030
|
onSelect: async (selectedPath, node, searchArgs) => {
|
|
77652
78031
|
if (node.handler) {
|
|
77653
|
-
const args = searchArgs || (selectedPath.length >
|
|
78032
|
+
const args = searchArgs || (selectedPath.length > path34.length ? selectedPath.slice(path34.length).join(" ") : void 0);
|
|
77654
78033
|
const commandPath = "/" + selectedPath.join("/");
|
|
77655
78034
|
if (!args && host.isInteractiveCommand(commandPath)) {
|
|
77656
78035
|
done();
|
|
@@ -77904,6 +78283,18 @@ async function prepareAgentTurn(host, context) {
|
|
|
77904
78283
|
};
|
|
77905
78284
|
}
|
|
77906
78285
|
function createInteractiveAgentSessionController(host) {
|
|
78286
|
+
try {
|
|
78287
|
+
recoverInterruptedPublishes({
|
|
78288
|
+
sessionsDir: getSessionsDir(),
|
|
78289
|
+
warn: (message) => {
|
|
78290
|
+
console.warn(message);
|
|
78291
|
+
if (typeof host.appendWarningSummary === "function") {
|
|
78292
|
+
host.appendWarningSummary(message);
|
|
78293
|
+
}
|
|
78294
|
+
}
|
|
78295
|
+
});
|
|
78296
|
+
} catch {
|
|
78297
|
+
}
|
|
77907
78298
|
let retryElapsedTicker;
|
|
77908
78299
|
let retryElapsedStartedAt = 0;
|
|
77909
78300
|
const stopRetryElapsedTicker = () => {
|
|
@@ -77963,8 +78354,7 @@ function createInteractiveAgentSessionController(host) {
|
|
|
77963
78354
|
return { aborted: true };
|
|
77964
78355
|
}
|
|
77965
78356
|
if (beforeCompact?.summary) {
|
|
77966
|
-
const
|
|
77967
|
-
const firstKeptEntryId = activeEntryId ? findFirstKeptEntryId(context.sessionManager.getPathToEntry(activeEntryId)) : void 0;
|
|
78357
|
+
const firstKeptEntryId = findFirstKeptEntrySummaryId(context.sessionManager.getActiveContextSummaries());
|
|
77968
78358
|
if (!firstKeptEntryId) return { aborted: true };
|
|
77969
78359
|
return { summary: beforeCompact.summary, firstKeptEntryId };
|
|
77970
78360
|
}
|
|
@@ -78138,6 +78528,14 @@ function createInteractiveAgentSessionController(host) {
|
|
|
78138
78528
|
return;
|
|
78139
78529
|
}
|
|
78140
78530
|
host.resetFileObservationState();
|
|
78531
|
+
if (!event.result?.aborted) {
|
|
78532
|
+
host.streamingComponent = void 0;
|
|
78533
|
+
host.pendingTools.clear();
|
|
78534
|
+
host.chatContainer.clear();
|
|
78535
|
+
host.lastStatusSpacer = void 0;
|
|
78536
|
+
host.lastStatusText = void 0;
|
|
78537
|
+
host.renderMessageHistory(host.sessionManager.getMessages());
|
|
78538
|
+
}
|
|
78141
78539
|
const contextUsage = host.calculateContextUsage();
|
|
78142
78540
|
const contextWindow = host.options.model?.contextWindow ?? 0;
|
|
78143
78541
|
const contextPercent = contextWindow > 0 && contextUsage.tokens !== null ? contextUsage.tokens / contextWindow * 100 : 0;
|
|
@@ -79093,8 +79491,8 @@ async function loadInteractiveExtensions(host) {
|
|
|
79093
79491
|
host.extensionRunner.setUIContext(host.extensionUIContext);
|
|
79094
79492
|
await restoreExtensionProviderCredentials(host.options.modelRegistry);
|
|
79095
79493
|
if (process.env.PIE_VERBOSE) {
|
|
79096
|
-
for (const { path:
|
|
79097
|
-
console.error(`[Extension] Failed to load ${
|
|
79494
|
+
for (const { path: path34, error } of errors) {
|
|
79495
|
+
console.error(`[Extension] Failed to load ${path34}: ${error}`);
|
|
79098
79496
|
}
|
|
79099
79497
|
}
|
|
79100
79498
|
const extensionTools = filterEnabledTools(convertExtensionTools(extensions), host.options.settingsManager);
|
|
@@ -79464,8 +79862,8 @@ var InteractiveMode = class {
|
|
|
79464
79862
|
waitForAgentIdle() {
|
|
79465
79863
|
return this.agentSessionController.waitForIdle();
|
|
79466
79864
|
}
|
|
79467
|
-
replaceAgentMessagesAndMarkSynced(messages
|
|
79468
|
-
this.agentSessionController.replaceMessagesAndMarkSynced(messages
|
|
79865
|
+
replaceAgentMessagesAndMarkSynced(messages) {
|
|
79866
|
+
this.agentSessionController.replaceMessagesAndMarkSynced(messages);
|
|
79469
79867
|
this.lastSyncedMessageCount = this.agentSessionController.syncedMessageCount;
|
|
79470
79868
|
}
|
|
79471
79869
|
syncAgentFromActiveSession(messages) {
|
|
@@ -79493,7 +79891,7 @@ var InteractiveMode = class {
|
|
|
79493
79891
|
async init() {
|
|
79494
79892
|
const activeSession = this.sessionManager.getActiveSession();
|
|
79495
79893
|
this.thinkingLevel = resolveInitialThinkingLevel({ session: activeSession, settingsManager: this.options.settingsManager });
|
|
79496
|
-
const { Agent } = await import("./chunks/src-
|
|
79894
|
+
const { Agent } = await import("./chunks/src-SXUQ7OY6.js");
|
|
79497
79895
|
this.agent = new Agent({
|
|
79498
79896
|
initialState: {
|
|
79499
79897
|
systemPrompt: this.buildSystemPrompt(),
|
|
@@ -79603,9 +80001,9 @@ var InteractiveMode = class {
|
|
|
79603
80001
|
if (this.isProcessing) {
|
|
79604
80002
|
throw new Error("Cannot reload while a response is being processed. Wait for the turn to finish or abort it first.");
|
|
79605
80003
|
}
|
|
79606
|
-
const builtinDir =
|
|
79607
|
-
const userDir =
|
|
79608
|
-
const projectDir =
|
|
80004
|
+
const builtinDir = path30.join(getBuiltinDir(), "skills");
|
|
80005
|
+
const userDir = path30.join(os8.homedir(), ".pie", "skills");
|
|
80006
|
+
const projectDir = path30.join(this.options.cwd, ".pie", "skills");
|
|
79609
80007
|
const { skills, diagnostics } = loadSkills({
|
|
79610
80008
|
dirs: buildSkillDirs({ builtinDir, userDir, projectDir, cwd: this.options.cwd })
|
|
79611
80009
|
});
|
|
@@ -79767,7 +80165,7 @@ var InteractiveMode = class {
|
|
|
79767
80165
|
return handleResumeCommand(this);
|
|
79768
80166
|
}
|
|
79769
80167
|
async loadSession(sessionId) {
|
|
79770
|
-
return
|
|
80168
|
+
return loadSession(this, sessionId);
|
|
79771
80169
|
}
|
|
79772
80170
|
updateTerminalTitle() {
|
|
79773
80171
|
return updateTerminalTitle(this);
|
|
@@ -79908,8 +80306,8 @@ var InteractiveMode = class {
|
|
|
79908
80306
|
};
|
|
79909
80307
|
|
|
79910
80308
|
// src/app/runtime-composition.ts
|
|
79911
|
-
import { existsSync as
|
|
79912
|
-
import * as
|
|
80309
|
+
import { existsSync as existsSync19, mkdirSync as mkdirSync14 } from "fs";
|
|
80310
|
+
import * as path31 from "path";
|
|
79913
80311
|
var CliMissingApiKeyError = class extends Error {
|
|
79914
80312
|
constructor(message) {
|
|
79915
80313
|
super(message);
|
|
@@ -79930,13 +80328,13 @@ var CliSessionResumeError = class extends Error {
|
|
|
79930
80328
|
function getCliRuntimePaths() {
|
|
79931
80329
|
const configDir = getConfigDir();
|
|
79932
80330
|
const sessionsDir = getSessionsDir();
|
|
79933
|
-
const skillsDir =
|
|
79934
|
-
const builtinSkillsDir =
|
|
80331
|
+
const skillsDir = path31.join(configDir, "skills");
|
|
80332
|
+
const builtinSkillsDir = path31.join(getBuiltinDir(), "skills");
|
|
79935
80333
|
return { configDir, sessionsDir, skillsDir, builtinSkillsDir };
|
|
79936
80334
|
}
|
|
79937
80335
|
function ensureCliRuntimePaths(paths = getCliRuntimePaths()) {
|
|
79938
|
-
if (!
|
|
79939
|
-
|
|
80336
|
+
if (!existsSync19(paths.skillsDir)) {
|
|
80337
|
+
mkdirSync14(paths.skillsDir, { recursive: true });
|
|
79940
80338
|
}
|
|
79941
80339
|
return paths;
|
|
79942
80340
|
}
|
|
@@ -80051,7 +80449,7 @@ async function composeCliRuntime(params) {
|
|
|
80051
80449
|
fileLogger.log("cli", `Using API key for provider ${provider}`, {
|
|
80052
80450
|
keyPrefix: apiKey ? maskApiKey2(apiKey) : "none"
|
|
80053
80451
|
});
|
|
80054
|
-
const projectSkillsDir =
|
|
80452
|
+
const projectSkillsDir = path31.join(cwd, ".pie", "skills");
|
|
80055
80453
|
const { skills: discoveredSkills, diagnostics } = loadSkills({
|
|
80056
80454
|
dirs: buildSkillDirs({
|
|
80057
80455
|
builtinDir: paths.builtinSkillsDir,
|
|
@@ -80326,7 +80724,7 @@ async function runPrintMode(params) {
|
|
|
80326
80724
|
`);
|
|
80327
80725
|
console.log("Assistant: ");
|
|
80328
80726
|
}
|
|
80329
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
80727
|
+
const { Agent: AgentClass } = await import("./chunks/src-SXUQ7OY6.js");
|
|
80330
80728
|
let agent;
|
|
80331
80729
|
const printModeExtensions = await loadPrintModeExtensions({
|
|
80332
80730
|
cwd: runtime.cwd,
|
|
@@ -80414,7 +80812,7 @@ async function runPrintMode(params) {
|
|
|
80414
80812
|
if (beforeCompact.cancel) return { aborted: true };
|
|
80415
80813
|
if (beforeCompact.summary) {
|
|
80416
80814
|
const activeEntryId = context.sessionManager.getActiveEntryId();
|
|
80417
|
-
const firstKeptEntryId = activeEntryId ?
|
|
80815
|
+
const firstKeptEntryId = activeEntryId ? findFirstKeptEntrySummaryId(context.sessionManager.getActiveContextSummaries()) : void 0;
|
|
80418
80816
|
if (!firstKeptEntryId) return { aborted: true };
|
|
80419
80817
|
return { summary: beforeCompact.summary, firstKeptEntryId };
|
|
80420
80818
|
}
|
|
@@ -80804,6 +81202,7 @@ async function runJsonEventsMode(params) {
|
|
|
80804
81202
|
let thinkingLevelInitialized = false;
|
|
80805
81203
|
let defaultRuntime;
|
|
80806
81204
|
let defaultModelState;
|
|
81205
|
+
let publishRecoveryDone = false;
|
|
80807
81206
|
const completedSessionControlRequests = /* @__PURE__ */ new Map();
|
|
80808
81207
|
const completedSidechatRequests = /* @__PURE__ */ new Map();
|
|
80809
81208
|
const ensureRuntimeInFlight = /* @__PURE__ */ new Map();
|
|
@@ -80893,12 +81292,22 @@ async function runJsonEventsMode(params) {
|
|
|
80893
81292
|
metadata.rootEntryId = existing?.rootEntryId ?? rootEntryId;
|
|
80894
81293
|
return metadata;
|
|
80895
81294
|
}
|
|
80896
|
-
|
|
81295
|
+
function persistMockTurn(message, assistantText) {
|
|
80897
81296
|
const store = new FileSessionStore(getSessionsDir());
|
|
80898
|
-
const
|
|
81297
|
+
const targetSessionId = message.sessionId ?? sessionId;
|
|
81298
|
+
const status = store.headStatus(targetSessionId);
|
|
81299
|
+
if (status === "legacy") {
|
|
81300
|
+
throw new SessionControlError("session_unsupported_format", `Session uses an unsupported old format: ${targetSessionId}`);
|
|
81301
|
+
}
|
|
81302
|
+
if (status === "corrupt") {
|
|
81303
|
+
throw new SessionControlError("session_unrecoverable", `Session could not be recovered: ${targetSessionId}`);
|
|
81304
|
+
}
|
|
81305
|
+
const existing = store.readHead(targetSessionId);
|
|
81306
|
+
if (existing) store.createHead(targetSessionId, { name: void 0, createdAt: existing.metadata.createdAt });
|
|
80899
81307
|
const startedAt = activeTurn?.startedAt ?? Date.now();
|
|
80900
|
-
const
|
|
80901
|
-
const
|
|
81308
|
+
const baseSeq = existing?.committedSeq ?? store.readHead(targetSessionId)?.committedSeq ?? 0;
|
|
81309
|
+
const userEntryId = generateEntryId(baseSeq + 1);
|
|
81310
|
+
const assistantEntryId = generateEntryId(baseSeq + 2);
|
|
80902
81311
|
const parentId = existing?.metadata.activeEntryId ?? null;
|
|
80903
81312
|
const userEntry = {
|
|
80904
81313
|
id: userEntryId,
|
|
@@ -80936,10 +81345,13 @@ async function runJsonEventsMode(params) {
|
|
|
80936
81345
|
timestamp: assistantTimestamp,
|
|
80937
81346
|
message: assistantMessage
|
|
80938
81347
|
};
|
|
80939
|
-
|
|
80940
|
-
|
|
80941
|
-
|
|
80942
|
-
|
|
81348
|
+
if (!existing) {
|
|
81349
|
+
store.createHead(targetSessionId);
|
|
81350
|
+
}
|
|
81351
|
+
store.appendEntries(
|
|
81352
|
+
targetSessionId,
|
|
81353
|
+
[userEntry, assistantEntry],
|
|
81354
|
+
assistantEntryId,
|
|
80943
81355
|
persistedMockMetadata(existing?.metadata, assistantEntryId, existing?.metadata.rootEntryId ?? userEntryId, message.cwd)
|
|
80944
81356
|
);
|
|
80945
81357
|
return assistantEntryId;
|
|
@@ -80962,7 +81374,7 @@ async function runJsonEventsMode(params) {
|
|
|
80962
81374
|
};
|
|
80963
81375
|
}
|
|
80964
81376
|
function errorToFailureDetail(error) {
|
|
80965
|
-
if (error instanceof CliSessionResumeError) {
|
|
81377
|
+
if (error instanceof CliSessionResumeError || error instanceof SessionControlError) {
|
|
80966
81378
|
return {
|
|
80967
81379
|
message: error.message,
|
|
80968
81380
|
code: error.code,
|
|
@@ -80972,7 +81384,10 @@ async function runJsonEventsMode(params) {
|
|
|
80972
81384
|
return error instanceof Error ? error.message : String(error);
|
|
80973
81385
|
}
|
|
80974
81386
|
function sessionControlStore() {
|
|
80975
|
-
return new FileSessionStore(
|
|
81387
|
+
return new FileSessionStore(sessionControlSessionsDir());
|
|
81388
|
+
}
|
|
81389
|
+
function sessionControlSessionsDir() {
|
|
81390
|
+
return runtime?.paths.sessionsDir ?? getSessionsDir();
|
|
80976
81391
|
}
|
|
80977
81392
|
function invalidSessionControl(message) {
|
|
80978
81393
|
return new SessionControlError("invalid_request", message);
|
|
@@ -81081,6 +81496,7 @@ async function runJsonEventsMode(params) {
|
|
|
81081
81496
|
await saveRuntimeSessionForControl();
|
|
81082
81497
|
const result = await forkStoredSession({
|
|
81083
81498
|
store: sessionControlStore(),
|
|
81499
|
+
sessionsDir: sessionControlSessionsDir(),
|
|
81084
81500
|
sourceSessionId: controlSessionId,
|
|
81085
81501
|
sourceEntryId,
|
|
81086
81502
|
targetSessionId,
|
|
@@ -81168,7 +81584,7 @@ async function runJsonEventsMode(params) {
|
|
|
81168
81584
|
return;
|
|
81169
81585
|
}
|
|
81170
81586
|
const parent = agent;
|
|
81171
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
81587
|
+
const { Agent: AgentClass } = await import("./chunks/src-SXUQ7OY6.js");
|
|
81172
81588
|
const sideAgent = new AgentClass({
|
|
81173
81589
|
initialState: {
|
|
81174
81590
|
systemPrompt: parent.state.systemPrompt,
|
|
@@ -81495,6 +81911,16 @@ async function runJsonEventsMode(params) {
|
|
|
81495
81911
|
if (!runtime) {
|
|
81496
81912
|
throw new Error("JSON events mode requires a CLI runtime");
|
|
81497
81913
|
}
|
|
81914
|
+
if (!publishRecoveryDone) {
|
|
81915
|
+
publishRecoveryDone = true;
|
|
81916
|
+
try {
|
|
81917
|
+
recoverInterruptedPublishes({
|
|
81918
|
+
sessionsDir: runtime.paths.sessionsDir ?? getSessionsDir(),
|
|
81919
|
+
warn: (message) => console.warn(message)
|
|
81920
|
+
});
|
|
81921
|
+
} catch {
|
|
81922
|
+
}
|
|
81923
|
+
}
|
|
81498
81924
|
if (defaultRuntime !== runtime) {
|
|
81499
81925
|
defaultRuntime = runtime;
|
|
81500
81926
|
defaultModelState = configuredDefaultModelState(runtime);
|
|
@@ -81502,7 +81928,7 @@ async function runJsonEventsMode(params) {
|
|
|
81502
81928
|
if (runtime.initialModel.unconfigured || controller) {
|
|
81503
81929
|
return;
|
|
81504
81930
|
}
|
|
81505
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
81931
|
+
const { Agent: AgentClass } = await import("./chunks/src-SXUQ7OY6.js");
|
|
81506
81932
|
const jsonModeExtensions = await loadJsonModeExtensions({ runtime, getAgent: () => agent });
|
|
81507
81933
|
extensionRunner = jsonModeExtensions.runner;
|
|
81508
81934
|
const tools = [...runtime.tools, ...jsonModeExtensions.extensionTools];
|
|
@@ -81695,9 +82121,9 @@ async function runJsonEventsMode(params) {
|
|
|
81695
82121
|
}
|
|
81696
82122
|
display(params.mockResponse);
|
|
81697
82123
|
try {
|
|
81698
|
-
mockActiveEntryId =
|
|
82124
|
+
mockActiveEntryId = persistMockTurn(message, params.mockResponse);
|
|
81699
82125
|
} catch (error) {
|
|
81700
|
-
finalize("failed",
|
|
82126
|
+
finalize("failed", errorToFailureDetail(error));
|
|
81701
82127
|
if (activeTurn === turn) emitSettled(turn);
|
|
81702
82128
|
if (activeTurn === turn) activeTurn = null;
|
|
81703
82129
|
return;
|
|
@@ -81965,19 +82391,19 @@ async function runJsonEventsMode(params) {
|
|
|
81965
82391
|
}
|
|
81966
82392
|
|
|
81967
82393
|
// src/developer-instructions.ts
|
|
81968
|
-
import * as
|
|
81969
|
-
import * as
|
|
82394
|
+
import * as fs28 from "fs";
|
|
82395
|
+
import * as path32 from "path";
|
|
81970
82396
|
var MAX_DEVELOPER_INSTRUCTIONS_CHARS = 64e3;
|
|
81971
82397
|
function readTextFileBounded(filePath) {
|
|
81972
|
-
const resolved =
|
|
81973
|
-
const stat2 =
|
|
82398
|
+
const resolved = path32.resolve(filePath);
|
|
82399
|
+
const stat2 = fs28.statSync(resolved);
|
|
81974
82400
|
if (!stat2.isFile()) {
|
|
81975
82401
|
throw new Error(`Developer instructions file is not a regular file: ${filePath}`);
|
|
81976
82402
|
}
|
|
81977
82403
|
if (stat2.size > MAX_DEVELOPER_INSTRUCTIONS_CHARS * 4) {
|
|
81978
82404
|
throw new Error(`Developer instructions file is too large: ${filePath}`);
|
|
81979
82405
|
}
|
|
81980
|
-
return
|
|
82406
|
+
return fs28.readFileSync(resolved, "utf8");
|
|
81981
82407
|
}
|
|
81982
82408
|
function collectFlagValues(args, flag) {
|
|
81983
82409
|
const values = [];
|
|
@@ -82056,8 +82482,8 @@ var logError = (msg, err) => {
|
|
|
82056
82482
|
const logPath = getRuntimeLogPath();
|
|
82057
82483
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
82058
82484
|
const stack = err instanceof Error ? err.stack || "" : "";
|
|
82059
|
-
|
|
82060
|
-
|
|
82485
|
+
fs29.mkdirSync(path33.dirname(logPath), { recursive: true });
|
|
82486
|
+
fs29.appendFileSync(logPath, `[${timestamp}] ${msg}
|
|
82061
82487
|
${stack}
|
|
82062
82488
|
|
|
82063
82489
|
`);
|
|
@@ -82091,7 +82517,7 @@ async function runWithJsonEventsConsoleIsolation(fn) {
|
|
|
82091
82517
|
}
|
|
82092
82518
|
async function createCliTestStreamFnFromEnv() {
|
|
82093
82519
|
if (!process.env.PIE_TEST_MOCK_STREAM_SEQUENCE) return void 0;
|
|
82094
|
-
return (await import("./chunks/test-stream-
|
|
82520
|
+
return (await import("./chunks/test-stream-OD3B57AS.js")).createTestStreamFnFromSequenceEnv();
|
|
82095
82521
|
}
|
|
82096
82522
|
function resolveJsonEventsDetailFlag() {
|
|
82097
82523
|
for (let index = 0; index < process.argv.length; index += 1) {
|