@prestyj/boss 4.10.1 → 4.12.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/README.md +4 -4
- package/dist/{chunk-72J6ZGVA.js → chunk-HYXLQEZL.js} +2294 -522
- package/dist/{chunk-72J6ZGVA.js.map → chunk-HYXLQEZL.js.map} +1 -1
- package/dist/cli.js +27 -266
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +5 -5
|
@@ -3225,8 +3225,8 @@ var require_utils = __commonJS({
|
|
|
3225
3225
|
}
|
|
3226
3226
|
return ind;
|
|
3227
3227
|
}
|
|
3228
|
-
function removeDotSegments(
|
|
3229
|
-
let input =
|
|
3228
|
+
function removeDotSegments(path49) {
|
|
3229
|
+
let input = path49;
|
|
3230
3230
|
const output = [];
|
|
3231
3231
|
let nextSlash = -1;
|
|
3232
3232
|
let len = 0;
|
|
@@ -3426,8 +3426,8 @@ var require_schemes = __commonJS({
|
|
|
3426
3426
|
wsComponent.secure = void 0;
|
|
3427
3427
|
}
|
|
3428
3428
|
if (wsComponent.resourceName) {
|
|
3429
|
-
const [
|
|
3430
|
-
wsComponent.path =
|
|
3429
|
+
const [path49, query] = wsComponent.resourceName.split("?");
|
|
3430
|
+
wsComponent.path = path49 && path49 !== "/" ? path49 : void 0;
|
|
3431
3431
|
wsComponent.query = query;
|
|
3432
3432
|
wsComponent.resourceName = void 0;
|
|
3433
3433
|
}
|
|
@@ -3486,7 +3486,7 @@ var require_schemes = __commonJS({
|
|
|
3486
3486
|
urnComponent.nss = (uuidComponent.uuid || "").toLowerCase();
|
|
3487
3487
|
return urnComponent;
|
|
3488
3488
|
}
|
|
3489
|
-
var
|
|
3489
|
+
var http2 = (
|
|
3490
3490
|
/** @type {SchemeHandler} */
|
|
3491
3491
|
{
|
|
3492
3492
|
scheme: "http",
|
|
@@ -3499,7 +3499,7 @@ var require_schemes = __commonJS({
|
|
|
3499
3499
|
/** @type {SchemeHandler} */
|
|
3500
3500
|
{
|
|
3501
3501
|
scheme: "https",
|
|
3502
|
-
domainHost:
|
|
3502
|
+
domainHost: http2.domainHost,
|
|
3503
3503
|
parse: httpParse,
|
|
3504
3504
|
serialize: httpSerialize
|
|
3505
3505
|
}
|
|
@@ -3543,7 +3543,7 @@ var require_schemes = __commonJS({
|
|
|
3543
3543
|
var SCHEMES = (
|
|
3544
3544
|
/** @type {Record<SchemeName, SchemeHandler>} */
|
|
3545
3545
|
{
|
|
3546
|
-
http,
|
|
3546
|
+
http: http2,
|
|
3547
3547
|
https,
|
|
3548
3548
|
ws,
|
|
3549
3549
|
wss,
|
|
@@ -6835,12 +6835,12 @@ var require_dist = __commonJS({
|
|
|
6835
6835
|
throw new Error(`Unknown format "${name}"`);
|
|
6836
6836
|
return f;
|
|
6837
6837
|
};
|
|
6838
|
-
function addFormats(ajv, list,
|
|
6838
|
+
function addFormats(ajv, list, fs40, exportName) {
|
|
6839
6839
|
var _a6;
|
|
6840
6840
|
var _b;
|
|
6841
6841
|
(_a6 = (_b = ajv.opts.code).formats) !== null && _a6 !== void 0 ? _a6 : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
6842
6842
|
for (const f of list)
|
|
6843
|
-
ajv.addFormat(f,
|
|
6843
|
+
ajv.addFormat(f, fs40[f]);
|
|
6844
6844
|
}
|
|
6845
6845
|
module.exports = exports = formatsPlugin;
|
|
6846
6846
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -6855,8 +6855,8 @@ var require_windows = __commonJS({
|
|
|
6855
6855
|
init_esm_shims();
|
|
6856
6856
|
module.exports = isexe;
|
|
6857
6857
|
isexe.sync = sync;
|
|
6858
|
-
var
|
|
6859
|
-
function checkPathExt(
|
|
6858
|
+
var fs40 = __require("fs");
|
|
6859
|
+
function checkPathExt(path49, options) {
|
|
6860
6860
|
var pathext = options.pathExt !== void 0 ? options.pathExt : process.env.PATHEXT;
|
|
6861
6861
|
if (!pathext) {
|
|
6862
6862
|
return true;
|
|
@@ -6867,25 +6867,25 @@ var require_windows = __commonJS({
|
|
|
6867
6867
|
}
|
|
6868
6868
|
for (var i = 0; i < pathext.length; i++) {
|
|
6869
6869
|
var p = pathext[i].toLowerCase();
|
|
6870
|
-
if (p &&
|
|
6870
|
+
if (p && path49.substr(-p.length).toLowerCase() === p) {
|
|
6871
6871
|
return true;
|
|
6872
6872
|
}
|
|
6873
6873
|
}
|
|
6874
6874
|
return false;
|
|
6875
6875
|
}
|
|
6876
|
-
function checkStat(stat,
|
|
6876
|
+
function checkStat(stat, path49, options) {
|
|
6877
6877
|
if (!stat.isSymbolicLink() && !stat.isFile()) {
|
|
6878
6878
|
return false;
|
|
6879
6879
|
}
|
|
6880
|
-
return checkPathExt(
|
|
6880
|
+
return checkPathExt(path49, options);
|
|
6881
6881
|
}
|
|
6882
|
-
function isexe(
|
|
6883
|
-
|
|
6884
|
-
cb(er, er ? false : checkStat(stat,
|
|
6882
|
+
function isexe(path49, options, cb) {
|
|
6883
|
+
fs40.stat(path49, function(er, stat) {
|
|
6884
|
+
cb(er, er ? false : checkStat(stat, path49, options));
|
|
6885
6885
|
});
|
|
6886
6886
|
}
|
|
6887
|
-
function sync(
|
|
6888
|
-
return checkStat(
|
|
6887
|
+
function sync(path49, options) {
|
|
6888
|
+
return checkStat(fs40.statSync(path49), path49, options);
|
|
6889
6889
|
}
|
|
6890
6890
|
}
|
|
6891
6891
|
});
|
|
@@ -6897,14 +6897,14 @@ var require_mode = __commonJS({
|
|
|
6897
6897
|
init_esm_shims();
|
|
6898
6898
|
module.exports = isexe;
|
|
6899
6899
|
isexe.sync = sync;
|
|
6900
|
-
var
|
|
6901
|
-
function isexe(
|
|
6902
|
-
|
|
6900
|
+
var fs40 = __require("fs");
|
|
6901
|
+
function isexe(path49, options, cb) {
|
|
6902
|
+
fs40.stat(path49, function(er, stat) {
|
|
6903
6903
|
cb(er, er ? false : checkStat(stat, options));
|
|
6904
6904
|
});
|
|
6905
6905
|
}
|
|
6906
|
-
function sync(
|
|
6907
|
-
return checkStat(
|
|
6906
|
+
function sync(path49, options) {
|
|
6907
|
+
return checkStat(fs40.statSync(path49), options);
|
|
6908
6908
|
}
|
|
6909
6909
|
function checkStat(stat, options) {
|
|
6910
6910
|
return stat.isFile() && checkMode(stat, options);
|
|
@@ -6930,7 +6930,7 @@ var require_isexe = __commonJS({
|
|
|
6930
6930
|
"../../node_modules/.pnpm/isexe@2.0.0/node_modules/isexe/index.js"(exports, module) {
|
|
6931
6931
|
"use strict";
|
|
6932
6932
|
init_esm_shims();
|
|
6933
|
-
var
|
|
6933
|
+
var fs40 = __require("fs");
|
|
6934
6934
|
var core;
|
|
6935
6935
|
if (process.platform === "win32" || global.TESTING_WINDOWS) {
|
|
6936
6936
|
core = require_windows();
|
|
@@ -6939,7 +6939,7 @@ var require_isexe = __commonJS({
|
|
|
6939
6939
|
}
|
|
6940
6940
|
module.exports = isexe;
|
|
6941
6941
|
isexe.sync = sync;
|
|
6942
|
-
function isexe(
|
|
6942
|
+
function isexe(path49, options, cb) {
|
|
6943
6943
|
if (typeof options === "function") {
|
|
6944
6944
|
cb = options;
|
|
6945
6945
|
options = {};
|
|
@@ -6949,7 +6949,7 @@ var require_isexe = __commonJS({
|
|
|
6949
6949
|
throw new TypeError("callback not provided");
|
|
6950
6950
|
}
|
|
6951
6951
|
return new Promise(function(resolve3, reject) {
|
|
6952
|
-
isexe(
|
|
6952
|
+
isexe(path49, options || {}, function(er, is) {
|
|
6953
6953
|
if (er) {
|
|
6954
6954
|
reject(er);
|
|
6955
6955
|
} else {
|
|
@@ -6958,7 +6958,7 @@ var require_isexe = __commonJS({
|
|
|
6958
6958
|
});
|
|
6959
6959
|
});
|
|
6960
6960
|
}
|
|
6961
|
-
core(
|
|
6961
|
+
core(path49, options || {}, function(er, is) {
|
|
6962
6962
|
if (er) {
|
|
6963
6963
|
if (er.code === "EACCES" || options && options.ignoreErrors) {
|
|
6964
6964
|
er = null;
|
|
@@ -6968,9 +6968,9 @@ var require_isexe = __commonJS({
|
|
|
6968
6968
|
cb(er, is);
|
|
6969
6969
|
});
|
|
6970
6970
|
}
|
|
6971
|
-
function sync(
|
|
6971
|
+
function sync(path49, options) {
|
|
6972
6972
|
try {
|
|
6973
|
-
return core.sync(
|
|
6973
|
+
return core.sync(path49, options || {});
|
|
6974
6974
|
} catch (er) {
|
|
6975
6975
|
if (options && options.ignoreErrors || er.code === "EACCES") {
|
|
6976
6976
|
return false;
|
|
@@ -6988,7 +6988,7 @@ var require_which = __commonJS({
|
|
|
6988
6988
|
"use strict";
|
|
6989
6989
|
init_esm_shims();
|
|
6990
6990
|
var isWindows3 = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
|
|
6991
|
-
var
|
|
6991
|
+
var path49 = __require("path");
|
|
6992
6992
|
var COLON = isWindows3 ? ";" : ":";
|
|
6993
6993
|
var isexe = require_isexe();
|
|
6994
6994
|
var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
|
|
@@ -7026,7 +7026,7 @@ var require_which = __commonJS({
|
|
|
7026
7026
|
return opt.all && found.length ? resolve3(found) : reject(getNotFoundError(cmd));
|
|
7027
7027
|
const ppRaw = pathEnv[i];
|
|
7028
7028
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
7029
|
-
const pCmd =
|
|
7029
|
+
const pCmd = path49.join(pathPart, cmd);
|
|
7030
7030
|
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
7031
7031
|
resolve3(subStep(p, i, 0));
|
|
7032
7032
|
});
|
|
@@ -7053,7 +7053,7 @@ var require_which = __commonJS({
|
|
|
7053
7053
|
for (let i = 0; i < pathEnv.length; i++) {
|
|
7054
7054
|
const ppRaw = pathEnv[i];
|
|
7055
7055
|
const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
|
|
7056
|
-
const pCmd =
|
|
7056
|
+
const pCmd = path49.join(pathPart, cmd);
|
|
7057
7057
|
const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
|
|
7058
7058
|
for (let j = 0; j < pathExt.length; j++) {
|
|
7059
7059
|
const cur = p + pathExt[j];
|
|
@@ -7103,7 +7103,7 @@ var require_resolveCommand = __commonJS({
|
|
|
7103
7103
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/resolveCommand.js"(exports, module) {
|
|
7104
7104
|
"use strict";
|
|
7105
7105
|
init_esm_shims();
|
|
7106
|
-
var
|
|
7106
|
+
var path49 = __require("path");
|
|
7107
7107
|
var which = require_which();
|
|
7108
7108
|
var getPathKey = require_path_key();
|
|
7109
7109
|
function resolveCommandAttempt(parsed, withoutPathExt) {
|
|
@@ -7121,7 +7121,7 @@ var require_resolveCommand = __commonJS({
|
|
|
7121
7121
|
try {
|
|
7122
7122
|
resolved = which.sync(parsed.command, {
|
|
7123
7123
|
path: env2[getPathKey({ env: env2 })],
|
|
7124
|
-
pathExt: withoutPathExt ?
|
|
7124
|
+
pathExt: withoutPathExt ? path49.delimiter : void 0
|
|
7125
7125
|
});
|
|
7126
7126
|
} catch (e) {
|
|
7127
7127
|
} finally {
|
|
@@ -7130,7 +7130,7 @@ var require_resolveCommand = __commonJS({
|
|
|
7130
7130
|
}
|
|
7131
7131
|
}
|
|
7132
7132
|
if (resolved) {
|
|
7133
|
-
resolved =
|
|
7133
|
+
resolved = path49.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
|
|
7134
7134
|
}
|
|
7135
7135
|
return resolved;
|
|
7136
7136
|
}
|
|
@@ -7187,8 +7187,8 @@ var require_shebang_command = __commonJS({
|
|
|
7187
7187
|
if (!match) {
|
|
7188
7188
|
return null;
|
|
7189
7189
|
}
|
|
7190
|
-
const [
|
|
7191
|
-
const binary =
|
|
7190
|
+
const [path49, argument] = match[0].replace(/#! ?/, "").split(" ");
|
|
7191
|
+
const binary = path49.split("/").pop();
|
|
7192
7192
|
if (binary === "env") {
|
|
7193
7193
|
return argument;
|
|
7194
7194
|
}
|
|
@@ -7202,16 +7202,16 @@ var require_readShebang = __commonJS({
|
|
|
7202
7202
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/util/readShebang.js"(exports, module) {
|
|
7203
7203
|
"use strict";
|
|
7204
7204
|
init_esm_shims();
|
|
7205
|
-
var
|
|
7205
|
+
var fs40 = __require("fs");
|
|
7206
7206
|
var shebangCommand = require_shebang_command();
|
|
7207
7207
|
function readShebang(command) {
|
|
7208
7208
|
const size = 150;
|
|
7209
7209
|
const buffer = Buffer.alloc(size);
|
|
7210
7210
|
let fd2;
|
|
7211
7211
|
try {
|
|
7212
|
-
fd2 =
|
|
7213
|
-
|
|
7214
|
-
|
|
7212
|
+
fd2 = fs40.openSync(command, "r");
|
|
7213
|
+
fs40.readSync(fd2, buffer, 0, size, 0);
|
|
7214
|
+
fs40.closeSync(fd2);
|
|
7215
7215
|
} catch (e) {
|
|
7216
7216
|
}
|
|
7217
7217
|
return shebangCommand(buffer.toString());
|
|
@@ -7225,7 +7225,7 @@ var require_parse = __commonJS({
|
|
|
7225
7225
|
"../../node_modules/.pnpm/cross-spawn@7.0.6/node_modules/cross-spawn/lib/parse.js"(exports, module) {
|
|
7226
7226
|
"use strict";
|
|
7227
7227
|
init_esm_shims();
|
|
7228
|
-
var
|
|
7228
|
+
var path49 = __require("path");
|
|
7229
7229
|
var resolveCommand = require_resolveCommand();
|
|
7230
7230
|
var escape4 = require_escape();
|
|
7231
7231
|
var readShebang = require_readShebang();
|
|
@@ -7250,7 +7250,7 @@ var require_parse = __commonJS({
|
|
|
7250
7250
|
const needsShell = !isExecutableRegExp.test(commandFile);
|
|
7251
7251
|
if (parsed.options.forceShell || needsShell) {
|
|
7252
7252
|
const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
|
|
7253
|
-
parsed.command =
|
|
7253
|
+
parsed.command = path49.normalize(parsed.command);
|
|
7254
7254
|
parsed.command = escape4.command(parsed.command);
|
|
7255
7255
|
parsed.args = parsed.args.map((arg) => escape4.argument(arg, needsDoubleEscapeMetaChars));
|
|
7256
7256
|
const shellCommand = [parsed.command].concat(parsed.args).join(" ");
|
|
@@ -17765,10 +17765,10 @@ var require_react_reconciler_development = __commonJS({
|
|
|
17765
17765
|
fiber = fiber.next, id2--;
|
|
17766
17766
|
return fiber;
|
|
17767
17767
|
}
|
|
17768
|
-
function copyWithSetImpl(obj,
|
|
17769
|
-
if (index >=
|
|
17770
|
-
var key =
|
|
17771
|
-
updated[key] = copyWithSetImpl(obj[key],
|
|
17768
|
+
function copyWithSetImpl(obj, path49, index, value) {
|
|
17769
|
+
if (index >= path49.length) return value;
|
|
17770
|
+
var key = path49[index], updated = isArrayImpl(obj) ? obj.slice() : assign({}, obj);
|
|
17771
|
+
updated[key] = copyWithSetImpl(obj[key], path49, index + 1, value);
|
|
17772
17772
|
return updated;
|
|
17773
17773
|
}
|
|
17774
17774
|
function copyWithRename(obj, oldPath, newPath) {
|
|
@@ -17795,11 +17795,11 @@ var require_react_reconciler_development = __commonJS({
|
|
|
17795
17795
|
);
|
|
17796
17796
|
return updated;
|
|
17797
17797
|
}
|
|
17798
|
-
function copyWithDeleteImpl(obj,
|
|
17799
|
-
var key =
|
|
17800
|
-
if (index + 1 ===
|
|
17798
|
+
function copyWithDeleteImpl(obj, path49, index) {
|
|
17799
|
+
var key = path49[index], updated = isArrayImpl(obj) ? obj.slice() : assign({}, obj);
|
|
17800
|
+
if (index + 1 === path49.length)
|
|
17801
17801
|
return isArrayImpl(updated) ? updated.splice(key, 1) : delete updated[key], updated;
|
|
17802
|
-
updated[key] = copyWithDeleteImpl(obj[key],
|
|
17802
|
+
updated[key] = copyWithDeleteImpl(obj[key], path49, index + 1);
|
|
17803
17803
|
return updated;
|
|
17804
17804
|
}
|
|
17805
17805
|
function shouldSuspendImpl() {
|
|
@@ -31076,29 +31076,29 @@ var require_react_reconciler_development = __commonJS({
|
|
|
31076
31076
|
var didWarnAboutNestedUpdates = false;
|
|
31077
31077
|
var didWarnAboutFindNodeInStrictMode = {};
|
|
31078
31078
|
var overrideHookState = null, overrideHookStateDeletePath = null, overrideHookStateRenamePath = null, overrideProps = null, overridePropsDeletePath = null, overridePropsRenamePath = null, scheduleUpdate = null, scheduleRetry = null, setErrorHandler = null, setSuspenseHandler = null;
|
|
31079
|
-
overrideHookState = function(fiber, id2,
|
|
31079
|
+
overrideHookState = function(fiber, id2, path49, value) {
|
|
31080
31080
|
id2 = findHook(fiber, id2);
|
|
31081
|
-
null !== id2 && (
|
|
31081
|
+
null !== id2 && (path49 = copyWithSetImpl(id2.memoizedState, path49, 0, value), id2.memoizedState = path49, id2.baseState = path49, fiber.memoizedProps = assign({}, fiber.memoizedProps), path49 = enqueueConcurrentRenderForLane(fiber, 2), null !== path49 && scheduleUpdateOnFiber(path49, fiber, 2));
|
|
31082
31082
|
};
|
|
31083
|
-
overrideHookStateDeletePath = function(fiber, id2,
|
|
31083
|
+
overrideHookStateDeletePath = function(fiber, id2, path49) {
|
|
31084
31084
|
id2 = findHook(fiber, id2);
|
|
31085
|
-
null !== id2 && (
|
|
31085
|
+
null !== id2 && (path49 = copyWithDeleteImpl(id2.memoizedState, path49, 0), id2.memoizedState = path49, id2.baseState = path49, fiber.memoizedProps = assign({}, fiber.memoizedProps), path49 = enqueueConcurrentRenderForLane(fiber, 2), null !== path49 && scheduleUpdateOnFiber(path49, fiber, 2));
|
|
31086
31086
|
};
|
|
31087
31087
|
overrideHookStateRenamePath = function(fiber, id2, oldPath, newPath) {
|
|
31088
31088
|
id2 = findHook(fiber, id2);
|
|
31089
31089
|
null !== id2 && (oldPath = copyWithRename(id2.memoizedState, oldPath, newPath), id2.memoizedState = oldPath, id2.baseState = oldPath, fiber.memoizedProps = assign({}, fiber.memoizedProps), oldPath = enqueueConcurrentRenderForLane(fiber, 2), null !== oldPath && scheduleUpdateOnFiber(oldPath, fiber, 2));
|
|
31090
31090
|
};
|
|
31091
|
-
overrideProps = function(fiber,
|
|
31092
|
-
fiber.pendingProps = copyWithSetImpl(fiber.memoizedProps,
|
|
31091
|
+
overrideProps = function(fiber, path49, value) {
|
|
31092
|
+
fiber.pendingProps = copyWithSetImpl(fiber.memoizedProps, path49, 0, value);
|
|
31093
31093
|
fiber.alternate && (fiber.alternate.pendingProps = fiber.pendingProps);
|
|
31094
|
-
|
|
31095
|
-
null !==
|
|
31094
|
+
path49 = enqueueConcurrentRenderForLane(fiber, 2);
|
|
31095
|
+
null !== path49 && scheduleUpdateOnFiber(path49, fiber, 2);
|
|
31096
31096
|
};
|
|
31097
|
-
overridePropsDeletePath = function(fiber,
|
|
31098
|
-
fiber.pendingProps = copyWithDeleteImpl(fiber.memoizedProps,
|
|
31097
|
+
overridePropsDeletePath = function(fiber, path49) {
|
|
31098
|
+
fiber.pendingProps = copyWithDeleteImpl(fiber.memoizedProps, path49, 0);
|
|
31099
31099
|
fiber.alternate && (fiber.alternate.pendingProps = fiber.pendingProps);
|
|
31100
|
-
|
|
31101
|
-
null !==
|
|
31100
|
+
path49 = enqueueConcurrentRenderForLane(fiber, 2);
|
|
31101
|
+
null !== path49 && scheduleUpdateOnFiber(path49, fiber, 2);
|
|
31102
31102
|
};
|
|
31103
31103
|
overridePropsRenamePath = function(fiber, oldPath, newPath) {
|
|
31104
31104
|
fiber.pendingProps = copyWithRename(
|
|
@@ -33840,13 +33840,13 @@ function __classPrivateFieldGet(receiver, state3, kind, f) {
|
|
|
33840
33840
|
// ../../node_modules/.pnpm/@anthropic-ai+sdk@0.94.0_zod@4.4.3/node_modules/@anthropic-ai/sdk/internal/utils/uuid.mjs
|
|
33841
33841
|
init_esm_shims();
|
|
33842
33842
|
var uuid4 = function() {
|
|
33843
|
-
const { crypto:
|
|
33844
|
-
if (
|
|
33845
|
-
uuid4 =
|
|
33846
|
-
return
|
|
33843
|
+
const { crypto: crypto13 } = globalThis;
|
|
33844
|
+
if (crypto13?.randomUUID) {
|
|
33845
|
+
uuid4 = crypto13.randomUUID.bind(crypto13);
|
|
33846
|
+
return crypto13.randomUUID();
|
|
33847
33847
|
}
|
|
33848
33848
|
const u8 = new Uint8Array(1);
|
|
33849
|
-
const randomByte =
|
|
33849
|
+
const randomByte = crypto13 ? () => crypto13.getRandomValues(u8)[0] : () => Math.random() * 255 & 255;
|
|
33850
33850
|
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c2) => (+c2 ^ randomByte() & 15 >> +c2 / 4).toString(16));
|
|
33851
33851
|
};
|
|
33852
33852
|
|
|
@@ -34333,15 +34333,15 @@ function redactSensitive(body) {
|
|
|
34333
34333
|
}
|
|
34334
34334
|
return null;
|
|
34335
34335
|
}
|
|
34336
|
-
async function checkCredentialsFileSafety(
|
|
34336
|
+
async function checkCredentialsFileSafety(path49, onWarn = (m) => console.warn(`anthropic-sdk: ${m}`)) {
|
|
34337
34337
|
if (typeof process === "undefined" || process.platform === "win32")
|
|
34338
34338
|
return;
|
|
34339
|
-
const
|
|
34340
|
-
let resolved =
|
|
34339
|
+
const fs40 = await import("fs");
|
|
34340
|
+
let resolved = path49;
|
|
34341
34341
|
let st;
|
|
34342
34342
|
try {
|
|
34343
|
-
resolved = await
|
|
34344
|
-
st = await
|
|
34343
|
+
resolved = await fs40.promises.realpath(path49);
|
|
34344
|
+
st = await fs40.promises.stat(resolved);
|
|
34345
34345
|
} catch {
|
|
34346
34346
|
return;
|
|
34347
34347
|
}
|
|
@@ -34357,27 +34357,27 @@ async function checkCredentialsFileSafety(path46, onWarn = (m) => console.warn(`
|
|
|
34357
34357
|
}
|
|
34358
34358
|
}
|
|
34359
34359
|
async function writeCredentialsFileAtomic(targetPath, data) {
|
|
34360
|
-
const
|
|
34361
|
-
const
|
|
34362
|
-
const dir =
|
|
34363
|
-
await
|
|
34360
|
+
const fs40 = await import("fs");
|
|
34361
|
+
const path49 = await import("path");
|
|
34362
|
+
const dir = path49.dirname(targetPath);
|
|
34363
|
+
await fs40.promises.mkdir(dir, { recursive: true, mode: 448 });
|
|
34364
34364
|
const tmpPath = `${targetPath}.${process.pid}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
34365
34365
|
try {
|
|
34366
|
-
const fh = await
|
|
34366
|
+
const fh = await fs40.promises.open(tmpPath, "w", 384);
|
|
34367
34367
|
try {
|
|
34368
34368
|
await fh.writeFile(JSON.stringify(data, null, 2));
|
|
34369
34369
|
await fh.sync();
|
|
34370
34370
|
} finally {
|
|
34371
34371
|
await fh.close();
|
|
34372
34372
|
}
|
|
34373
|
-
await
|
|
34373
|
+
await fs40.promises.rename(tmpPath, targetPath);
|
|
34374
34374
|
} catch (err) {
|
|
34375
|
-
await
|
|
34375
|
+
await fs40.promises.unlink(tmpPath).catch(() => {
|
|
34376
34376
|
});
|
|
34377
34377
|
throw err;
|
|
34378
34378
|
}
|
|
34379
34379
|
try {
|
|
34380
|
-
const dirFh = await
|
|
34380
|
+
const dirFh = await fs40.promises.open(dir, "r");
|
|
34381
34381
|
try {
|
|
34382
34382
|
await dirFh.sync();
|
|
34383
34383
|
} finally {
|
|
@@ -34679,12 +34679,12 @@ var loadConfigWithSource = async (profile) => {
|
|
|
34679
34679
|
return null;
|
|
34680
34680
|
}
|
|
34681
34681
|
validateProfileName(profileName);
|
|
34682
|
-
const
|
|
34683
|
-
const
|
|
34684
|
-
const configPath =
|
|
34682
|
+
const fs40 = await import("fs");
|
|
34683
|
+
const path49 = await import("path");
|
|
34684
|
+
const configPath = path49.join(rootConfigPath, "configs", `${profileName}.json`);
|
|
34685
34685
|
let configRaw;
|
|
34686
34686
|
try {
|
|
34687
|
-
configRaw = await
|
|
34687
|
+
configRaw = await fs40.promises.readFile(configPath, "utf-8");
|
|
34688
34688
|
} catch (err) {
|
|
34689
34689
|
if (err?.code !== "ENOENT") {
|
|
34690
34690
|
throw new Error(`failed to read config file ${configPath}: ${err}`);
|
|
@@ -34765,37 +34765,37 @@ var getCredentialsPath = async (config2, profile) => {
|
|
|
34765
34765
|
return null;
|
|
34766
34766
|
}
|
|
34767
34767
|
validateProfileName(profileName);
|
|
34768
|
-
const
|
|
34769
|
-
return
|
|
34768
|
+
const path49 = await import("path");
|
|
34769
|
+
return path49.join(rootConfigPath, "credentials", `${profileName}.json`);
|
|
34770
34770
|
};
|
|
34771
34771
|
var getRootConfigPath = async () => {
|
|
34772
34772
|
if (!supportsLocalConfigFiles()) {
|
|
34773
34773
|
return null;
|
|
34774
34774
|
}
|
|
34775
|
-
const
|
|
34775
|
+
const path49 = await import("path");
|
|
34776
34776
|
const configDir = readEnv("ANTHROPIC_CONFIG_DIR");
|
|
34777
34777
|
if (configDir) {
|
|
34778
34778
|
return configDir;
|
|
34779
34779
|
}
|
|
34780
|
-
const
|
|
34781
|
-
if (
|
|
34780
|
+
const os13 = getPlatformHeaders()["X-Stainless-OS"];
|
|
34781
|
+
if (os13 === "Windows") {
|
|
34782
34782
|
const appData = readEnv("APPDATA");
|
|
34783
34783
|
if (appData) {
|
|
34784
|
-
return
|
|
34784
|
+
return path49.join(appData, "Anthropic");
|
|
34785
34785
|
}
|
|
34786
34786
|
const userProfile = readEnv("USERPROFILE");
|
|
34787
34787
|
if (userProfile) {
|
|
34788
|
-
return
|
|
34788
|
+
return path49.join(userProfile, "AppData", "Roaming", "Anthropic");
|
|
34789
34789
|
}
|
|
34790
34790
|
return null;
|
|
34791
34791
|
}
|
|
34792
34792
|
const xdgConfigHome = readEnv("XDG_CONFIG_HOME");
|
|
34793
34793
|
if (xdgConfigHome) {
|
|
34794
|
-
return
|
|
34794
|
+
return path49.join(xdgConfigHome, "anthropic");
|
|
34795
34795
|
}
|
|
34796
34796
|
const home = readEnv("HOME");
|
|
34797
34797
|
if (home) {
|
|
34798
|
-
return
|
|
34798
|
+
return path49.join(home, ".config", "anthropic");
|
|
34799
34799
|
}
|
|
34800
34800
|
return null;
|
|
34801
34801
|
};
|
|
@@ -34812,11 +34812,11 @@ var getActiveProfileName = async () => {
|
|
|
34812
34812
|
if (profileName) {
|
|
34813
34813
|
return profileName;
|
|
34814
34814
|
}
|
|
34815
|
-
const
|
|
34816
|
-
const
|
|
34817
|
-
const filePath =
|
|
34815
|
+
const fs40 = await import("fs");
|
|
34816
|
+
const path49 = await import("path");
|
|
34817
|
+
const filePath = path49.join(rootConfigPath, "active_config");
|
|
34818
34818
|
try {
|
|
34819
|
-
return (await
|
|
34819
|
+
return (await fs40.promises.readFile(filePath, "utf-8")).trim() || "default";
|
|
34820
34820
|
} catch (err) {
|
|
34821
34821
|
if (err?.code !== "ENOENT") {
|
|
34822
34822
|
throw new Error(`failed to read ${filePath}: ${err}`);
|
|
@@ -34827,21 +34827,21 @@ var getActiveProfileName = async () => {
|
|
|
34827
34827
|
|
|
34828
34828
|
// ../../node_modules/.pnpm/@anthropic-ai+sdk@0.94.0_zod@4.4.3/node_modules/@anthropic-ai/sdk/lib/credentials/identity-token.mjs
|
|
34829
34829
|
init_esm_shims();
|
|
34830
|
-
function identityTokenFromFile(
|
|
34831
|
-
if (!
|
|
34830
|
+
function identityTokenFromFile(path49) {
|
|
34831
|
+
if (!path49) {
|
|
34832
34832
|
throw new AnthropicError("Identity token file path is empty");
|
|
34833
34833
|
}
|
|
34834
34834
|
return async () => {
|
|
34835
|
-
const
|
|
34835
|
+
const fs40 = await import("fs");
|
|
34836
34836
|
let content;
|
|
34837
34837
|
try {
|
|
34838
|
-
content = await
|
|
34838
|
+
content = await fs40.promises.readFile(path49, "utf-8");
|
|
34839
34839
|
} catch (err) {
|
|
34840
|
-
throw new AnthropicError(`Failed to read identity token file at ${
|
|
34840
|
+
throw new AnthropicError(`Failed to read identity token file at ${path49}: ${err}`);
|
|
34841
34841
|
}
|
|
34842
34842
|
const token = content.trim();
|
|
34843
34843
|
if (!token) {
|
|
34844
|
-
throw new AnthropicError(`Identity token file at ${
|
|
34844
|
+
throw new AnthropicError(`Identity token file at ${path49} is empty`);
|
|
34845
34845
|
}
|
|
34846
34846
|
return token;
|
|
34847
34847
|
};
|
|
@@ -34916,11 +34916,11 @@ function oidcFederationProvider(config2) {
|
|
|
34916
34916
|
init_esm_shims();
|
|
34917
34917
|
function userOAuthProvider(config2) {
|
|
34918
34918
|
return async (opts) => {
|
|
34919
|
-
const
|
|
34919
|
+
const fs40 = await import("fs");
|
|
34920
34920
|
await checkCredentialsFileSafety(config2.credentialsPath, config2.onSafetyWarning);
|
|
34921
34921
|
let raw;
|
|
34922
34922
|
try {
|
|
34923
|
-
raw = await
|
|
34923
|
+
raw = await fs40.promises.readFile(config2.credentialsPath, "utf-8");
|
|
34924
34924
|
} catch (err) {
|
|
34925
34925
|
throw new WorkloadIdentityError(`Credentials file not found at ${config2.credentialsPath}: ${err}`);
|
|
34926
34926
|
}
|
|
@@ -35084,11 +35084,11 @@ function resolveIdentityTokenProvider(auth2) {
|
|
|
35084
35084
|
}
|
|
35085
35085
|
function cachedExchangeProvider(exchange, credentialsPath, onCacheWriteError, onSafetyWarning) {
|
|
35086
35086
|
return async (opts) => {
|
|
35087
|
-
const
|
|
35087
|
+
const fs40 = await import("fs");
|
|
35088
35088
|
await checkCredentialsFileSafety(credentialsPath, onSafetyWarning);
|
|
35089
35089
|
let existing;
|
|
35090
35090
|
try {
|
|
35091
|
-
const raw = await
|
|
35091
|
+
const raw = await fs40.promises.readFile(credentialsPath, "utf-8");
|
|
35092
35092
|
existing = JSON.parse(raw);
|
|
35093
35093
|
const token = existing?.["access_token"];
|
|
35094
35094
|
if (token && !opts?.forceRefresh) {
|
|
@@ -35927,12 +35927,12 @@ function encodeURIPath(str2) {
|
|
|
35927
35927
|
return str2.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
|
|
35928
35928
|
}
|
|
35929
35929
|
var EMPTY = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
35930
|
-
var createPathTagFunction = (pathEncoder = encodeURIPath) => function
|
|
35930
|
+
var createPathTagFunction = (pathEncoder = encodeURIPath) => function path49(statics, ...params) {
|
|
35931
35931
|
if (statics.length === 1)
|
|
35932
35932
|
return statics[0];
|
|
35933
35933
|
let postPath = false;
|
|
35934
35934
|
const invalidSegments = [];
|
|
35935
|
-
const
|
|
35935
|
+
const path50 = statics.reduce((previousValue, currentValue, index) => {
|
|
35936
35936
|
if (/[?#]/.test(currentValue)) {
|
|
35937
35937
|
postPath = true;
|
|
35938
35938
|
}
|
|
@@ -35949,7 +35949,7 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path46(sta
|
|
|
35949
35949
|
}
|
|
35950
35950
|
return previousValue + currentValue + (index === params.length ? "" : encoded);
|
|
35951
35951
|
}, "");
|
|
35952
|
-
const pathOnly =
|
|
35952
|
+
const pathOnly = path50.split(/[?#]/, 1)[0];
|
|
35953
35953
|
const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
|
|
35954
35954
|
let match;
|
|
35955
35955
|
while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
|
|
@@ -35970,10 +35970,10 @@ var createPathTagFunction = (pathEncoder = encodeURIPath) => function path46(sta
|
|
|
35970
35970
|
}, "");
|
|
35971
35971
|
throw new AnthropicError(`Path parameters result in path with invalid segments:
|
|
35972
35972
|
${invalidSegments.map((e) => e.error).join("\n")}
|
|
35973
|
-
${
|
|
35973
|
+
${path50}
|
|
35974
35974
|
${underline}`);
|
|
35975
35975
|
}
|
|
35976
|
-
return
|
|
35976
|
+
return path50;
|
|
35977
35977
|
};
|
|
35978
35978
|
var path = /* @__PURE__ */ createPathTagFunction(encodeURIPath);
|
|
35979
35979
|
|
|
@@ -40734,9 +40734,9 @@ var BaseAnthropic = class {
|
|
|
40734
40734
|
makeStatusError(status, error51, message, headers) {
|
|
40735
40735
|
return APIError.generate(status, error51, message, headers);
|
|
40736
40736
|
}
|
|
40737
|
-
buildURL(
|
|
40737
|
+
buildURL(path49, query, defaultBaseURL) {
|
|
40738
40738
|
const baseURL = !__classPrivateFieldGet(this, _BaseAnthropic_instances, "m", _BaseAnthropic_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
|
|
40739
|
-
const url2 = isAbsoluteURL(
|
|
40739
|
+
const url2 = isAbsoluteURL(path49) ? new URL(path49) : new URL(baseURL + (baseURL.endsWith("/") && path49.startsWith("/") ? path49.slice(1) : path49));
|
|
40740
40740
|
const defaultQuery = this.defaultQuery();
|
|
40741
40741
|
const pathQuery = Object.fromEntries(url2.searchParams);
|
|
40742
40742
|
if (!isEmptyObj(defaultQuery) || !isEmptyObj(pathQuery)) {
|
|
@@ -40780,24 +40780,24 @@ var BaseAnthropic = class {
|
|
|
40780
40780
|
request.headers = headers;
|
|
40781
40781
|
}
|
|
40782
40782
|
}
|
|
40783
|
-
get(
|
|
40784
|
-
return this.methodRequest("get",
|
|
40783
|
+
get(path49, opts) {
|
|
40784
|
+
return this.methodRequest("get", path49, opts);
|
|
40785
40785
|
}
|
|
40786
|
-
post(
|
|
40787
|
-
return this.methodRequest("post",
|
|
40786
|
+
post(path49, opts) {
|
|
40787
|
+
return this.methodRequest("post", path49, opts);
|
|
40788
40788
|
}
|
|
40789
|
-
patch(
|
|
40790
|
-
return this.methodRequest("patch",
|
|
40789
|
+
patch(path49, opts) {
|
|
40790
|
+
return this.methodRequest("patch", path49, opts);
|
|
40791
40791
|
}
|
|
40792
|
-
put(
|
|
40793
|
-
return this.methodRequest("put",
|
|
40792
|
+
put(path49, opts) {
|
|
40793
|
+
return this.methodRequest("put", path49, opts);
|
|
40794
40794
|
}
|
|
40795
|
-
delete(
|
|
40796
|
-
return this.methodRequest("delete",
|
|
40795
|
+
delete(path49, opts) {
|
|
40796
|
+
return this.methodRequest("delete", path49, opts);
|
|
40797
40797
|
}
|
|
40798
|
-
methodRequest(method,
|
|
40798
|
+
methodRequest(method, path49, opts) {
|
|
40799
40799
|
return this.request(Promise.resolve(opts).then((opts2) => {
|
|
40800
|
-
return { method, path:
|
|
40800
|
+
return { method, path: path49, ...opts2 };
|
|
40801
40801
|
}));
|
|
40802
40802
|
}
|
|
40803
40803
|
request(options, remainingRetries = null) {
|
|
@@ -40902,8 +40902,8 @@ var BaseAnthropic = class {
|
|
|
40902
40902
|
}));
|
|
40903
40903
|
return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
|
|
40904
40904
|
}
|
|
40905
|
-
getAPIList(
|
|
40906
|
-
return this.requestAPIList(Page3, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path:
|
|
40905
|
+
getAPIList(path49, Page3, opts) {
|
|
40906
|
+
return this.requestAPIList(Page3, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path49, ...opts2 })) : { method: "get", path: path49, ...opts });
|
|
40907
40907
|
}
|
|
40908
40908
|
requestAPIList(Page3, options) {
|
|
40909
40909
|
const request = this.makeRequest(options, null, void 0);
|
|
@@ -40997,14 +40997,14 @@ var BaseAnthropic = class {
|
|
|
40997
40997
|
}
|
|
40998
40998
|
async buildRequest(inputOptions, { retryCount = 0 } = {}) {
|
|
40999
40999
|
const options = { ...inputOptions };
|
|
41000
|
-
const { method, path:
|
|
41000
|
+
const { method, path: path49, query, defaultBaseURL } = options;
|
|
41001
41001
|
if (this._authState.resolution) {
|
|
41002
41002
|
await this._authState.resolution;
|
|
41003
41003
|
}
|
|
41004
41004
|
if (!this._baseURLIsExplicit && this._authState.baseURL && this.baseURL !== this._authState.baseURL) {
|
|
41005
41005
|
this.baseURL = this._authState.baseURL;
|
|
41006
41006
|
}
|
|
41007
|
-
const url2 = this.buildURL(
|
|
41007
|
+
const url2 = this.buildURL(path49, query, defaultBaseURL);
|
|
41008
41008
|
if ("timeout" in options)
|
|
41009
41009
|
validatePositiveInteger("timeout", options.timeout);
|
|
41010
41010
|
options.timeout = options.timeout ?? this.timeout;
|
|
@@ -41891,10 +41891,10 @@ function mergeDefs(...defs) {
|
|
|
41891
41891
|
function cloneDef(schema) {
|
|
41892
41892
|
return mergeDefs(schema._zod.def);
|
|
41893
41893
|
}
|
|
41894
|
-
function getElementAtPath(obj,
|
|
41895
|
-
if (!
|
|
41894
|
+
function getElementAtPath(obj, path49) {
|
|
41895
|
+
if (!path49)
|
|
41896
41896
|
return obj;
|
|
41897
|
-
return
|
|
41897
|
+
return path49.reduce((acc, key) => acc?.[key], obj);
|
|
41898
41898
|
}
|
|
41899
41899
|
function promiseAllObject(promisesObj) {
|
|
41900
41900
|
const keys = Object.keys(promisesObj);
|
|
@@ -42303,11 +42303,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
42303
42303
|
}
|
|
42304
42304
|
return false;
|
|
42305
42305
|
}
|
|
42306
|
-
function prefixIssues(
|
|
42306
|
+
function prefixIssues(path49, issues) {
|
|
42307
42307
|
return issues.map((iss) => {
|
|
42308
42308
|
var _a6;
|
|
42309
42309
|
(_a6 = iss).path ?? (_a6.path = []);
|
|
42310
|
-
iss.path.unshift(
|
|
42310
|
+
iss.path.unshift(path49);
|
|
42311
42311
|
return iss;
|
|
42312
42312
|
});
|
|
42313
42313
|
}
|
|
@@ -42454,16 +42454,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
42454
42454
|
}
|
|
42455
42455
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
42456
42456
|
const fieldErrors = { _errors: [] };
|
|
42457
|
-
const processError = (error52,
|
|
42457
|
+
const processError = (error52, path49 = []) => {
|
|
42458
42458
|
for (const issue2 of error52.issues) {
|
|
42459
42459
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
42460
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
42460
|
+
issue2.errors.map((issues) => processError({ issues }, [...path49, ...issue2.path]));
|
|
42461
42461
|
} else if (issue2.code === "invalid_key") {
|
|
42462
|
-
processError({ issues: issue2.issues }, [...
|
|
42462
|
+
processError({ issues: issue2.issues }, [...path49, ...issue2.path]);
|
|
42463
42463
|
} else if (issue2.code === "invalid_element") {
|
|
42464
|
-
processError({ issues: issue2.issues }, [...
|
|
42464
|
+
processError({ issues: issue2.issues }, [...path49, ...issue2.path]);
|
|
42465
42465
|
} else {
|
|
42466
|
-
const fullpath = [...
|
|
42466
|
+
const fullpath = [...path49, ...issue2.path];
|
|
42467
42467
|
if (fullpath.length === 0) {
|
|
42468
42468
|
fieldErrors._errors.push(mapper(issue2));
|
|
42469
42469
|
} else {
|
|
@@ -42490,17 +42490,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
42490
42490
|
}
|
|
42491
42491
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
42492
42492
|
const result = { errors: [] };
|
|
42493
|
-
const processError = (error52,
|
|
42493
|
+
const processError = (error52, path49 = []) => {
|
|
42494
42494
|
var _a6, _b;
|
|
42495
42495
|
for (const issue2 of error52.issues) {
|
|
42496
42496
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
42497
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
42497
|
+
issue2.errors.map((issues) => processError({ issues }, [...path49, ...issue2.path]));
|
|
42498
42498
|
} else if (issue2.code === "invalid_key") {
|
|
42499
|
-
processError({ issues: issue2.issues }, [...
|
|
42499
|
+
processError({ issues: issue2.issues }, [...path49, ...issue2.path]);
|
|
42500
42500
|
} else if (issue2.code === "invalid_element") {
|
|
42501
|
-
processError({ issues: issue2.issues }, [...
|
|
42501
|
+
processError({ issues: issue2.issues }, [...path49, ...issue2.path]);
|
|
42502
42502
|
} else {
|
|
42503
|
-
const fullpath = [...
|
|
42503
|
+
const fullpath = [...path49, ...issue2.path];
|
|
42504
42504
|
if (fullpath.length === 0) {
|
|
42505
42505
|
result.errors.push(mapper(issue2));
|
|
42506
42506
|
continue;
|
|
@@ -42532,8 +42532,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
42532
42532
|
}
|
|
42533
42533
|
function toDotPath(_path) {
|
|
42534
42534
|
const segs = [];
|
|
42535
|
-
const
|
|
42536
|
-
for (const seg of
|
|
42535
|
+
const path49 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
42536
|
+
for (const seg of path49) {
|
|
42537
42537
|
if (typeof seg === "number")
|
|
42538
42538
|
segs.push(`[${seg}]`);
|
|
42539
42539
|
else if (typeof seg === "symbol")
|
|
@@ -55306,13 +55306,13 @@ function resolveRef(ref, ctx) {
|
|
|
55306
55306
|
if (!ref.startsWith("#")) {
|
|
55307
55307
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
55308
55308
|
}
|
|
55309
|
-
const
|
|
55310
|
-
if (
|
|
55309
|
+
const path49 = ref.slice(1).split("/").filter(Boolean);
|
|
55310
|
+
if (path49.length === 0) {
|
|
55311
55311
|
return ctx.rootSchema;
|
|
55312
55312
|
}
|
|
55313
55313
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
55314
|
-
if (
|
|
55315
|
-
const key =
|
|
55314
|
+
if (path49[0] === defsKey) {
|
|
55315
|
+
const key = path49[1];
|
|
55316
55316
|
if (!key || !ctx.defs[key]) {
|
|
55317
55317
|
throw new Error(`Reference not found: ${ref}`);
|
|
55318
55318
|
}
|
|
@@ -55749,13 +55749,13 @@ function __classPrivateFieldGet2(receiver, state3, kind, f) {
|
|
|
55749
55749
|
// ../../node_modules/.pnpm/openai@6.34.0_ws@8.20.0_zod@4.4.3/node_modules/openai/internal/utils/uuid.mjs
|
|
55750
55750
|
init_esm_shims();
|
|
55751
55751
|
var uuid43 = function() {
|
|
55752
|
-
const { crypto:
|
|
55753
|
-
if (
|
|
55754
|
-
uuid43 =
|
|
55755
|
-
return
|
|
55752
|
+
const { crypto: crypto13 } = globalThis;
|
|
55753
|
+
if (crypto13?.randomUUID) {
|
|
55754
|
+
uuid43 = crypto13.randomUUID.bind(crypto13);
|
|
55755
|
+
return crypto13.randomUUID();
|
|
55756
55756
|
}
|
|
55757
55757
|
const u8 = new Uint8Array(1);
|
|
55758
|
-
const randomByte =
|
|
55758
|
+
const randomByte = crypto13 ? () => crypto13.getRandomValues(u8)[0] : () => Math.random() * 255 & 255;
|
|
55759
55759
|
return "10000000-1000-4000-8000-100000000000".replace(/[018]/g, (c2) => (+c2 ^ randomByte() & 15 >> +c2 / 4).toString(16));
|
|
55760
55760
|
};
|
|
55761
55761
|
|
|
@@ -57541,12 +57541,12 @@ function encodeURIPath2(str2) {
|
|
|
57541
57541
|
return str2.replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]+/g, encodeURIComponent);
|
|
57542
57542
|
}
|
|
57543
57543
|
var EMPTY2 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.create(null));
|
|
57544
|
-
var createPathTagFunction2 = (pathEncoder = encodeURIPath2) => function
|
|
57544
|
+
var createPathTagFunction2 = (pathEncoder = encodeURIPath2) => function path49(statics, ...params) {
|
|
57545
57545
|
if (statics.length === 1)
|
|
57546
57546
|
return statics[0];
|
|
57547
57547
|
let postPath = false;
|
|
57548
57548
|
const invalidSegments = [];
|
|
57549
|
-
const
|
|
57549
|
+
const path50 = statics.reduce((previousValue, currentValue, index) => {
|
|
57550
57550
|
if (/[?#]/.test(currentValue)) {
|
|
57551
57551
|
postPath = true;
|
|
57552
57552
|
}
|
|
@@ -57563,7 +57563,7 @@ var createPathTagFunction2 = (pathEncoder = encodeURIPath2) => function path46(s
|
|
|
57563
57563
|
}
|
|
57564
57564
|
return previousValue + currentValue + (index === params.length ? "" : encoded);
|
|
57565
57565
|
}, "");
|
|
57566
|
-
const pathOnly =
|
|
57566
|
+
const pathOnly = path50.split(/[?#]/, 1)[0];
|
|
57567
57567
|
const invalidSegmentPattern = /(?<=^|\/)(?:\.|%2e){1,2}(?=\/|$)/gi;
|
|
57568
57568
|
let match;
|
|
57569
57569
|
while ((match = invalidSegmentPattern.exec(pathOnly)) !== null) {
|
|
@@ -57584,10 +57584,10 @@ var createPathTagFunction2 = (pathEncoder = encodeURIPath2) => function path46(s
|
|
|
57584
57584
|
}, "");
|
|
57585
57585
|
throw new OpenAIError(`Path parameters result in path with invalid segments:
|
|
57586
57586
|
${invalidSegments.map((e) => e.error).join("\n")}
|
|
57587
|
-
${
|
|
57587
|
+
${path50}
|
|
57588
57588
|
${underline}`);
|
|
57589
57589
|
}
|
|
57590
|
-
return
|
|
57590
|
+
return path50;
|
|
57591
57591
|
};
|
|
57592
57592
|
var path2 = /* @__PURE__ */ createPathTagFunction2(encodeURIPath2);
|
|
57593
57593
|
|
|
@@ -62713,9 +62713,9 @@ var OpenAI = class {
|
|
|
62713
62713
|
this.apiKey = token;
|
|
62714
62714
|
return true;
|
|
62715
62715
|
}
|
|
62716
|
-
buildURL(
|
|
62716
|
+
buildURL(path49, query, defaultBaseURL) {
|
|
62717
62717
|
const baseURL = !__classPrivateFieldGet2(this, _OpenAI_instances, "m", _OpenAI_baseURLOverridden).call(this) && defaultBaseURL || this.baseURL;
|
|
62718
|
-
const url2 = isAbsoluteURL2(
|
|
62718
|
+
const url2 = isAbsoluteURL2(path49) ? new URL(path49) : new URL(baseURL + (baseURL.endsWith("/") && path49.startsWith("/") ? path49.slice(1) : path49));
|
|
62719
62719
|
const defaultQuery = this.defaultQuery();
|
|
62720
62720
|
const pathQuery = Object.fromEntries(url2.searchParams);
|
|
62721
62721
|
if (!isEmptyObj2(defaultQuery) || !isEmptyObj2(pathQuery)) {
|
|
@@ -62740,24 +62740,24 @@ var OpenAI = class {
|
|
|
62740
62740
|
*/
|
|
62741
62741
|
async prepareRequest(request, { url: url2, options }) {
|
|
62742
62742
|
}
|
|
62743
|
-
get(
|
|
62744
|
-
return this.methodRequest("get",
|
|
62743
|
+
get(path49, opts) {
|
|
62744
|
+
return this.methodRequest("get", path49, opts);
|
|
62745
62745
|
}
|
|
62746
|
-
post(
|
|
62747
|
-
return this.methodRequest("post",
|
|
62746
|
+
post(path49, opts) {
|
|
62747
|
+
return this.methodRequest("post", path49, opts);
|
|
62748
62748
|
}
|
|
62749
|
-
patch(
|
|
62750
|
-
return this.methodRequest("patch",
|
|
62749
|
+
patch(path49, opts) {
|
|
62750
|
+
return this.methodRequest("patch", path49, opts);
|
|
62751
62751
|
}
|
|
62752
|
-
put(
|
|
62753
|
-
return this.methodRequest("put",
|
|
62752
|
+
put(path49, opts) {
|
|
62753
|
+
return this.methodRequest("put", path49, opts);
|
|
62754
62754
|
}
|
|
62755
|
-
delete(
|
|
62756
|
-
return this.methodRequest("delete",
|
|
62755
|
+
delete(path49, opts) {
|
|
62756
|
+
return this.methodRequest("delete", path49, opts);
|
|
62757
62757
|
}
|
|
62758
|
-
methodRequest(method,
|
|
62758
|
+
methodRequest(method, path49, opts) {
|
|
62759
62759
|
return this.request(Promise.resolve(opts).then((opts2) => {
|
|
62760
|
-
return { method, path:
|
|
62760
|
+
return { method, path: path49, ...opts2 };
|
|
62761
62761
|
}));
|
|
62762
62762
|
}
|
|
62763
62763
|
request(options, remainingRetries = null) {
|
|
@@ -62875,8 +62875,8 @@ var OpenAI = class {
|
|
|
62875
62875
|
}));
|
|
62876
62876
|
return { response, options, controller, requestLogID, retryOfRequestLogID, startTime };
|
|
62877
62877
|
}
|
|
62878
|
-
getAPIList(
|
|
62879
|
-
return this.requestAPIList(Page3, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path:
|
|
62878
|
+
getAPIList(path49, Page3, opts) {
|
|
62879
|
+
return this.requestAPIList(Page3, opts && "then" in opts ? opts.then((opts2) => ({ method: "get", path: path49, ...opts2 })) : { method: "get", path: path49, ...opts });
|
|
62880
62880
|
}
|
|
62881
62881
|
requestAPIList(Page3, options) {
|
|
62882
62882
|
const request = this.makeRequest(options, null, void 0);
|
|
@@ -62967,8 +62967,8 @@ var OpenAI = class {
|
|
|
62967
62967
|
}
|
|
62968
62968
|
async buildRequest(inputOptions, { retryCount = 0 } = {}) {
|
|
62969
62969
|
const options = { ...inputOptions };
|
|
62970
|
-
const { method, path:
|
|
62971
|
-
const url2 = this.buildURL(
|
|
62970
|
+
const { method, path: path49, query, defaultBaseURL } = options;
|
|
62971
|
+
const url2 = this.buildURL(path49, query, defaultBaseURL);
|
|
62972
62972
|
if ("timeout" in options)
|
|
62973
62973
|
validatePositiveInteger2("timeout", options.timeout);
|
|
62974
62974
|
options.timeout = options.timeout ?? this.timeout;
|
|
@@ -63452,10 +63452,15 @@ var StreamResult = class {
|
|
|
63452
63452
|
return this.response.then(onfulfilled, onrejected);
|
|
63453
63453
|
}
|
|
63454
63454
|
};
|
|
63455
|
+
var schemaCache = /* @__PURE__ */ new WeakMap();
|
|
63455
63456
|
function zodToJsonSchema(schema) {
|
|
63457
|
+
const cached4 = schemaCache.get(schema);
|
|
63458
|
+
if (cached4) return cached4;
|
|
63456
63459
|
const jsonSchema = external_exports.toJSONSchema(schema);
|
|
63457
63460
|
const { $schema: _schema, ...rest } = jsonSchema;
|
|
63458
|
-
|
|
63461
|
+
const normalized = normalizeRootForAnthropic(rest);
|
|
63462
|
+
schemaCache.set(schema, normalized);
|
|
63463
|
+
return normalized;
|
|
63459
63464
|
}
|
|
63460
63465
|
function resolveToolSchema(tool) {
|
|
63461
63466
|
return tool.rawInputSchema ?? zodToJsonSchema(tool.parameters);
|
|
@@ -63845,16 +63850,17 @@ function toAnthropicThinking(level, maxTokens, model) {
|
|
|
63845
63850
|
outputConfig: { effort }
|
|
63846
63851
|
};
|
|
63847
63852
|
}
|
|
63853
|
+
const VISIBLE_FLOOR = 1024;
|
|
63848
63854
|
const effectiveLevel = level === "xhigh" || level === "max" ? "high" : level;
|
|
63849
63855
|
const budgetMap = {
|
|
63850
|
-
low: Math.max(1024, Math.floor(maxTokens * 0.
|
|
63851
|
-
medium: Math.max(2048, Math.floor(maxTokens * 0.
|
|
63852
|
-
high: Math.max(4096, maxTokens)
|
|
63856
|
+
low: Math.max(1024, Math.floor(maxTokens * 0.2)),
|
|
63857
|
+
medium: Math.max(2048, Math.floor(maxTokens * 0.45)),
|
|
63858
|
+
high: Math.max(4096, Math.floor(maxTokens * 0.8))
|
|
63853
63859
|
};
|
|
63854
|
-
const budget = budgetMap[effectiveLevel];
|
|
63860
|
+
const budget = Math.max(0, Math.min(budgetMap[effectiveLevel], maxTokens - VISIBLE_FLOOR));
|
|
63855
63861
|
return {
|
|
63856
63862
|
thinking: { type: "enabled", budget_tokens: budget },
|
|
63857
|
-
maxTokens
|
|
63863
|
+
maxTokens
|
|
63858
63864
|
};
|
|
63859
63865
|
}
|
|
63860
63866
|
function remapToolCallId(id2, idMap) {
|
|
@@ -64056,26 +64062,86 @@ function parseToolArguments(argsJson) {
|
|
|
64056
64062
|
return {};
|
|
64057
64063
|
}
|
|
64058
64064
|
}
|
|
64065
|
+
var anthropicClientCache = /* @__PURE__ */ new Map();
|
|
64059
64066
|
function createClient(options) {
|
|
64060
64067
|
const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
|
|
64061
|
-
|
|
64068
|
+
const userAgent = isOAuth ? options.userAgent ?? "claude-cli/2.1.75 (external, cli)" : "";
|
|
64069
|
+
const cacheKey = `${options.apiKey ?? ""}|${options.baseUrl ?? ""}|${userAgent}`;
|
|
64070
|
+
if (!options.fetch) {
|
|
64071
|
+
const cached4 = anthropicClientCache.get(cacheKey);
|
|
64072
|
+
if (cached4) return cached4;
|
|
64073
|
+
}
|
|
64074
|
+
const client = new Anthropic({
|
|
64062
64075
|
...isOAuth ? { apiKey: null, authToken: options.apiKey } : { apiKey: options.apiKey },
|
|
64063
64076
|
...options.baseUrl ? { baseURL: options.baseUrl } : {},
|
|
64064
64077
|
...options.fetch ? { fetch: options.fetch } : {},
|
|
64065
|
-
// Disable SDK retries — the agent loop has its own stall/overload retry
|
|
64066
|
-
// logic that surfaces errors properly. SDK retries on 429s can cause
|
|
64067
|
-
// multi-minute hangs when the provider stops responding mid-retry.
|
|
64068
64078
|
maxRetries: 0,
|
|
64069
64079
|
...isOAuth ? {
|
|
64070
64080
|
defaultHeaders: {
|
|
64071
64081
|
// Anthropic's OAuth edge validates the claude-cli version. Callers
|
|
64072
64082
|
// (ezcoder) resolve the live version at runtime; the literal here
|
|
64073
|
-
// is the offline fallback for direct
|
|
64074
|
-
"user-agent":
|
|
64083
|
+
// is the offline fallback for direct ai consumers.
|
|
64084
|
+
"user-agent": userAgent,
|
|
64075
64085
|
"x-app": "cli"
|
|
64076
64086
|
}
|
|
64077
64087
|
} : {}
|
|
64078
64088
|
});
|
|
64089
|
+
if (!options.fetch) {
|
|
64090
|
+
if (anthropicClientCache.size >= 8) {
|
|
64091
|
+
const oldest = anthropicClientCache.keys().next().value;
|
|
64092
|
+
if (oldest) anthropicClientCache.delete(oldest);
|
|
64093
|
+
}
|
|
64094
|
+
anthropicClientCache.set(cacheKey, client);
|
|
64095
|
+
}
|
|
64096
|
+
return client;
|
|
64097
|
+
}
|
|
64098
|
+
async function prewarmAnthropicCache(options) {
|
|
64099
|
+
try {
|
|
64100
|
+
const client = createClient({
|
|
64101
|
+
apiKey: options.apiKey,
|
|
64102
|
+
baseUrl: options.baseUrl,
|
|
64103
|
+
userAgent: options.userAgent
|
|
64104
|
+
});
|
|
64105
|
+
const cacheControl = toAnthropicCacheControl(options.cacheRetention ?? "long", options.baseUrl);
|
|
64106
|
+
const { system, messages } = toAnthropicMessages(
|
|
64107
|
+
[
|
|
64108
|
+
{ role: "system", content: options.system },
|
|
64109
|
+
{ role: "user", content: "." }
|
|
64110
|
+
],
|
|
64111
|
+
cacheControl
|
|
64112
|
+
);
|
|
64113
|
+
const isOAuth = options.apiKey.startsWith("sk-ant-oat");
|
|
64114
|
+
const fullSystem = isOAuth ? [
|
|
64115
|
+
{
|
|
64116
|
+
type: "text",
|
|
64117
|
+
text: "You are Claude Code, Anthropic's official CLI for Claude."
|
|
64118
|
+
},
|
|
64119
|
+
...system ?? []
|
|
64120
|
+
] : system;
|
|
64121
|
+
const tools = options.tools?.length ? toAnthropicTools(options.tools, {
|
|
64122
|
+
cacheControl,
|
|
64123
|
+
enableFineGrainedToolStreaming: true
|
|
64124
|
+
}) : void 0;
|
|
64125
|
+
await client.messages.create(
|
|
64126
|
+
{
|
|
64127
|
+
model: options.model,
|
|
64128
|
+
max_tokens: 1,
|
|
64129
|
+
messages,
|
|
64130
|
+
...fullSystem ? { system: fullSystem } : {},
|
|
64131
|
+
...tools ? {
|
|
64132
|
+
tools: [
|
|
64133
|
+
...tools,
|
|
64134
|
+
...options.serverTools ?? []
|
|
64135
|
+
]
|
|
64136
|
+
} : {}
|
|
64137
|
+
},
|
|
64138
|
+
{
|
|
64139
|
+
signal: options.signal ?? void 0,
|
|
64140
|
+
...isOAuth ? { headers: { "anthropic-beta": "claude-code-20250219,oauth-2025-04-20" } } : {}
|
|
64141
|
+
}
|
|
64142
|
+
);
|
|
64143
|
+
} catch {
|
|
64144
|
+
}
|
|
64079
64145
|
}
|
|
64080
64146
|
function streamAnthropic(options) {
|
|
64081
64147
|
return new StreamResult(runStream(options), options.signal);
|
|
@@ -64639,13 +64705,27 @@ function extractOpenAIUsage(usage) {
|
|
|
64639
64705
|
cacheRead
|
|
64640
64706
|
};
|
|
64641
64707
|
}
|
|
64708
|
+
var openaiClientCache = /* @__PURE__ */ new Map();
|
|
64642
64709
|
function createClient2(options) {
|
|
64643
|
-
|
|
64710
|
+
const cacheKey = `${options.apiKey ?? ""}|${options.baseUrl ?? ""}|${JSON.stringify(options.defaultHeaders ?? {})}`;
|
|
64711
|
+
if (!options.fetch) {
|
|
64712
|
+
const cached4 = openaiClientCache.get(cacheKey);
|
|
64713
|
+
if (cached4) return cached4;
|
|
64714
|
+
}
|
|
64715
|
+
const client = new OpenAI({
|
|
64644
64716
|
apiKey: options.apiKey,
|
|
64645
64717
|
...options.baseUrl ? { baseURL: options.baseUrl } : {},
|
|
64646
64718
|
...options.fetch ? { fetch: options.fetch } : {},
|
|
64647
64719
|
...options.defaultHeaders ? { defaultHeaders: options.defaultHeaders } : {}
|
|
64648
64720
|
});
|
|
64721
|
+
if (!options.fetch) {
|
|
64722
|
+
if (openaiClientCache.size >= 8) {
|
|
64723
|
+
const oldest = openaiClientCache.keys().next().value;
|
|
64724
|
+
if (oldest) openaiClientCache.delete(oldest);
|
|
64725
|
+
}
|
|
64726
|
+
openaiClientCache.set(cacheKey, client);
|
|
64727
|
+
}
|
|
64728
|
+
return client;
|
|
64649
64729
|
}
|
|
64650
64730
|
function streamOpenAI(options) {
|
|
64651
64731
|
return new StreamResult(runStream2(options), options.signal);
|
|
@@ -64703,11 +64783,11 @@ async function* runStream2(options) {
|
|
|
64703
64783
|
}
|
|
64704
64784
|
}
|
|
64705
64785
|
if (getEnvironment()?.GGAI_DUMP_REQUEST) {
|
|
64706
|
-
const
|
|
64786
|
+
const fs40 = await import("fs");
|
|
64707
64787
|
const ts = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
64708
64788
|
const dumpPath = `/tmp/ggai-request-${ts}.json`;
|
|
64709
|
-
|
|
64710
|
-
|
|
64789
|
+
fs40.writeFileSync(dumpPath, JSON.stringify(params, null, 2));
|
|
64790
|
+
fs40.appendFileSync(
|
|
64711
64791
|
"/tmp/ggai-requests.log",
|
|
64712
64792
|
`[${ts}] ${dumpPath} messages=${params.messages.length}
|
|
64713
64793
|
`
|
|
@@ -65051,9 +65131,6 @@ async function* runStream3(options) {
|
|
|
65051
65131
|
body.tools = toCodexTools(options.tools);
|
|
65052
65132
|
}
|
|
65053
65133
|
body.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
|
|
65054
|
-
if (options.cacheRetention === "long") {
|
|
65055
|
-
body.prompt_cache_retention = "24h";
|
|
65056
|
-
}
|
|
65057
65134
|
if (options.temperature != null && !options.thinking) {
|
|
65058
65135
|
body.temperature = options.temperature;
|
|
65059
65136
|
}
|
|
@@ -67501,7 +67578,7 @@ var Agent = class {
|
|
|
67501
67578
|
}
|
|
67502
67579
|
};
|
|
67503
67580
|
|
|
67504
|
-
// ../core/dist/chunk-
|
|
67581
|
+
// ../core/dist/chunk-RHNQ3WBA.js
|
|
67505
67582
|
init_esm_shims();
|
|
67506
67583
|
var MODELS = [
|
|
67507
67584
|
// ── Anthropic ──────────────────────────────────────────
|
|
@@ -67665,6 +67742,20 @@ var MODELS = [
|
|
|
67665
67742
|
maxThinkingLevel: "high"
|
|
67666
67743
|
},
|
|
67667
67744
|
// ── Z.AI (GLM) ─────────────────────────────────────────
|
|
67745
|
+
// GLM-5.2: coding-first flagship with a usable 1M-token context window
|
|
67746
|
+
// (5x jump over GLM-5.1's ~200K) and 131K max output. Released 2026-06-13.
|
|
67747
|
+
{
|
|
67748
|
+
id: "glm-5.2",
|
|
67749
|
+
name: "GLM-5.2",
|
|
67750
|
+
provider: "glm",
|
|
67751
|
+
contextWindow: 1e6,
|
|
67752
|
+
maxOutputTokens: 131072,
|
|
67753
|
+
supportsThinking: true,
|
|
67754
|
+
supportsImages: false,
|
|
67755
|
+
supportsVideo: false,
|
|
67756
|
+
costTier: "medium",
|
|
67757
|
+
maxThinkingLevel: "high"
|
|
67758
|
+
},
|
|
67668
67759
|
{
|
|
67669
67760
|
id: "glm-5.1",
|
|
67670
67761
|
name: "GLM-5.1",
|
|
@@ -67802,7 +67893,7 @@ function getDefaultModel(provider) {
|
|
|
67802
67893
|
if (provider === "xiaomi") return MODELS.find((m) => m.id === "mimo-v2.5-pro");
|
|
67803
67894
|
if (provider === "openai") return MODELS.find((m) => m.id === "gpt-5.5");
|
|
67804
67895
|
if (provider === "gemini") return MODELS.find((m) => m.id === "gemini-3.1-flash-lite-preview");
|
|
67805
|
-
if (provider === "glm") return MODELS.find((m) => m.id === "glm-5.
|
|
67896
|
+
if (provider === "glm") return MODELS.find((m) => m.id === "glm-5.2");
|
|
67806
67897
|
if (provider === "moonshot") return MODELS.find((m) => m.id === "kimi-k2.7-code");
|
|
67807
67898
|
if (provider === "minimax") return MODELS.find((m) => m.id === "MiniMax-M3");
|
|
67808
67899
|
if (provider === "deepseek") return MODELS.find((m) => m.id === "deepseek-v4-pro");
|
|
@@ -67837,7 +67928,7 @@ function getSummaryModel(provider, currentModelId) {
|
|
|
67837
67928
|
// ../core/dist/index.js
|
|
67838
67929
|
init_esm_shims();
|
|
67839
67930
|
|
|
67840
|
-
// ../core/dist/chunk-
|
|
67931
|
+
// ../core/dist/chunk-WQFTKHPJ.js
|
|
67841
67932
|
init_esm_shims();
|
|
67842
67933
|
import path3 from "path";
|
|
67843
67934
|
import os2 from "os";
|
|
@@ -67851,6 +67942,7 @@ function getAppPaths() {
|
|
|
67851
67942
|
telegramFile: path3.join(agentDir, "telegram.json"),
|
|
67852
67943
|
agentHomeFile: path3.join(agentDir, "agent-home.json"),
|
|
67853
67944
|
mcpFile: path3.join(agentDir, "mcp.json"),
|
|
67945
|
+
mcpAuthFile: path3.join(agentDir, "mcp-auth.json"),
|
|
67854
67946
|
logFile: path3.join(agentDir, "debug.log"),
|
|
67855
67947
|
skillsDir: path3.join(agentDir, "skills"),
|
|
67856
67948
|
extensionsDir: path3.join(agentDir, "extensions"),
|
|
@@ -68303,12 +68395,12 @@ function macOsProductVersion() {
|
|
|
68303
68395
|
}
|
|
68304
68396
|
}
|
|
68305
68397
|
function deviceModel() {
|
|
68306
|
-
const
|
|
68398
|
+
const os13 = type();
|
|
68307
68399
|
const version2 = release();
|
|
68308
68400
|
const osArch = arch();
|
|
68309
|
-
if (
|
|
68310
|
-
if (
|
|
68311
|
-
return `${
|
|
68401
|
+
if (os13 === "Darwin") return `macOS ${macOsProductVersion() ?? version2} ${osArch}`;
|
|
68402
|
+
if (os13 === "Windows_NT") return `Windows ${version2} ${osArch}`;
|
|
68403
|
+
return `${os13} ${version2} ${osArch}`.trim();
|
|
68312
68404
|
}
|
|
68313
68405
|
function deviceId() {
|
|
68314
68406
|
const idPath = path32.join(getAppPaths().agentDir, "kimi_device_id");
|
|
@@ -69123,7 +69215,7 @@ init_esm_shims();
|
|
|
69123
69215
|
import { spawn as spawn2, spawnSync } from "child_process";
|
|
69124
69216
|
import fs6 from "fs";
|
|
69125
69217
|
import fsp from "fs/promises";
|
|
69126
|
-
import
|
|
69218
|
+
import path7 from "path";
|
|
69127
69219
|
import os3 from "os";
|
|
69128
69220
|
import crypto2 from "crypto";
|
|
69129
69221
|
|
|
@@ -69181,7 +69273,34 @@ var ENV_ALLOWLIST = /* @__PURE__ */ new Set([
|
|
|
69181
69273
|
"ANDROID_SDK_ROOT",
|
|
69182
69274
|
"RUBY_VERSION",
|
|
69183
69275
|
"GEM_HOME",
|
|
69184
|
-
"RBENV_ROOT"
|
|
69276
|
+
"RBENV_ROOT",
|
|
69277
|
+
// Windows essentials. Without these, child processes (cmd.exe, Git Bash,
|
|
69278
|
+
// node, npm, MCP stdio servers) misbehave or fail to spawn: SystemRoot +
|
|
69279
|
+
// PATHEXT are required by the Windows loader/resolver, ComSpec is the
|
|
69280
|
+
// cmd.exe path, and the USERPROFILE/APPDATA/TEMP family is where toolchains
|
|
69281
|
+
// read and write. Stripping them was a silent cause of broken shell calls.
|
|
69282
|
+
"SystemRoot",
|
|
69283
|
+
"SystemDrive",
|
|
69284
|
+
"windir",
|
|
69285
|
+
"PATHEXT",
|
|
69286
|
+
"ComSpec",
|
|
69287
|
+
"COMSPEC",
|
|
69288
|
+
"USERPROFILE",
|
|
69289
|
+
"HOMEDRIVE",
|
|
69290
|
+
"HOMEPATH",
|
|
69291
|
+
"APPDATA",
|
|
69292
|
+
"LOCALAPPDATA",
|
|
69293
|
+
"PROGRAMDATA",
|
|
69294
|
+
"ProgramData",
|
|
69295
|
+
"ProgramFiles",
|
|
69296
|
+
"ProgramFiles(x86)",
|
|
69297
|
+
"ProgramW6432",
|
|
69298
|
+
"TEMP",
|
|
69299
|
+
"TMP",
|
|
69300
|
+
"NUMBER_OF_PROCESSORS",
|
|
69301
|
+
"PROCESSOR_ARCHITECTURE",
|
|
69302
|
+
// Git Bash override for the agent shell (see core/shell.ts).
|
|
69303
|
+
"GG_BASH"
|
|
69185
69304
|
]);
|
|
69186
69305
|
function getSafeToolEnv(sourceEnv = process.env) {
|
|
69187
69306
|
const env2 = { TERM: "dumb", EZ_CODER: "true" };
|
|
@@ -69193,8 +69312,68 @@ function getSafeToolEnv(sourceEnv = process.env) {
|
|
|
69193
69312
|
return env2;
|
|
69194
69313
|
}
|
|
69195
69314
|
|
|
69315
|
+
// ../cli/dist/core/shell.js
|
|
69316
|
+
init_esm_shims();
|
|
69317
|
+
import { existsSync as existsSync2 } from "fs";
|
|
69318
|
+
import path6 from "path";
|
|
69319
|
+
function gitBashFixedCandidates(env2) {
|
|
69320
|
+
const programFiles = env2.ProgramFiles ?? "C:\\Program Files";
|
|
69321
|
+
const programFilesX86 = env2["ProgramFiles(x86)"] ?? "C:\\Program Files (x86)";
|
|
69322
|
+
const localAppData = env2.LOCALAPPDATA;
|
|
69323
|
+
const candidates = [
|
|
69324
|
+
path6.win32.join(programFiles, "Git", "bin", "bash.exe"),
|
|
69325
|
+
path6.win32.join(programFilesX86, "Git", "bin", "bash.exe")
|
|
69326
|
+
];
|
|
69327
|
+
if (localAppData) {
|
|
69328
|
+
candidates.push(path6.win32.join(localAppData, "Programs", "Git", "bin", "bash.exe"));
|
|
69329
|
+
}
|
|
69330
|
+
return candidates;
|
|
69331
|
+
}
|
|
69332
|
+
function gitBashFromPath(env2, exists) {
|
|
69333
|
+
const rawPath = env2.PATH ?? env2.Path ?? "";
|
|
69334
|
+
if (!rawPath)
|
|
69335
|
+
return null;
|
|
69336
|
+
for (const dir of rawPath.split(";")) {
|
|
69337
|
+
if (!dir)
|
|
69338
|
+
continue;
|
|
69339
|
+
const gitExe = path6.win32.join(dir, "git.exe");
|
|
69340
|
+
if (!exists(gitExe))
|
|
69341
|
+
continue;
|
|
69342
|
+
const gitRoot = path6.win32.dirname(path6.win32.dirname(gitExe));
|
|
69343
|
+
const bash2 = path6.win32.join(gitRoot, "bin", "bash.exe");
|
|
69344
|
+
if (exists(bash2))
|
|
69345
|
+
return bash2;
|
|
69346
|
+
}
|
|
69347
|
+
return null;
|
|
69348
|
+
}
|
|
69349
|
+
function findGitBash(env2, exists) {
|
|
69350
|
+
for (const candidate of gitBashFixedCandidates(env2)) {
|
|
69351
|
+
if (exists(candidate))
|
|
69352
|
+
return candidate;
|
|
69353
|
+
}
|
|
69354
|
+
return gitBashFromPath(env2, exists);
|
|
69355
|
+
}
|
|
69356
|
+
function resolveShell(command, opts = {}) {
|
|
69357
|
+
const platform2 = opts.platform ?? process.platform;
|
|
69358
|
+
const env2 = opts.env ?? process.env;
|
|
69359
|
+
const exists = opts.exists ?? existsSync2;
|
|
69360
|
+
const override = env2.GG_BASH?.trim();
|
|
69361
|
+
if (override) {
|
|
69362
|
+
return { file: override, args: ["-c", command], isCmdFallback: false };
|
|
69363
|
+
}
|
|
69364
|
+
if (platform2 !== "win32") {
|
|
69365
|
+
return { file: "bash", args: ["-c", command], isCmdFallback: false };
|
|
69366
|
+
}
|
|
69367
|
+
const gitBash = findGitBash(env2, exists);
|
|
69368
|
+
if (gitBash) {
|
|
69369
|
+
return { file: gitBash, args: ["-c", command], isCmdFallback: false };
|
|
69370
|
+
}
|
|
69371
|
+
const comspec = env2.ComSpec ?? env2.COMSPEC ?? "C:\\Windows\\System32\\cmd.exe";
|
|
69372
|
+
return { file: comspec, args: ["/d", "/s", "/c", command], isCmdFallback: true };
|
|
69373
|
+
}
|
|
69374
|
+
|
|
69196
69375
|
// ../cli/dist/core/process-manager.js
|
|
69197
|
-
var BG_DIR =
|
|
69376
|
+
var BG_DIR = path7.join(os3.homedir(), ".ezcoder", "bg");
|
|
69198
69377
|
function stopProcessTree(pid, ops = {}) {
|
|
69199
69378
|
if ((ops.platform ?? process.platform) === "win32") {
|
|
69200
69379
|
(ops.spawnSync ?? spawnSync)("taskkill", ["/pid", String(pid), "/T", "/F"], {
|
|
@@ -69214,9 +69393,10 @@ var ProcessManager = class {
|
|
|
69214
69393
|
async start(command, cwd2) {
|
|
69215
69394
|
await fsp.mkdir(BG_DIR, { recursive: true });
|
|
69216
69395
|
const id2 = crypto2.randomUUID().slice(0, 8);
|
|
69217
|
-
const logFile =
|
|
69396
|
+
const logFile = path7.join(BG_DIR, `${id2}.log`);
|
|
69218
69397
|
const fd2 = fs6.openSync(logFile, "w");
|
|
69219
|
-
const
|
|
69398
|
+
const shell2 = resolveShell(command);
|
|
69399
|
+
const child = spawn2(shell2.file, shell2.args, {
|
|
69220
69400
|
cwd: cwd2,
|
|
69221
69401
|
detached: true,
|
|
69222
69402
|
// stdin is a pipe so callers can drive interactive processes (REPLs,
|
|
@@ -69359,7 +69539,7 @@ var ProcessManager = class {
|
|
|
69359
69539
|
|
|
69360
69540
|
// ../cli/dist/core/lsp/manager.js
|
|
69361
69541
|
init_esm_shims();
|
|
69362
|
-
import
|
|
69542
|
+
import path9 from "path";
|
|
69363
69543
|
|
|
69364
69544
|
// ../cli/dist/core/logger.js
|
|
69365
69545
|
init_esm_shims();
|
|
@@ -69728,7 +69908,7 @@ Diagnostics in ${relPath} (informational \u2014 may resolve after related edits)
|
|
|
69728
69908
|
// ../cli/dist/core/lsp/servers.js
|
|
69729
69909
|
init_esm_shims();
|
|
69730
69910
|
import fs7 from "fs";
|
|
69731
|
-
import
|
|
69911
|
+
import path8 from "path";
|
|
69732
69912
|
import { fileURLToPath } from "url";
|
|
69733
69913
|
var WINDOWS_SUFFIXES = [".cmd", ".exe", ".bat"];
|
|
69734
69914
|
function isExecutableFile(candidate) {
|
|
@@ -69744,13 +69924,13 @@ function candidateNames(name) {
|
|
|
69744
69924
|
return [name];
|
|
69745
69925
|
return [name, ...WINDOWS_SUFFIXES.map((suffix) => `${name}${suffix}`)];
|
|
69746
69926
|
}
|
|
69747
|
-
var MODULE_DIR =
|
|
69927
|
+
var MODULE_DIR = path8.dirname(fileURLToPath(import.meta.url));
|
|
69748
69928
|
function binDirsUpFrom(start) {
|
|
69749
69929
|
const dirs = [];
|
|
69750
69930
|
let dir = start;
|
|
69751
69931
|
for (; ; ) {
|
|
69752
|
-
dirs.push(
|
|
69753
|
-
const parent =
|
|
69932
|
+
dirs.push(path8.join(dir, "node_modules", ".bin"));
|
|
69933
|
+
const parent = path8.dirname(dir);
|
|
69754
69934
|
if (parent === dir)
|
|
69755
69935
|
break;
|
|
69756
69936
|
dir = parent;
|
|
@@ -69762,17 +69942,17 @@ function findExecutable(name, projectRoot) {
|
|
|
69762
69942
|
const binDirs = [...binDirsUpFrom(projectRoot), ...binDirsUpFrom(MODULE_DIR)];
|
|
69763
69943
|
for (const binDir of binDirs) {
|
|
69764
69944
|
for (const candidate of names) {
|
|
69765
|
-
const binPath =
|
|
69945
|
+
const binPath = path8.join(binDir, candidate);
|
|
69766
69946
|
if (isExecutableFile(binPath))
|
|
69767
69947
|
return binPath;
|
|
69768
69948
|
}
|
|
69769
69949
|
}
|
|
69770
69950
|
const pathEnv = process.env.PATH ?? "";
|
|
69771
|
-
for (const pathDir of pathEnv.split(
|
|
69951
|
+
for (const pathDir of pathEnv.split(path8.delimiter)) {
|
|
69772
69952
|
if (!pathDir)
|
|
69773
69953
|
continue;
|
|
69774
69954
|
for (const candidate of names) {
|
|
69775
|
-
const binPath =
|
|
69955
|
+
const binPath = path8.join(pathDir, candidate);
|
|
69776
69956
|
if (isExecutableFile(binPath))
|
|
69777
69957
|
return binPath;
|
|
69778
69958
|
}
|
|
@@ -69782,17 +69962,17 @@ function findExecutable(name, projectRoot) {
|
|
|
69782
69962
|
function findInNodeModulesUp(relPath, start) {
|
|
69783
69963
|
let dir = start;
|
|
69784
69964
|
for (; ; ) {
|
|
69785
|
-
const candidate =
|
|
69965
|
+
const candidate = path8.join(dir, "node_modules", relPath);
|
|
69786
69966
|
if (fs7.existsSync(candidate))
|
|
69787
69967
|
return candidate;
|
|
69788
|
-
const parent =
|
|
69968
|
+
const parent = path8.dirname(dir);
|
|
69789
69969
|
if (parent === dir)
|
|
69790
69970
|
return null;
|
|
69791
69971
|
dir = parent;
|
|
69792
69972
|
}
|
|
69793
69973
|
}
|
|
69794
69974
|
function findPackageBinScript(pkgName, binName, start) {
|
|
69795
|
-
const pkgJsonPath = findInNodeModulesUp(
|
|
69975
|
+
const pkgJsonPath = findInNodeModulesUp(path8.join(pkgName, "package.json"), start);
|
|
69796
69976
|
if (!pkgJsonPath)
|
|
69797
69977
|
return null;
|
|
69798
69978
|
try {
|
|
@@ -69800,7 +69980,7 @@ function findPackageBinScript(pkgName, binName, start) {
|
|
|
69800
69980
|
const bin = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.[binName];
|
|
69801
69981
|
if (!bin)
|
|
69802
69982
|
return null;
|
|
69803
|
-
const script =
|
|
69983
|
+
const script = path8.join(path8.dirname(pkgJsonPath), bin);
|
|
69804
69984
|
return fs7.existsSync(script) ? script : null;
|
|
69805
69985
|
} catch {
|
|
69806
69986
|
return null;
|
|
@@ -69813,7 +69993,7 @@ function resolveNodeServer(pkgName, binName, projectRoot, args) {
|
|
|
69813
69993
|
const bin = findExecutable(binName, projectRoot);
|
|
69814
69994
|
return bin ? { command: bin, args } : null;
|
|
69815
69995
|
}
|
|
69816
|
-
var TSSERVER_REL_PATH =
|
|
69996
|
+
var TSSERVER_REL_PATH = path8.join("typescript", "lib", "tsserver.js");
|
|
69817
69997
|
function projectTsserverPath(projectRoot) {
|
|
69818
69998
|
return findInNodeModulesUp(TSSERVER_REL_PATH, projectRoot);
|
|
69819
69999
|
}
|
|
@@ -69903,27 +70083,27 @@ var LSP_SERVER_CATALOG = [
|
|
|
69903
70083
|
}
|
|
69904
70084
|
];
|
|
69905
70085
|
function serverForFile(filePath, catalog = LSP_SERVER_CATALOG) {
|
|
69906
|
-
const extension =
|
|
70086
|
+
const extension = path8.extname(filePath).toLowerCase();
|
|
69907
70087
|
if (!extension)
|
|
69908
70088
|
return null;
|
|
69909
70089
|
return catalog.find((spec) => spec.extensions.includes(extension)) ?? null;
|
|
69910
70090
|
}
|
|
69911
70091
|
function findProjectRoot(filePath, markers, ceiling) {
|
|
69912
|
-
const fileDir =
|
|
69913
|
-
const cap =
|
|
69914
|
-
const underCeiling = fileDir === cap || fileDir.startsWith(cap +
|
|
70092
|
+
const fileDir = path8.dirname(path8.resolve(filePath));
|
|
70093
|
+
const cap = path8.resolve(ceiling);
|
|
70094
|
+
const underCeiling = fileDir === cap || fileDir.startsWith(cap + path8.sep);
|
|
69915
70095
|
let dir = fileDir;
|
|
69916
70096
|
for (; ; ) {
|
|
69917
70097
|
for (const marker of markers) {
|
|
69918
70098
|
try {
|
|
69919
|
-
fs7.statSync(
|
|
70099
|
+
fs7.statSync(path8.join(dir, marker));
|
|
69920
70100
|
return dir;
|
|
69921
70101
|
} catch {
|
|
69922
70102
|
}
|
|
69923
70103
|
}
|
|
69924
70104
|
if (underCeiling && dir === cap)
|
|
69925
70105
|
break;
|
|
69926
|
-
const parent =
|
|
70106
|
+
const parent = path8.dirname(dir);
|
|
69927
70107
|
if (parent === dir)
|
|
69928
70108
|
break;
|
|
69929
70109
|
dir = parent;
|
|
@@ -69994,12 +70174,12 @@ var LspManager = class {
|
|
|
69994
70174
|
log("WARN", "lsp", `${spec.id} server died`, { root });
|
|
69995
70175
|
return "";
|
|
69996
70176
|
}
|
|
69997
|
-
const uri = client.syncDocument(
|
|
70177
|
+
const uri = client.syncDocument(path9.resolve(this.cwd, filePath), content);
|
|
69998
70178
|
const diagnostics = await client.collectDiagnostics(uri, budgetMs);
|
|
69999
70179
|
this.warmKeys.add(key);
|
|
70000
70180
|
if (diagnostics === null)
|
|
70001
70181
|
return "";
|
|
70002
|
-
const relPath =
|
|
70182
|
+
const relPath = path9.relative(this.cwd, path9.resolve(this.cwd, filePath));
|
|
70003
70183
|
return formatDiagnostics(relPath, diagnostics);
|
|
70004
70184
|
}
|
|
70005
70185
|
ensureClient(key, spec, root) {
|
|
@@ -70050,18 +70230,18 @@ function withBudget(work, budgetMs) {
|
|
|
70050
70230
|
// ../cli/dist/tools/read.js
|
|
70051
70231
|
init_esm_shims();
|
|
70052
70232
|
import fs12 from "fs/promises";
|
|
70053
|
-
import
|
|
70233
|
+
import path13 from "path";
|
|
70054
70234
|
|
|
70055
70235
|
// ../cli/dist/tools/path-utils.js
|
|
70056
70236
|
init_esm_shims();
|
|
70057
70237
|
import fs8 from "fs/promises";
|
|
70058
|
-
import
|
|
70238
|
+
import path10 from "path";
|
|
70059
70239
|
import os4 from "os";
|
|
70060
70240
|
function resolvePath(cwd2, filePath) {
|
|
70061
70241
|
if (filePath.startsWith("~")) {
|
|
70062
|
-
filePath =
|
|
70242
|
+
filePath = path10.join(os4.homedir(), filePath.slice(1));
|
|
70063
70243
|
}
|
|
70064
|
-
return
|
|
70244
|
+
return path10.resolve(cwd2, filePath);
|
|
70065
70245
|
}
|
|
70066
70246
|
async function rejectSymlink(resolved) {
|
|
70067
70247
|
try {
|
|
@@ -70128,9 +70308,9 @@ function truncateTail(content, maxLines = MAX_LINES, maxBytes = MAX_BYTES2) {
|
|
|
70128
70308
|
init_esm_shims();
|
|
70129
70309
|
import fs9 from "fs/promises";
|
|
70130
70310
|
import os5 from "os";
|
|
70131
|
-
import
|
|
70311
|
+
import path11 from "path";
|
|
70132
70312
|
async function writeOverflow(content, prefix) {
|
|
70133
|
-
const filePath =
|
|
70313
|
+
const filePath = path11.join(os5.tmpdir(), `ezcoder-${prefix}-${Date.now()}.txt`);
|
|
70134
70314
|
await fs9.writeFile(filePath, content, { encoding: "utf-8", mode: 384 });
|
|
70135
70315
|
return filePath;
|
|
70136
70316
|
}
|
|
@@ -70141,18 +70321,18 @@ import fs10 from "fs/promises";
|
|
|
70141
70321
|
import { spawn as spawn4 } from "child_process";
|
|
70142
70322
|
import { createReadStream } from "fs";
|
|
70143
70323
|
var localOperations = {
|
|
70144
|
-
readFile: (
|
|
70145
|
-
writeFile: async (
|
|
70324
|
+
readFile: (path49) => fs10.readFile(path49, "utf-8"),
|
|
70325
|
+
writeFile: async (path49, content) => {
|
|
70146
70326
|
const { dirname: dirname3 } = await import("path");
|
|
70147
|
-
await fs10.mkdir(dirname3(
|
|
70148
|
-
await fs10.writeFile(
|
|
70327
|
+
await fs10.mkdir(dirname3(path49), { recursive: true });
|
|
70328
|
+
await fs10.writeFile(path49, content, "utf-8");
|
|
70149
70329
|
},
|
|
70150
|
-
stat: (
|
|
70151
|
-
lstat: (
|
|
70152
|
-
readdir: (
|
|
70153
|
-
mkdir: (
|
|
70330
|
+
stat: (path49) => fs10.stat(path49),
|
|
70331
|
+
lstat: (path49) => fs10.lstat(path49),
|
|
70332
|
+
readdir: (path49, options) => fs10.readdir(path49, options),
|
|
70333
|
+
mkdir: (path49) => fs10.mkdir(path49, { recursive: true }).then(() => {
|
|
70154
70334
|
}),
|
|
70155
|
-
createReadStream: (
|
|
70335
|
+
createReadStream: (path49, encoding) => createReadStream(path49, { encoding }),
|
|
70156
70336
|
spawn: (command, args, options) => spawn4(command, args, {
|
|
70157
70337
|
cwd: options.cwd,
|
|
70158
70338
|
env: options.env,
|
|
@@ -70198,7 +70378,7 @@ async function assertFresh(tracker, resolvedPath, ops) {
|
|
|
70198
70378
|
init_esm_shims();
|
|
70199
70379
|
import fs11 from "fs/promises";
|
|
70200
70380
|
import os6 from "os";
|
|
70201
|
-
import
|
|
70381
|
+
import path12 from "path";
|
|
70202
70382
|
import { execFile } from "child_process";
|
|
70203
70383
|
import { promisify } from "util";
|
|
70204
70384
|
var execFileAsync = promisify(execFile);
|
|
@@ -70246,7 +70426,7 @@ async function compressVideoToFit(inputPath, targetBytes = COMPRESS_TARGET_BYTES
|
|
|
70246
70426
|
}
|
|
70247
70427
|
const totalKbps = Math.floor(targetBytes * 8 / durationSec / 1e3 * 0.9);
|
|
70248
70428
|
const videoKbps = Math.max(COMPRESS_MIN_VIDEO_KBPS, totalKbps - COMPRESS_AUDIO_KBPS);
|
|
70249
|
-
const outPath =
|
|
70429
|
+
const outPath = path12.join(os6.tmpdir(), `ezcoder-compressed-${Date.now()}.mp4`);
|
|
70250
70430
|
try {
|
|
70251
70431
|
await execFileAsync("ffmpeg", [
|
|
70252
70432
|
"-y",
|
|
@@ -70318,7 +70498,7 @@ var VIDEO_MEDIA_TYPES = {
|
|
|
70318
70498
|
};
|
|
70319
70499
|
var MEDIA_TYPES = IMAGE_MEDIA_TYPES;
|
|
70320
70500
|
function isAttachablePath(filePath) {
|
|
70321
|
-
const ext =
|
|
70501
|
+
const ext = path12.extname(filePath).toLowerCase();
|
|
70322
70502
|
return ATTACHABLE_EXTENSIONS.has(ext);
|
|
70323
70503
|
}
|
|
70324
70504
|
function resolvePath2(filePath, cwd2) {
|
|
@@ -70331,9 +70511,9 @@ function resolvePath2(filePath, cwd2) {
|
|
|
70331
70511
|
}
|
|
70332
70512
|
resolved = resolved.replace(/\\(.)/g, "$1");
|
|
70333
70513
|
if (resolved.startsWith("~/")) {
|
|
70334
|
-
resolved =
|
|
70335
|
-
} else if (!
|
|
70336
|
-
resolved =
|
|
70514
|
+
resolved = path12.join(process.env.HOME ?? "/", resolved.slice(2));
|
|
70515
|
+
} else if (!path12.isAbsolute(resolved)) {
|
|
70516
|
+
resolved = path12.join(cwd2, resolved);
|
|
70337
70517
|
}
|
|
70338
70518
|
return resolved;
|
|
70339
70519
|
}
|
|
@@ -70446,8 +70626,8 @@ async function downscaleForPreview(buffer) {
|
|
|
70446
70626
|
}
|
|
70447
70627
|
}
|
|
70448
70628
|
async function readImageFile(filePath) {
|
|
70449
|
-
const ext =
|
|
70450
|
-
const fileName =
|
|
70629
|
+
const ext = path12.extname(filePath).toLowerCase();
|
|
70630
|
+
const fileName = path12.basename(filePath);
|
|
70451
70631
|
if (VIDEO_EXTENSIONS.has(ext)) {
|
|
70452
70632
|
try {
|
|
70453
70633
|
const mediaType = VIDEO_MEDIA_TYPES[ext] ?? "video/mp4";
|
|
@@ -70612,7 +70792,7 @@ function createReadTool(cwd2, readFiles, ops = localOperations, onFileRead, vide
|
|
|
70612
70792
|
async execute({ file_path, offset, limit: limit2 }, context) {
|
|
70613
70793
|
const resolved = resolvePath(cwd2, file_path);
|
|
70614
70794
|
await rejectSymlink(resolved);
|
|
70615
|
-
const ext =
|
|
70795
|
+
const ext = path13.extname(resolved).toLowerCase();
|
|
70616
70796
|
if (IMAGE_EXTENSIONS.has(ext)) {
|
|
70617
70797
|
try {
|
|
70618
70798
|
const rawBuffer = await fs12.readFile(resolved);
|
|
@@ -70739,7 +70919,7 @@ init_esm_shims();
|
|
|
70739
70919
|
// ../cli/dist/tools/write.js
|
|
70740
70920
|
init_esm_shims();
|
|
70741
70921
|
import fs13 from "fs/promises";
|
|
70742
|
-
import
|
|
70922
|
+
import path14 from "path";
|
|
70743
70923
|
|
|
70744
70924
|
// ../cli/dist/core/runtime-mode.js
|
|
70745
70925
|
init_esm_shims();
|
|
@@ -70801,9 +70981,9 @@ function createWriteTool(cwd2, readFiles, ops = localOperations, planModeRefOrOn
|
|
|
70801
70981
|
return goalModeMutationRestriction("write", goalMode);
|
|
70802
70982
|
}
|
|
70803
70983
|
if (isPlanModeActive(planModeRef)) {
|
|
70804
|
-
const plansDir =
|
|
70805
|
-
const relative =
|
|
70806
|
-
if (relative.startsWith("..") ||
|
|
70984
|
+
const plansDir = path14.join(cwd2, ".ezcoder", "plans");
|
|
70985
|
+
const relative = path14.relative(plansDir, resolved);
|
|
70986
|
+
if (relative.startsWith("..") || path14.isAbsolute(relative)) {
|
|
70807
70987
|
return `Error: write is restricted in plan mode. You can only write to .ezcoder/plans/. Got: ${file_path}`;
|
|
70808
70988
|
}
|
|
70809
70989
|
await fs13.mkdir(plansDir, { recursive: true });
|
|
@@ -70833,7 +71013,7 @@ function createWriteTool(cwd2, readFiles, ops = localOperations, planModeRefOrOn
|
|
|
70833
71013
|
|
|
70834
71014
|
// ../cli/dist/tools/edit.js
|
|
70835
71015
|
init_esm_shims();
|
|
70836
|
-
import
|
|
71016
|
+
import path15 from "path";
|
|
70837
71017
|
|
|
70838
71018
|
// ../cli/dist/tools/edit-diff.js
|
|
70839
71019
|
init_esm_shims();
|
|
@@ -70942,16 +71122,16 @@ var Diff = class {
|
|
|
70942
71122
|
}
|
|
70943
71123
|
}
|
|
70944
71124
|
}
|
|
70945
|
-
addToPath(
|
|
70946
|
-
const last =
|
|
71125
|
+
addToPath(path49, added, removed, oldPosInc, options) {
|
|
71126
|
+
const last = path49.lastComponent;
|
|
70947
71127
|
if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
70948
71128
|
return {
|
|
70949
|
-
oldPos:
|
|
71129
|
+
oldPos: path49.oldPos + oldPosInc,
|
|
70950
71130
|
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
70951
71131
|
};
|
|
70952
71132
|
} else {
|
|
70953
71133
|
return {
|
|
70954
|
-
oldPos:
|
|
71134
|
+
oldPos: path49.oldPos + oldPosInc,
|
|
70955
71135
|
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
70956
71136
|
};
|
|
70957
71137
|
}
|
|
@@ -71726,7 +71906,7 @@ function createEditTool(cwd2, readFiles, ops = localOperations, planModeRefOrOnF
|
|
|
71726
71906
|
const hasCRLF = original.includes("\r\n");
|
|
71727
71907
|
const originalNormalized = hasCRLF ? original.replace(/\r\n/g, "\n") : original;
|
|
71728
71908
|
let working = originalNormalized;
|
|
71729
|
-
const fileName =
|
|
71909
|
+
const fileName = path15.basename(resolved);
|
|
71730
71910
|
const outcomes = new Array(edits.length);
|
|
71731
71911
|
for (let i = 0; i < edits.length; i++) {
|
|
71732
71912
|
const { old_text, new_text, replace_all } = edits[i];
|
|
@@ -71828,7 +72008,7 @@ ${f.closestSnippet}`;
|
|
|
71828
72008
|
` : "";
|
|
71829
72009
|
throw new Error(header + formatFailures());
|
|
71830
72010
|
}
|
|
71831
|
-
const relPath =
|
|
72011
|
+
const relPath = path15.relative(cwd2, resolved);
|
|
71832
72012
|
const diff3 = generateDiff(originalNormalized, working, relPath);
|
|
71833
72013
|
const changed = working !== originalNormalized;
|
|
71834
72014
|
let diagnosticsNote = "";
|
|
@@ -72037,7 +72217,8 @@ Use task_output with id="${result.id}" to read output, task_send to type input/a
|
|
|
72037
72217
|
}
|
|
72038
72218
|
const effectiveTimeout = timeoutMs ?? DEFAULT_TIMEOUT;
|
|
72039
72219
|
return new Promise((resolve3) => {
|
|
72040
|
-
const
|
|
72220
|
+
const shell2 = resolveShell(command);
|
|
72221
|
+
const child = ops.spawn(shell2.file, shell2.args, {
|
|
72041
72222
|
cwd: cwd2,
|
|
72042
72223
|
detached: true,
|
|
72043
72224
|
stdio: ["ignore", "pipe", "pipe"],
|
|
@@ -72095,6 +72276,9 @@ ${output}`;
|
|
|
72095
72276
|
output = `[Truncated: showing last ${result.keptLines} of ${result.totalLines} lines.${overflowNotice}]
|
|
72096
72277
|
${output}`;
|
|
72097
72278
|
}
|
|
72279
|
+
if (shell2.isCmdFallback) {
|
|
72280
|
+
output = "[Ran under Windows cmd.exe \u2014 bash is unavailable. Use cmd syntax (dir, findstr, type); POSIX commands and quoting will fail. Install Git for Windows to get bash.]\n" + output;
|
|
72281
|
+
}
|
|
72098
72282
|
const exitCode = timedOut ? `TIMEOUT (${effectiveTimeout}ms)` : killed ? "KILLED" : String(code ?? 1);
|
|
72099
72283
|
resolve3(`Exit code: ${exitCode}
|
|
72100
72284
|
${output}`);
|
|
@@ -72113,7 +72297,7 @@ Failed to spawn: ${err.message}`);
|
|
|
72113
72297
|
// ../cli/dist/tools/find.js
|
|
72114
72298
|
init_esm_shims();
|
|
72115
72299
|
import fs14 from "fs/promises";
|
|
72116
|
-
import
|
|
72300
|
+
import path16 from "path";
|
|
72117
72301
|
var FindParams = external_exports.object({
|
|
72118
72302
|
pattern: external_exports.string().describe("Glob pattern to match files (e.g. '**/*.ts', 'src/**/*.tsx')"),
|
|
72119
72303
|
path: external_exports.string().optional().describe("Directory to search in (defaults to cwd)")
|
|
@@ -72159,7 +72343,7 @@ ${filtered.length} file(s) found`;
|
|
|
72159
72343
|
}
|
|
72160
72344
|
async function loadGitignore(dir) {
|
|
72161
72345
|
try {
|
|
72162
|
-
const content = await fs14.readFile(
|
|
72346
|
+
const content = await fs14.readFile(path16.join(dir, ".gitignore"), "utf-8");
|
|
72163
72347
|
return content.split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
72164
72348
|
} catch {
|
|
72165
72349
|
return [];
|
|
@@ -72169,7 +72353,7 @@ async function loadGitignore(dir) {
|
|
|
72169
72353
|
// ../cli/dist/tools/grep.js
|
|
72170
72354
|
init_esm_shims();
|
|
72171
72355
|
import readline from "readline";
|
|
72172
|
-
import
|
|
72356
|
+
import path17 from "path";
|
|
72173
72357
|
var GrepParams = external_exports.object({
|
|
72174
72358
|
pattern: external_exports.string().describe("Search pattern (regex supported)"),
|
|
72175
72359
|
path: external_exports.string().optional().describe("File or directory to search (defaults to cwd)"),
|
|
@@ -72225,10 +72409,10 @@ function createGrepTool(cwd2, ops = localOperations) {
|
|
|
72225
72409
|
}
|
|
72226
72410
|
scannedCandidates += 1;
|
|
72227
72411
|
const entry = typeof item === "string" ? item : item.path;
|
|
72228
|
-
const ext =
|
|
72412
|
+
const ext = path17.extname(entry).toLowerCase();
|
|
72229
72413
|
if (BINARY_EXTENSIONS.has(ext))
|
|
72230
72414
|
continue;
|
|
72231
|
-
const filePath =
|
|
72415
|
+
const filePath = path17.join(dir, entry);
|
|
72232
72416
|
const fileResults = await searchFile(filePath, regex2, cwd2, maxResults - results.length, ops);
|
|
72233
72417
|
results.push(...fileResults);
|
|
72234
72418
|
}
|
|
@@ -72238,7 +72422,7 @@ function createGrepTool(cwd2, ops = localOperations) {
|
|
|
72238
72422
|
}
|
|
72239
72423
|
async function searchFile(filePath, regex2, cwd2, maxResults, ops) {
|
|
72240
72424
|
const results = [];
|
|
72241
|
-
const relPath =
|
|
72425
|
+
const relPath = path17.relative(cwd2, filePath);
|
|
72242
72426
|
try {
|
|
72243
72427
|
const fileStat = await ops.stat(filePath);
|
|
72244
72428
|
if (fileStat.size > MAX_FILE_SIZE)
|
|
@@ -72300,7 +72484,7 @@ ${results.length} match(es) found`;
|
|
|
72300
72484
|
|
|
72301
72485
|
// ../cli/dist/tools/ls.js
|
|
72302
72486
|
init_esm_shims();
|
|
72303
|
-
import
|
|
72487
|
+
import path18 from "path";
|
|
72304
72488
|
var LsParams = external_exports.object({
|
|
72305
72489
|
path: external_exports.string().optional().describe("Directory path (defaults to cwd)"),
|
|
72306
72490
|
all: external_exports.boolean().optional().describe("Show hidden files (default: false)")
|
|
@@ -72322,7 +72506,7 @@ function createLsTool(cwd2, ops = localOperations) {
|
|
|
72322
72506
|
}
|
|
72323
72507
|
for (const file2 of files) {
|
|
72324
72508
|
try {
|
|
72325
|
-
const stat = await ops.stat(
|
|
72509
|
+
const stat = await ops.stat(path18.join(resolved, file2.name));
|
|
72326
72510
|
const size = formatSize(stat.size);
|
|
72327
72511
|
const type2 = file2.isSymbolicLink() ? "l" : "f";
|
|
72328
72512
|
lines.push(`${type2} ${size.padStart(8)} ${file2.name}`);
|
|
@@ -72350,25 +72534,22 @@ function formatSize(bytes) {
|
|
|
72350
72534
|
init_esm_shims();
|
|
72351
72535
|
import { spawn as spawn5 } from "child_process";
|
|
72352
72536
|
import { createInterface } from "readline";
|
|
72537
|
+
import { existsSync as existsSync3 } from "fs";
|
|
72538
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
72353
72539
|
var SUB_AGENT_MAX_TURNS = 10;
|
|
72354
72540
|
var SUB_AGENT_MAX_OUTPUT_CHARS = 1e5;
|
|
72355
72541
|
var SUB_AGENT_MAX_OUTPUT_LINES = 500;
|
|
72356
72542
|
var SUB_AGENT_MAX_STDERR_CHARS = 1e4;
|
|
72357
72543
|
var SUB_AGENT_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
72358
|
-
function
|
|
72359
|
-
|
|
72360
|
-
|
|
72361
|
-
function isGoalModeRef4(value) {
|
|
72362
|
-
return typeof value === "object" && value !== null && typeof value.current === "string";
|
|
72544
|
+
function resolveCliEntry() {
|
|
72545
|
+
const cliPath = fileURLToPath2(new URL("../cli.js", import.meta.url));
|
|
72546
|
+
return existsSync3(cliPath) ? cliPath : process.argv[1];
|
|
72363
72547
|
}
|
|
72364
72548
|
var SubAgentParams = external_exports.object({
|
|
72365
72549
|
task: external_exports.string().describe("The task to delegate to the sub-agent"),
|
|
72366
72550
|
agent: external_exports.string().optional().describe("Named agent definition to use (from ~/.ezcoder/agents/ or .ezcoder/agents/)")
|
|
72367
72551
|
});
|
|
72368
|
-
function createSubAgentTool(cwd2, agents,
|
|
72369
|
-
const getParentCacheKey = typeof getParentCacheKeyOrGoalModeRef === "function" ? getParentCacheKeyOrGoalModeRef : void 0;
|
|
72370
|
-
const goalModeRef = isGoalModeRef4(getParentCacheKeyOrGoalModeRef) ? getParentCacheKeyOrGoalModeRef : goalModeRefArg;
|
|
72371
|
-
const planModeRef = isPlanModeRef4(planModeRefArg) ? planModeRefArg : void 0;
|
|
72552
|
+
function createSubAgentTool(cwd2, agents, getParentProvider, getParentModel, getParentCacheKey, planModeRef, goalModeRef) {
|
|
72372
72553
|
const agentList = agents.map((a) => `- ${a.name}: ${a.description}`).join("\n");
|
|
72373
72554
|
const agentDesc = agentList ? `
|
|
72374
72555
|
|
|
@@ -72402,13 +72583,14 @@ ${agentList}` : "\n\nNo named agents configured.";
|
|
|
72402
72583
|
};
|
|
72403
72584
|
}
|
|
72404
72585
|
}
|
|
72405
|
-
const useProvider =
|
|
72586
|
+
const useProvider = getParentProvider();
|
|
72587
|
+
const useModel = getParentModel();
|
|
72406
72588
|
const cliArgs = [
|
|
72407
72589
|
"--json",
|
|
72408
72590
|
"--provider",
|
|
72409
72591
|
useProvider,
|
|
72410
72592
|
"--model",
|
|
72411
|
-
|
|
72593
|
+
useModel,
|
|
72412
72594
|
"--max-turns",
|
|
72413
72595
|
String(SUB_AGENT_MAX_TURNS)
|
|
72414
72596
|
];
|
|
@@ -72420,8 +72602,7 @@ ${agentList}` : "\n\nNo named agents configured.";
|
|
|
72420
72602
|
cliArgs.push("--system-prompt", agentDef.systemPrompt);
|
|
72421
72603
|
}
|
|
72422
72604
|
cliArgs.push(args.task);
|
|
72423
|
-
const
|
|
72424
|
-
const child = spawn5(process.execPath, [binPath, ...cliArgs], {
|
|
72605
|
+
const child = spawn5(process.execPath, [resolveCliEntry(), ...cliArgs], {
|
|
72425
72606
|
cwd: cwd2,
|
|
72426
72607
|
stdio: ["ignore", "pipe", "pipe"],
|
|
72427
72608
|
env: { ...process.env }
|
|
@@ -72436,7 +72617,7 @@ ${agentList}` : "\n\nNo named agents configured.";
|
|
|
72436
72617
|
log("INFO", "subagent", "Sub-agent spawn", {
|
|
72437
72618
|
cacheKey: subCacheKey,
|
|
72438
72619
|
provider: useProvider,
|
|
72439
|
-
model:
|
|
72620
|
+
model: useModel,
|
|
72440
72621
|
agent: agentDef?.name ?? "(default)"
|
|
72441
72622
|
});
|
|
72442
72623
|
let childExited = false;
|
|
@@ -73815,8 +73996,8 @@ function createWebSearchTool() {
|
|
|
73815
73996
|
// ../cli/dist/tools/source-path.js
|
|
73816
73997
|
init_esm_shims();
|
|
73817
73998
|
import { spawn as spawn6 } from "child_process";
|
|
73818
|
-
import
|
|
73819
|
-
import { fileURLToPath as
|
|
73999
|
+
import path19 from "path";
|
|
74000
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
73820
74001
|
var SOURCE_PATH_TIMEOUT_MS = 12e4;
|
|
73821
74002
|
var MAX_STDERR_CHARS = 1e4;
|
|
73822
74003
|
var OPENSRC_BIN_ENV = "EZ_CODER_OPENSRC_BIN";
|
|
@@ -73916,8 +74097,8 @@ function getBundledOpenSrcBinPath() {
|
|
|
73916
74097
|
const override = process.env[OPENSRC_BIN_ENV]?.trim() ?? process.env[LEGACY_OPENSRC_BIN_ENV]?.trim();
|
|
73917
74098
|
if (override)
|
|
73918
74099
|
return override;
|
|
73919
|
-
const currentDir =
|
|
73920
|
-
return
|
|
74100
|
+
const currentDir = path19.dirname(fileURLToPath3(import.meta.url));
|
|
74101
|
+
return path19.resolve(currentDir, "../../node_modules/opensrc/bin/opensrc.js");
|
|
73921
74102
|
}
|
|
73922
74103
|
function getOpenSrcEnv() {
|
|
73923
74104
|
return {
|
|
@@ -74001,7 +74182,7 @@ import { randomUUID as randomUUID2 } from "crypto";
|
|
|
74001
74182
|
init_esm_shims();
|
|
74002
74183
|
import { createHash } from "crypto";
|
|
74003
74184
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
|
74004
|
-
import { existsSync as
|
|
74185
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
74005
74186
|
import { homedir } from "os";
|
|
74006
74187
|
import { basename, join } from "path";
|
|
74007
74188
|
var DEFAULT_TASKS_BASE = join(homedir(), ".ezcoder", "tasks", "projects");
|
|
@@ -74068,7 +74249,7 @@ async function migrateLegacyTasksIfNeeded(cwd2) {
|
|
|
74068
74249
|
if (!legacyBase)
|
|
74069
74250
|
return null;
|
|
74070
74251
|
const targetFile = tasksFilePath(cwd2);
|
|
74071
|
-
if (
|
|
74252
|
+
if (existsSync4(targetFile))
|
|
74072
74253
|
return null;
|
|
74073
74254
|
const legacyTasks = await readTasksFromBase(cwd2, legacyBase);
|
|
74074
74255
|
if (!legacyTasks)
|
|
@@ -74208,7 +74389,7 @@ ${list}`;
|
|
|
74208
74389
|
|
|
74209
74390
|
// ../cli/dist/tools/screenshot.js
|
|
74210
74391
|
init_esm_shims();
|
|
74211
|
-
import
|
|
74392
|
+
import path20 from "path";
|
|
74212
74393
|
import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
|
|
74213
74394
|
var INSTALL_HINT = "Browser engine not installed. Add the optional dependency and download Chromium:\n pnpm add -w playwright && npx playwright install chromium\nThen retry the screenshot.";
|
|
74214
74395
|
var ActionInput = external_exports.object({
|
|
@@ -74246,7 +74427,7 @@ function isBrowserBinaryMissing(err) {
|
|
|
74246
74427
|
}
|
|
74247
74428
|
function defaultOutPath(cwd2) {
|
|
74248
74429
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
74249
|
-
return
|
|
74430
|
+
return path20.join(cwd2, ".ezcoder", "screenshots", `${stamp}.png`);
|
|
74250
74431
|
}
|
|
74251
74432
|
async function runActions(page, actions) {
|
|
74252
74433
|
for (const action of actions ?? []) {
|
|
@@ -74297,7 +74478,7 @@ function createScreenshotTool(cwd2) {
|
|
|
74297
74478
|
await runActions(page, args.actions);
|
|
74298
74479
|
const raw = await page.screenshot({ fullPage: args.full_page ?? false });
|
|
74299
74480
|
context.signal.removeEventListener("abort", onAbort);
|
|
74300
|
-
await mkdir2(
|
|
74481
|
+
await mkdir2(path20.dirname(outPath), { recursive: true });
|
|
74301
74482
|
await writeFile2(outPath, raw);
|
|
74302
74483
|
const { buffer, mediaType } = await shrinkToFit(raw, "image/png");
|
|
74303
74484
|
const previewBuffer = await downscaleForPreview(buffer);
|
|
@@ -74329,6 +74510,215 @@ function createScreenshotTool(cwd2) {
|
|
|
74329
74510
|
};
|
|
74330
74511
|
}
|
|
74331
74512
|
|
|
74513
|
+
// ../cli/dist/tools/generate-image.js
|
|
74514
|
+
init_esm_shims();
|
|
74515
|
+
import path21 from "path";
|
|
74516
|
+
import { mkdir as mkdir3, writeFile as writeFile3, readFile as readFile2 } from "fs/promises";
|
|
74517
|
+
var CODEX_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
|
|
74518
|
+
var IMAGE_GEN_MODEL = "gpt-5.5";
|
|
74519
|
+
var GenerateImageParams = external_exports.object({
|
|
74520
|
+
prompt: external_exports.string().describe("Text description of the image to generate or the edit to apply"),
|
|
74521
|
+
image: external_exports.string().optional().describe("Path to an existing image file to edit (use the path returned by a previous generate_image call, or a user-attached image path). When omitted, a new image is generated from scratch."),
|
|
74522
|
+
size: external_exports.string().optional().describe("Output resolution. gpt-image-2 accepts any size where both edges are multiples of 16px, max edge \u22643840px, long:short ratio \u22643:1, total pixels 655,360\u20138,294,400. Popular: 1024x1024, 1536x1024, 1024x1536, 2048x2048. Default: auto."),
|
|
74523
|
+
quality: external_exports.enum(["low", "medium", "high", "auto"]).optional().describe("Rendering quality. Use 'low' for fast drafts, 'high' for final assets. Default: auto."),
|
|
74524
|
+
n: external_exports.number().int().min(1).max(4).optional().describe("Number of images to generate (1\u20134, default 1)"),
|
|
74525
|
+
out_path: external_exports.string().optional().describe("Where to save the generated image (relative to cwd or absolute). Defaults to .gg/generated/<timestamp>.png"),
|
|
74526
|
+
output_format: external_exports.enum(["png", "jpeg", "webp"]).optional().describe("Output file format (default png)"),
|
|
74527
|
+
background: external_exports.enum(["opaque", "auto"]).optional().describe("Background type (default auto; gpt-image-2 does not support transparent)")
|
|
74528
|
+
});
|
|
74529
|
+
function defaultOutPath2(cwd2, format) {
|
|
74530
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
74531
|
+
const ext = format === "png" ? "png" : format === "jpeg" ? "jpg" : "webp";
|
|
74532
|
+
return path21.join(cwd2, ".ezcoder", "generated", `${stamp}.${ext}`);
|
|
74533
|
+
}
|
|
74534
|
+
function mediaTypeFor(format) {
|
|
74535
|
+
if (format === "jpeg")
|
|
74536
|
+
return "image/jpeg";
|
|
74537
|
+
if (format === "webp")
|
|
74538
|
+
return "image/webp";
|
|
74539
|
+
return "image/png";
|
|
74540
|
+
}
|
|
74541
|
+
function createGenerateImageTool(cwd2, auth2) {
|
|
74542
|
+
return {
|
|
74543
|
+
name: "generate_image",
|
|
74544
|
+
description: "Generate or edit images using OpenAI's gpt-image-2 model. Works even when a different chat provider is active \u2014 only requires OpenAI to be connected. Only use this tool when the user explicitly asks to create, generate, or edit an image. Pass `image` with a file path to edit an existing image (e.g. a previously generated one or a user attachment). Use `out_path` to save to a specific location (defaults to .gg/generated/).",
|
|
74545
|
+
parameters: GenerateImageParams,
|
|
74546
|
+
async execute(args, context) {
|
|
74547
|
+
if (context.signal.aborted)
|
|
74548
|
+
return "Image generation aborted before start.";
|
|
74549
|
+
let token;
|
|
74550
|
+
let accountId;
|
|
74551
|
+
try {
|
|
74552
|
+
const creds = await auth2.resolveCredentials("openai");
|
|
74553
|
+
token = creds.accessToken;
|
|
74554
|
+
accountId = creds.accountId;
|
|
74555
|
+
} catch {
|
|
74556
|
+
return "OpenAI is not connected. The user needs to connect their OpenAI account to use image generation.";
|
|
74557
|
+
}
|
|
74558
|
+
const outputFormat = args.output_format ?? "png";
|
|
74559
|
+
const mediaType = mediaTypeFor(outputFormat);
|
|
74560
|
+
const outPath = args.out_path ? resolvePath(cwd2, args.out_path) : defaultOutPath2(cwd2, outputFormat);
|
|
74561
|
+
try {
|
|
74562
|
+
const imageTool = {
|
|
74563
|
+
type: "image_generation",
|
|
74564
|
+
output_format: outputFormat
|
|
74565
|
+
};
|
|
74566
|
+
if (args.size)
|
|
74567
|
+
imageTool.size = args.size;
|
|
74568
|
+
if (args.quality)
|
|
74569
|
+
imageTool.quality = args.quality;
|
|
74570
|
+
if (args.n)
|
|
74571
|
+
imageTool.n = args.n;
|
|
74572
|
+
if (args.background)
|
|
74573
|
+
imageTool.background = args.background;
|
|
74574
|
+
const inputContent = [
|
|
74575
|
+
{ type: "input_text", text: args.prompt }
|
|
74576
|
+
];
|
|
74577
|
+
if (args.image) {
|
|
74578
|
+
const imagePath = resolvePath(cwd2, args.image);
|
|
74579
|
+
let fileBuffer;
|
|
74580
|
+
try {
|
|
74581
|
+
fileBuffer = await readFile2(imagePath);
|
|
74582
|
+
} catch {
|
|
74583
|
+
return `Could not read the image at ${args.image}. Check the path is correct.`;
|
|
74584
|
+
}
|
|
74585
|
+
const refMediaType = imagePath.toLowerCase().endsWith(".jpg") || imagePath.toLowerCase().endsWith(".jpeg") ? "image/jpeg" : imagePath.toLowerCase().endsWith(".webp") ? "image/webp" : "image/png";
|
|
74586
|
+
inputContent.push({
|
|
74587
|
+
type: "input_image",
|
|
74588
|
+
image_url: `data:${refMediaType};base64,${fileBuffer.toString("base64")}`
|
|
74589
|
+
});
|
|
74590
|
+
imageTool.action = "edit";
|
|
74591
|
+
} else {
|
|
74592
|
+
imageTool.action = "generate";
|
|
74593
|
+
}
|
|
74594
|
+
const imageBuffers = await callImageGeneration(inputContent, imageTool, token, accountId, context.signal);
|
|
74595
|
+
if (imageBuffers.length === 0) {
|
|
74596
|
+
return "Image generation returned no results. The prompt may have been blocked by content moderation.";
|
|
74597
|
+
}
|
|
74598
|
+
const savedPaths = [];
|
|
74599
|
+
for (let i = 0; i < imageBuffers.length; i++) {
|
|
74600
|
+
const buf = imageBuffers[i];
|
|
74601
|
+
const savePath = imageBuffers.length === 1 ? outPath : insertIndex(outPath, i);
|
|
74602
|
+
await mkdir3(path21.dirname(savePath), { recursive: true });
|
|
74603
|
+
await writeFile3(savePath, buf);
|
|
74604
|
+
savedPaths.push(savePath);
|
|
74605
|
+
}
|
|
74606
|
+
const primary = imageBuffers[0];
|
|
74607
|
+
const primaryPath = savedPaths[0];
|
|
74608
|
+
const { buffer: shrunk, mediaType: detectedType } = await shrinkToFit(primary, mediaType);
|
|
74609
|
+
const previewBuffer = await downscaleForPreview(shrunk);
|
|
74610
|
+
const imagePreviews = [
|
|
74611
|
+
{
|
|
74612
|
+
base64: previewBuffer.toString("base64"),
|
|
74613
|
+
mediaType: detectedType,
|
|
74614
|
+
path: primaryPath
|
|
74615
|
+
}
|
|
74616
|
+
];
|
|
74617
|
+
for (let i = 1; i < imageBuffers.length; i++) {
|
|
74618
|
+
const extraBuf = imageBuffers[i];
|
|
74619
|
+
const extraPath = savedPaths[i];
|
|
74620
|
+
const extraShrunk = await shrinkToFit(extraBuf, mediaType);
|
|
74621
|
+
const extraPreview = await downscaleForPreview(extraShrunk.buffer);
|
|
74622
|
+
imagePreviews.push({
|
|
74623
|
+
base64: extraPreview.toString("base64"),
|
|
74624
|
+
mediaType: extraShrunk.mediaType,
|
|
74625
|
+
path: extraPath
|
|
74626
|
+
});
|
|
74627
|
+
}
|
|
74628
|
+
const summary = savedPaths.length === 1 ? `Generated image \u2192 ${primaryPath}` : `Generated ${savedPaths.length} images \u2192 ${savedPaths.join(", ")}`;
|
|
74629
|
+
const allContent = [
|
|
74630
|
+
{ type: "text", text: summary },
|
|
74631
|
+
{
|
|
74632
|
+
type: "image",
|
|
74633
|
+
mediaType: detectedType,
|
|
74634
|
+
data: shrunk.toString("base64")
|
|
74635
|
+
}
|
|
74636
|
+
];
|
|
74637
|
+
return {
|
|
74638
|
+
content: allContent,
|
|
74639
|
+
details: { imagePreviews }
|
|
74640
|
+
};
|
|
74641
|
+
} catch (err) {
|
|
74642
|
+
if (context.signal.aborted)
|
|
74643
|
+
return "Image generation aborted.";
|
|
74644
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
74645
|
+
return `Image generation failed: ${reason}`;
|
|
74646
|
+
}
|
|
74647
|
+
}
|
|
74648
|
+
};
|
|
74649
|
+
}
|
|
74650
|
+
function insertIndex(filePath, index) {
|
|
74651
|
+
const ext = path21.extname(filePath);
|
|
74652
|
+
const base = filePath.slice(0, filePath.length - ext.length);
|
|
74653
|
+
return `${base}_${index}${ext}`;
|
|
74654
|
+
}
|
|
74655
|
+
async function callImageGeneration(inputContent, imageTool, token, accountId, signal) {
|
|
74656
|
+
const body = {
|
|
74657
|
+
model: IMAGE_GEN_MODEL,
|
|
74658
|
+
store: false,
|
|
74659
|
+
stream: true,
|
|
74660
|
+
instructions: "Generate the image the user requested.",
|
|
74661
|
+
input: [{ role: "user", content: inputContent }],
|
|
74662
|
+
tools: [imageTool],
|
|
74663
|
+
tool_choice: "auto",
|
|
74664
|
+
reasoning: { effort: "low" }
|
|
74665
|
+
};
|
|
74666
|
+
const response = await fetch(CODEX_ENDPOINT, {
|
|
74667
|
+
method: "POST",
|
|
74668
|
+
headers: {
|
|
74669
|
+
"Content-Type": "application/json",
|
|
74670
|
+
Authorization: `Bearer ${token}`,
|
|
74671
|
+
...accountId ? { "chatgpt-account-id": accountId } : {},
|
|
74672
|
+
originator: "ezcoder"
|
|
74673
|
+
},
|
|
74674
|
+
body: JSON.stringify(body),
|
|
74675
|
+
signal
|
|
74676
|
+
});
|
|
74677
|
+
if (!response.ok) {
|
|
74678
|
+
const text = await response.text();
|
|
74679
|
+
let detail = text;
|
|
74680
|
+
try {
|
|
74681
|
+
const parsed = JSON.parse(text);
|
|
74682
|
+
if (parsed.detail)
|
|
74683
|
+
detail = parsed.detail;
|
|
74684
|
+
else if (parsed.error?.message)
|
|
74685
|
+
detail = parsed.error.message;
|
|
74686
|
+
} catch {
|
|
74687
|
+
}
|
|
74688
|
+
throw new Error(`OpenAI Image API (${response.status}): ${detail}`);
|
|
74689
|
+
}
|
|
74690
|
+
if (!response.body) {
|
|
74691
|
+
throw new Error("OpenAI Image API returned no response body.");
|
|
74692
|
+
}
|
|
74693
|
+
const reader = response.body.getReader();
|
|
74694
|
+
const decoder = new TextDecoder();
|
|
74695
|
+
let buffer = "";
|
|
74696
|
+
const imageBuffers = [];
|
|
74697
|
+
while (true) {
|
|
74698
|
+
const { done, value } = await reader.read();
|
|
74699
|
+
if (done)
|
|
74700
|
+
break;
|
|
74701
|
+
buffer += decoder.decode(value, { stream: true });
|
|
74702
|
+
const lines = buffer.split("\n");
|
|
74703
|
+
buffer = lines.pop() ?? "";
|
|
74704
|
+
for (const line of lines) {
|
|
74705
|
+
if (!line.startsWith("data: "))
|
|
74706
|
+
continue;
|
|
74707
|
+
const data = line.slice(6);
|
|
74708
|
+
if (data === "[DONE]")
|
|
74709
|
+
continue;
|
|
74710
|
+
try {
|
|
74711
|
+
const evt = JSON.parse(data);
|
|
74712
|
+
if (evt.type === "response.output_item.done" && evt.item?.type === "image_generation_call" && evt.item.result) {
|
|
74713
|
+
imageBuffers.push(Buffer.from(evt.item.result, "base64"));
|
|
74714
|
+
}
|
|
74715
|
+
} catch {
|
|
74716
|
+
}
|
|
74717
|
+
}
|
|
74718
|
+
}
|
|
74719
|
+
return imageBuffers;
|
|
74720
|
+
}
|
|
74721
|
+
|
|
74332
74722
|
// ../cli/dist/tools/enter-plan.js
|
|
74333
74723
|
init_esm_shims();
|
|
74334
74724
|
var EnterPlanParams = external_exports.object({
|
|
@@ -74353,7 +74743,7 @@ function createEnterPlanTool(onEnterPlan) {
|
|
|
74353
74743
|
// ../cli/dist/tools/exit-plan.js
|
|
74354
74744
|
init_esm_shims();
|
|
74355
74745
|
import fs15 from "fs/promises";
|
|
74356
|
-
import
|
|
74746
|
+
import path23 from "path";
|
|
74357
74747
|
var ExitPlanParams = external_exports.object({
|
|
74358
74748
|
plan_path: external_exports.string().describe("Path to the plan markdown file; must be under .ezcoder/plans/")
|
|
74359
74749
|
});
|
|
@@ -74365,9 +74755,9 @@ function createExitPlanTool(cwd2, onExitPlan) {
|
|
|
74365
74755
|
executionMode: "sequential",
|
|
74366
74756
|
async execute({ plan_path }) {
|
|
74367
74757
|
const resolved = resolvePath(cwd2, plan_path);
|
|
74368
|
-
const plansDir =
|
|
74369
|
-
const relative =
|
|
74370
|
-
if (relative.startsWith("..") ||
|
|
74758
|
+
const plansDir = path23.join(cwd2, ".ezcoder", "plans");
|
|
74759
|
+
const relative = path23.relative(plansDir, resolved);
|
|
74760
|
+
if (relative.startsWith("..") || path23.isAbsolute(relative)) {
|
|
74371
74761
|
return `Error: plan_path must be under .ezcoder/plans/. Got: ${plan_path}`;
|
|
74372
74762
|
}
|
|
74373
74763
|
try {
|
|
@@ -74393,7 +74783,7 @@ init_esm_shims();
|
|
|
74393
74783
|
// ../cli/dist/core/goal-store.js
|
|
74394
74784
|
init_esm_shims();
|
|
74395
74785
|
import { createHash as createHash2, randomUUID as randomUUID3 } from "crypto";
|
|
74396
|
-
import { mkdir as
|
|
74786
|
+
import { mkdir as mkdir4, open, readdir, readFile as readFile3, rename, rm, writeFile as writeFile4 } from "fs/promises";
|
|
74397
74787
|
import { homedir as homedir2 } from "os";
|
|
74398
74788
|
import { basename as basename2, join as join2, resolve } from "path";
|
|
74399
74789
|
var GOALS_BASE_ENV = "GG_GOALS_BASE";
|
|
@@ -74644,7 +75034,7 @@ async function writeGoalRunsFile(cwd2, runs) {
|
|
|
74644
75034
|
const normalizedCwd = normalizeProjectPath(cwd2);
|
|
74645
75035
|
const dir = projectDir(normalizedCwd);
|
|
74646
75036
|
await withGoalStoreLock(dir, async () => {
|
|
74647
|
-
await
|
|
75037
|
+
await mkdir4(dir, { recursive: true });
|
|
74648
75038
|
const goalsPath = join2(dir, "goals.json");
|
|
74649
75039
|
const existingRuns = await readGoalRunsFile(normalizedCwd);
|
|
74650
75040
|
const omittedActive = omittedActiveGoalRuns(existingRuns, runs);
|
|
@@ -74678,7 +75068,7 @@ async function writeGoalRunsFile(cwd2, runs) {
|
|
|
74678
75068
|
});
|
|
74679
75069
|
}
|
|
74680
75070
|
async function withGoalStoreLock(dir, fn) {
|
|
74681
|
-
await
|
|
75071
|
+
await mkdir4(dir, { recursive: true });
|
|
74682
75072
|
const lockPath = join2(dir, "goals.lock");
|
|
74683
75073
|
const deadline = Date.now() + 1e4;
|
|
74684
75074
|
for (; ; ) {
|
|
@@ -74702,15 +75092,15 @@ ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
|
74702
75092
|
}
|
|
74703
75093
|
}
|
|
74704
75094
|
}
|
|
74705
|
-
async function atomicWriteJson(
|
|
74706
|
-
const tmpPath = `${
|
|
74707
|
-
await
|
|
74708
|
-
await rename(tmpPath,
|
|
75095
|
+
async function atomicWriteJson(path49, value) {
|
|
75096
|
+
const tmpPath = `${path49}.${process.pid}.${Date.now()}.tmp`;
|
|
75097
|
+
await writeFile4(tmpPath, JSON.stringify(value, null, 2) + "\n", "utf-8");
|
|
75098
|
+
await rename(tmpPath, path49);
|
|
74709
75099
|
}
|
|
74710
75100
|
async function readGoalRunsFile(cwd2) {
|
|
74711
75101
|
const normalizedCwd = normalizeProjectPath(cwd2);
|
|
74712
75102
|
try {
|
|
74713
|
-
const data = await
|
|
75103
|
+
const data = await readFile3(join2(projectDir(normalizedCwd), "goals.json"), "utf-8");
|
|
74714
75104
|
const parsed = JSON.parse(data);
|
|
74715
75105
|
if (!Array.isArray(parsed))
|
|
74716
75106
|
return [];
|
|
@@ -74736,7 +75126,7 @@ async function discoverGoalRunsById(id2) {
|
|
|
74736
75126
|
const dir = join2(goalsBaseDir(), entry.name);
|
|
74737
75127
|
const meta3 = await readProjectMeta(dir);
|
|
74738
75128
|
const fallbackProjectPath = meta3?.path ?? dir;
|
|
74739
|
-
const data = await
|
|
75129
|
+
const data = await readFile3(join2(dir, "goals.json"), "utf-8");
|
|
74740
75130
|
const parsed = JSON.parse(data);
|
|
74741
75131
|
if (!Array.isArray(parsed))
|
|
74742
75132
|
continue;
|
|
@@ -74756,7 +75146,7 @@ async function discoverGoalRunsById(id2) {
|
|
|
74756
75146
|
}
|
|
74757
75147
|
async function readProjectMeta(dir) {
|
|
74758
75148
|
try {
|
|
74759
|
-
const parsed = JSON.parse(await
|
|
75149
|
+
const parsed = JSON.parse(await readFile3(join2(dir, "meta.json"), "utf-8"));
|
|
74760
75150
|
return isObject2(parsed) && typeof parsed.path === "string" ? { path: parsed.path } : null;
|
|
74761
75151
|
} catch {
|
|
74762
75152
|
return null;
|
|
@@ -74966,8 +75356,8 @@ function formatGoalBlockingPrerequisites(run) {
|
|
|
74966
75356
|
}
|
|
74967
75357
|
async function writeGoalProgressJournalFromRun(cwd2, run) {
|
|
74968
75358
|
const dir = join2(projectDir(cwd2), "journals");
|
|
74969
|
-
await
|
|
74970
|
-
const
|
|
75359
|
+
await mkdir4(dir, { recursive: true });
|
|
75360
|
+
const path49 = join2(dir, `${run.id}.md`);
|
|
74971
75361
|
const lines = [
|
|
74972
75362
|
`# ${run.title}`,
|
|
74973
75363
|
"",
|
|
@@ -74996,8 +75386,8 @@ async function writeGoalProgressJournalFromRun(cwd2, run) {
|
|
|
74996
75386
|
...run.evidence.slice(-10).map((item) => `- ${item.createdAt} [${item.kind}] ${item.label}${item.path ? ` (${item.path})` : ""}${item.content ? ` \u2014 ${item.content}` : ""}`),
|
|
74997
75387
|
""
|
|
74998
75388
|
];
|
|
74999
|
-
await
|
|
75000
|
-
return
|
|
75389
|
+
await writeFile4(path49, lines.join("\n"), "utf-8");
|
|
75390
|
+
return path49;
|
|
75001
75391
|
}
|
|
75002
75392
|
|
|
75003
75393
|
// ../cli/dist/core/goal-controller.js
|
|
@@ -76135,7 +76525,7 @@ function createGoalsTool(cwd2, goalModeRef) {
|
|
|
76135
76525
|
}
|
|
76136
76526
|
|
|
76137
76527
|
// ../cli/dist/tools/index.js
|
|
76138
|
-
function createTools(cwd2, opts) {
|
|
76528
|
+
async function createTools(cwd2, opts) {
|
|
76139
76529
|
const readFiles = /* @__PURE__ */ new Map();
|
|
76140
76530
|
const processManager = new ProcessManager();
|
|
76141
76531
|
const ops = opts?.operations ?? localOperations;
|
|
@@ -76166,7 +76556,7 @@ function createTools(cwd2, opts) {
|
|
|
76166
76556
|
tools.push(createWebSearchTool());
|
|
76167
76557
|
}
|
|
76168
76558
|
if (opts?.agents && opts.agents.length > 0 && opts.provider && opts.model) {
|
|
76169
|
-
tools.push(createSubAgentTool(cwd2, opts.agents, opts.provider, opts.model, opts.getCacheKey, planModeRef, goalModeRef));
|
|
76559
|
+
tools.push(createSubAgentTool(cwd2, opts.agents, () => opts.getProvider?.() ?? opts.provider, () => opts.getModel?.() ?? opts.model, opts.getCacheKey, planModeRef, goalModeRef));
|
|
76170
76560
|
}
|
|
76171
76561
|
if (opts?.skills && opts.skills.length > 0) {
|
|
76172
76562
|
tools.push(createSkillTool(opts.skills));
|
|
@@ -76177,6 +76567,14 @@ function createTools(cwd2, opts) {
|
|
|
76177
76567
|
if (opts?.onExitPlan) {
|
|
76178
76568
|
tools.push(createExitPlanTool(cwd2, opts.onExitPlan));
|
|
76179
76569
|
}
|
|
76570
|
+
if (opts?.authStorage) {
|
|
76571
|
+
try {
|
|
76572
|
+
if (await opts.authStorage.hasProviderAuth("openai")) {
|
|
76573
|
+
tools.push(createGenerateImageTool(cwd2, opts.authStorage));
|
|
76574
|
+
}
|
|
76575
|
+
} catch {
|
|
76576
|
+
}
|
|
76577
|
+
}
|
|
76180
76578
|
const rebuildReadTool = (model) => createReadTool(cwd2, readFiles, ops, opts?.onFileRead, getVideoByteLimit(model));
|
|
76181
76579
|
return { tools, processManager, rebuildReadTool, lspManager };
|
|
76182
76580
|
}
|
|
@@ -76184,18 +76582,18 @@ function createTools(cwd2, opts) {
|
|
|
76184
76582
|
// ../cli/dist/system-prompt.js
|
|
76185
76583
|
init_esm_shims();
|
|
76186
76584
|
import fs20 from "fs/promises";
|
|
76187
|
-
import
|
|
76585
|
+
import path28 from "path";
|
|
76188
76586
|
|
|
76189
76587
|
// ../cli/dist/core/skills.js
|
|
76190
76588
|
init_esm_shims();
|
|
76191
76589
|
import fs16 from "fs/promises";
|
|
76192
|
-
import
|
|
76590
|
+
import path24 from "path";
|
|
76193
76591
|
async function discoverSkills(options) {
|
|
76194
76592
|
const skills = [];
|
|
76195
76593
|
const globalSkills = await loadSkillsFromDir(options.globalSkillsDir, "global");
|
|
76196
76594
|
skills.push(...globalSkills);
|
|
76197
76595
|
if (options.projectDir) {
|
|
76198
|
-
const projectSkillsDir =
|
|
76596
|
+
const projectSkillsDir = path24.join(options.projectDir, ".ezcoder", "skills");
|
|
76199
76597
|
const projectSkills = await loadSkillsFromDir(projectSkillsDir, "project");
|
|
76200
76598
|
skills.push(...projectSkills);
|
|
76201
76599
|
}
|
|
@@ -76210,20 +76608,20 @@ async function loadSkillsFromDir(dir, source2) {
|
|
|
76210
76608
|
return skills;
|
|
76211
76609
|
}
|
|
76212
76610
|
for (const entry of dirents) {
|
|
76213
|
-
const entryPath =
|
|
76611
|
+
const entryPath = path24.join(dir, entry.name);
|
|
76214
76612
|
if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
76215
76613
|
try {
|
|
76216
76614
|
const content = await fs16.readFile(entryPath, "utf-8");
|
|
76217
76615
|
const skill = parseSkillFile(content, source2);
|
|
76218
76616
|
if (!skill.name)
|
|
76219
|
-
skill.name =
|
|
76617
|
+
skill.name = path24.basename(entry.name, ".md");
|
|
76220
76618
|
skills.push(skill);
|
|
76221
76619
|
} catch {
|
|
76222
76620
|
}
|
|
76223
76621
|
continue;
|
|
76224
76622
|
}
|
|
76225
76623
|
if (entry.isDirectory()) {
|
|
76226
|
-
const skillFile =
|
|
76624
|
+
const skillFile = path24.join(entryPath, "SKILL.md");
|
|
76227
76625
|
try {
|
|
76228
76626
|
const content = await fs16.readFile(skillFile, "utf-8");
|
|
76229
76627
|
const skill = parseSkillFile(content, source2);
|
|
@@ -76284,6 +76682,7 @@ var TOOL_PROMPT_HINTS = {
|
|
|
76284
76682
|
exit_plan: "Submit a .ezcoder/plans/ markdown plan for user approval and leave plan mode.",
|
|
76285
76683
|
subagent: "Delegate focused, isolated subtasks (research, parallel exploration).",
|
|
76286
76684
|
skill: "Invoke a named skill for specialized instructions.",
|
|
76685
|
+
generate_image: "Generate or edit images using OpenAI's gpt-image-2 model. Only use when the user explicitly asks to create or edit an image \u2014 never generate images proactively. Requires OpenAI to be connected. Pass `image` with a file path to edit an existing image. Save with `out_path`.",
|
|
76287
76686
|
"mcp__kencode-search__referenceSources": "Get curated, categorized reference repos for examples, inspiration, architecture, UI, agents, SaaS, workflows, and domain patterns. Repo-only starting points; fetch docs/source, then verify code with searchCode.",
|
|
76288
76687
|
"mcp__kencode-search__discoverRepos": "Search GitHub repos live by keyword/language/topic/stars/recency. Use for current/top repos or long-tail discovery; returns metadata, not snippets. Follow with docs/source and searchCode.",
|
|
76289
76688
|
"mcp__kencode-search__searchCode": "Verify public GitHub code by literal text or RE2 regex; NOT semantic. Put code/import/API tokens in `query`; `path` is a literal file-path substring, not a concept. Start broad/peek, then narrow by repo/path. RE2 multi-line needs `(?s)`."
|
|
@@ -76318,6 +76717,7 @@ var DEFAULT_TOOL_NAMES = [
|
|
|
76318
76717
|
"exit_plan",
|
|
76319
76718
|
"subagent",
|
|
76320
76719
|
"skill",
|
|
76720
|
+
"generate_image",
|
|
76321
76721
|
"mcp__kencode-search__referenceSources",
|
|
76322
76722
|
"mcp__kencode-search__discoverRepos",
|
|
76323
76723
|
"mcp__kencode-search__searchCode"
|
|
@@ -76326,12 +76726,12 @@ var DEFAULT_TOOL_NAMES = [
|
|
|
76326
76726
|
// ../cli/dist/core/style-packs/index.js
|
|
76327
76727
|
init_esm_shims();
|
|
76328
76728
|
import fs18 from "fs";
|
|
76329
|
-
import
|
|
76729
|
+
import path26 from "path";
|
|
76330
76730
|
|
|
76331
76731
|
// ../cli/dist/core/language-detector.js
|
|
76332
76732
|
init_esm_shims();
|
|
76333
76733
|
import fs17 from "fs";
|
|
76334
|
-
import
|
|
76734
|
+
import path25 from "path";
|
|
76335
76735
|
var MARKERS = {
|
|
76336
76736
|
typescript: { manifests: ["tsconfig.json"], extensions: [".ts", ".tsx", ".mts", ".cts"] },
|
|
76337
76737
|
// JS is only flagged when there's a package.json AND no tsconfig — pure JS projects.
|
|
@@ -76619,7 +77019,7 @@ var PACKS = {
|
|
|
76619
77019
|
|
|
76620
77020
|
// ../cli/dist/core/style-packs/index.js
|
|
76621
77021
|
function loadPack(id2, cwd2) {
|
|
76622
|
-
const overridePath =
|
|
77022
|
+
const overridePath = path26.join(cwd2, ".ezcoder", "styles", `${id2}.md`);
|
|
76623
77023
|
try {
|
|
76624
77024
|
const stat = fs18.statSync(overridePath);
|
|
76625
77025
|
if (stat.isFile()) {
|
|
@@ -76663,7 +77063,7 @@ Universal rules for agent-written code:
|
|
|
76663
77063
|
// ../cli/dist/core/verify-commands.js
|
|
76664
77064
|
init_esm_shims();
|
|
76665
77065
|
import fs19 from "fs";
|
|
76666
|
-
import
|
|
77066
|
+
import path27 from "path";
|
|
76667
77067
|
function detectVerifyCommands(cwd2, active) {
|
|
76668
77068
|
const cmds = [];
|
|
76669
77069
|
if (active.has("typescript") || active.has("javascript")) {
|
|
@@ -76690,12 +77090,12 @@ function detectVerifyCommands(cwd2, active) {
|
|
|
76690
77090
|
const testScript = pick2("test", "test:unit");
|
|
76691
77091
|
if (testScript)
|
|
76692
77092
|
cmds.push({ label: "test", command: `${runner} ${testScript}`, language: lang });
|
|
76693
|
-
} else if (active.has("typescript") && fileExists2(
|
|
77093
|
+
} else if (active.has("typescript") && fileExists2(path27.join(cwd2, "tsconfig.json"))) {
|
|
76694
77094
|
cmds.push({ label: "typecheck", command: "tsc --noEmit", language: "typescript" });
|
|
76695
77095
|
}
|
|
76696
77096
|
}
|
|
76697
77097
|
if (active.has("python")) {
|
|
76698
|
-
const pyproject = readFileSafe(
|
|
77098
|
+
const pyproject = readFileSafe(path27.join(cwd2, "pyproject.toml"));
|
|
76699
77099
|
if (pyproject) {
|
|
76700
77100
|
if (/\[tool\.ruff/.test(pyproject)) {
|
|
76701
77101
|
cmds.push({ label: "lint", command: "ruff check .", language: "python" });
|
|
@@ -76727,10 +77127,10 @@ function detectVerifyCommands(cwd2, active) {
|
|
|
76727
77127
|
}
|
|
76728
77128
|
if (active.has("java") || active.has("kotlin")) {
|
|
76729
77129
|
const lang = active.has("kotlin") ? "kotlin" : "java";
|
|
76730
|
-
if (fileExists2(
|
|
77130
|
+
if (fileExists2(path27.join(cwd2, "gradlew"))) {
|
|
76731
77131
|
cmds.push({ label: "build", command: "./gradlew build", language: lang });
|
|
76732
77132
|
cmds.push({ label: "test", command: "./gradlew test", language: lang });
|
|
76733
|
-
} else if (fileExists2(
|
|
77133
|
+
} else if (fileExists2(path27.join(cwd2, "pom.xml"))) {
|
|
76734
77134
|
cmds.push({ label: "verify", command: "mvn verify", language: lang });
|
|
76735
77135
|
}
|
|
76736
77136
|
}
|
|
@@ -76744,7 +77144,7 @@ function detectVerifyCommands(cwd2, active) {
|
|
|
76744
77144
|
cmds.push({ label: "test", command: "dotnet test", language: "csharp" });
|
|
76745
77145
|
}
|
|
76746
77146
|
if (active.has("ruby")) {
|
|
76747
|
-
if (fileExists2(
|
|
77147
|
+
if (fileExists2(path27.join(cwd2, "Gemfile"))) {
|
|
76748
77148
|
cmds.push({ label: "lint", command: "bundle exec rubocop", language: "ruby" });
|
|
76749
77149
|
cmds.push({ label: "test", command: "bundle exec rspec", language: "ruby" });
|
|
76750
77150
|
}
|
|
@@ -76754,7 +77154,7 @@ function detectVerifyCommands(cwd2, active) {
|
|
|
76754
77154
|
cmds.push({ label: "test", command: "mix test", language: "elixir" });
|
|
76755
77155
|
}
|
|
76756
77156
|
if (active.has("php")) {
|
|
76757
|
-
if (fileExists2(
|
|
77157
|
+
if (fileExists2(path27.join(cwd2, "composer.json"))) {
|
|
76758
77158
|
cmds.push({ label: "test", command: "composer test", language: "php" });
|
|
76759
77159
|
}
|
|
76760
77160
|
}
|
|
@@ -76786,7 +77186,7 @@ function readFileSafe(p) {
|
|
|
76786
77186
|
}
|
|
76787
77187
|
}
|
|
76788
77188
|
function readPackageJsonScripts(cwd2) {
|
|
76789
|
-
const raw = readFileSafe(
|
|
77189
|
+
const raw = readFileSafe(path27.join(cwd2, "package.json"));
|
|
76790
77190
|
if (!raw)
|
|
76791
77191
|
return null;
|
|
76792
77192
|
try {
|
|
@@ -76797,11 +77197,11 @@ function readPackageJsonScripts(cwd2) {
|
|
|
76797
77197
|
}
|
|
76798
77198
|
}
|
|
76799
77199
|
function detectNodeRunner(cwd2) {
|
|
76800
|
-
if (fileExists2(
|
|
77200
|
+
if (fileExists2(path27.join(cwd2, "pnpm-lock.yaml")))
|
|
76801
77201
|
return "pnpm";
|
|
76802
|
-
if (fileExists2(
|
|
77202
|
+
if (fileExists2(path27.join(cwd2, "yarn.lock")))
|
|
76803
77203
|
return "yarn";
|
|
76804
|
-
if (fileExists2(
|
|
77204
|
+
if (fileExists2(path27.join(cwd2, "bun.lockb")))
|
|
76805
77205
|
return "bun";
|
|
76806
77206
|
return "npm run";
|
|
76807
77207
|
}
|
|
@@ -77009,17 +77409,17 @@ async function collectProjectContext(cwd2) {
|
|
|
77009
77409
|
while (!visited.has(dir)) {
|
|
77010
77410
|
visited.add(dir);
|
|
77011
77411
|
for (const name of CONTEXT_FILES) {
|
|
77012
|
-
const filePath =
|
|
77412
|
+
const filePath = path28.join(dir, name);
|
|
77013
77413
|
try {
|
|
77014
77414
|
const content = await fs20.readFile(filePath, "utf-8");
|
|
77015
|
-
const relPath =
|
|
77415
|
+
const relPath = path28.relative(cwd2, filePath) || name;
|
|
77016
77416
|
contextParts.push(`### ${relPath}
|
|
77017
77417
|
|
|
77018
77418
|
${content.trim()}`);
|
|
77019
77419
|
} catch {
|
|
77020
77420
|
}
|
|
77021
77421
|
}
|
|
77022
|
-
const parent =
|
|
77422
|
+
const parent = path28.dirname(dir);
|
|
77023
77423
|
if (parent === dir)
|
|
77024
77424
|
break;
|
|
77025
77425
|
dir = parent;
|
|
@@ -77093,10 +77493,10 @@ async function buildSystemPrompt(cwd2, skills, planMode, approvedPlanPath, toolN
|
|
|
77093
77493
|
// ../cli/dist/session.js
|
|
77094
77494
|
init_esm_shims();
|
|
77095
77495
|
import fs21 from "fs/promises";
|
|
77096
|
-
import
|
|
77496
|
+
import path29 from "path";
|
|
77097
77497
|
import os7 from "os";
|
|
77098
77498
|
import crypto4 from "crypto";
|
|
77099
|
-
var SESSION_DIR =
|
|
77499
|
+
var SESSION_DIR = path29.join(os7.homedir(), ".ezcoder", "sessions");
|
|
77100
77500
|
|
|
77101
77501
|
// ../cli/dist/core/index.js
|
|
77102
77502
|
init_esm_shims();
|
|
@@ -77164,7 +77564,8 @@ var EventBus = class {
|
|
|
77164
77564
|
toolCallId: event.toolCallId,
|
|
77165
77565
|
result: event.result,
|
|
77166
77566
|
isError: event.isError,
|
|
77167
|
-
durationMs: event.durationMs
|
|
77567
|
+
durationMs: event.durationMs,
|
|
77568
|
+
details: event.details
|
|
77168
77569
|
});
|
|
77169
77570
|
break;
|
|
77170
77571
|
case "turn_end":
|
|
@@ -77213,7 +77614,7 @@ import fs23 from "fs/promises";
|
|
|
77213
77614
|
|
|
77214
77615
|
// ../cli/dist/config.js
|
|
77215
77616
|
init_esm_shims();
|
|
77216
|
-
import
|
|
77617
|
+
import path30 from "path";
|
|
77217
77618
|
import fs22 from "fs/promises";
|
|
77218
77619
|
import fsSync from "fs";
|
|
77219
77620
|
async function ensureAppDirs() {
|
|
@@ -77279,7 +77680,7 @@ Rules:
|
|
|
77279
77680
|
`
|
|
77280
77681
|
};
|
|
77281
77682
|
for (const [filename, content] of Object.entries(defaults2)) {
|
|
77282
|
-
const filePath =
|
|
77683
|
+
const filePath = path30.join(agentsDir, filename);
|
|
77283
77684
|
try {
|
|
77284
77685
|
await fs22.access(filePath);
|
|
77285
77686
|
} catch {
|
|
@@ -77292,7 +77693,7 @@ async function seedDefaultSkills(skillsDir) {
|
|
|
77292
77693
|
"find-skills.md": FIND_SKILLS_MD
|
|
77293
77694
|
};
|
|
77294
77695
|
for (const [filename, content] of Object.entries(defaults2)) {
|
|
77295
|
-
const filePath =
|
|
77696
|
+
const filePath = path30.join(skillsDir, filename);
|
|
77296
77697
|
try {
|
|
77297
77698
|
await fs22.access(filePath);
|
|
77298
77699
|
} catch {
|
|
@@ -77420,7 +77821,11 @@ var SettingsSchema = external_exports.object({
|
|
|
77420
77821
|
lspDiagnostics: external_exports.boolean().default(true),
|
|
77421
77822
|
enabledTools: external_exports.array(external_exports.string()).optional(),
|
|
77422
77823
|
/** Delete session transcripts older than this many days at startup. 0 disables pruning. */
|
|
77423
|
-
sessionRetentionDays: external_exports.number().int().min(0).default(30)
|
|
77824
|
+
sessionRetentionDays: external_exports.number().int().min(0).default(30),
|
|
77825
|
+
/** Speed optimization profile.
|
|
77826
|
+
* - "baseline": 5-min cache TTL, no pre-warm
|
|
77827
|
+
* - "optimized": 1-h cache TTL, cache pre-warming on first prompt (default) */
|
|
77828
|
+
speedProfile: external_exports.enum(["baseline", "optimized"]).default("optimized")
|
|
77424
77829
|
});
|
|
77425
77830
|
var DEFAULT_SETTINGS = {
|
|
77426
77831
|
autoCompact: true,
|
|
@@ -77433,7 +77838,8 @@ var DEFAULT_SETTINGS = {
|
|
|
77433
77838
|
idealReviewEnabled: true,
|
|
77434
77839
|
autoApprovePlans: true,
|
|
77435
77840
|
lspDiagnostics: true,
|
|
77436
|
-
sessionRetentionDays: 30
|
|
77841
|
+
sessionRetentionDays: 30,
|
|
77842
|
+
speedProfile: "optimized"
|
|
77437
77843
|
};
|
|
77438
77844
|
var SettingsManager = class {
|
|
77439
77845
|
settings = { ...DEFAULT_SETTINGS };
|
|
@@ -77474,7 +77880,7 @@ init_esm_shims();
|
|
|
77474
77880
|
import fs24 from "fs/promises";
|
|
77475
77881
|
import { createReadStream as createReadStream2 } from "fs";
|
|
77476
77882
|
import { createInterface as createInterface2 } from "readline";
|
|
77477
|
-
import
|
|
77883
|
+
import path31 from "path";
|
|
77478
77884
|
import crypto6 from "crypto";
|
|
77479
77885
|
var DISPLAY_ITEM_CUSTOM_KIND = "display_item";
|
|
77480
77886
|
function isCompletedItemLike(value) {
|
|
@@ -77509,7 +77915,7 @@ var SessionManager = class _SessionManager {
|
|
|
77509
77915
|
this.onPersistError?.(err);
|
|
77510
77916
|
}
|
|
77511
77917
|
dirForCwd(cwd2) {
|
|
77512
|
-
return
|
|
77918
|
+
return path31.join(this.sessionsDir, encodeCwd(cwd2));
|
|
77513
77919
|
}
|
|
77514
77920
|
async create(cwd2, provider, model) {
|
|
77515
77921
|
const id2 = crypto6.randomUUID();
|
|
@@ -77517,7 +77923,7 @@ var SessionManager = class _SessionManager {
|
|
|
77517
77923
|
const dir = this.dirForCwd(cwd2);
|
|
77518
77924
|
await fs24.mkdir(dir, { recursive: true });
|
|
77519
77925
|
const fileName = `${timestamp.replace(/[:.]/g, "-")}_${id2.slice(0, 8)}.jsonl`;
|
|
77520
|
-
const filePath =
|
|
77926
|
+
const filePath = path31.join(dir, fileName);
|
|
77521
77927
|
const header = {
|
|
77522
77928
|
type: "session",
|
|
77523
77929
|
version: 2,
|
|
@@ -77589,7 +77995,7 @@ var SessionManager = class _SessionManager {
|
|
|
77589
77995
|
for (const file2 of files) {
|
|
77590
77996
|
if (!file2.endsWith(".jsonl"))
|
|
77591
77997
|
continue;
|
|
77592
|
-
const filePath =
|
|
77998
|
+
const filePath = path31.join(dir, file2);
|
|
77593
77999
|
try {
|
|
77594
78000
|
const rl = createInterface2({
|
|
77595
78001
|
input: createReadStream2(filePath, { encoding: "utf-8" }),
|
|
@@ -77652,7 +78058,7 @@ var SessionManager = class _SessionManager {
|
|
|
77652
78058
|
if (options.maxAgeDays <= 0)
|
|
77653
78059
|
return result;
|
|
77654
78060
|
const cutoffMs = Date.now() - options.maxAgeDays * 864e5;
|
|
77655
|
-
const keep = new Set((options.keepPaths ?? []).map((p) =>
|
|
78061
|
+
const keep = new Set((options.keepPaths ?? []).map((p) => path31.resolve(p)));
|
|
77656
78062
|
let cwdDirs;
|
|
77657
78063
|
try {
|
|
77658
78064
|
cwdDirs = await fs24.readdir(this.sessionsDir);
|
|
@@ -77660,7 +78066,7 @@ var SessionManager = class _SessionManager {
|
|
|
77660
78066
|
return result;
|
|
77661
78067
|
}
|
|
77662
78068
|
for (const dirName of cwdDirs) {
|
|
77663
|
-
const dir =
|
|
78069
|
+
const dir = path31.join(this.sessionsDir, dirName);
|
|
77664
78070
|
let files;
|
|
77665
78071
|
try {
|
|
77666
78072
|
const stat = await fs24.stat(dir);
|
|
@@ -77674,8 +78080,8 @@ var SessionManager = class _SessionManager {
|
|
|
77674
78080
|
for (const file2 of files) {
|
|
77675
78081
|
if (!file2.endsWith(".jsonl"))
|
|
77676
78082
|
continue;
|
|
77677
|
-
const filePath =
|
|
77678
|
-
if (keep.has(
|
|
78083
|
+
const filePath = path31.join(dir, file2);
|
|
78084
|
+
if (keep.has(path31.resolve(filePath)))
|
|
77679
78085
|
continue;
|
|
77680
78086
|
try {
|
|
77681
78087
|
const stat = await fs24.stat(filePath);
|
|
@@ -77928,25 +78334,25 @@ function createBuiltinCommands() {
|
|
|
77928
78334
|
async execute(args) {
|
|
77929
78335
|
const { execSync } = await import("child_process");
|
|
77930
78336
|
const { createRequire: createRequire2 } = await import("module");
|
|
77931
|
-
const
|
|
77932
|
-
const
|
|
78337
|
+
const path49 = await import("path");
|
|
78338
|
+
const fs40 = await import("fs");
|
|
77933
78339
|
const _require = createRequire2(import.meta.url);
|
|
77934
|
-
const pkgPath =
|
|
78340
|
+
const pkgPath = path49.default.resolve(path49.default.dirname(_require.resolve("../package.json")));
|
|
77935
78341
|
let repoRoot = process.cwd();
|
|
77936
|
-
let scriptPath =
|
|
77937
|
-
if (!
|
|
78342
|
+
let scriptPath = path49.default.join(repoRoot, "scripts", "sync-upstream.sh");
|
|
78343
|
+
if (!fs40.existsSync(scriptPath)) {
|
|
77938
78344
|
let dir = pkgPath;
|
|
77939
78345
|
for (let i = 0; i < 5; i++) {
|
|
77940
|
-
dir =
|
|
77941
|
-
const candidate =
|
|
77942
|
-
if (
|
|
78346
|
+
dir = path49.default.dirname(dir);
|
|
78347
|
+
const candidate = path49.default.join(dir, "scripts", "sync-upstream.sh");
|
|
78348
|
+
if (fs40.existsSync(candidate)) {
|
|
77943
78349
|
scriptPath = candidate;
|
|
77944
78350
|
repoRoot = dir;
|
|
77945
78351
|
break;
|
|
77946
78352
|
}
|
|
77947
78353
|
}
|
|
77948
78354
|
}
|
|
77949
|
-
if (!
|
|
78355
|
+
if (!fs40.existsSync(scriptPath)) {
|
|
77950
78356
|
return "sync-upstream.sh not found. Make sure you're in the ezcoder repo root,\nor that scripts/sync-upstream.sh exists.\n\nYou can create it by checking the repo: https://github.com/Gahroot/ezcoder";
|
|
77951
78357
|
}
|
|
77952
78358
|
const dryRun = args.trim() === "--dry-run";
|
|
@@ -78044,6 +78450,16 @@ function createBuiltinCommands() {
|
|
|
78044
78450
|
return "New session created.";
|
|
78045
78451
|
}
|
|
78046
78452
|
},
|
|
78453
|
+
{
|
|
78454
|
+
name: "clear",
|
|
78455
|
+
aliases: [],
|
|
78456
|
+
description: "Clear the conversation (start a new session)",
|
|
78457
|
+
usage: "/clear",
|
|
78458
|
+
async execute(_args, ctx) {
|
|
78459
|
+
await ctx.newSession();
|
|
78460
|
+
return "Session cleared.";
|
|
78461
|
+
}
|
|
78462
|
+
},
|
|
78047
78463
|
{
|
|
78048
78464
|
name: "branch",
|
|
78049
78465
|
aliases: ["b"],
|
|
@@ -78289,6 +78705,97 @@ If the user chooses D, stop after the report.
|
|
|
78289
78705
|
- **No finding without a concrete, code-grounded first-run scenario.** No "could be polished" nudges.
|
|
78290
78706
|
- **Report-first.** No edits, installs, or commits until the user picks an option.
|
|
78291
78707
|
- **Every generated task must end with the exact line:** use kencode to reference working code. /commit when done.`
|
|
78708
|
+
},
|
|
78709
|
+
{
|
|
78710
|
+
name: "test-drive",
|
|
78711
|
+
aliases: ["qa", "td"],
|
|
78712
|
+
description: "Actually run the app, click around, screenshot, file bugs as tasks",
|
|
78713
|
+
prompt: `# /test-drive: Empirically Test the App and File Bugs as Tasks
|
|
78714
|
+
|
|
78715
|
+
You are a hands-on QA agent. Your job is to ACTUALLY RUN this app and use it like a real user \u2014 launch it, click around, type into it, navigate every reachable surface, and LOOK at the result with your own eyes (screenshots / captured output / logs). This is empirical, not a code review: you must drive the running app, not just read source. Every bug you find is recorded so it can be fixed later by another agent working through the task list \u2014 except bugs that block YOU from testing further, which you fix immediately so you can keep going.
|
|
78716
|
+
|
|
78717
|
+
This command is **project-agnostic**. Profile what THIS app is and how it runs before testing. If the user passed arguments to /test-drive, treat them as the area/flow to focus the test pass on, but still sanity-check the rest of the app.
|
|
78718
|
+
|
|
78719
|
+
## Phase 0: Figure out how to run it
|
|
78720
|
+
|
|
78721
|
+
Inspect the project (manifests, scripts, README, entry points) and determine how a user actually runs this app, then start it:
|
|
78722
|
+
|
|
78723
|
+
- **Web app / dev server** \u2014 find the dev/start script (e.g. \`pnpm dev\`, \`npm start\`, \`vite\`). Launch it with bash as a **background process** (\`run_in_background: true\`), wait for it to be ready, and read its output with task_output to learn the local URL (e.g. http://localhost:3000).
|
|
78724
|
+
- **CLI / TUI** \u2014 run the binary/entry command. For interactive programs, launch as a background process and drive it with task_send (type input / answer prompts) + task_output (read what it printed). Use task_stop to end it.
|
|
78725
|
+
- **Desktop app (Tauri/Electron/etc.)** \u2014 start it the way the project documents. If it exposes a local webview URL or dev server, point the screenshot tool at that; otherwise launch it and rely on captured logs/output for evidence.
|
|
78726
|
+
- **Library / no runnable surface** \u2014 there's nothing to "click around." Run its examples/tests/demo instead, or report that there is no interactive surface to test and stop.
|
|
78727
|
+
|
|
78728
|
+
If you cannot get the app to start at all, that is itself the first blocking bug \u2014 fix it (Phase 2, blocking path) so you have something to test, then continue.
|
|
78729
|
+
|
|
78730
|
+
## Phase 1: Drive it and LOOK \u2014 use your eyes
|
|
78731
|
+
|
|
78732
|
+
Exercise the app like a real user, surface by surface. Use the real perception tools available to you:
|
|
78733
|
+
|
|
78734
|
+
- **screenshot tool** \u2014 your eyes for anything with a UI. Open each URL/screen, run \`actions\` (click / type / wait) to walk real flows, and CAPTURE the result so you actually see what rendered. Vary viewport for responsive surfaces and use \`full_page\` for long pages. Don't assume a screen works \u2014 look at it.
|
|
78735
|
+
- **task_output / task_send** \u2014 your eyes and hands for CLIs, TUIs, and dev-server logs: read what the process emitted, type input to drive it, watch for errors/stack traces/warnings in the output.
|
|
78736
|
+
- **bash** \u2014 hit health/API endpoints, trigger flows, and inspect logs the app writes.
|
|
78737
|
+
|
|
78738
|
+
Walk the real journeys, not just the happy path that's easy to reach. For each surface, exercise:
|
|
78739
|
+
|
|
78740
|
+
1. **Primary flows** \u2014 the main things a user comes here to do, start to finish.
|
|
78741
|
+
2. **Inputs & forms** \u2014 submit valid input, empty input, and obviously wrong input; check validation and error messages.
|
|
78742
|
+
3. **Navigation** \u2014 every reachable link/button/route/tab/command; look for dead ends, broken links, blank screens, 404s, console/stderr errors.
|
|
78743
|
+
4. **States** \u2014 empty, loading, error, offline/slow, and "no data yet" states. These are where apps break most.
|
|
78744
|
+
5. **Visual integrity** \u2014 overlapping/cut-off/misaligned elements, unstyled flashes, illegible text, broken images \u2014 things only visible by actually looking at a screenshot.
|
|
78745
|
+
|
|
78746
|
+
As you go, keep a running list of every bug with: what you did, what you expected, what actually happened, the evidence (screenshot path / captured output / log line), and the file/area it most likely lives in.
|
|
78747
|
+
|
|
78748
|
+
## Phase 2: Triage each bug \u2014 blocking vs deferrable
|
|
78749
|
+
|
|
78750
|
+
For every bug, decide one of two paths:
|
|
78751
|
+
|
|
78752
|
+
**A) BLOCKING \u2014 it stops you from testing further.** The app won't start, a screen crashes, a flow can't be completed, or a broken gate hides everything behind it. You cannot meaningfully continue the test pass until it's fixed. **Fix these immediately**, right now, so you can keep testing:
|
|
78753
|
+
|
|
78754
|
+
1. Reproduce it and find the root cause in the code.
|
|
78755
|
+
2. Use the \`mcp__kencode-search__searchCode\` tool to reference how real projects implement the same pattern correctly, and base your fix on that working code. (If the kencode-search MCP tool isn't connected, note that and fix using project conventions + authoritative docs.)
|
|
78756
|
+
3. Implement the fix, then re-run the app and CONFIRM with your eyes (re-screenshot / re-read output) that the bug is actually gone.
|
|
78757
|
+
4. Commit the fix by running the \`/commit\` command, so each fix lands on working, committed code before you continue.
|
|
78758
|
+
5. Resume the test pass from where you were blocked.
|
|
78759
|
+
|
|
78760
|
+
**B) DEFERRABLE \u2014 it's a real bug but you can keep testing around it.** Cosmetic issues, non-blocking errors, secondary-flow breakage, edge-case mishandling. **Do NOT fix these now.** Record them and move on \u2014 they'll be handed off as tasks for another agent to fix in a later session.
|
|
78761
|
+
|
|
78762
|
+
When unsure, prefer DEFER: only fix inline what genuinely blocks the test pass. The point is to keep driving the app and cataloguing bugs, not to stop and fix everything.
|
|
78763
|
+
|
|
78764
|
+
## Phase 3: File deferrable bugs as tasks
|
|
78765
|
+
|
|
78766
|
+
For every deferrable bug (or a tightly-coupled group), add one task with the \`tasks\` tool (action=add). Running /test-drive is the user's explicit request to populate the task list, so this is expected \u2014 but only file REAL, reproduced bugs, not speculation. **Before filing, trace each bug to its root cause and confirm it's an actual code defect \u2014 not bad seed/test/mock data, a misconfig, or expected behavior.** This app is full of synthetic data, so "these numbers look insane" is very often just the data, not a bug. Reading the code/data/DB to establish cause is REQUIRED here, not an "assumption" \u2014 the no-assumptions rule means don't claim a screen works without looking, it does not mean skip root-cause analysis. For any numeric/calculation bug, reproduce the arithmetic from the underlying inputs before filing. Order tasks by user impact and severity. Each task needs a short title and a standalone prompt (the next agent has NO context from this session) that includes:
|
|
78767
|
+
|
|
78768
|
+
- **The bug**: what you did, what you expected, what actually happened.
|
|
78769
|
+
- **Reproduction steps**: the exact flow to trigger it (URL/screen/command + clicks/inputs).
|
|
78770
|
+
- **Evidence**: the screenshot path / captured output / log line you saw.
|
|
78771
|
+
- **Root cause**: the traced reason it's a code defect (not data/config/expected behavior) \u2014 for numeric bugs, the inputs and the arithmetic you reproduced.
|
|
78772
|
+
- **Where to look**: the file(s)/area the bug most likely lives in.
|
|
78773
|
+
|
|
78774
|
+
End EVERY task's standalone prompt with this exact line, verbatim, on its own line:
|
|
78775
|
+
|
|
78776
|
+
use kencode to reference working code. /commit when done.
|
|
78777
|
+
|
|
78778
|
+
That line guarantees the next agent bases its fix on real working code (via the kencode MCP) and commits it.
|
|
78779
|
+
|
|
78780
|
+
## Phase 4: Report
|
|
78781
|
+
|
|
78782
|
+
When the test pass is done (or you've covered the focus area), summarize:
|
|
78783
|
+
|
|
78784
|
+
- What you ran and which surfaces/flows you actually drove (with screenshot/output evidence).
|
|
78785
|
+
- **Blocking bugs you fixed inline** \u2014 each with its root cause and the commit.
|
|
78786
|
+
- **Deferrable bugs filed as tasks** \u2014 a short list of titles.
|
|
78787
|
+
|
|
78788
|
+
Then tell the user exactly: "Tasks added. Press Ctrl+T to open the task list and run them." Do not start executing those deferred tasks unless the user explicitly says so.
|
|
78789
|
+
|
|
78790
|
+
## Rules
|
|
78791
|
+
|
|
78792
|
+
- **Actually run the app and look.** Don't claim a screen works without observing it \u2014 a screenshot, captured output, or log line. No "this should work." But observation alone is not a filed bug: confirming a defect requires tracing the cause, which means reading the code/data/inputs.
|
|
78793
|
+
- **Trace cause before filing.** A symptom is not a bug until you've traced it to a code defect and ruled out bad seed/test/mock data, misconfig, and expected behavior. For numeric/calculation bugs, reproduce the arithmetic from the underlying inputs.
|
|
78794
|
+
- **An AI/agent (or the model itself) noticing something looks wrong is NOT evidence** \u2014 a model flags "big number vs small position" the same way whether the cause is data or logic. Only reproduced behavior plus a traced cause counts.
|
|
78795
|
+
- **Only fix what blocks you.** Blocking bugs get fixed inline (kencode-referenced + \`/commit\`); everything else becomes a task. When in doubt, defer.
|
|
78796
|
+
- **Every fix is on working, committed code** \u2014 reference real code via kencode, verify the fix by re-running, then \`/commit\`.
|
|
78797
|
+
- **Every filed task ends with the exact line:** use kencode to reference working code. /commit when done.
|
|
78798
|
+
- **File only reproduced bugs with a traced root cause.** No speculative or "could be improved" tasks, and no symptoms with an unverified cause \u2014 this is a bug hunt, not a polish wishlist.`
|
|
78292
78799
|
},
|
|
78293
78800
|
{
|
|
78294
78801
|
name: "elon",
|
|
@@ -78400,6 +78907,118 @@ If the user chooses D, stop after the report.
|
|
|
78400
78907
|
- **App-wide first, specific areas second** \u2014 in both the hunt and the ledger.
|
|
78401
78908
|
- **No deletion without code-grounded evidence** that the thing is dead weight (no callers / write-only / unreachable / redundant). No "feels bloated" nudges.
|
|
78402
78909
|
- **Report-first. No deletions, edits, installs, or commits until the user picks an option.**
|
|
78910
|
+
- **Every generated task must end with the exact line:** use kencode to reference working code. /commit when done.`
|
|
78911
|
+
},
|
|
78912
|
+
{
|
|
78913
|
+
name: "elon-2",
|
|
78914
|
+
aliases: ["step-2", "add-back"],
|
|
78915
|
+
description: "Finish the Elon algorithm: add back the ~10%, then simplify/accelerate/automate",
|
|
78916
|
+
prompt: `# /elon-2: The Add-Back & Optimize Pass
|
|
78917
|
+
|
|
78918
|
+
This is the SECOND HALF of /elon, and it only makes sense AFTER deletions have landed. /elon runs steps 1\u20132 of Elon Musk's algorithm \u2014 make the requirement less dumb, then delete the part/process \u2014 and it deletes aggressively, on purpose, until things break. /elon-2 runs the rest of the same algorithm, IN ORDER:
|
|
78919
|
+
|
|
78920
|
+
1. ~~Make the requirement less dumb~~ \u2014 done by /elon.
|
|
78921
|
+
2. ~~Delete the part or process~~ \u2014 done by /elon.
|
|
78922
|
+
3. **Simplify** \u2014 only what survived deletion.
|
|
78923
|
+
4. **Accelerate** \u2014 only what survived simplification.
|
|
78924
|
+
5. **Automate** \u2014 last, never first.
|
|
78925
|
+
|
|
78926
|
+
Before step 3, this command does the move /elon deliberately leaves undone \u2014 the famous Musk rule: **"if you're not adding ~10% back, you didn't delete enough."** Aggressive deletion overshoots; some small piece you cut was actually load-bearing and has to come back. **Phase 1 recovers that ~10%.** Only then do steps 3\u20135 run, on what survived.
|
|
78927
|
+
|
|
78928
|
+
This command is **project-agnostic** and **report-first**: the only deliverable is a single ranked ledger, after which you hand the work off as tasks. **Do not edit, install, or implement anything until the user confirms by choosing an option at the end.**
|
|
78929
|
+
|
|
78930
|
+
If the user passed arguments to /elon-2, treat them as a focus area: narrow the pass to that feature/surface, but still run the full algorithm within it.
|
|
78931
|
+
|
|
78932
|
+
**Hard scope rules:**
|
|
78933
|
+
- **Add-backs are strictly the minimal load-bearing piece that broke.** Restoring functionality the deletions removed is NOT re-adding scope. If an "add-back" is really a net-new capability or a scope re-expansion, that is /expand \u2014 drop it here.
|
|
78934
|
+
- **Steps 3\u20135 operate ONLY on survivors.** Never simplify, accelerate, or automate something that should have been deleted \u2014 /elon already made those calls. Do not re-litigate deletions (revert-the-whole-deletion is the one exception, see Phase 1).
|
|
78935
|
+
- **Order is law.** Add-back \u2192 simplify \u2192 accelerate \u2192 automate. Never accelerate or automate something before it has been simplified.
|
|
78936
|
+
|
|
78937
|
+
## Phase 0: Establish what changed + a baseline oracle (main agent)
|
|
78938
|
+
|
|
78939
|
+
You cannot add back what broke without knowing what was cut. Build two maps from real evidence, not memory:
|
|
78940
|
+
|
|
78941
|
+
- **Deletion map** \u2014 what /elon actually removed. Derive it from \`git log\`/\`git diff\` over the relevant range, completed deletion tasks, and removed files/symbols/flags/dependencies. For each deletion, note its predicted add-back (zero / fold-in / seam) from the /elon ledger if available.
|
|
78942
|
+
- **Survivor map** \u2014 the user-facing surfaces, flows, and internal pieces that remain after the deletions.
|
|
78943
|
+
|
|
78944
|
+
Then run the project's own **build / typecheck / test / lint** (whatever it has) to capture a baseline oracle: what is broken right now, after the deletions. Note dangling imports, broken routes, failing tests, dead references, and any flow that no longer completes.
|
|
78945
|
+
|
|
78946
|
+
## Phase 1: Add-back recovery (the ~10%)
|
|
78947
|
+
|
|
78948
|
+
Empirically find what the deletions broke or over-cut. Spawn subagents in parallel using the subagent tool (call the subagent tool multiple times in a single response), one per high-risk deletion cluster from the deletion map (cap at 6).
|
|
78949
|
+
|
|
78950
|
+
Each subagent must:
|
|
78951
|
+
|
|
78952
|
+
1. Walk the deletion and find **breakage evidence** grounded in code: failing build/typecheck/test output, dangling references to removed symbols, routes/commands that no longer resolve, a real user flow that now dead-ends, behavior that callers still expect.
|
|
78953
|
+
2. For every breakage, identify the **minimal add-back** \u2014 the smallest piece of the deleted thing that must return so dependents work again (mirror the zero / fold-in / seam shapes from /elon). Cite the file:line that proves the breakage and what the restore touches.
|
|
78954
|
+
3. **Right-size the add-back.** If the minimal restore is large, vague, or "we'd basically rebuild the deleted thing," that is the signal the deletion itself was wrong \u2014 flag it as **REVERT** (undo the whole deletion) rather than a partial add-back. A small, well-scoped add-back is a true ~10%; a large one means the cut went too far.
|
|
78955
|
+
|
|
78956
|
+
A deletion that broke nothing needs no add-back \u2014 that is a clean cut, leave it. The goal is to restore the minimum, not to undo the diet.
|
|
78957
|
+
|
|
78958
|
+
## Phase 2: Steps 3\u20135 on survivors (in order)
|
|
78959
|
+
|
|
78960
|
+
For the survivor map only, spawn subagents in parallel (cap at 6 total across the three steps) to find optimization candidates, strictly in algorithm order:
|
|
78961
|
+
|
|
78962
|
+
- **Step 3 \u2014 Simplify.** Indirection, layers, branches, or config that only existed to serve now-deleted things and can be collapsed or inlined; survivors that can be merged; flows that can be flattened. This is where most leverage lives post-deletion.
|
|
78963
|
+
- **Step 4 \u2014 Accelerate.** Only what survived simplification: hot paths, redundant work, slow startup, repeated computation that can be sped up. A candidate may not be accelerated until it has been simplified first.
|
|
78964
|
+
- **Step 5 \u2014 Automate.** Last: manual steps in surviving flows that the system should do for the user. Never propose automating something that should instead be simplified away.
|
|
78965
|
+
|
|
78966
|
+
Each subagent must cite file:line anchors, name which step it belongs to, and estimate effort (small / medium / large) and leverage.
|
|
78967
|
+
|
|
78968
|
+
## Phase 3: Validate against the repo (main agent)
|
|
78969
|
+
|
|
78970
|
+
For every candidate:
|
|
78971
|
+
|
|
78972
|
+
1. **Add-backs:** confirm the breakage is real against the baseline oracle and that the restore is genuinely minimal. If the restore turns out large, reclassify as REVERT or drop it.
|
|
78973
|
+
2. **Simplify/accelerate/automate:** confirm the candidate is a survivor (not something that should have been deleted), and that the step order holds (nothing accelerated/automated before being simplified).
|
|
78974
|
+
3. Confirm scope: add-backs restore removed behavior only \u2014 anything that is net-new capability is /expand, make-it-work polish is /raise-floor, security is /bullet-proof. Drop out-of-scope items.
|
|
78975
|
+
4. Merge duplicates. Rank by **completion leverage = (breakage severity or surface improved) \xF7 effort**, with all add-backs ahead of all step 3\u20135 work.
|
|
78976
|
+
|
|
78977
|
+
## Phase 4: The completion ledger (report)
|
|
78978
|
+
|
|
78979
|
+
Output the report. **Add-back (recover) rows first, then simplify, then accelerate, then automate** \u2014 algorithm order. Start with one line: project name + a one-sentence summary of how far the deletions overshot and where the biggest post-deletion wins are. Then a single table:
|
|
78980
|
+
|
|
78981
|
+
| ID | Step | Candidate | Evidence (file:line) | What it restores / improves | Effort | Leverage |
|
|
78982
|
+
|---|---|---|---|---|---|---|
|
|
78983
|
+
| E2-001 | add-back | re-add the one default the deleted settings screen applied | flow X dead-ends after delete (path:line) | onboarding applies the default inline; nothing else returns | small | high |
|
|
78984
|
+
| E2-002 | simplify | inline the adapter layer that only wrapped the deleted backend | single caller left (path:line) | one fewer indirection; survivors merge | small | high |
|
|
78985
|
+
|
|
78986
|
+
Use IDs like E2-001. Add-back rows lead, then step 3, then 4, then 5. Mark any deletion that overshot as **REVERT** with the reason. The ledger is structured so a later empirical mode can run each row against the project's build/check/test as the "is it fixed / still green?" oracle. Do not run that loop now \u2014 this is report-only.
|
|
78987
|
+
|
|
78988
|
+
After the table, ask exactly:
|
|
78989
|
+
|
|
78990
|
+
What should I do?
|
|
78991
|
+
A) Add tasks for everything (add-backs first, then simplify/accelerate/automate)
|
|
78992
|
+
B) Add tasks for the add-backs only (just recover what broke)
|
|
78993
|
+
C) Add tasks for specific rows (give IDs, e.g. "E2-001, E2-004")
|
|
78994
|
+
D) None \u2014 report only
|
|
78995
|
+
|
|
78996
|
+
Do not start implementing until the user chooses.
|
|
78997
|
+
|
|
78998
|
+
## Phase 5: Hand off as tasks
|
|
78999
|
+
|
|
79000
|
+
If the user chooses A, B, or C, do not implement directly. Add one task per selected row (or tightly coupled group) using the \`tasks\` tool (action=add), ordered by algorithm step then leverage \u2014 **add-backs first, then simplify, then accelerate, then automate**. Each task needs a short title and a standalone prompt that includes:
|
|
79001
|
+
|
|
79002
|
+
- the row ID, its step, and exactly what to restore or change (files/symbols/flags + anchors),
|
|
79003
|
+
- for add-backs: the breakage it fixes and the minimal restore (never re-expand scope),
|
|
79004
|
+
- the blast radius to touch (call sites, imports, tests, docs, config),
|
|
79005
|
+
- the project's verification commands to prove the build/tests are green again after the change.
|
|
79006
|
+
|
|
79007
|
+
End EVERY task's standalone prompt with this exact line, verbatim, on its own line:
|
|
79008
|
+
|
|
79009
|
+
use kencode to reference working code. /commit when done.
|
|
79010
|
+
|
|
79011
|
+
After adding the tasks, tell the user exactly: "Tasks added. Press Ctrl+T to open the task list and run them." Do not begin executing them unless the user explicitly says so.
|
|
79012
|
+
|
|
79013
|
+
If the user chooses D, stop after the report.
|
|
79014
|
+
|
|
79015
|
+
## Rules
|
|
79016
|
+
|
|
79017
|
+
- **Runs after /elon.** This pass assumes deletions already landed; Phase 0 derives them from git history and completed tasks.
|
|
79018
|
+
- **Add back the ~10%, no more.** Restore only the minimal load-bearing piece that broke. A large add-back means the deletion overshot \u2014 mark it REVERT, don't quietly rebuild.
|
|
79019
|
+
- **Algorithm order is law.** Add-back \u2192 simplify \u2192 accelerate \u2192 automate. Never accelerate or automate before simplifying.
|
|
79020
|
+
- **Survivors only for steps 3\u20135.** Don't optimize something that should have been deleted; don't re-add scope (that's /expand).
|
|
79021
|
+
- **Report-first. No edits, installs, or commits until the user picks an option.**
|
|
78403
79022
|
- **Every generated task must end with the exact line:** use kencode to reference working code. /commit when done.`
|
|
78404
79023
|
},
|
|
78405
79024
|
{
|
|
@@ -78943,9 +79562,9 @@ function getPromptCommand(name) {
|
|
|
78943
79562
|
// ../cli/dist/core/custom-commands.js
|
|
78944
79563
|
init_esm_shims();
|
|
78945
79564
|
import fs25 from "fs/promises";
|
|
78946
|
-
import
|
|
79565
|
+
import path33 from "path";
|
|
78947
79566
|
async function loadCustomCommands(cwd2) {
|
|
78948
|
-
const commandsDir =
|
|
79567
|
+
const commandsDir = path33.join(cwd2, ".ezcoder", "commands");
|
|
78949
79568
|
const commands = [];
|
|
78950
79569
|
let files;
|
|
78951
79570
|
try {
|
|
@@ -78956,11 +79575,11 @@ async function loadCustomCommands(cwd2) {
|
|
|
78956
79575
|
for (const file2 of files) {
|
|
78957
79576
|
if (!file2.endsWith(".md"))
|
|
78958
79577
|
continue;
|
|
78959
|
-
const filePath =
|
|
79578
|
+
const filePath = path33.join(commandsDir, file2);
|
|
78960
79579
|
try {
|
|
78961
79580
|
const raw = await fs25.readFile(filePath, "utf-8");
|
|
78962
79581
|
const parsed = parseSkillFile(raw, "project");
|
|
78963
|
-
const name = parsed.name ||
|
|
79582
|
+
const name = parsed.name || path33.basename(file2, ".md");
|
|
78964
79583
|
commands.push({
|
|
78965
79584
|
name,
|
|
78966
79585
|
description: parsed.description || `Custom command from .ezcoder/commands/${file2}`,
|
|
@@ -78982,7 +79601,7 @@ init_esm_shims();
|
|
|
78982
79601
|
// ../cli/dist/core/extensions/loader.js
|
|
78983
79602
|
init_esm_shims();
|
|
78984
79603
|
import fs26 from "fs/promises";
|
|
78985
|
-
import
|
|
79604
|
+
import path34 from "path";
|
|
78986
79605
|
var ExtensionLoader = class {
|
|
78987
79606
|
loaded = [];
|
|
78988
79607
|
async loadAll(extensionsDir, context) {
|
|
@@ -78995,7 +79614,7 @@ var ExtensionLoader = class {
|
|
|
78995
79614
|
for (const file2 of files) {
|
|
78996
79615
|
if (!file2.endsWith(".js"))
|
|
78997
79616
|
continue;
|
|
78998
|
-
const filePath =
|
|
79617
|
+
const filePath = path34.join(extensionsDir, file2);
|
|
78999
79618
|
try {
|
|
79000
79619
|
const mod = await import(filePath);
|
|
79001
79620
|
const factory = typeof mod.default === "function" ? mod.default : mod.createExtension;
|
|
@@ -85229,7 +85848,138 @@ var StdioClientTransport = class {
|
|
|
85229
85848
|
};
|
|
85230
85849
|
|
|
85231
85850
|
// ../cli/dist/core/mcp/client.js
|
|
85851
|
+
import http from "http";
|
|
85232
85852
|
import os8 from "os";
|
|
85853
|
+
|
|
85854
|
+
// ../cli/dist/core/mcp/oauth-provider.js
|
|
85855
|
+
init_esm_shims();
|
|
85856
|
+
import crypto8 from "crypto";
|
|
85857
|
+
|
|
85858
|
+
// ../cli/dist/core/mcp/oauth-store.js
|
|
85859
|
+
init_esm_shims();
|
|
85860
|
+
import fs27 from "fs/promises";
|
|
85861
|
+
var McpOAuthStore = class {
|
|
85862
|
+
filePath;
|
|
85863
|
+
constructor(filePath = getAppPaths().mcpAuthFile) {
|
|
85864
|
+
this.filePath = filePath;
|
|
85865
|
+
}
|
|
85866
|
+
async readAll() {
|
|
85867
|
+
try {
|
|
85868
|
+
const raw = await fs27.readFile(this.filePath, "utf-8");
|
|
85869
|
+
const parsed = JSON.parse(raw);
|
|
85870
|
+
return { version: 1, servers: parsed.servers ?? {} };
|
|
85871
|
+
} catch {
|
|
85872
|
+
return { version: 1, servers: {} };
|
|
85873
|
+
}
|
|
85874
|
+
}
|
|
85875
|
+
async writeAll(data) {
|
|
85876
|
+
try {
|
|
85877
|
+
await fs27.writeFile(this.filePath, JSON.stringify(data, null, 2), {
|
|
85878
|
+
encoding: "utf-8",
|
|
85879
|
+
mode: 384
|
|
85880
|
+
});
|
|
85881
|
+
} catch (err) {
|
|
85882
|
+
log("WARN", "mcp", "failed to persist MCP OAuth store", {
|
|
85883
|
+
message: err instanceof Error ? err.message : String(err)
|
|
85884
|
+
});
|
|
85885
|
+
}
|
|
85886
|
+
}
|
|
85887
|
+
async get(name) {
|
|
85888
|
+
const all = await this.readAll();
|
|
85889
|
+
return all.servers[name] ?? {};
|
|
85890
|
+
}
|
|
85891
|
+
/** Merge a partial entry into the server's record (read-modify-write). */
|
|
85892
|
+
async patch(name, patch) {
|
|
85893
|
+
const all = await this.readAll();
|
|
85894
|
+
all.servers[name] = { ...all.servers[name] ?? {}, ...patch };
|
|
85895
|
+
await this.writeAll(all);
|
|
85896
|
+
}
|
|
85897
|
+
/** Drop a server's whole OAuth record (used on logout / removal). */
|
|
85898
|
+
async clear(name) {
|
|
85899
|
+
const all = await this.readAll();
|
|
85900
|
+
if (all.servers[name]) {
|
|
85901
|
+
delete all.servers[name];
|
|
85902
|
+
await this.writeAll(all);
|
|
85903
|
+
}
|
|
85904
|
+
}
|
|
85905
|
+
/** Whether this server has saved tokens (i.e. has completed login at least once). */
|
|
85906
|
+
async hasTokens(name) {
|
|
85907
|
+
const entry = await this.get(name);
|
|
85908
|
+
return !!entry.tokens?.access_token;
|
|
85909
|
+
}
|
|
85910
|
+
};
|
|
85911
|
+
|
|
85912
|
+
// ../cli/dist/core/mcp/oauth-provider.js
|
|
85913
|
+
var MCP_OAUTH_CALLBACK_PORT = 41999;
|
|
85914
|
+
var MCP_OAUTH_CALLBACK_PATH = "/oauth/callback";
|
|
85915
|
+
function mcpOAuthRedirectUrl() {
|
|
85916
|
+
return `http://localhost:${MCP_OAUTH_CALLBACK_PORT}${MCP_OAUTH_CALLBACK_PATH}`;
|
|
85917
|
+
}
|
|
85918
|
+
var McpOAuthProvider = class {
|
|
85919
|
+
store;
|
|
85920
|
+
serverName;
|
|
85921
|
+
onRedirect;
|
|
85922
|
+
scope;
|
|
85923
|
+
constructor(opts) {
|
|
85924
|
+
this.serverName = opts.serverName;
|
|
85925
|
+
this.store = opts.store ?? new McpOAuthStore();
|
|
85926
|
+
this.onRedirect = opts.onRedirect;
|
|
85927
|
+
this.scope = opts.scope;
|
|
85928
|
+
}
|
|
85929
|
+
get redirectUrl() {
|
|
85930
|
+
return mcpOAuthRedirectUrl();
|
|
85931
|
+
}
|
|
85932
|
+
get clientMetadata() {
|
|
85933
|
+
return {
|
|
85934
|
+
client_name: "EZ Coder",
|
|
85935
|
+
client_uri: "https://github.com/kenkaiii/ezcoder",
|
|
85936
|
+
redirect_uris: [this.redirectUrl],
|
|
85937
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
85938
|
+
response_types: ["code"],
|
|
85939
|
+
token_endpoint_auth_method: "none",
|
|
85940
|
+
...this.scope ? { scope: this.scope } : {}
|
|
85941
|
+
};
|
|
85942
|
+
}
|
|
85943
|
+
async state() {
|
|
85944
|
+
const entry = await this.store.get(this.serverName);
|
|
85945
|
+
if (entry.state)
|
|
85946
|
+
return entry.state;
|
|
85947
|
+
const fresh = crypto8.randomBytes(16).toString("hex");
|
|
85948
|
+
await this.store.patch(this.serverName, { state: fresh });
|
|
85949
|
+
return fresh;
|
|
85950
|
+
}
|
|
85951
|
+
async clientInformation() {
|
|
85952
|
+
const entry = await this.store.get(this.serverName);
|
|
85953
|
+
return entry.clientInformation;
|
|
85954
|
+
}
|
|
85955
|
+
async saveClientInformation(info) {
|
|
85956
|
+
await this.store.patch(this.serverName, {
|
|
85957
|
+
clientInformation: info
|
|
85958
|
+
});
|
|
85959
|
+
}
|
|
85960
|
+
async tokens() {
|
|
85961
|
+
const entry = await this.store.get(this.serverName);
|
|
85962
|
+
return entry.tokens;
|
|
85963
|
+
}
|
|
85964
|
+
async saveTokens(tokens2) {
|
|
85965
|
+
await this.store.patch(this.serverName, { tokens: tokens2 });
|
|
85966
|
+
}
|
|
85967
|
+
redirectToAuthorization(authorizationUrl) {
|
|
85968
|
+
this.onRedirect?.(authorizationUrl);
|
|
85969
|
+
}
|
|
85970
|
+
async saveCodeVerifier(codeVerifier) {
|
|
85971
|
+
await this.store.patch(this.serverName, { codeVerifier });
|
|
85972
|
+
}
|
|
85973
|
+
async codeVerifier() {
|
|
85974
|
+
const entry = await this.store.get(this.serverName);
|
|
85975
|
+
if (!entry.codeVerifier) {
|
|
85976
|
+
throw new Error("No PKCE code verifier saved for this MCP server.");
|
|
85977
|
+
}
|
|
85978
|
+
return entry.codeVerifier;
|
|
85979
|
+
}
|
|
85980
|
+
};
|
|
85981
|
+
|
|
85982
|
+
// ../cli/dist/core/mcp/client.js
|
|
85233
85983
|
var MCPClientManager = class {
|
|
85234
85984
|
servers = [];
|
|
85235
85985
|
async connectAll(configs) {
|
|
@@ -85251,9 +86001,10 @@ var MCPClientManager = class {
|
|
|
85251
86001
|
if (result.status === "fulfilled") {
|
|
85252
86002
|
return { name, ok: true, toolCount: result.value.length, tools: result.value };
|
|
85253
86003
|
}
|
|
85254
|
-
const
|
|
86004
|
+
const requiresAuth = isUnauthorized(result.reason);
|
|
86005
|
+
const error51 = requiresAuth ? "Requires login." : formatConnectError(result.reason);
|
|
85255
86006
|
log("WARN", "mcp", `Failed to connect to MCP server "${name}"`, { error: error51 });
|
|
85256
|
-
return { name, ok: false, toolCount: 0, tools: [], error: error51 };
|
|
86007
|
+
return { name, ok: false, toolCount: 0, tools: [], error: error51, requiresAuth };
|
|
85257
86008
|
});
|
|
85258
86009
|
const connected = results.filter((r2) => r2.ok).length;
|
|
85259
86010
|
const toolCount = results.reduce((sum, r2) => sum + r2.toolCount, 0);
|
|
@@ -85278,8 +86029,120 @@ var MCPClientManager = class {
|
|
|
85278
86029
|
}
|
|
85279
86030
|
return { name: config2.name, ok: true, toolCount: tools.length, tools };
|
|
85280
86031
|
} catch (err) {
|
|
85281
|
-
const
|
|
85282
|
-
|
|
86032
|
+
const requiresAuth = isUnauthorized(err);
|
|
86033
|
+
const error51 = requiresAuth ? "Requires login." : formatConnectError(err);
|
|
86034
|
+
return { name: config2.name, ok: false, toolCount: 0, tools: [], error: error51, requiresAuth };
|
|
86035
|
+
}
|
|
86036
|
+
}
|
|
86037
|
+
/**
|
|
86038
|
+
* Run the interactive OAuth login for one remote MCP server end-to-end:
|
|
86039
|
+
* start a loopback callback server, let the SDK open the browser via
|
|
86040
|
+
* `onAuthorizationUrl`, capture the redirect, exchange the code, then verify
|
|
86041
|
+
* the authorized connection by listing tools. Tokens are persisted by the
|
|
86042
|
+
* provider so later (non-interactive) connects succeed silently.
|
|
86043
|
+
*
|
|
86044
|
+
* `onAuthorizationUrl` is invoked with the authorize URL so the host can open
|
|
86045
|
+
* it (the ezcoder-app broadcasts it to the webview, which opens the system
|
|
86046
|
+
* browser; the CLI prints it). Never throws — returns `{ ok:false, error }`.
|
|
86047
|
+
*/
|
|
86048
|
+
async login(config2, onAuthorizationUrl, timeoutMs = 18e4) {
|
|
86049
|
+
if (!config2.url) {
|
|
86050
|
+
return { ok: false, toolCount: 0, error: "Login is only supported for HTTP MCP servers." };
|
|
86051
|
+
}
|
|
86052
|
+
const url2 = new URL(config2.url);
|
|
86053
|
+
const store2 = new McpOAuthStore();
|
|
86054
|
+
await store2.patch(config2.name, { codeVerifier: void 0, state: void 0 });
|
|
86055
|
+
let codeResolve;
|
|
86056
|
+
let codeReject;
|
|
86057
|
+
const codePromise = new Promise((resolve3, reject) => {
|
|
86058
|
+
codeResolve = resolve3;
|
|
86059
|
+
codeReject = reject;
|
|
86060
|
+
});
|
|
86061
|
+
const provider = new McpOAuthProvider({
|
|
86062
|
+
serverName: config2.name,
|
|
86063
|
+
store: store2,
|
|
86064
|
+
onRedirect: (authUrl) => onAuthorizationUrl(authUrl.toString())
|
|
86065
|
+
});
|
|
86066
|
+
const expectedState = await provider.state();
|
|
86067
|
+
const server = http.createServer((req, res) => {
|
|
86068
|
+
const reqUrl = new URL(req.url || "", `http://localhost:${MCP_OAUTH_CALLBACK_PORT}`);
|
|
86069
|
+
if (reqUrl.pathname !== MCP_OAUTH_CALLBACK_PATH) {
|
|
86070
|
+
res.statusCode = 404;
|
|
86071
|
+
res.end("Not found");
|
|
86072
|
+
return;
|
|
86073
|
+
}
|
|
86074
|
+
const err = reqUrl.searchParams.get("error");
|
|
86075
|
+
const code = reqUrl.searchParams.get("code");
|
|
86076
|
+
const state3 = reqUrl.searchParams.get("state");
|
|
86077
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
86078
|
+
if (err) {
|
|
86079
|
+
res.end(`<html><body><h1>Login failed</h1><p>${escapeHtml(err)}</p></body></html>`);
|
|
86080
|
+
codeReject?.(new Error(`Authorization failed: ${err}`));
|
|
86081
|
+
return;
|
|
86082
|
+
}
|
|
86083
|
+
if (!code) {
|
|
86084
|
+
res.end("<html><body><h1>Login failed</h1><p>No authorization code.</p></body></html>");
|
|
86085
|
+
codeReject?.(new Error("No authorization code in callback."));
|
|
86086
|
+
return;
|
|
86087
|
+
}
|
|
86088
|
+
if (state3 !== expectedState) {
|
|
86089
|
+
res.end("<html><body><h1>Login failed</h1><p>State mismatch.</p></body></html>");
|
|
86090
|
+
codeReject?.(new Error("OAuth state mismatch."));
|
|
86091
|
+
return;
|
|
86092
|
+
}
|
|
86093
|
+
res.end("<html><body><h1>Login successful!</h1><p>You can close this tab and return to EZ Coder.</p></body></html>");
|
|
86094
|
+
codeResolve?.(code);
|
|
86095
|
+
});
|
|
86096
|
+
try {
|
|
86097
|
+
await new Promise((resolve3, reject) => {
|
|
86098
|
+
server.once("error", reject);
|
|
86099
|
+
server.listen(MCP_OAUTH_CALLBACK_PORT, "127.0.0.1", () => resolve3());
|
|
86100
|
+
});
|
|
86101
|
+
} catch (err) {
|
|
86102
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
86103
|
+
const hint = msg.includes("EADDRINUSE") || msg.includes("in use") ? `Port ${MCP_OAUTH_CALLBACK_PORT} is in use \u2014 close whatever is using it and retry.` : msg;
|
|
86104
|
+
return { ok: false, toolCount: 0, error: `Could not start login callback server: ${hint}` };
|
|
86105
|
+
}
|
|
86106
|
+
const overallTimeout = setTimeout(() => {
|
|
86107
|
+
codeReject?.(new Error("Login timed out waiting for the browser callback."));
|
|
86108
|
+
}, timeoutMs);
|
|
86109
|
+
overallTimeout.unref();
|
|
86110
|
+
try {
|
|
86111
|
+
const loginTransport = new StreamableHTTPClientTransport(url2, {
|
|
86112
|
+
requestInit: config2.headers ? { headers: config2.headers } : void 0,
|
|
86113
|
+
authProvider: provider
|
|
86114
|
+
});
|
|
86115
|
+
const loginClient = new Client({ name: "ezcoder", version: "1.0.0" });
|
|
86116
|
+
try {
|
|
86117
|
+
await loginClient.connect(loginTransport);
|
|
86118
|
+
const { tools: tools2 } = await loginClient.listTools();
|
|
86119
|
+
await loginClient.close().catch(() => {
|
|
86120
|
+
});
|
|
86121
|
+
return { ok: true, toolCount: tools2.length };
|
|
86122
|
+
} catch (err) {
|
|
86123
|
+
if (!isUnauthorized(err))
|
|
86124
|
+
throw err;
|
|
86125
|
+
}
|
|
86126
|
+
const code = await codePromise;
|
|
86127
|
+
await loginTransport.finishAuth(code);
|
|
86128
|
+
await loginClient.close().catch(() => {
|
|
86129
|
+
});
|
|
86130
|
+
const verifyTransport = new StreamableHTTPClientTransport(url2, {
|
|
86131
|
+
requestInit: config2.headers ? { headers: config2.headers } : void 0,
|
|
86132
|
+
authProvider: provider
|
|
86133
|
+
});
|
|
86134
|
+
const verifyClient = new Client({ name: "ezcoder", version: "1.0.0" });
|
|
86135
|
+
await verifyClient.connect(verifyTransport);
|
|
86136
|
+
const { tools } = await verifyClient.listTools();
|
|
86137
|
+
await verifyClient.close().catch(() => {
|
|
86138
|
+
});
|
|
86139
|
+
return { ok: true, toolCount: tools.length };
|
|
86140
|
+
} catch (err) {
|
|
86141
|
+
return { ok: false, toolCount: 0, error: formatConnectError(err) };
|
|
86142
|
+
} finally {
|
|
86143
|
+
clearTimeout(overallTimeout);
|
|
86144
|
+
server.close();
|
|
86145
|
+
await store2.patch(config2.name, { codeVerifier: void 0, state: void 0 });
|
|
85283
86146
|
}
|
|
85284
86147
|
}
|
|
85285
86148
|
async connectServer(config2) {
|
|
@@ -85311,19 +86174,24 @@ var MCPClientManager = class {
|
|
|
85311
86174
|
} else {
|
|
85312
86175
|
const url2 = new URL(config2.url);
|
|
85313
86176
|
const reqInit = config2.headers ? { headers: config2.headers } : void 0;
|
|
86177
|
+
const authProvider = new McpOAuthProvider({ serverName: config2.name });
|
|
85314
86178
|
try {
|
|
85315
86179
|
transport = new StreamableHTTPClientTransport(url2, {
|
|
85316
|
-
requestInit: reqInit
|
|
86180
|
+
requestInit: reqInit,
|
|
86181
|
+
authProvider
|
|
85317
86182
|
});
|
|
85318
86183
|
client = new Client({ name: "ezcoder", version: "1.0.0" });
|
|
85319
86184
|
await client.connect(transport, { timeout });
|
|
85320
86185
|
} catch (streamableErr) {
|
|
86186
|
+
if (isUnauthorized(streamableErr))
|
|
86187
|
+
throw streamableErr;
|
|
85321
86188
|
log("INFO", "mcp", `StreamableHTTP failed for "${config2.name}", trying SSE fallback`, {
|
|
85322
86189
|
error: String(streamableErr)
|
|
85323
86190
|
});
|
|
85324
86191
|
transport = new SSEClientTransport(url2, {
|
|
85325
86192
|
eventSourceInit: config2.headers ? { fetch: createHeaderFetch(config2.headers) } : void 0,
|
|
85326
|
-
requestInit: reqInit
|
|
86193
|
+
requestInit: reqInit,
|
|
86194
|
+
authProvider
|
|
85327
86195
|
});
|
|
85328
86196
|
client = new Client({ name: "ezcoder", version: "1.0.0" });
|
|
85329
86197
|
await client.connect(transport, { timeout });
|
|
@@ -85388,6 +86256,15 @@ function formatConnectError(reason) {
|
|
|
85388
86256
|
}
|
|
85389
86257
|
return msg;
|
|
85390
86258
|
}
|
|
86259
|
+
function isUnauthorized(reason) {
|
|
86260
|
+
if (reason instanceof UnauthorizedError)
|
|
86261
|
+
return true;
|
|
86262
|
+
const msg = reason instanceof Error ? reason.message : String(reason);
|
|
86263
|
+
return msg.includes("Unauthorized") || msg.includes("401") || msg.toLowerCase().includes("invalid_token");
|
|
86264
|
+
}
|
|
86265
|
+
function escapeHtml(value) {
|
|
86266
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
86267
|
+
}
|
|
85391
86268
|
function createHeaderFetch(extraHeaders) {
|
|
85392
86269
|
return (url2, init) => {
|
|
85393
86270
|
const existing = init?.headers ?? {};
|
|
@@ -85400,8 +86277,8 @@ init_esm_shims();
|
|
|
85400
86277
|
|
|
85401
86278
|
// ../cli/dist/core/mcp/store.js
|
|
85402
86279
|
init_esm_shims();
|
|
85403
|
-
import
|
|
85404
|
-
import
|
|
86280
|
+
import path35 from "path";
|
|
86281
|
+
import fs28 from "fs/promises";
|
|
85405
86282
|
var StoredServerEntrySchema = external_exports.object({
|
|
85406
86283
|
type: external_exports.enum(["stdio", "http", "streamable-http", "sse"]).optional(),
|
|
85407
86284
|
url: external_exports.string().optional(),
|
|
@@ -85419,12 +86296,12 @@ function globalMcpPath() {
|
|
|
85419
86296
|
return getAppPaths().mcpFile;
|
|
85420
86297
|
}
|
|
85421
86298
|
function projectMcpPath(cwd2) {
|
|
85422
|
-
return
|
|
86299
|
+
return path35.join(cwd2, ".ezcoder", "mcp.json");
|
|
85423
86300
|
}
|
|
85424
86301
|
async function readMcpFile(filePath) {
|
|
85425
86302
|
let content;
|
|
85426
86303
|
try {
|
|
85427
|
-
content = await
|
|
86304
|
+
content = await fs28.readFile(filePath, "utf-8");
|
|
85428
86305
|
} catch {
|
|
85429
86306
|
return { mcpServers: {} };
|
|
85430
86307
|
}
|
|
@@ -85477,8 +86354,8 @@ async function loadServers(cwd2) {
|
|
|
85477
86354
|
|
|
85478
86355
|
// ../cli/dist/core/mcp/defaults.js
|
|
85479
86356
|
import { createRequire } from "module";
|
|
85480
|
-
import { existsSync as
|
|
85481
|
-
import
|
|
86357
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
86358
|
+
import path36 from "path";
|
|
85482
86359
|
var KENCODE_PACKAGE = "@kenkaiiii/kencode-search";
|
|
85483
86360
|
function resolveKencodeServer() {
|
|
85484
86361
|
try {
|
|
@@ -85487,8 +86364,8 @@ function resolveKencodeServer() {
|
|
|
85487
86364
|
const pkg = JSON.parse(readFileSync3(pkgJsonPath, "utf8"));
|
|
85488
86365
|
const binRel = typeof pkg.bin === "string" ? pkg.bin : pkg.bin?.["kencode-search"] ?? Object.values(pkg.bin ?? {})[0] ?? pkg.main;
|
|
85489
86366
|
if (binRel) {
|
|
85490
|
-
const binPath =
|
|
85491
|
-
if (
|
|
86367
|
+
const binPath = path36.join(path36.dirname(pkgJsonPath), binRel);
|
|
86368
|
+
if (existsSync5(binPath)) {
|
|
85492
86369
|
return { name: "kencode-search", command: process.execPath, args: [binPath] };
|
|
85493
86370
|
}
|
|
85494
86371
|
}
|
|
@@ -85545,12 +86422,12 @@ init_esm_shims();
|
|
|
85545
86422
|
|
|
85546
86423
|
// ../cli/dist/core/agents.js
|
|
85547
86424
|
init_esm_shims();
|
|
85548
|
-
import
|
|
85549
|
-
import
|
|
86425
|
+
import fs29 from "fs/promises";
|
|
86426
|
+
import path37 from "path";
|
|
85550
86427
|
async function discoverAgents(options) {
|
|
85551
86428
|
const agents = [];
|
|
85552
86429
|
if (options.projectDir) {
|
|
85553
|
-
const projectAgentsDir =
|
|
86430
|
+
const projectAgentsDir = path37.join(options.projectDir, ".ezcoder", "agents");
|
|
85554
86431
|
const projectAgents = await loadAgentsFromDir(projectAgentsDir, "project");
|
|
85555
86432
|
agents.push(...projectAgents);
|
|
85556
86433
|
}
|
|
@@ -85568,19 +86445,19 @@ async function loadAgentsFromDir(dir, source2) {
|
|
|
85568
86445
|
const agents = [];
|
|
85569
86446
|
let files;
|
|
85570
86447
|
try {
|
|
85571
|
-
files = await
|
|
86448
|
+
files = await fs29.readdir(dir);
|
|
85572
86449
|
} catch {
|
|
85573
86450
|
return agents;
|
|
85574
86451
|
}
|
|
85575
86452
|
for (const file2 of files) {
|
|
85576
86453
|
if (!file2.endsWith(".md"))
|
|
85577
86454
|
continue;
|
|
85578
|
-
const filePath =
|
|
86455
|
+
const filePath = path37.join(dir, file2);
|
|
85579
86456
|
try {
|
|
85580
|
-
const content = await
|
|
86457
|
+
const content = await fs29.readFile(filePath, "utf-8");
|
|
85581
86458
|
const agent = parseAgentFile(content, source2);
|
|
85582
86459
|
if (!agent.name) {
|
|
85583
|
-
agent.name =
|
|
86460
|
+
agent.name = path37.basename(file2, ".md");
|
|
85584
86461
|
}
|
|
85585
86462
|
agents.push(agent);
|
|
85586
86463
|
} catch {
|
|
@@ -85711,10 +86588,197 @@ var BUNDLED_AGENTS = [
|
|
|
85711
86588
|
}
|
|
85712
86589
|
];
|
|
85713
86590
|
|
|
86591
|
+
// ../cli/dist/utils/session-title.js
|
|
86592
|
+
init_esm_shims();
|
|
86593
|
+
var TITLE_PROMPT = `Generate an extremely short title (3-7 words) summarizing what the user is asking for. Just the title, nothing else. No quotes, no punctuation at the end.`;
|
|
86594
|
+
async function generateSessionTitle(opts) {
|
|
86595
|
+
let apiKey = opts.apiKey;
|
|
86596
|
+
let accountId = opts.accountId;
|
|
86597
|
+
if (opts.resolveCredentials) {
|
|
86598
|
+
const creds = await opts.resolveCredentials();
|
|
86599
|
+
apiKey = creds.apiKey;
|
|
86600
|
+
accountId = creds.accountId;
|
|
86601
|
+
}
|
|
86602
|
+
const model = opts.provider === "anthropic" ? "claude-haiku-4-5-20251001" : opts.provider === "openai" ? "gpt-5.1-codex-mini" : opts.provider === "glm" ? "glm-4.7-flash" : opts.provider === "moonshot" ? "kimi-k2.7-code" : "claude-haiku-4-5-20251001";
|
|
86603
|
+
const messages = [
|
|
86604
|
+
{ role: "system", content: TITLE_PROMPT },
|
|
86605
|
+
{
|
|
86606
|
+
role: "user",
|
|
86607
|
+
content: `User asked: "${truncate2(opts.userMessage, 300)}"
|
|
86608
|
+
|
|
86609
|
+
Assistant began: "${truncate2(opts.assistantPreview, 200)}"`
|
|
86610
|
+
}
|
|
86611
|
+
];
|
|
86612
|
+
try {
|
|
86613
|
+
const result = stream({
|
|
86614
|
+
provider: opts.provider,
|
|
86615
|
+
model,
|
|
86616
|
+
messages,
|
|
86617
|
+
maxTokens: 30,
|
|
86618
|
+
temperature: 0,
|
|
86619
|
+
apiKey,
|
|
86620
|
+
baseUrl: opts.baseUrl,
|
|
86621
|
+
accountId
|
|
86622
|
+
});
|
|
86623
|
+
result.response.catch(() => {
|
|
86624
|
+
});
|
|
86625
|
+
const response = await result;
|
|
86626
|
+
const msg = response.message;
|
|
86627
|
+
const text = typeof msg.content === "string" ? msg.content : msg.content.filter((c2) => c2.type === "text").map((c2) => c2.text).join("");
|
|
86628
|
+
return text.trim().replace(/[."]+$/, "") || "New conversation";
|
|
86629
|
+
} catch {
|
|
86630
|
+
return fallbackTitle(opts.userMessage);
|
|
86631
|
+
}
|
|
86632
|
+
}
|
|
86633
|
+
function truncate2(s, max) {
|
|
86634
|
+
if (s.length <= max)
|
|
86635
|
+
return s;
|
|
86636
|
+
return s.slice(0, max) + "\u2026";
|
|
86637
|
+
}
|
|
86638
|
+
function fallbackTitle(userMessage) {
|
|
86639
|
+
if (!userMessage)
|
|
86640
|
+
return "New conversation";
|
|
86641
|
+
const cleaned = userMessage.replace(/^\/\S+\s*/, "").replace(/\s+/g, " ").trim();
|
|
86642
|
+
const first = cleaned.split(/[.\n]/)[0]?.trim() ?? cleaned;
|
|
86643
|
+
if (first.length <= 50)
|
|
86644
|
+
return first;
|
|
86645
|
+
const t = first.slice(0, 50);
|
|
86646
|
+
const sp = t.lastIndexOf(" ");
|
|
86647
|
+
return (sp > 20 ? t.slice(0, sp) : t) + "\u2026";
|
|
86648
|
+
}
|
|
86649
|
+
|
|
86650
|
+
// ../cli/dist/core/ideal-review.js
|
|
86651
|
+
init_esm_shims();
|
|
86652
|
+
var IDEAL_REVIEW_PROMPT = "Ideal? Review the actual work against the user's request before the final response. Is it simple, focused, correct, and aligned? Did you over-edit, leave TODOs, miss an obvious case the request called for, or introduce risk? Judge this by reading the code you changed \u2014 do NOT run builds, typechecks, linters, or test suites now; that happens at commit time via /commit. If anything is wrong, fix it now. If everything is good, respond with the final answer only; do not mention this ideal review unless it changed the work.";
|
|
86653
|
+
function evaluateIdealReview(stats) {
|
|
86654
|
+
const reasons = [];
|
|
86655
|
+
let score = 0;
|
|
86656
|
+
if (stats.changedLines >= 120) {
|
|
86657
|
+
score += 2;
|
|
86658
|
+
reasons.push(`${stats.changedLines} changed lines`);
|
|
86659
|
+
} else if (stats.changedLines >= 60) {
|
|
86660
|
+
score += 1;
|
|
86661
|
+
reasons.push(`${stats.changedLines} changed lines`);
|
|
86662
|
+
}
|
|
86663
|
+
if (stats.toolCalls >= 8) {
|
|
86664
|
+
score += 1;
|
|
86665
|
+
reasons.push(`${stats.toolCalls} tool calls`);
|
|
86666
|
+
}
|
|
86667
|
+
if (stats.writeCalls + stats.editCalls >= 4) {
|
|
86668
|
+
score += 2;
|
|
86669
|
+
reasons.push(`${stats.writeCalls + stats.editCalls} file mutation calls`);
|
|
86670
|
+
} else if (stats.writeCalls + stats.editCalls >= 2) {
|
|
86671
|
+
score += 1;
|
|
86672
|
+
reasons.push(`${stats.writeCalls + stats.editCalls} file mutation calls`);
|
|
86673
|
+
}
|
|
86674
|
+
if (stats.bashCalls > 0 && stats.writeCalls + stats.editCalls > 0) {
|
|
86675
|
+
score += 1;
|
|
86676
|
+
reasons.push("shell command plus file mutation");
|
|
86677
|
+
}
|
|
86678
|
+
if (stats.toolFailures > 0) {
|
|
86679
|
+
score += 2;
|
|
86680
|
+
reasons.push(`${stats.toolFailures} failed tool calls`);
|
|
86681
|
+
}
|
|
86682
|
+
if (stats.turns >= 6) {
|
|
86683
|
+
score += 1;
|
|
86684
|
+
reasons.push(`${stats.turns} agent turns`);
|
|
86685
|
+
}
|
|
86686
|
+
return { shouldReview: score >= 4, score, reasons };
|
|
86687
|
+
}
|
|
86688
|
+
function buildIdealReviewMessage(reasons) {
|
|
86689
|
+
const reasonText = reasons.length > 0 ? ` Triggered because: ${reasons.join(", ")}.` : "";
|
|
86690
|
+
return {
|
|
86691
|
+
role: "user",
|
|
86692
|
+
content: `${IDEAL_REVIEW_PROMPT}${reasonText}`
|
|
86693
|
+
};
|
|
86694
|
+
}
|
|
86695
|
+
|
|
86696
|
+
// ../cli/dist/core/loop-breaker.js
|
|
86697
|
+
init_esm_shims();
|
|
86698
|
+
var CONSECUTIVE_FAILURE_LIMIT = 3;
|
|
86699
|
+
var SIGNATURE_REPEAT_LIMIT = 3;
|
|
86700
|
+
var SAME_FILE_EDIT_LIMIT = 5;
|
|
86701
|
+
var LOOP_BREAK_PROMPT = "Stuck? You've repeated essentially the same action and it keeps failing or not advancing. Stop and break the pattern. Read the latest error or result literally \u2014 not what you expected it to say. Then question the assumption underneath your approach: the file, path, API, command, or premise you've been treating as true may be wrong. Either try a fundamentally different approach or, if you genuinely cannot make progress, stop and tell the user what's blocking you and what you need. Do NOT repeat the previous attempt with minor tweaks. Do not mention this note unless it changed your approach.";
|
|
86702
|
+
function toolCallSignature(name, args) {
|
|
86703
|
+
return `${name}\0${canonicalize(args)}`;
|
|
86704
|
+
}
|
|
86705
|
+
function canonicalize(value) {
|
|
86706
|
+
if (value === null || typeof value !== "object") {
|
|
86707
|
+
return JSON.stringify(value) ?? "null";
|
|
86708
|
+
}
|
|
86709
|
+
if (Array.isArray(value)) {
|
|
86710
|
+
return `[${value.map(canonicalize).join(",")}]`;
|
|
86711
|
+
}
|
|
86712
|
+
const entries = Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
86713
|
+
return `{${entries.map(([k, v]) => `${JSON.stringify(k)}:${canonicalize(v)}`).join(",")}}`;
|
|
86714
|
+
}
|
|
86715
|
+
var TEXT_REPETITION_MIN_LENGTH = 40;
|
|
86716
|
+
var TEXT_REPETITION_MIN_REPEATS = 3;
|
|
86717
|
+
var TEXT_REPETITION_TAIL = 4096;
|
|
86718
|
+
function detectTextRepetition(text) {
|
|
86719
|
+
if (text.length < TEXT_REPETITION_MIN_LENGTH * TEXT_REPETITION_MIN_REPEATS) {
|
|
86720
|
+
return false;
|
|
86721
|
+
}
|
|
86722
|
+
const tail = text.slice(-TEXT_REPETITION_TAIL);
|
|
86723
|
+
const maxBlock = Math.floor(tail.length / TEXT_REPETITION_MIN_REPEATS);
|
|
86724
|
+
for (let block2 = TEXT_REPETITION_MIN_LENGTH; block2 <= maxBlock; block2++) {
|
|
86725
|
+
const unit = tail.slice(tail.length - block2);
|
|
86726
|
+
let repeats = 1;
|
|
86727
|
+
let offset = tail.length - block2 * 2;
|
|
86728
|
+
while (offset >= 0 && tail.slice(offset, offset + block2) === unit) {
|
|
86729
|
+
repeats++;
|
|
86730
|
+
offset -= block2;
|
|
86731
|
+
}
|
|
86732
|
+
if (repeats >= TEXT_REPETITION_MIN_REPEATS)
|
|
86733
|
+
return true;
|
|
86734
|
+
}
|
|
86735
|
+
return false;
|
|
86736
|
+
}
|
|
86737
|
+
function evaluateLoopBreak(stats) {
|
|
86738
|
+
const reasons = [];
|
|
86739
|
+
if (stats.consecutiveFailures >= CONSECUTIVE_FAILURE_LIMIT) {
|
|
86740
|
+
reasons.push(`${stats.consecutiveFailures} consecutive failed tool calls`);
|
|
86741
|
+
}
|
|
86742
|
+
if (stats.maxSignatureRepeats >= SIGNATURE_REPEAT_LIMIT) {
|
|
86743
|
+
reasons.push(`identical tool call repeated ${stats.maxSignatureRepeats}x`);
|
|
86744
|
+
}
|
|
86745
|
+
if (stats.maxSameFileEdits >= SAME_FILE_EDIT_LIMIT) {
|
|
86746
|
+
reasons.push(`${stats.maxSameFileEdits} edits to the same file`);
|
|
86747
|
+
}
|
|
86748
|
+
if (stats.textRepetitionDetected) {
|
|
86749
|
+
reasons.push("repeated output detected");
|
|
86750
|
+
}
|
|
86751
|
+
return { shouldBreak: reasons.length > 0, reasons };
|
|
86752
|
+
}
|
|
86753
|
+
function buildLoopBreakMessage(reasons) {
|
|
86754
|
+
const reasonText = reasons.length > 0 ? ` Triggered because: ${reasons.join(", ")}.` : "";
|
|
86755
|
+
return {
|
|
86756
|
+
role: "user",
|
|
86757
|
+
content: `${LOOP_BREAK_PROMPT}${reasonText}`
|
|
86758
|
+
};
|
|
86759
|
+
}
|
|
86760
|
+
|
|
86761
|
+
// ../cli/dist/core/regrounding.js
|
|
86762
|
+
init_esm_shims();
|
|
86763
|
+
function buildRegroundingMessage(originalRequest) {
|
|
86764
|
+
const trimmed = originalRequest.trim();
|
|
86765
|
+
const pin = trimmed.length > 0 ? `
|
|
86766
|
+
|
|
86767
|
+
The user's original request was:
|
|
86768
|
+
|
|
86769
|
+
${trimmed}
|
|
86770
|
+
|
|
86771
|
+
` : " The original request is in the earlier messages that remain. ";
|
|
86772
|
+
return {
|
|
86773
|
+
role: "user",
|
|
86774
|
+
content: "Re-ground. The conversation was just compacted, so earlier detail is now a summary and easy to drift from." + pin + "Before continuing, re-anchor on two things: that original request, and the specific objective you're working on right now. Verify your next step still serves the original ask \u2014 not a reshaped or narrowed version of it. If the summary dropped a constraint, file, or requirement you were tracking, recover it from the messages that remain before acting. Then continue. Do not restate this note; just proceed correctly."
|
|
86775
|
+
};
|
|
86776
|
+
}
|
|
86777
|
+
|
|
85714
86778
|
// ../cli/dist/core/agent-session.js
|
|
85715
|
-
import
|
|
85716
|
-
import
|
|
85717
|
-
import
|
|
86779
|
+
import crypto9 from "crypto";
|
|
86780
|
+
import fs30 from "fs/promises";
|
|
86781
|
+
import path38 from "path";
|
|
85718
86782
|
var AgentSession = class {
|
|
85719
86783
|
eventBus = new EventBus();
|
|
85720
86784
|
slashCommands = new SlashCommandRegistry();
|
|
@@ -85724,8 +86788,44 @@ var AgentSession = class {
|
|
|
85724
86788
|
extensionLoader = new ExtensionLoader();
|
|
85725
86789
|
messages = [];
|
|
85726
86790
|
tools = [];
|
|
86791
|
+
/** Rebuilds the read tool for a new model (video byte cap is baked in at
|
|
86792
|
+
* creation). Called from switchModel so video-capable models get the
|
|
86793
|
+
* read-tool's native-video path after a mid-session model change. */
|
|
86794
|
+
rebuildReadTool;
|
|
85727
86795
|
skills = [];
|
|
85728
86796
|
cacheKeyLogged = false;
|
|
86797
|
+
// ── Self-correction hook state (mirrors the TUI's useAgentLoop refs) ──
|
|
86798
|
+
// Reset at the start of every run; observed from the event stream; read by
|
|
86799
|
+
// the loop-break (mid-loop) and ideal-review (pre-stop) callbacks.
|
|
86800
|
+
hookStats = {
|
|
86801
|
+
changedLines: 0,
|
|
86802
|
+
toolCalls: 0,
|
|
86803
|
+
toolFailures: 0,
|
|
86804
|
+
turns: 0,
|
|
86805
|
+
writeCalls: 0,
|
|
86806
|
+
editCalls: 0,
|
|
86807
|
+
bashCalls: 0
|
|
86808
|
+
};
|
|
86809
|
+
hookText = "";
|
|
86810
|
+
hookConsecutiveFailures = 0;
|
|
86811
|
+
hookMaxSignatureRepeats = 0;
|
|
86812
|
+
hookMaxSameFileEdits = 0;
|
|
86813
|
+
hookSignatureCounts = /* @__PURE__ */ new Map();
|
|
86814
|
+
hookFileEditCounts = /* @__PURE__ */ new Map();
|
|
86815
|
+
hookToolCalls = /* @__PURE__ */ new Map();
|
|
86816
|
+
idealReviewInjected = false;
|
|
86817
|
+
loopBreakInjected = false;
|
|
86818
|
+
regroundingInjected = false;
|
|
86819
|
+
compactionOccurred = false;
|
|
86820
|
+
originalRequest = "";
|
|
86821
|
+
/** True after the cache has been pre-warmed for this session. Ensures we only
|
|
86822
|
+
* fire the warm-up call once (before the first real turn). */
|
|
86823
|
+
cachePrewarmed = false;
|
|
86824
|
+
// Messages queued by the user while a run is in flight. Drained at the
|
|
86825
|
+
// mid-loop steering boundary (user steering wins over the hooks), mirroring
|
|
86826
|
+
// the TUI's getSteeringMessages. Each entry carries its own attachments so a
|
|
86827
|
+
// user can queue media (images/video/files) mid-run, not just plain text.
|
|
86828
|
+
userQueue = [];
|
|
85729
86829
|
processManager;
|
|
85730
86830
|
lspManager;
|
|
85731
86831
|
mcpManager;
|
|
@@ -85736,6 +86836,12 @@ var AgentSession = class {
|
|
|
85736
86836
|
maxTokens;
|
|
85737
86837
|
thinkingLevel;
|
|
85738
86838
|
customSystemPrompt;
|
|
86839
|
+
/** Shared with the tool layer so plan-mode restrictions read live state. */
|
|
86840
|
+
planModeRef = { current: false };
|
|
86841
|
+
/** Path of the approved plan currently being implemented, or undefined. When
|
|
86842
|
+
* set, the system prompt carries the `[DONE:n]` progress contract so the
|
|
86843
|
+
* model emits step-completion markers the UI's plan-progress widget reads. */
|
|
86844
|
+
approvedPlanPath;
|
|
85739
86845
|
sessionId = "";
|
|
85740
86846
|
sessionPath = "";
|
|
85741
86847
|
lastPersistedIndex = 0;
|
|
@@ -85748,10 +86854,25 @@ var AgentSession = class {
|
|
|
85748
86854
|
this.model = options.model;
|
|
85749
86855
|
this.cwd = options.cwd;
|
|
85750
86856
|
this.baseUrl = options.baseUrl;
|
|
85751
|
-
this.maxTokens =
|
|
86857
|
+
this.maxTokens = this.resolveMaxTokens(options.model);
|
|
85752
86858
|
this.thinkingLevel = options.thinkingLevel;
|
|
85753
86859
|
this.customSystemPrompt = options.systemPrompt;
|
|
85754
86860
|
}
|
|
86861
|
+
/**
|
|
86862
|
+
* Derive the output-token cap for a model. Follows the active model's
|
|
86863
|
+
* `maxOutputTokens` so a session booted on a large-output model (e.g. Kimi's
|
|
86864
|
+
* 256K) doesn't carry that cap to a smaller one (e.g. Opus's 128K) after a
|
|
86865
|
+
* model switch — that mismatch surfaces from the provider as
|
|
86866
|
+
* `max_tokens: 262144 > 128000, which is the maximum allowed …`. An explicit
|
|
86867
|
+
* `maxTokens` override is honored but clamped to the model's ceiling.
|
|
86868
|
+
*/
|
|
86869
|
+
resolveMaxTokens(modelId) {
|
|
86870
|
+
const modelInfo = getModel(modelId);
|
|
86871
|
+
if (this.opts.maxTokens) {
|
|
86872
|
+
return modelInfo ? Math.min(this.opts.maxTokens, modelInfo.maxOutputTokens) : this.opts.maxTokens;
|
|
86873
|
+
}
|
|
86874
|
+
return modelInfo?.maxOutputTokens ?? 16384;
|
|
86875
|
+
}
|
|
85755
86876
|
async initialize() {
|
|
85756
86877
|
setEstimatorModel(this.model);
|
|
85757
86878
|
const paths = await ensureAppDirs();
|
|
@@ -85760,10 +86881,10 @@ var AgentSession = class {
|
|
|
85760
86881
|
this.authStorage = new AuthStorage(paths.authFile);
|
|
85761
86882
|
await this.authStorage.load();
|
|
85762
86883
|
this.sessionManager = new SessionManager(paths.sessionsDir);
|
|
85763
|
-
const localEzDir =
|
|
85764
|
-
await
|
|
85765
|
-
await
|
|
85766
|
-
await
|
|
86884
|
+
const localEzDir = path38.join(this.cwd, ".ezcoder");
|
|
86885
|
+
await fs30.mkdir(path38.join(localEzDir, "skills"), { recursive: true });
|
|
86886
|
+
await fs30.mkdir(path38.join(localEzDir, "commands"), { recursive: true });
|
|
86887
|
+
await fs30.mkdir(path38.join(localEzDir, "agents"), { recursive: true });
|
|
85767
86888
|
this.skills = await discoverSkills({
|
|
85768
86889
|
globalSkillsDir: paths.skillsDir,
|
|
85769
86890
|
projectDir: this.cwd
|
|
@@ -85772,33 +86893,35 @@ var AgentSession = class {
|
|
|
85772
86893
|
globalAgentsDir: paths.agentsDir,
|
|
85773
86894
|
projectDir: this.cwd
|
|
85774
86895
|
});
|
|
85775
|
-
const { tools, processManager, lspManager } = createTools(this.cwd, {
|
|
86896
|
+
const { tools, processManager, rebuildReadTool, lspManager } = await createTools(this.cwd, {
|
|
85776
86897
|
agents,
|
|
85777
86898
|
skills: this.skills,
|
|
85778
86899
|
provider: this.provider,
|
|
85779
86900
|
model: this.model,
|
|
85780
86901
|
lspDiagnostics: this.settingsManager.get("lspDiagnostics"),
|
|
85781
|
-
|
|
85782
|
-
//
|
|
85783
|
-
|
|
86902
|
+
authStorage: this.authStorage,
|
|
86903
|
+
// Lazy — sessionId/model/provider can change after createTools() runs, so
|
|
86904
|
+
// sub-agent spawns read the current parent state at execution time.
|
|
86905
|
+
getProvider: () => this.provider,
|
|
86906
|
+
getModel: () => this.model,
|
|
86907
|
+
getCacheKey: () => this.getPromptCacheKey(),
|
|
86908
|
+
// Plan mode: only wired when the host supplies callbacks. The ref is
|
|
86909
|
+
// shared so bash/edit/write enforce read-only restrictions live.
|
|
86910
|
+
...this.opts.onEnterPlan || this.opts.onExitPlan ? {
|
|
86911
|
+
planModeRef: this.planModeRef,
|
|
86912
|
+
onEnterPlan: this.opts.onEnterPlan,
|
|
86913
|
+
onExitPlan: this.opts.onExitPlan
|
|
86914
|
+
} : {}
|
|
85784
86915
|
});
|
|
85785
86916
|
this.tools = tools;
|
|
86917
|
+
this.rebuildReadTool = rebuildReadTool;
|
|
85786
86918
|
this.processManager = processManager;
|
|
85787
86919
|
this.lspManager = lspManager;
|
|
85788
86920
|
this.mcpManager = new MCPClientManager();
|
|
85789
|
-
|
|
85790
|
-
|
|
85791
|
-
|
|
85792
|
-
|
|
85793
|
-
const glmCreds = await this.authStorage.resolveCredentials("glm");
|
|
85794
|
-
apiKey = glmCreds.accessToken;
|
|
85795
|
-
} catch {
|
|
85796
|
-
}
|
|
85797
|
-
}
|
|
85798
|
-
const mcpTools = await this.mcpManager.connectAll(getMCPServers(this.provider, apiKey));
|
|
85799
|
-
this.tools.push(...mcpTools);
|
|
85800
|
-
} catch (err) {
|
|
85801
|
-
log("WARN", "mcp", `MCP initialization failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
86921
|
+
if (this.opts.backgroundMcpConnect) {
|
|
86922
|
+
void this.connectMcpServers();
|
|
86923
|
+
} else {
|
|
86924
|
+
await this.connectMcpServers();
|
|
85802
86925
|
}
|
|
85803
86926
|
const basePrompt = this.customSystemPrompt ?? await buildSystemPrompt(this.cwd, this.skills, false, void 0, this.tools.map((tool) => tool.name), void 0, this.provider);
|
|
85804
86927
|
this.messages = [{ role: "system", content: basePrompt }];
|
|
@@ -85855,6 +86978,36 @@ var AgentSession = class {
|
|
|
85855
86978
|
await this.extensionLoader.loadAll(paths.extensionsDir, extContext);
|
|
85856
86979
|
this.eventBus.emit("session_start", { sessionId: this.sessionId });
|
|
85857
86980
|
}
|
|
86981
|
+
/**
|
|
86982
|
+
* Connect all configured MCP servers and append their tools to `this.tools`.
|
|
86983
|
+
* Resolves the GLM api key first (Z.AI's bundled servers need it). Never
|
|
86984
|
+
* throws — a failed connect is logged and skipped — so it is safe to either
|
|
86985
|
+
* `await` (CLI: tools ready before the first turn) or fire-and-forget
|
|
86986
|
+
* (sidecar: `backgroundMcpConnect`, so a slow stdio server can't stall
|
|
86987
|
+
* startup). Tools are pushed onto the live array the agent loop reads each
|
|
86988
|
+
* turn, so background-connected servers become available on the next prompt.
|
|
86989
|
+
*/
|
|
86990
|
+
async connectMcpServers() {
|
|
86991
|
+
if (!this.mcpManager)
|
|
86992
|
+
return;
|
|
86993
|
+
try {
|
|
86994
|
+
let apiKey;
|
|
86995
|
+
if (this.provider === "glm") {
|
|
86996
|
+
try {
|
|
86997
|
+
const glmCreds = await this.authStorage.resolveCredentials("glm");
|
|
86998
|
+
apiKey = glmCreds.accessToken;
|
|
86999
|
+
} catch {
|
|
87000
|
+
}
|
|
87001
|
+
}
|
|
87002
|
+
const mcpTools = await this.mcpManager.connectAll(await getAllMcpServers(this.provider, apiKey, this.cwd));
|
|
87003
|
+
this.tools.push(...mcpTools);
|
|
87004
|
+
if (this.opts.backgroundMcpConnect && mcpTools.length > 0) {
|
|
87005
|
+
await this.rebuildSystemPromptInPlace();
|
|
87006
|
+
}
|
|
87007
|
+
} catch (err) {
|
|
87008
|
+
log("WARN", "mcp", `MCP initialization failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
87009
|
+
}
|
|
87010
|
+
}
|
|
85858
87011
|
/**
|
|
85859
87012
|
* Process user input. Handles slash commands or runs agent loop.
|
|
85860
87013
|
*/
|
|
@@ -85891,6 +87044,208 @@ ${parsed.args}` : promptText;
|
|
|
85891
87044
|
this.lastPersistedIndex = this.messages.length;
|
|
85892
87045
|
await this.runLoop();
|
|
85893
87046
|
}
|
|
87047
|
+
/**
|
|
87048
|
+
* Prompt with multimodal attachments (images / videos) alongside optional
|
|
87049
|
+
* text. Images and videos become native content blocks the model can see;
|
|
87050
|
+
* non-media files are surfaced as a text note with their saved path so the
|
|
87051
|
+
* agent can open them with its tools. Slash-command parsing is skipped —
|
|
87052
|
+
* attachments are always a direct conversational turn.
|
|
87053
|
+
*/
|
|
87054
|
+
async promptWithAttachments(text, attachments) {
|
|
87055
|
+
const parts = this.buildAttachmentParts(text, attachments);
|
|
87056
|
+
if (parts.length === 0)
|
|
87057
|
+
return;
|
|
87058
|
+
const userMessage = { role: "user", content: parts };
|
|
87059
|
+
this.messages.push(userMessage);
|
|
87060
|
+
await this.persistMessage(userMessage);
|
|
87061
|
+
this.lastPersistedIndex = this.messages.length;
|
|
87062
|
+
await this.runLoop();
|
|
87063
|
+
}
|
|
87064
|
+
/**
|
|
87065
|
+
* Build the native content blocks (text + image/video notes + file notes) for
|
|
87066
|
+
* a user message with attachments. Shared by {@link promptWithAttachments} and
|
|
87067
|
+
* the mid-run steering drain so queued media is delivered identically.
|
|
87068
|
+
*/
|
|
87069
|
+
buildAttachmentParts(text, attachments) {
|
|
87070
|
+
const parts = [];
|
|
87071
|
+
const fileNotes = [];
|
|
87072
|
+
const modelSupportsVideo = getModel(this.model)?.supportsVideo ?? false;
|
|
87073
|
+
for (const a of attachments) {
|
|
87074
|
+
if (a.kind === "image") {
|
|
87075
|
+
parts.push({ type: "image", mediaType: a.mediaType, data: a.data });
|
|
87076
|
+
if (a.path) {
|
|
87077
|
+
parts.push({ type: "text", text: `[Image saved at ${a.path}]` });
|
|
87078
|
+
}
|
|
87079
|
+
} else if (a.kind === "video") {
|
|
87080
|
+
if (modelSupportsVideo && a.path) {
|
|
87081
|
+
parts.push({
|
|
87082
|
+
type: "text",
|
|
87083
|
+
text: `The user attached a video at ${a.path}. You CAN watch it: call the read tool on this exact path now, then answer based on what you see. Do not say you cannot watch video \u2014 reading the file lets you analyze it.`
|
|
87084
|
+
});
|
|
87085
|
+
} else if (a.path) {
|
|
87086
|
+
parts.push({
|
|
87087
|
+
type: "text",
|
|
87088
|
+
text: `[User attached a video file at ${a.path}. You cannot watch video directly; if needed, use ffmpeg to extract frames or audio.]`
|
|
87089
|
+
});
|
|
87090
|
+
} else {
|
|
87091
|
+
parts.push({
|
|
87092
|
+
type: "text",
|
|
87093
|
+
text: `[User attached a video file but it could not be saved for analysis.]`
|
|
87094
|
+
});
|
|
87095
|
+
}
|
|
87096
|
+
} else if (a.path) {
|
|
87097
|
+
fileNotes.push(`- ${a.name} (saved at ${a.path})`);
|
|
87098
|
+
}
|
|
87099
|
+
}
|
|
87100
|
+
const textParts = [];
|
|
87101
|
+
if (text.trim())
|
|
87102
|
+
textParts.push(text.trim());
|
|
87103
|
+
if (fileNotes.length > 0) {
|
|
87104
|
+
textParts.push(`Attached files (inspect with your tools):
|
|
87105
|
+
${fileNotes.join("\n")}`);
|
|
87106
|
+
}
|
|
87107
|
+
if (textParts.length > 0)
|
|
87108
|
+
parts.unshift({ type: "text", text: textParts.join("\n\n") });
|
|
87109
|
+
return parts;
|
|
87110
|
+
}
|
|
87111
|
+
/**
|
|
87112
|
+
* Reset per-run self-correction hook state. Mirrors the TUI's run_start
|
|
87113
|
+
* resets so each run evaluates the hooks from a clean slate. `originalRequest`
|
|
87114
|
+
* is the verbatim user ask, pinned for post-compaction re-grounding.
|
|
87115
|
+
*/
|
|
87116
|
+
resetHookState(originalRequest) {
|
|
87117
|
+
this.hookStats = {
|
|
87118
|
+
changedLines: 0,
|
|
87119
|
+
toolCalls: 0,
|
|
87120
|
+
toolFailures: 0,
|
|
87121
|
+
turns: 0,
|
|
87122
|
+
writeCalls: 0,
|
|
87123
|
+
editCalls: 0,
|
|
87124
|
+
bashCalls: 0
|
|
87125
|
+
};
|
|
87126
|
+
this.hookText = "";
|
|
87127
|
+
this.hookConsecutiveFailures = 0;
|
|
87128
|
+
this.hookMaxSignatureRepeats = 0;
|
|
87129
|
+
this.hookMaxSameFileEdits = 0;
|
|
87130
|
+
this.hookSignatureCounts.clear();
|
|
87131
|
+
this.hookFileEditCounts.clear();
|
|
87132
|
+
this.hookToolCalls.clear();
|
|
87133
|
+
this.idealReviewInjected = false;
|
|
87134
|
+
this.loopBreakInjected = false;
|
|
87135
|
+
this.regroundingInjected = false;
|
|
87136
|
+
this.compactionOccurred = false;
|
|
87137
|
+
this.originalRequest = originalRequest;
|
|
87138
|
+
}
|
|
87139
|
+
/**
|
|
87140
|
+
* Fold one agent event into the hook stat accumulators. Pure bookkeeping —
|
|
87141
|
+
* the same signals the TUI's useAgentLoop collects, so the loop-break and
|
|
87142
|
+
* ideal-review decisions match across the CLI and the app.
|
|
87143
|
+
*/
|
|
87144
|
+
trackHookEvent(event) {
|
|
87145
|
+
switch (event.type) {
|
|
87146
|
+
case "text_delta":
|
|
87147
|
+
this.hookText += event.text;
|
|
87148
|
+
break;
|
|
87149
|
+
case "tool_call_start":
|
|
87150
|
+
this.hookToolCalls.set(event.toolCallId, { name: event.name, args: event.args ?? {} });
|
|
87151
|
+
break;
|
|
87152
|
+
case "tool_call_end": {
|
|
87153
|
+
const call = this.hookToolCalls.get(event.toolCallId);
|
|
87154
|
+
const name = call?.name ?? "";
|
|
87155
|
+
const args = call?.args;
|
|
87156
|
+
this.hookStats.toolCalls += 1;
|
|
87157
|
+
if (event.isError)
|
|
87158
|
+
this.hookStats.toolFailures += 1;
|
|
87159
|
+
if (name === "write")
|
|
87160
|
+
this.hookStats.writeCalls += 1;
|
|
87161
|
+
if (name === "edit")
|
|
87162
|
+
this.hookStats.editCalls += 1;
|
|
87163
|
+
if (name === "bash")
|
|
87164
|
+
this.hookStats.bashCalls += 1;
|
|
87165
|
+
this.hookConsecutiveFailures = event.isError ? this.hookConsecutiveFailures + 1 : 0;
|
|
87166
|
+
const sig = toolCallSignature(name, args);
|
|
87167
|
+
const sigNext = (this.hookSignatureCounts.get(sig) ?? 0) + 1;
|
|
87168
|
+
this.hookSignatureCounts.set(sig, sigNext);
|
|
87169
|
+
if (sigNext > this.hookMaxSignatureRepeats)
|
|
87170
|
+
this.hookMaxSignatureRepeats = sigNext;
|
|
87171
|
+
if ((name === "edit" || name === "write") && args) {
|
|
87172
|
+
const filePath = args.file_path;
|
|
87173
|
+
if (typeof filePath === "string") {
|
|
87174
|
+
const fileNext = (this.hookFileEditCounts.get(filePath) ?? 0) + 1;
|
|
87175
|
+
this.hookFileEditCounts.set(filePath, fileNext);
|
|
87176
|
+
if (fileNext > this.hookMaxSameFileEdits)
|
|
87177
|
+
this.hookMaxSameFileEdits = fileNext;
|
|
87178
|
+
}
|
|
87179
|
+
}
|
|
87180
|
+
if (name === "edit" && !event.isError) {
|
|
87181
|
+
const diff3 = event.details?.diff ?? event.result;
|
|
87182
|
+
const added = (diff3.match(/^\+[^+]/gm) ?? []).length;
|
|
87183
|
+
const removed = (diff3.match(/^-[^-]/gm) ?? []).length;
|
|
87184
|
+
this.hookStats.changedLines += added + removed;
|
|
87185
|
+
}
|
|
87186
|
+
break;
|
|
87187
|
+
}
|
|
87188
|
+
case "turn_end":
|
|
87189
|
+
this.hookStats.turns = event.turn;
|
|
87190
|
+
break;
|
|
87191
|
+
}
|
|
87192
|
+
}
|
|
87193
|
+
/**
|
|
87194
|
+
* Mid-loop steering hook: fires the loop-breaker when the agent looks stuck,
|
|
87195
|
+
* then post-compaction re-grounding. At most one of each per run. Mirrors the
|
|
87196
|
+
* TUI's getSteeringMessages ordering (minus user steering, which the app
|
|
87197
|
+
* delivers as normal prompts).
|
|
87198
|
+
*/
|
|
87199
|
+
getHookSteeringMessages() {
|
|
87200
|
+
if (this.userQueue.length > 0) {
|
|
87201
|
+
const queued = this.userQueue.splice(0);
|
|
87202
|
+
if (queued.every((m) => m.attachments.length === 0)) {
|
|
87203
|
+
const merged = queued.map((m) => m.text).join("\n\n");
|
|
87204
|
+
return [{ role: "user", content: merged }];
|
|
87205
|
+
}
|
|
87206
|
+
const parts = [];
|
|
87207
|
+
for (const m of queued)
|
|
87208
|
+
parts.push(...this.buildAttachmentParts(m.text, m.attachments));
|
|
87209
|
+
return [{ role: "user", content: parts }];
|
|
87210
|
+
}
|
|
87211
|
+
if (!this.settingsManager.get("idealReviewEnabled"))
|
|
87212
|
+
return null;
|
|
87213
|
+
if (!this.loopBreakInjected) {
|
|
87214
|
+
const decision = evaluateLoopBreak({
|
|
87215
|
+
consecutiveFailures: this.hookConsecutiveFailures,
|
|
87216
|
+
maxSignatureRepeats: this.hookMaxSignatureRepeats,
|
|
87217
|
+
maxSameFileEdits: this.hookMaxSameFileEdits,
|
|
87218
|
+
textRepetitionDetected: detectTextRepetition(this.hookText)
|
|
87219
|
+
});
|
|
87220
|
+
if (decision.shouldBreak) {
|
|
87221
|
+
this.loopBreakInjected = true;
|
|
87222
|
+
this.eventBus.emit("hook", { kind: "loop_break" });
|
|
87223
|
+
return [buildLoopBreakMessage(decision.reasons)];
|
|
87224
|
+
}
|
|
87225
|
+
}
|
|
87226
|
+
if (!this.regroundingInjected && this.compactionOccurred) {
|
|
87227
|
+
this.regroundingInjected = true;
|
|
87228
|
+
this.eventBus.emit("hook", { kind: "regrounding" });
|
|
87229
|
+
return [buildRegroundingMessage(this.originalRequest)];
|
|
87230
|
+
}
|
|
87231
|
+
return null;
|
|
87232
|
+
}
|
|
87233
|
+
/**
|
|
87234
|
+
* Pre-stop follow-up hook: runs the ideal review once, when the agent would
|
|
87235
|
+
* otherwise finish and the change set is substantial enough to warrant it.
|
|
87236
|
+
*/
|
|
87237
|
+
getHookFollowUpMessages() {
|
|
87238
|
+
if (!this.settingsManager.get("idealReviewEnabled"))
|
|
87239
|
+
return null;
|
|
87240
|
+
if (this.idealReviewInjected)
|
|
87241
|
+
return null;
|
|
87242
|
+
const decision = evaluateIdealReview(this.hookStats);
|
|
87243
|
+
if (!decision.shouldReview)
|
|
87244
|
+
return null;
|
|
87245
|
+
this.idealReviewInjected = true;
|
|
87246
|
+
this.eventBus.emit("hook", { kind: "ideal" });
|
|
87247
|
+
return [buildIdealReviewMessage(decision.reasons)];
|
|
87248
|
+
}
|
|
85894
87249
|
/** Auto-compact if needed, run agent loop with auth retry, and persist messages. */
|
|
85895
87250
|
async runLoop() {
|
|
85896
87251
|
if (!this.cacheKeyLogged) {
|
|
@@ -85902,6 +87257,9 @@ ${parsed.args}` : promptText;
|
|
|
85902
87257
|
transient: String(!!this.opts.transient)
|
|
85903
87258
|
});
|
|
85904
87259
|
}
|
|
87260
|
+
const lastUser = [...this.messages].reverse().find((m) => m.role === "user");
|
|
87261
|
+
const originalRequest = typeof lastUser?.content === "string" ? lastUser.content : "";
|
|
87262
|
+
this.resetHookState(originalRequest);
|
|
85905
87263
|
let creds = await this.authStorage.resolveCredentials(this.provider);
|
|
85906
87264
|
if (this.settingsManager.get("autoCompact")) {
|
|
85907
87265
|
const contextWindow = getContextWindow(this.model, {
|
|
@@ -85911,6 +87269,7 @@ ${parsed.args}` : promptText;
|
|
|
85911
87269
|
const threshold = this.settingsManager.get("compactThreshold");
|
|
85912
87270
|
if (shouldCompact(this.messages, contextWindow, threshold)) {
|
|
85913
87271
|
await this.compact(creds);
|
|
87272
|
+
this.compactionOccurred = true;
|
|
85914
87273
|
}
|
|
85915
87274
|
}
|
|
85916
87275
|
const userAgent = this.provider === "anthropic" ? await getClaudeCliUserAgent() : void 0;
|
|
@@ -85933,20 +87292,28 @@ ${parsed.args}` : promptText;
|
|
|
85933
87292
|
// Kimi For Coding gates the managed endpoint on coding-agent identity
|
|
85934
87293
|
// headers; attach them only when the Kimi OAuth token is in use.
|
|
85935
87294
|
defaultHeaders: this.provider === "moonshot" && isKimiCodingEndpoint(effectiveBaseUrl) ? kimiCodingHeaders() : void 0,
|
|
85936
|
-
|
|
87295
|
+
// speedProfile "optimized": 1-h cache TTL (survives turns >5 min apart)
|
|
87296
|
+
// + pre-warm before the first turn. "baseline": current 5-min default.
|
|
87297
|
+
cacheRetention: this.isSpeedOptimized() ? "long" : "short",
|
|
85937
87298
|
promptCacheKey: this.getPromptCacheKey(),
|
|
85938
87299
|
supportsImages: modelInfo?.supportsImages,
|
|
85939
87300
|
supportsVideo: modelInfo?.supportsVideo,
|
|
85940
87301
|
userAgent,
|
|
85941
87302
|
// clearToolUses disabled — causes model to output unsolicited context summaries
|
|
85942
87303
|
// Single tool result shouldn't exceed 30% of context window (in chars)
|
|
85943
|
-
maxToolResultChars: Math.floor(getContextWindow(this.model, { provider: this.provider, accountId }) * 3.5 * 0.3)
|
|
87304
|
+
maxToolResultChars: Math.floor(getContextWindow(this.model, { provider: this.provider, accountId }) * 3.5 * 0.3),
|
|
87305
|
+
// Self-correction hooks (same as the TUI): loop-break + re-grounding are
|
|
87306
|
+
// polled mid-loop; the ideal review is polled when the agent would stop.
|
|
87307
|
+
getSteeringMessages: () => this.getHookSteeringMessages(),
|
|
87308
|
+
getFollowUpMessages: () => this.getHookFollowUpMessages()
|
|
85944
87309
|
});
|
|
85945
87310
|
for await (const event of generator) {
|
|
87311
|
+
this.trackHookEvent(event);
|
|
85946
87312
|
this.eventBus.forwardAgentEvent(event);
|
|
85947
87313
|
}
|
|
85948
87314
|
};
|
|
85949
87315
|
try {
|
|
87316
|
+
await this.maybePrewarmCache(creds);
|
|
85950
87317
|
await runAgentLoop(creds.accessToken, creds.accountId, creds.projectId);
|
|
85951
87318
|
} catch (err) {
|
|
85952
87319
|
if (isAbortError4(err) || this.opts.signal?.aborted) {
|
|
@@ -85977,7 +87344,16 @@ ${parsed.args}` : promptText;
|
|
|
85977
87344
|
this.provider = provider;
|
|
85978
87345
|
this.model = model;
|
|
85979
87346
|
setEstimatorModel(model);
|
|
85980
|
-
this.
|
|
87347
|
+
this.maxTokens = this.resolveMaxTokens(model);
|
|
87348
|
+
this.eventBus.emit("model_change", {
|
|
87349
|
+
provider: this.provider,
|
|
87350
|
+
model: this.model,
|
|
87351
|
+
supportsVideo: getModel(this.model)?.supportsVideo ?? false
|
|
87352
|
+
});
|
|
87353
|
+
if (this.rebuildReadTool) {
|
|
87354
|
+
const newReadTool = this.rebuildReadTool(model);
|
|
87355
|
+
this.tools = this.tools.map((t) => t.name === "read" ? newReadTool : t);
|
|
87356
|
+
}
|
|
85981
87357
|
if (provider && provider !== prevProvider) {
|
|
85982
87358
|
const hasWebSearch = this.tools.some((t) => t.name === "web_search");
|
|
85983
87359
|
if (this.provider === "anthropic" && hasWebSearch) {
|
|
@@ -86040,6 +87416,8 @@ ${parsed.args}` : promptText;
|
|
|
86040
87416
|
});
|
|
86041
87417
|
}
|
|
86042
87418
|
async newSession() {
|
|
87419
|
+
this.planModeRef.current = false;
|
|
87420
|
+
this.approvedPlanPath = void 0;
|
|
86043
87421
|
const basePrompt = this.customSystemPrompt ?? await buildSystemPrompt(this.cwd, this.skills, false, void 0, this.tools.map((tool) => tool.name), void 0, this.provider);
|
|
86044
87422
|
this.messages = [{ role: "system", content: basePrompt }];
|
|
86045
87423
|
await this.createNewSession();
|
|
@@ -86094,16 +87472,151 @@ ${parsed.args}` : promptText;
|
|
|
86094
87472
|
cwd: this.cwd,
|
|
86095
87473
|
sessionId: this.sessionId,
|
|
86096
87474
|
sessionPath: this.sessionPath,
|
|
86097
|
-
messageCount: this.messages.length
|
|
87475
|
+
messageCount: this.messages.length,
|
|
87476
|
+
planMode: this.planModeRef.current
|
|
86098
87477
|
};
|
|
86099
87478
|
}
|
|
87479
|
+
getPlanMode() {
|
|
87480
|
+
return this.planModeRef.current;
|
|
87481
|
+
}
|
|
87482
|
+
/** Queue a user message (optionally with attachments) to be injected mid-run
|
|
87483
|
+
* as steering. Returns the new queue length. No-op semantics are the caller's
|
|
87484
|
+
* concern. */
|
|
87485
|
+
queueMessage(text, attachments = []) {
|
|
87486
|
+
this.userQueue.push({ text, attachments });
|
|
87487
|
+
return this.userQueue.length;
|
|
87488
|
+
}
|
|
87489
|
+
/** Number of messages currently queued. */
|
|
87490
|
+
getQueuedCount() {
|
|
87491
|
+
return this.userQueue.length;
|
|
87492
|
+
}
|
|
87493
|
+
/** Clear the queue, returning the combined text (to restore to the composer).
|
|
87494
|
+
* Queued attachments are dropped on cancel — the composer only restores text. */
|
|
87495
|
+
drainQueue() {
|
|
87496
|
+
return this.userQueue.splice(0).map((m) => m.text).join("\n\n");
|
|
87497
|
+
}
|
|
87498
|
+
/** Snapshot of background processes (bash run_in_background), newest-state. */
|
|
87499
|
+
listBackgroundProcesses() {
|
|
87500
|
+
return this.processManager?.list() ?? [];
|
|
87501
|
+
}
|
|
87502
|
+
/** Stop a background process by id. Returns a human-readable status string. */
|
|
87503
|
+
async killBackgroundProcess(id2) {
|
|
87504
|
+
if (!this.processManager)
|
|
87505
|
+
return `No background process with id "${id2}"`;
|
|
87506
|
+
return this.processManager.stop(id2);
|
|
87507
|
+
}
|
|
87508
|
+
/**
|
|
87509
|
+
* Toggle plan mode: flips the shared ref (so tools enforce read-only
|
|
87510
|
+
* restrictions) and rebuilds the system prompt in place so the model is told
|
|
87511
|
+
* about the mode change on its next turn. No-op when a custom system prompt
|
|
87512
|
+
* is in force (the host owns the prompt then).
|
|
87513
|
+
*/
|
|
87514
|
+
async setPlanMode(active) {
|
|
87515
|
+
this.planModeRef.current = active;
|
|
87516
|
+
if (active)
|
|
87517
|
+
this.approvedPlanPath = void 0;
|
|
87518
|
+
await this.rebuildSystemPromptInPlace();
|
|
87519
|
+
}
|
|
87520
|
+
/**
|
|
87521
|
+
* Bake an approved plan into the system prompt so the model is told to emit
|
|
87522
|
+
* `[DONE:n]` markers as it completes each step (the contract the UI's
|
|
87523
|
+
* plan-progress widget reads). Pass `undefined` to clear it. No-op when a
|
|
87524
|
+
* custom system prompt is in force (the host owns the prompt then).
|
|
87525
|
+
*/
|
|
87526
|
+
async setApprovedPlan(approvedPlanPath) {
|
|
87527
|
+
this.approvedPlanPath = approvedPlanPath;
|
|
87528
|
+
await this.rebuildSystemPromptInPlace();
|
|
87529
|
+
}
|
|
87530
|
+
/** Rebuild messages[0] from current plan-mode + approved-plan state. */
|
|
87531
|
+
async rebuildSystemPromptInPlace() {
|
|
87532
|
+
if (this.customSystemPrompt)
|
|
87533
|
+
return;
|
|
87534
|
+
const rebuilt = await buildSystemPrompt(this.cwd, this.skills, this.planModeRef.current, this.approvedPlanPath, this.tools.map((tool) => tool.name), void 0, this.provider);
|
|
87535
|
+
if (this.messages[0]?.role === "system") {
|
|
87536
|
+
this.messages[0] = { role: "system", content: rebuilt };
|
|
87537
|
+
} else {
|
|
87538
|
+
this.messages.unshift({ role: "system", content: rebuilt });
|
|
87539
|
+
}
|
|
87540
|
+
}
|
|
86100
87541
|
getMessages() {
|
|
86101
87542
|
return this.messages;
|
|
86102
87543
|
}
|
|
87544
|
+
/**
|
|
87545
|
+
* Generate a short LLM session title from the conversation so far (first user
|
|
87546
|
+
* message + first assistant reply). Best-effort; returns null on failure or
|
|
87547
|
+
* when there's no user message yet. Uses the cheapest model for the provider.
|
|
87548
|
+
*/
|
|
87549
|
+
async generateTitle() {
|
|
87550
|
+
const extractText = (content) => typeof content === "string" ? content : content.map((c2) => c2.type === "text" && "text" in c2 && typeof c2.text === "string" ? c2.text : "").join(" ");
|
|
87551
|
+
const userMsg = this.messages.find((m) => m.role === "user");
|
|
87552
|
+
const assistantMsg = this.messages.find((m) => m.role === "assistant");
|
|
87553
|
+
const userText = userMsg ? extractText(userMsg.content) : "";
|
|
87554
|
+
if (!userText.trim())
|
|
87555
|
+
return null;
|
|
87556
|
+
try {
|
|
87557
|
+
const creds = await this.authStorage.resolveCredentials(this.provider);
|
|
87558
|
+
const title = await generateSessionTitle({
|
|
87559
|
+
provider: this.provider,
|
|
87560
|
+
userMessage: userText,
|
|
87561
|
+
assistantPreview: assistantMsg ? extractText(assistantMsg.content).slice(0, 200) : "",
|
|
87562
|
+
apiKey: creds.accessToken,
|
|
87563
|
+
baseUrl: this.baseUrl ?? creds.baseUrl,
|
|
87564
|
+
accountId: creds.accountId
|
|
87565
|
+
});
|
|
87566
|
+
return title || null;
|
|
87567
|
+
} catch {
|
|
87568
|
+
return null;
|
|
87569
|
+
}
|
|
87570
|
+
}
|
|
87571
|
+
/** Current reasoning/thinking level, or undefined when thinking is off. */
|
|
87572
|
+
getThinkingLevel() {
|
|
87573
|
+
return this.thinkingLevel;
|
|
87574
|
+
}
|
|
87575
|
+
/** Set the reasoning/thinking level (undefined turns thinking off). Takes
|
|
87576
|
+
* effect on the next prompt, since the in-flight loop reads it at start. */
|
|
87577
|
+
setThinkingLevel(level) {
|
|
87578
|
+
this.thinkingLevel = level;
|
|
87579
|
+
}
|
|
86103
87580
|
/** Replace the abort signal (e.g. after cancellation). */
|
|
86104
87581
|
setSignal(signal) {
|
|
86105
87582
|
this.opts = { ...this.opts, signal };
|
|
86106
87583
|
}
|
|
87584
|
+
/** True when speedProfile is "optimized" (1-h cache TTL + pre-warm). */
|
|
87585
|
+
isSpeedOptimized() {
|
|
87586
|
+
return this.settingsManager?.get("speedProfile") === "optimized";
|
|
87587
|
+
}
|
|
87588
|
+
/** Fire a cache pre-warm request for Anthropic so the first real turn is a
|
|
87589
|
+
* cache read instead of a cold write. No-op for other providers and when
|
|
87590
|
+
* speedProfile is not "optimized". Entirely best-effort — any failure is
|
|
87591
|
+
* swallowed so prewarm never blocks or aborts the real prompt. */
|
|
87592
|
+
async maybePrewarmCache(creds) {
|
|
87593
|
+
if (this.cachePrewarmed || !this.isSpeedOptimized() || this.provider !== "anthropic") {
|
|
87594
|
+
return;
|
|
87595
|
+
}
|
|
87596
|
+
this.cachePrewarmed = true;
|
|
87597
|
+
try {
|
|
87598
|
+
const userAgent = await getClaudeCliUserAgent();
|
|
87599
|
+
const systemText = typeof this.messages[0]?.content === "string" ? this.messages[0].content : "";
|
|
87600
|
+
if (!systemText)
|
|
87601
|
+
return;
|
|
87602
|
+
await prewarmAnthropicCache({
|
|
87603
|
+
apiKey: creds.accessToken,
|
|
87604
|
+
model: this.model,
|
|
87605
|
+
system: systemText,
|
|
87606
|
+
tools: this.tools.map((t) => ({
|
|
87607
|
+
name: t.name,
|
|
87608
|
+
description: t.description,
|
|
87609
|
+
parameters: t.parameters,
|
|
87610
|
+
...t.rawInputSchema ? { rawInputSchema: t.rawInputSchema } : {}
|
|
87611
|
+
})),
|
|
87612
|
+
baseUrl: this.baseUrl ?? creds.baseUrl,
|
|
87613
|
+
userAgent,
|
|
87614
|
+
cacheRetention: "long",
|
|
87615
|
+
signal: this.opts.signal
|
|
87616
|
+
});
|
|
87617
|
+
} catch {
|
|
87618
|
+
}
|
|
87619
|
+
}
|
|
86107
87620
|
getPromptCacheKey() {
|
|
86108
87621
|
if (this.opts.promptCacheKey)
|
|
86109
87622
|
return this.opts.promptCacheKey;
|
|
@@ -86176,7 +87689,7 @@ ${parsed.args}` : promptText;
|
|
|
86176
87689
|
async persistMessage(message) {
|
|
86177
87690
|
if (!this.sessionPath)
|
|
86178
87691
|
return;
|
|
86179
|
-
const entryId =
|
|
87692
|
+
const entryId = crypto9.randomUUID();
|
|
86180
87693
|
const entry = {
|
|
86181
87694
|
type: "message",
|
|
86182
87695
|
id: entryId,
|
|
@@ -87045,7 +88558,7 @@ import process14 from "process";
|
|
|
87045
88558
|
init_esm_shims();
|
|
87046
88559
|
var import_react15 = __toESM(require_react(), 1);
|
|
87047
88560
|
import process13 from "process";
|
|
87048
|
-
import
|
|
88561
|
+
import fs33 from "fs";
|
|
87049
88562
|
|
|
87050
88563
|
// ../../node_modules/.pnpm/es-toolkit@1.46.1/node_modules/es-toolkit/dist/compat/index.mjs
|
|
87051
88564
|
init_esm_shims();
|
|
@@ -89238,7 +90751,7 @@ function wrapAnsi2(string4, columns, options) {
|
|
|
89238
90751
|
init_esm_shims();
|
|
89239
90752
|
import process5 from "process";
|
|
89240
90753
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
89241
|
-
import
|
|
90754
|
+
import fs31 from "fs";
|
|
89242
90755
|
import tty from "tty";
|
|
89243
90756
|
var defaultColumns = 80;
|
|
89244
90757
|
var defaultRows = 24;
|
|
@@ -89268,7 +90781,7 @@ var isForegroundProcess = () => {
|
|
|
89268
90781
|
return true;
|
|
89269
90782
|
}
|
|
89270
90783
|
try {
|
|
89271
|
-
const statContents =
|
|
90784
|
+
const statContents = fs31.readFileSync("/proc/self/stat", "utf8");
|
|
89272
90785
|
const closingParenthesisIndex = statContents.lastIndexOf(") ");
|
|
89273
90786
|
if (closingParenthesisIndex === -1) {
|
|
89274
90787
|
return false;
|
|
@@ -89312,8 +90825,8 @@ function terminalSize() {
|
|
|
89312
90825
|
}
|
|
89313
90826
|
var devTty = () => {
|
|
89314
90827
|
try {
|
|
89315
|
-
const flags = process5.platform === "darwin" ?
|
|
89316
|
-
const { columns, rows } = tty.WriteStream(
|
|
90828
|
+
const flags = process5.platform === "darwin" ? fs31.constants.O_EVTONLY | fs31.constants.O_NONBLOCK : fs31.constants.O_NONBLOCK;
|
|
90829
|
+
const { columns, rows } = tty.WriteStream(fs31.openSync("/dev/tty", flags));
|
|
89317
90830
|
return { columns, rows };
|
|
89318
90831
|
} catch {
|
|
89319
90832
|
}
|
|
@@ -91125,8 +92638,8 @@ var cleanupYogaNode = (node) => {
|
|
|
91125
92638
|
var currentUpdatePriority = import_constants3.NoEventPriority;
|
|
91126
92639
|
var currentRootNode;
|
|
91127
92640
|
async function loadPackageJson() {
|
|
91128
|
-
const
|
|
91129
|
-
const content =
|
|
92641
|
+
const fs40 = await import("fs");
|
|
92642
|
+
const content = fs40.readFileSync(new URL("../package.json", import.meta.url), "utf8");
|
|
91130
92643
|
return JSON.parse(content);
|
|
91131
92644
|
}
|
|
91132
92645
|
var packageJson = isDev() ? await loadPackageJson() : { name: void 0, version: void 0 };
|
|
@@ -92688,7 +94201,7 @@ var import_react13 = __toESM(require_react(), 1);
|
|
|
92688
94201
|
init_esm_shims();
|
|
92689
94202
|
var import_react12 = __toESM(require_react(), 1);
|
|
92690
94203
|
var import_stack_utils = __toESM(require_stack_utils(), 1);
|
|
92691
|
-
import * as
|
|
94204
|
+
import * as fs32 from "fs";
|
|
92692
94205
|
import { cwd } from "process";
|
|
92693
94206
|
|
|
92694
94207
|
// ../../node_modules/.pnpm/code-excerpt@4.0.0/node_modules/code-excerpt/dist/index.js
|
|
@@ -92816,8 +94329,8 @@ function Text({ color: color2, backgroundColor, dimColor = false, bold = false,
|
|
|
92816
94329
|
}
|
|
92817
94330
|
|
|
92818
94331
|
// ../../node_modules/.pnpm/ink@6.8.0_patch_hash=6c70099ec5b01a8329f3b7bd932ceef28779e4c7f5795e7ff44fa28c2f9d6782_@types+react@19.2.15_react@19.2.6/node_modules/ink/build/components/ErrorOverview.js
|
|
92819
|
-
var cleanupPath = (
|
|
92820
|
-
return
|
|
94332
|
+
var cleanupPath = (path49) => {
|
|
94333
|
+
return path49?.replace(`file://${cwd()}/`, "");
|
|
92821
94334
|
};
|
|
92822
94335
|
var stackUtils = new import_stack_utils.default({
|
|
92823
94336
|
cwd: cwd(),
|
|
@@ -92829,8 +94342,8 @@ function ErrorOverview({ error: error51 }) {
|
|
|
92829
94342
|
const filePath = cleanupPath(origin?.file);
|
|
92830
94343
|
let excerpt;
|
|
92831
94344
|
let lineWidth = 0;
|
|
92832
|
-
if (filePath && origin?.line &&
|
|
92833
|
-
const sourceCode =
|
|
94345
|
+
if (filePath && origin?.line && fs32.existsSync(filePath)) {
|
|
94346
|
+
const sourceCode = fs32.readFileSync(filePath, "utf8");
|
|
92834
94347
|
excerpt = dist_default3(sourceCode, origin.line);
|
|
92835
94348
|
if (excerpt) {
|
|
92836
94349
|
for (const { line } of excerpt) {
|
|
@@ -93649,7 +95162,7 @@ var Ink = class {
|
|
|
93649
95162
|
}
|
|
93650
95163
|
if (process13.env["GG_INK_DEBUG"] === "1" && (delta !== 0 || this.framePadDebt > 0)) {
|
|
93651
95164
|
try {
|
|
93652
|
-
|
|
95165
|
+
fs33.appendFileSync("/tmp/gg-ink-debug.log", JSON.stringify({
|
|
93653
95166
|
t: Date.now() % 1e5,
|
|
93654
95167
|
delta,
|
|
93655
95168
|
ins: insertLineCount,
|
|
@@ -95371,7 +96884,7 @@ var import_react37 = __toESM(require_react(), 1);
|
|
|
95371
96884
|
|
|
95372
96885
|
// ../cli/dist/core/session-compaction.js
|
|
95373
96886
|
init_esm_shims();
|
|
95374
|
-
import
|
|
96887
|
+
import crypto10 from "crypto";
|
|
95375
96888
|
|
|
95376
96889
|
// ../cli/dist/ui/hooks/useContextCompaction.js
|
|
95377
96890
|
init_esm_shims();
|
|
@@ -95485,18 +96998,15 @@ var taskBarStore = createStore({
|
|
|
95485
96998
|
// ../cli/dist/utils/sound.js
|
|
95486
96999
|
init_esm_shims();
|
|
95487
97000
|
import { execFile as execFile2 } from "child_process";
|
|
95488
|
-
import { fileURLToPath as
|
|
97001
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
95489
97002
|
import { resolve as resolve2, dirname } from "path";
|
|
95490
|
-
var __dirname2 = dirname(
|
|
97003
|
+
var __dirname2 = dirname(fileURLToPath4(import.meta.url));
|
|
95491
97004
|
var notificationPath = resolve2(__dirname2, "../../assets/end-notification.mp3");
|
|
95492
97005
|
|
|
95493
97006
|
// ../cli/dist/ui/hooks/useAgentLoop.js
|
|
95494
97007
|
init_esm_shims();
|
|
95495
97008
|
var import_react43 = __toESM(require_react(), 1);
|
|
95496
97009
|
|
|
95497
|
-
// ../cli/dist/core/loop-breaker.js
|
|
95498
|
-
init_esm_shims();
|
|
95499
|
-
|
|
95500
97010
|
// ../cli/dist/ui/hooks/useTranscriptHistory.js
|
|
95501
97011
|
init_esm_shims();
|
|
95502
97012
|
var import_react44 = __toESM(require_react(), 1);
|
|
@@ -96105,8 +97615,8 @@ function shortenValue(value, maxLength = MAX_DETAIL_LENGTH) {
|
|
|
96105
97615
|
const tailLength = maxLength - 1 - headLength;
|
|
96106
97616
|
return `${normalized.slice(0, headLength)}\u2026${normalized.slice(-tailLength)}`;
|
|
96107
97617
|
}
|
|
96108
|
-
function basename3(
|
|
96109
|
-
const trimmed =
|
|
97618
|
+
function basename3(path49) {
|
|
97619
|
+
const trimmed = path49.replace(/\/+$/u, "");
|
|
96110
97620
|
return trimmed.split("/").filter(Boolean).at(-1) ?? trimmed;
|
|
96111
97621
|
}
|
|
96112
97622
|
function uniqueValues(values) {
|
|
@@ -109900,8 +111410,8 @@ function ok() {
|
|
|
109900
111410
|
|
|
109901
111411
|
// ../../node_modules/.pnpm/highlight.js@11.11.1/node_modules/highlight.js/es/core.js
|
|
109902
111412
|
init_esm_shims();
|
|
109903
|
-
var
|
|
109904
|
-
var core_default =
|
|
111413
|
+
var import_core20 = __toESM(require_core3(), 1);
|
|
111414
|
+
var core_default = import_core20.default;
|
|
109905
111415
|
|
|
109906
111416
|
// ../../node_modules/.pnpm/lowlight@3.3.0/node_modules/lowlight/lib/index.js
|
|
109907
111417
|
var emptyOptions = {};
|
|
@@ -111089,7 +112599,7 @@ function collapseSubmittedUserText(text) {
|
|
|
111089
112599
|
}
|
|
111090
112600
|
|
|
111091
112601
|
// ../cli/dist/ui/terminal-history.js
|
|
111092
|
-
import
|
|
112602
|
+
import path39 from "path";
|
|
111093
112603
|
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
111094
112604
|
|
|
111095
112605
|
// ../cli/dist/ui/utils/terminal-graphics.js
|
|
@@ -112135,7 +113645,7 @@ function TaskPickerMenu({ tasks, selectedIndex, width }) {
|
|
|
112135
113645
|
// ../cli/dist/ui/components/InputArea.js
|
|
112136
113646
|
import { homedir as homedir3 } from "os";
|
|
112137
113647
|
import { join as join3 } from "path";
|
|
112138
|
-
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync3, renameSync, unlinkSync, existsSync as
|
|
113648
|
+
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, appendFileSync, mkdirSync as mkdirSync3, renameSync, unlinkSync, existsSync as existsSync7 } from "fs";
|
|
112139
113649
|
var MAX_VISIBLE_LINES = 12;
|
|
112140
113650
|
var PROMPT = "> ";
|
|
112141
113651
|
var PLACEHOLDER = " Type your message or / to run a command";
|
|
@@ -112275,7 +113785,7 @@ function compactHistory2() {
|
|
|
112275
113785
|
lineCountEstimate = trimmed.length;
|
|
112276
113786
|
} catch {
|
|
112277
113787
|
try {
|
|
112278
|
-
if (
|
|
113788
|
+
if (existsSync7(tempPath))
|
|
112279
113789
|
unlinkSync(tempPath);
|
|
112280
113790
|
} catch {
|
|
112281
113791
|
}
|
|
@@ -113414,7 +114924,7 @@ var import_react69 = __toESM(require_react(), 1);
|
|
|
113414
114924
|
|
|
113415
114925
|
// ../cli/dist/ui/pixel.js
|
|
113416
114926
|
init_esm_shims();
|
|
113417
|
-
import { existsSync as
|
|
114927
|
+
import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
|
|
113418
114928
|
import { homedir as homedir4 } from "os";
|
|
113419
114929
|
import { join as join5 } from "path";
|
|
113420
114930
|
|
|
@@ -113423,9 +114933,9 @@ init_esm_shims();
|
|
|
113423
114933
|
import { execFile as execFile3 } from "child_process";
|
|
113424
114934
|
import { readFileSync as readFileSync6 } from "fs";
|
|
113425
114935
|
import { dirname as dirname2, join as join4 } from "path";
|
|
113426
|
-
import { fileURLToPath as
|
|
114936
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
113427
114937
|
function resolveCliVersion() {
|
|
113428
|
-
let dir = dirname2(
|
|
114938
|
+
let dir = dirname2(fileURLToPath5(import.meta.url));
|
|
113429
114939
|
for (let i = 0; i < 6; i++) {
|
|
113430
114940
|
try {
|
|
113431
114941
|
const manifest = JSON.parse(readFileSync6(join4(dir, "package.json"), "utf8"));
|
|
@@ -113454,7 +114964,7 @@ function visualWidth2(str2) {
|
|
|
113454
114964
|
}
|
|
113455
114965
|
|
|
113456
114966
|
// ../cli/dist/ui/components/PlanOverlay.js
|
|
113457
|
-
import { readdir as readdir2, readFile as
|
|
114967
|
+
import { readdir as readdir2, readFile as readFile4, unlink } from "fs/promises";
|
|
113458
114968
|
import { join as join6 } from "path";
|
|
113459
114969
|
var PLAN_LOGO = [
|
|
113460
114970
|
" \u2588\u2580\u2580\u2580 \u2580\u2580\u2580\u2588",
|
|
@@ -113491,26 +115001,23 @@ import { execFile as execFile4 } from "child_process";
|
|
|
113491
115001
|
|
|
113492
115002
|
// ../cli/dist/core/auto-update.js
|
|
113493
115003
|
init_esm_shims();
|
|
113494
|
-
import
|
|
115004
|
+
import path40 from "path";
|
|
113495
115005
|
import os10 from "os";
|
|
113496
115006
|
var updater = createAutoUpdater({
|
|
113497
115007
|
packageName: "@prestyj/cli",
|
|
113498
|
-
stateFilePath: () =>
|
|
115008
|
+
stateFilePath: () => path40.join(os10.homedir(), ".ezcoder", "update-state.json")
|
|
113499
115009
|
});
|
|
113500
115010
|
var checkAndAutoUpdate = updater.checkAndAutoUpdate;
|
|
113501
115011
|
var getPendingUpdate = updater.getPendingUpdate;
|
|
113502
115012
|
var startPeriodicUpdateCheck = updater.startPeriodicUpdateCheck;
|
|
113503
115013
|
var stopPeriodicUpdateCheck = updater.stopPeriodicUpdateCheck;
|
|
113504
115014
|
|
|
113505
|
-
// ../cli/dist/utils/session-title.js
|
|
113506
|
-
init_esm_shims();
|
|
113507
|
-
|
|
113508
115015
|
// ../cli/dist/core/setup-history.js
|
|
113509
115016
|
init_esm_shims();
|
|
113510
|
-
import
|
|
113511
|
-
import
|
|
115017
|
+
import fs34 from "fs";
|
|
115018
|
+
import path41 from "path";
|
|
113512
115019
|
import os11 from "os";
|
|
113513
|
-
var HISTORY_PATH =
|
|
115020
|
+
var HISTORY_PATH = path41.join(os11.homedir(), ".ezcoder", "setup-history.json");
|
|
113514
115021
|
|
|
113515
115022
|
// ../cli/dist/ui/components/RewindOverlay.js
|
|
113516
115023
|
init_esm_shims();
|
|
@@ -113535,12 +115042,6 @@ init_esm_shims();
|
|
|
113535
115042
|
// ../cli/dist/ui/submit-slash-commands.js
|
|
113536
115043
|
init_esm_shims();
|
|
113537
115044
|
|
|
113538
|
-
// ../cli/dist/core/ideal-review.js
|
|
113539
|
-
init_esm_shims();
|
|
113540
|
-
|
|
113541
|
-
// ../cli/dist/core/regrounding.js
|
|
113542
|
-
init_esm_shims();
|
|
113543
|
-
|
|
113544
115045
|
// ../cli/dist/ui/thinking-level.js
|
|
113545
115046
|
init_esm_shims();
|
|
113546
115047
|
|
|
@@ -113760,7 +115261,7 @@ function MessageResponse({ children, height, accentColor }) {
|
|
|
113760
115261
|
|
|
113761
115262
|
// ../cli/dist/ui/utils/highlight.js
|
|
113762
115263
|
init_esm_shims();
|
|
113763
|
-
import
|
|
115264
|
+
import path43 from "path";
|
|
113764
115265
|
var EXT_TO_LANG = {
|
|
113765
115266
|
ts: "typescript",
|
|
113766
115267
|
tsx: "typescript",
|
|
@@ -113788,7 +115289,7 @@ var EXT_TO_LANG = {
|
|
|
113788
115289
|
dockerfile: "dockerfile"
|
|
113789
115290
|
};
|
|
113790
115291
|
function langFromPath(filePath) {
|
|
113791
|
-
const ext =
|
|
115292
|
+
const ext = path43.extname(filePath).replace(/^\./, "").toLowerCase();
|
|
113792
115293
|
return EXT_TO_LANG[ext];
|
|
113793
115294
|
}
|
|
113794
115295
|
var hlModule;
|
|
@@ -114588,7 +116089,7 @@ init_esm_shims();
|
|
|
114588
116089
|
// ../cli/dist/core/goal-verifier.js
|
|
114589
116090
|
init_esm_shims();
|
|
114590
116091
|
import { spawn as spawn9 } from "child_process";
|
|
114591
|
-
import { mkdir as
|
|
116092
|
+
import { mkdir as mkdir5, writeFile as writeFile5 } from "fs/promises";
|
|
114592
116093
|
import { join as join7 } from "path";
|
|
114593
116094
|
var DEFAULT_GOAL_VERIFIER_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
114594
116095
|
|
|
@@ -114596,8 +116097,8 @@ var DEFAULT_GOAL_VERIFIER_TIMEOUT_MS = 10 * 60 * 1e3;
|
|
|
114596
116097
|
init_esm_shims();
|
|
114597
116098
|
import { spawn as spawn10 } from "child_process";
|
|
114598
116099
|
import { createInterface as createInterface3 } from "readline";
|
|
114599
|
-
import { createWriteStream, existsSync as
|
|
114600
|
-
import { mkdir as
|
|
116100
|
+
import { createWriteStream, existsSync as existsSync9 } from "fs";
|
|
116101
|
+
import { mkdir as mkdir6 } from "fs/promises";
|
|
114601
116102
|
import { join as join8 } from "path";
|
|
114602
116103
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
114603
116104
|
var DEFAULT_GOAL_WORKER_TIMEOUT_MS = 30 * 60 * 1e3;
|
|
@@ -114654,6 +116155,276 @@ var DISABLE_MODIFY_OTHER_KEYS = "\x1B[>4;0m";
|
|
|
114654
116155
|
var SCREEN_CLEAR = DISABLE_MODIFY_OTHER_KEYS + "\x1B[2J\x1B[3J\x1B[H";
|
|
114655
116156
|
var VIEWPORT_CLEAR = DISABLE_MODIFY_OTHER_KEYS + "\x1B[2J\x1B[H";
|
|
114656
116157
|
|
|
116158
|
+
// ../cli/dist/core/project-discovery.js
|
|
116159
|
+
init_esm_shims();
|
|
116160
|
+
import fs35 from "fs/promises";
|
|
116161
|
+
import { createReadStream as createReadStream3 } from "fs";
|
|
116162
|
+
import readline3 from "readline";
|
|
116163
|
+
import os12 from "os";
|
|
116164
|
+
import path44 from "path";
|
|
116165
|
+
async function discoverProjects() {
|
|
116166
|
+
const [gg, cc, cx] = await Promise.all([
|
|
116167
|
+
discoverGgcoderProjects(),
|
|
116168
|
+
discoverClaudeProjects(),
|
|
116169
|
+
discoverCodexProjects()
|
|
116170
|
+
]);
|
|
116171
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
116172
|
+
for (const p of [...gg, ...cc, ...cx]) {
|
|
116173
|
+
const existing = byPath.get(p.path);
|
|
116174
|
+
if (!existing) {
|
|
116175
|
+
byPath.set(p.path, p);
|
|
116176
|
+
continue;
|
|
116177
|
+
}
|
|
116178
|
+
byPath.set(p.path, {
|
|
116179
|
+
name: existing.name,
|
|
116180
|
+
path: existing.path,
|
|
116181
|
+
lastActiveMs: Math.max(existing.lastActiveMs, p.lastActiveMs),
|
|
116182
|
+
lastActiveDisplay: "",
|
|
116183
|
+
// recomputed below
|
|
116184
|
+
sources: mergeSources(existing.sources, p.sources)
|
|
116185
|
+
});
|
|
116186
|
+
}
|
|
116187
|
+
const merged = Array.from(byPath.values()).map((p) => ({
|
|
116188
|
+
...p,
|
|
116189
|
+
lastActiveDisplay: formatRelativeTime(p.lastActiveMs)
|
|
116190
|
+
}));
|
|
116191
|
+
merged.sort((a, b) => b.lastActiveMs - a.lastActiveMs);
|
|
116192
|
+
return merged;
|
|
116193
|
+
}
|
|
116194
|
+
var SOURCE_ORDER = {
|
|
116195
|
+
ezcoder: 0,
|
|
116196
|
+
"claude-code": 1,
|
|
116197
|
+
codex: 2
|
|
116198
|
+
};
|
|
116199
|
+
function mergeSources(a, b) {
|
|
116200
|
+
const set2 = /* @__PURE__ */ new Set([...a, ...b]);
|
|
116201
|
+
return Array.from(set2).sort((x, y) => SOURCE_ORDER[x] - SOURCE_ORDER[y]);
|
|
116202
|
+
}
|
|
116203
|
+
async function discoverGgcoderProjects() {
|
|
116204
|
+
const sessionsDir = getAppPaths().sessionsDir;
|
|
116205
|
+
let entries;
|
|
116206
|
+
try {
|
|
116207
|
+
entries = await fs35.readdir(sessionsDir);
|
|
116208
|
+
} catch {
|
|
116209
|
+
return [];
|
|
116210
|
+
}
|
|
116211
|
+
const results = [];
|
|
116212
|
+
for (const entry of entries) {
|
|
116213
|
+
const dir = path44.join(sessionsDir, entry);
|
|
116214
|
+
const mtime = await maxJsonlMtime(dir);
|
|
116215
|
+
if (mtime === null)
|
|
116216
|
+
continue;
|
|
116217
|
+
const decoded = path44.resolve("/" + entry.replace(/_/g, "/"));
|
|
116218
|
+
if (!await isDirectory(decoded))
|
|
116219
|
+
continue;
|
|
116220
|
+
results.push({
|
|
116221
|
+
name: path44.basename(decoded),
|
|
116222
|
+
path: decoded,
|
|
116223
|
+
lastActiveMs: mtime,
|
|
116224
|
+
lastActiveDisplay: formatRelativeTime(mtime),
|
|
116225
|
+
sources: ["ezcoder"]
|
|
116226
|
+
});
|
|
116227
|
+
}
|
|
116228
|
+
return results;
|
|
116229
|
+
}
|
|
116230
|
+
async function discoverClaudeProjects() {
|
|
116231
|
+
const projectsDir = path44.join(os12.homedir(), ".claude", "projects");
|
|
116232
|
+
let entries;
|
|
116233
|
+
try {
|
|
116234
|
+
entries = await fs35.readdir(projectsDir);
|
|
116235
|
+
} catch {
|
|
116236
|
+
return [];
|
|
116237
|
+
}
|
|
116238
|
+
const results = await Promise.all(entries.map(async (entry) => {
|
|
116239
|
+
const dir = path44.join(projectsDir, entry);
|
|
116240
|
+
const mtime = await maxJsonlMtime(dir);
|
|
116241
|
+
if (mtime === null)
|
|
116242
|
+
return null;
|
|
116243
|
+
const cwd2 = await readFirstFromJsonlDir(dir, claudeCwdExtractor) ?? fallbackDashDecode(entry);
|
|
116244
|
+
if (!cwd2)
|
|
116245
|
+
return null;
|
|
116246
|
+
if (!await isDirectory(cwd2))
|
|
116247
|
+
return null;
|
|
116248
|
+
return {
|
|
116249
|
+
name: path44.basename(cwd2),
|
|
116250
|
+
path: cwd2,
|
|
116251
|
+
lastActiveMs: mtime,
|
|
116252
|
+
lastActiveDisplay: formatRelativeTime(mtime),
|
|
116253
|
+
sources: ["claude-code"]
|
|
116254
|
+
};
|
|
116255
|
+
}));
|
|
116256
|
+
return results.filter((p) => p !== null);
|
|
116257
|
+
}
|
|
116258
|
+
async function discoverCodexProjects() {
|
|
116259
|
+
const sessionsDir = path44.join(os12.homedir(), ".codex", "sessions");
|
|
116260
|
+
if (!await isDirectory(sessionsDir))
|
|
116261
|
+
return [];
|
|
116262
|
+
const files = await collectJsonlFiles(sessionsDir, 4);
|
|
116263
|
+
if (files.length === 0)
|
|
116264
|
+
return [];
|
|
116265
|
+
files.sort((a, b) => b.mtime - a.mtime);
|
|
116266
|
+
const byCwd = /* @__PURE__ */ new Map();
|
|
116267
|
+
for (const f of files) {
|
|
116268
|
+
const cwd2 = await readFirstFromFile(f.path, codexCwdExtractor);
|
|
116269
|
+
if (!cwd2)
|
|
116270
|
+
continue;
|
|
116271
|
+
const prev = byCwd.get(cwd2);
|
|
116272
|
+
if (prev === void 0 || f.mtime > prev)
|
|
116273
|
+
byCwd.set(cwd2, f.mtime);
|
|
116274
|
+
}
|
|
116275
|
+
const results = [];
|
|
116276
|
+
for (const [cwd2, mtime] of byCwd) {
|
|
116277
|
+
if (!await isDirectory(cwd2))
|
|
116278
|
+
continue;
|
|
116279
|
+
results.push({
|
|
116280
|
+
name: path44.basename(cwd2),
|
|
116281
|
+
path: cwd2,
|
|
116282
|
+
lastActiveMs: mtime,
|
|
116283
|
+
lastActiveDisplay: formatRelativeTime(mtime),
|
|
116284
|
+
sources: ["codex"]
|
|
116285
|
+
});
|
|
116286
|
+
}
|
|
116287
|
+
return results;
|
|
116288
|
+
}
|
|
116289
|
+
async function isDirectory(p) {
|
|
116290
|
+
try {
|
|
116291
|
+
const s = await fs35.stat(p);
|
|
116292
|
+
return s.isDirectory();
|
|
116293
|
+
} catch {
|
|
116294
|
+
return false;
|
|
116295
|
+
}
|
|
116296
|
+
}
|
|
116297
|
+
async function maxJsonlMtime(dir) {
|
|
116298
|
+
if (!await isDirectory(dir))
|
|
116299
|
+
return null;
|
|
116300
|
+
const files = await collectJsonlFiles(dir, 2);
|
|
116301
|
+
if (files.length === 0)
|
|
116302
|
+
return null;
|
|
116303
|
+
let max = 0;
|
|
116304
|
+
for (const f of files)
|
|
116305
|
+
if (f.mtime > max)
|
|
116306
|
+
max = f.mtime;
|
|
116307
|
+
return max > 0 ? max : null;
|
|
116308
|
+
}
|
|
116309
|
+
async function collectJsonlFiles(dir, maxDepth) {
|
|
116310
|
+
const out = [];
|
|
116311
|
+
await walk(dir, 0);
|
|
116312
|
+
return out;
|
|
116313
|
+
async function walk(current, depth) {
|
|
116314
|
+
let entries;
|
|
116315
|
+
try {
|
|
116316
|
+
entries = await fs35.readdir(current, { withFileTypes: true });
|
|
116317
|
+
} catch {
|
|
116318
|
+
return;
|
|
116319
|
+
}
|
|
116320
|
+
for (const e of entries) {
|
|
116321
|
+
const full = path44.join(current, e.name);
|
|
116322
|
+
if (e.isFile() && e.name.endsWith(".jsonl")) {
|
|
116323
|
+
try {
|
|
116324
|
+
const s = await fs35.stat(full);
|
|
116325
|
+
out.push({ path: full, mtime: s.mtimeMs });
|
|
116326
|
+
} catch {
|
|
116327
|
+
}
|
|
116328
|
+
} else if (e.isDirectory() && depth < maxDepth) {
|
|
116329
|
+
await walk(full, depth + 1);
|
|
116330
|
+
}
|
|
116331
|
+
}
|
|
116332
|
+
}
|
|
116333
|
+
}
|
|
116334
|
+
var claudeCwdExtractor = (line) => {
|
|
116335
|
+
try {
|
|
116336
|
+
const parsed = JSON.parse(line);
|
|
116337
|
+
if (typeof parsed.cwd === "string" && parsed.cwd.startsWith("/"))
|
|
116338
|
+
return parsed.cwd;
|
|
116339
|
+
} catch {
|
|
116340
|
+
}
|
|
116341
|
+
return null;
|
|
116342
|
+
};
|
|
116343
|
+
var CODEX_CWD_RE = /<cwd>([^<]+)<\/cwd>/;
|
|
116344
|
+
var codexCwdExtractor = (line) => {
|
|
116345
|
+
try {
|
|
116346
|
+
const parsed = JSON.parse(line);
|
|
116347
|
+
const cwd2 = parsed.payload?.cwd;
|
|
116348
|
+
if (typeof cwd2 === "string" && cwd2.startsWith("/"))
|
|
116349
|
+
return cwd2;
|
|
116350
|
+
} catch {
|
|
116351
|
+
}
|
|
116352
|
+
const m = CODEX_CWD_RE.exec(line);
|
|
116353
|
+
if (m && m[1] && m[1].startsWith("/"))
|
|
116354
|
+
return m[1];
|
|
116355
|
+
return null;
|
|
116356
|
+
};
|
|
116357
|
+
async function readFirstFromJsonlDir(dir, extractor) {
|
|
116358
|
+
const files = await collectJsonlFiles(dir, 2);
|
|
116359
|
+
if (files.length === 0)
|
|
116360
|
+
return null;
|
|
116361
|
+
files.sort((a, b) => b.mtime - a.mtime);
|
|
116362
|
+
for (const f of files) {
|
|
116363
|
+
const v = await readFirstFromFile(f.path, extractor);
|
|
116364
|
+
if (v)
|
|
116365
|
+
return v;
|
|
116366
|
+
}
|
|
116367
|
+
return null;
|
|
116368
|
+
}
|
|
116369
|
+
async function readFirstFromFile(file2, extractor) {
|
|
116370
|
+
return new Promise((resolve3) => {
|
|
116371
|
+
const stream2 = createReadStream3(file2, { encoding: "utf-8" });
|
|
116372
|
+
const rl = readline3.createInterface({ input: stream2, crlfDelay: Infinity });
|
|
116373
|
+
let lines = 0;
|
|
116374
|
+
let done = false;
|
|
116375
|
+
const MAX_LINES2 = 200;
|
|
116376
|
+
const finish = (value) => {
|
|
116377
|
+
if (done)
|
|
116378
|
+
return;
|
|
116379
|
+
done = true;
|
|
116380
|
+
resolve3(value);
|
|
116381
|
+
rl.close();
|
|
116382
|
+
stream2.destroy();
|
|
116383
|
+
};
|
|
116384
|
+
rl.on("line", (line) => {
|
|
116385
|
+
if (done)
|
|
116386
|
+
return;
|
|
116387
|
+
lines++;
|
|
116388
|
+
if (lines > MAX_LINES2) {
|
|
116389
|
+
finish(null);
|
|
116390
|
+
return;
|
|
116391
|
+
}
|
|
116392
|
+
const v = extractor(line);
|
|
116393
|
+
if (v)
|
|
116394
|
+
finish(v);
|
|
116395
|
+
});
|
|
116396
|
+
rl.on("close", () => finish(null));
|
|
116397
|
+
rl.on("error", () => finish(null));
|
|
116398
|
+
stream2.on("error", () => finish(null));
|
|
116399
|
+
});
|
|
116400
|
+
}
|
|
116401
|
+
function fallbackDashDecode(entry) {
|
|
116402
|
+
if (!entry.startsWith("-"))
|
|
116403
|
+
return null;
|
|
116404
|
+
return "/" + entry.slice(1).replace(/-/g, "/");
|
|
116405
|
+
}
|
|
116406
|
+
function formatRelativeTime(ms) {
|
|
116407
|
+
if (ms === 0)
|
|
116408
|
+
return "\u2014";
|
|
116409
|
+
const diff3 = Date.now() - ms;
|
|
116410
|
+
if (diff3 < 6e4)
|
|
116411
|
+
return "just now";
|
|
116412
|
+
const min = 6e4;
|
|
116413
|
+
const hour = 60 * min;
|
|
116414
|
+
const day = 24 * hour;
|
|
116415
|
+
const week = 7 * day;
|
|
116416
|
+
const month = 30 * day;
|
|
116417
|
+
if (diff3 < hour)
|
|
116418
|
+
return `${Math.floor(diff3 / min)}m ago`;
|
|
116419
|
+
if (diff3 < day)
|
|
116420
|
+
return `${Math.floor(diff3 / hour)}h ago`;
|
|
116421
|
+
if (diff3 < week)
|
|
116422
|
+
return `${Math.floor(diff3 / day)}d ago`;
|
|
116423
|
+
if (diff3 < month)
|
|
116424
|
+
return `${Math.floor(diff3 / week)}w ago`;
|
|
116425
|
+
return `${Math.floor(diff3 / month)}mo ago`;
|
|
116426
|
+
}
|
|
116427
|
+
|
|
114657
116428
|
// src/boss-store.ts
|
|
114658
116429
|
init_esm_shims();
|
|
114659
116430
|
var import_react99 = __toESM(require_react(), 1);
|
|
@@ -115918,17 +117689,17 @@ var EventQueue = class {
|
|
|
115918
117689
|
|
|
115919
117690
|
// src/settings.ts
|
|
115920
117691
|
init_esm_shims();
|
|
115921
|
-
import
|
|
115922
|
-
import
|
|
117692
|
+
import fs36 from "fs/promises";
|
|
117693
|
+
import path45 from "path";
|
|
115923
117694
|
function settingsPath() {
|
|
115924
|
-
return
|
|
117695
|
+
return path45.join(getAppPaths().agentDir, "boss", "settings.json");
|
|
115925
117696
|
}
|
|
115926
117697
|
async function ensureDir() {
|
|
115927
|
-
await
|
|
117698
|
+
await fs36.mkdir(path45.dirname(settingsPath()), { recursive: true, mode: 448 });
|
|
115928
117699
|
}
|
|
115929
117700
|
async function loadSettings() {
|
|
115930
117701
|
try {
|
|
115931
|
-
const content = await
|
|
117702
|
+
const content = await fs36.readFile(settingsPath(), "utf-8");
|
|
115932
117703
|
const parsed = JSON.parse(content);
|
|
115933
117704
|
if (!parsed || typeof parsed !== "object") return {};
|
|
115934
117705
|
return parsed;
|
|
@@ -115943,8 +117714,8 @@ async function saveSettings(patch) {
|
|
|
115943
117714
|
const merged = { ...current, ...patch };
|
|
115944
117715
|
await ensureDir();
|
|
115945
117716
|
const tmp = `${settingsPath()}.${process.pid}.tmp`;
|
|
115946
|
-
await
|
|
115947
|
-
await
|
|
117717
|
+
await fs36.writeFile(tmp, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
117718
|
+
await fs36.rename(tmp, settingsPath());
|
|
115948
117719
|
});
|
|
115949
117720
|
writeChain = next.catch(() => void 0);
|
|
115950
117721
|
await next;
|
|
@@ -116336,18 +118107,18 @@ init_esm_shims();
|
|
|
116336
118107
|
// src/tasks-store.ts
|
|
116337
118108
|
init_esm_shims();
|
|
116338
118109
|
var import_react100 = __toESM(require_react(), 1);
|
|
116339
|
-
import
|
|
116340
|
-
import
|
|
116341
|
-
import
|
|
118110
|
+
import fs37 from "fs/promises";
|
|
118111
|
+
import path46 from "path";
|
|
118112
|
+
import crypto11 from "crypto";
|
|
116342
118113
|
function getPlanPath() {
|
|
116343
|
-
return
|
|
118114
|
+
return path46.join(getAppPaths().agentDir, "boss", "plan.json");
|
|
116344
118115
|
}
|
|
116345
118116
|
async function ensureDir2() {
|
|
116346
|
-
await
|
|
118117
|
+
await fs37.mkdir(path46.dirname(getPlanPath()), { recursive: true, mode: 448 });
|
|
116347
118118
|
}
|
|
116348
118119
|
async function loadPlan() {
|
|
116349
118120
|
try {
|
|
116350
|
-
const content = await
|
|
118121
|
+
const content = await fs37.readFile(getPlanPath(), "utf-8");
|
|
116351
118122
|
const parsed = JSON.parse(content);
|
|
116352
118123
|
return Array.isArray(parsed.tasks) ? parsed.tasks : [];
|
|
116353
118124
|
} catch {
|
|
@@ -116361,8 +118132,8 @@ async function persist(tasks) {
|
|
|
116361
118132
|
await ensureDir2();
|
|
116362
118133
|
const finalPath = getPlanPath();
|
|
116363
118134
|
const tmpPath = `${finalPath}.${process.pid}.tmp`;
|
|
116364
|
-
await
|
|
116365
|
-
await
|
|
118135
|
+
await fs37.writeFile(tmpPath, snapshot, "utf-8");
|
|
118136
|
+
await fs37.rename(tmpPath, finalPath);
|
|
116366
118137
|
});
|
|
116367
118138
|
persistChain = next.catch(() => void 0);
|
|
116368
118139
|
await next;
|
|
@@ -116385,7 +118156,7 @@ function useTasksState() {
|
|
|
116385
118156
|
return (0, import_react100.useSyncExternalStore)(subscribe2, getSnapshot2, getSnapshot2);
|
|
116386
118157
|
}
|
|
116387
118158
|
function newId() {
|
|
116388
|
-
return
|
|
118159
|
+
return crypto11.randomBytes(6).toString("hex");
|
|
116389
118160
|
}
|
|
116390
118161
|
function now() {
|
|
116391
118162
|
return (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -116631,12 +118402,12 @@ function createTaskTools(deps) {
|
|
|
116631
118402
|
// src/audio.ts
|
|
116632
118403
|
init_esm_shims();
|
|
116633
118404
|
import { spawn as spawn11, execFileSync as execFileSync4 } from "child_process";
|
|
116634
|
-
import { fileURLToPath as
|
|
116635
|
-
import
|
|
116636
|
-
import
|
|
118405
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
118406
|
+
import path47 from "path";
|
|
118407
|
+
import fs38 from "fs";
|
|
116637
118408
|
function readMp3DurationMs(file2) {
|
|
116638
118409
|
try {
|
|
116639
|
-
const buf =
|
|
118410
|
+
const buf = fs38.readFileSync(file2);
|
|
116640
118411
|
let i = 0;
|
|
116641
118412
|
if (buf.length >= 10 && buf[0] === 73 && buf[1] === 68 && buf[2] === 51) {
|
|
116642
118413
|
const tagSize = (buf[6] & 127) << 21 | (buf[7] & 127) << 14 | (buf[8] & 127) << 7 | buf[9] & 127;
|
|
@@ -116693,10 +118464,10 @@ function getSplashAudioDurationMs() {
|
|
|
116693
118464
|
return ms && ms > 0 ? ms : 1500;
|
|
116694
118465
|
}
|
|
116695
118466
|
function assetPath(name) {
|
|
116696
|
-
const here =
|
|
116697
|
-
const dist =
|
|
116698
|
-
if (
|
|
116699
|
-
return
|
|
118467
|
+
const here = path47.dirname(fileURLToPath6(import.meta.url));
|
|
118468
|
+
const dist = path47.join(here, name);
|
|
118469
|
+
if (fs38.existsSync(dist)) return dist;
|
|
118470
|
+
return path47.join(here, "..", "assets", name);
|
|
116700
118471
|
}
|
|
116701
118472
|
function splashAssetPath() {
|
|
116702
118473
|
return assetPath("splash.mp3");
|
|
@@ -116736,15 +118507,15 @@ function trySpawn(cmd, args) {
|
|
|
116736
118507
|
}
|
|
116737
118508
|
function isWsl() {
|
|
116738
118509
|
if (process.platform !== "linux") return false;
|
|
116739
|
-
return !!process.env.WSL_DISTRO_NAME ||
|
|
118510
|
+
return !!process.env.WSL_DISTRO_NAME || fs38.existsSync("/proc/sys/fs/binfmt_misc/WSLInterop");
|
|
116740
118511
|
}
|
|
116741
118512
|
async function tryPlayOnWindowsHost(file2) {
|
|
116742
118513
|
try {
|
|
116743
|
-
const here =
|
|
116744
|
-
const devAssets =
|
|
116745
|
-
const resolved =
|
|
116746
|
-
const inDist = resolved === here || resolved.startsWith(here +
|
|
116747
|
-
const inAssets = resolved === devAssets || resolved.startsWith(devAssets +
|
|
118514
|
+
const here = path47.dirname(fileURLToPath6(import.meta.url));
|
|
118515
|
+
const devAssets = path47.resolve(here, "..", "assets");
|
|
118516
|
+
const resolved = path47.resolve(file2);
|
|
118517
|
+
const inDist = resolved === here || resolved.startsWith(here + path47.sep);
|
|
118518
|
+
const inAssets = resolved === devAssets || resolved.startsWith(devAssets + path47.sep);
|
|
116748
118519
|
if (!inDist && !inAssets) {
|
|
116749
118520
|
return false;
|
|
116750
118521
|
}
|
|
@@ -116808,7 +118579,7 @@ async function tryPlayOnWindowsHost(file2) {
|
|
|
116808
118579
|
}
|
|
116809
118580
|
}
|
|
116810
118581
|
async function playFile(file2) {
|
|
116811
|
-
if (!
|
|
118582
|
+
if (!fs38.existsSync(file2)) return;
|
|
116812
118583
|
const platform2 = process.platform;
|
|
116813
118584
|
if (platform2 === "darwin") {
|
|
116814
118585
|
await trySpawn("afplay", [file2]);
|
|
@@ -116906,37 +118677,37 @@ function truncateOversizedToolResults2(messages, opts = {}) {
|
|
|
116906
118677
|
|
|
116907
118678
|
// src/sessions.ts
|
|
116908
118679
|
init_esm_shims();
|
|
116909
|
-
import
|
|
116910
|
-
import
|
|
116911
|
-
import
|
|
118680
|
+
import fs39 from "fs/promises";
|
|
118681
|
+
import path48 from "path";
|
|
118682
|
+
import crypto12 from "crypto";
|
|
116912
118683
|
var BOSS_SUBDIR = "boss";
|
|
116913
118684
|
var SESSIONS_SUBDIR = "sessions";
|
|
116914
118685
|
function getBossDir() {
|
|
116915
|
-
return
|
|
118686
|
+
return path48.join(getAppPaths().agentDir, BOSS_SUBDIR);
|
|
116916
118687
|
}
|
|
116917
118688
|
function getSessionsDir() {
|
|
116918
|
-
return
|
|
118689
|
+
return path48.join(getBossDir(), SESSIONS_SUBDIR);
|
|
116919
118690
|
}
|
|
116920
118691
|
async function ensureSessionsDir() {
|
|
116921
118692
|
const dir = getSessionsDir();
|
|
116922
|
-
await
|
|
118693
|
+
await fs39.mkdir(dir, { recursive: true, mode: 448 });
|
|
116923
118694
|
return dir;
|
|
116924
118695
|
}
|
|
116925
118696
|
async function createSession2() {
|
|
116926
118697
|
await ensureSessionsDir();
|
|
116927
|
-
const id2 = `${Date.now()}-${
|
|
116928
|
-
const filePath =
|
|
116929
|
-
await
|
|
118698
|
+
const id2 = `${Date.now()}-${crypto12.randomBytes(4).toString("hex")}`;
|
|
118699
|
+
const filePath = path48.join(getSessionsDir(), `${id2}.jsonl`);
|
|
118700
|
+
await fs39.writeFile(filePath, "", "utf-8");
|
|
116930
118701
|
return { id: id2, filePath };
|
|
116931
118702
|
}
|
|
116932
118703
|
async function appendMessages(filePath, msgs) {
|
|
116933
118704
|
if (msgs.length === 0) return;
|
|
116934
118705
|
const lines = msgs.map((m) => JSON.stringify(m)).join("\n") + "\n";
|
|
116935
|
-
await
|
|
118706
|
+
await fs39.appendFile(filePath, lines, "utf-8");
|
|
116936
118707
|
}
|
|
116937
118708
|
async function loadSession2(filePath) {
|
|
116938
118709
|
try {
|
|
116939
|
-
const content = await
|
|
118710
|
+
const content = await fs39.readFile(filePath, "utf-8");
|
|
116940
118711
|
const lines = content.split("\n").filter((l) => l.length > 0);
|
|
116941
118712
|
const messages = [];
|
|
116942
118713
|
for (const line of lines) {
|
|
@@ -116952,8 +118723,8 @@ async function loadSession2(filePath) {
|
|
|
116952
118723
|
}
|
|
116953
118724
|
async function inspectSession(filePath, id2) {
|
|
116954
118725
|
try {
|
|
116955
|
-
const stat = await
|
|
116956
|
-
const content = await
|
|
118726
|
+
const stat = await fs39.stat(filePath);
|
|
118727
|
+
const content = await fs39.readFile(filePath, "utf-8");
|
|
116957
118728
|
const lines = content.split("\n").filter((l) => l.length > 0);
|
|
116958
118729
|
let firstUserMessage;
|
|
116959
118730
|
for (const line of lines) {
|
|
@@ -116986,7 +118757,7 @@ async function listSessions2() {
|
|
|
116986
118757
|
await ensureSessionsDir();
|
|
116987
118758
|
let entries;
|
|
116988
118759
|
try {
|
|
116989
|
-
entries = await
|
|
118760
|
+
entries = await fs39.readdir(getSessionsDir());
|
|
116990
118761
|
} catch {
|
|
116991
118762
|
return [];
|
|
116992
118763
|
}
|
|
@@ -116994,7 +118765,7 @@ async function listSessions2() {
|
|
|
116994
118765
|
for (const name of entries) {
|
|
116995
118766
|
if (!name.endsWith(".jsonl")) continue;
|
|
116996
118767
|
const id2 = name.replace(/\.jsonl$/, "");
|
|
116997
|
-
const info = await inspectSession(
|
|
118768
|
+
const info = await inspectSession(path48.join(getSessionsDir(), name), id2);
|
|
116998
118769
|
if (info) infos.push(info);
|
|
116999
118770
|
}
|
|
117000
118771
|
infos.sort((a, b) => b.lastModified - a.lastModified);
|
|
@@ -117005,7 +118776,7 @@ async function getMostRecent() {
|
|
|
117005
118776
|
return all[0] ?? null;
|
|
117006
118777
|
}
|
|
117007
118778
|
async function getSessionById(id2) {
|
|
117008
|
-
const filePath =
|
|
118779
|
+
const filePath = path48.join(getSessionsDir(), `${id2}.jsonl`);
|
|
117009
118780
|
return inspectSession(filePath, id2);
|
|
117010
118781
|
}
|
|
117011
118782
|
|
|
@@ -117824,6 +119595,7 @@ export {
|
|
|
117824
119595
|
MessageResponse,
|
|
117825
119596
|
ToolExecution,
|
|
117826
119597
|
ToolGroupExecution,
|
|
119598
|
+
discoverProjects,
|
|
117827
119599
|
bossToolGroupRenderers,
|
|
117828
119600
|
useBossState,
|
|
117829
119601
|
subscribeToBossStore,
|
|
@@ -117959,4 +119731,4 @@ react/cjs/react-jsx-runtime.development.js:
|
|
|
117959
119731
|
* LICENSE file in the root directory of this source tree.
|
|
117960
119732
|
*)
|
|
117961
119733
|
*/
|
|
117962
|
-
//# sourceMappingURL=chunk-
|
|
119734
|
+
//# sourceMappingURL=chunk-HYXLQEZL.js.map
|