nestor-sh 3.5.0 → 3.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/nestor.mjs
CHANGED
|
@@ -516,7 +516,22 @@ var init_encryption = __esm({
|
|
|
516
516
|
if (!secret || secret.length < 16) {
|
|
517
517
|
throw new Error("Encryption secret must be at least 16 characters");
|
|
518
518
|
}
|
|
519
|
-
const
|
|
519
|
+
const envSalt = process.env["NESTOR_ENCRYPTION_SALT"];
|
|
520
|
+
let saltSource;
|
|
521
|
+
if (envSalt) {
|
|
522
|
+
if (envSalt.length < 16) {
|
|
523
|
+
throw new Error(
|
|
524
|
+
`NESTOR_ENCRYPTION_SALT must be at least 16 characters. Generate one with: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"`
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
saltSource = envSalt;
|
|
528
|
+
} else {
|
|
529
|
+
console.warn(
|
|
530
|
+
"[nestor:encryption] NESTOR_ENCRYPTION_SALT is not set. Falling back to the legacy hardcoded salt. This reduces security (deployments share key derivation). Set NESTOR_ENCRYPTION_SALT to a unique 32+ char random string. Support for the hardcoded fallback will be removed in v4.0."
|
|
531
|
+
);
|
|
532
|
+
saltSource = "nestor-field-encryption-v1";
|
|
533
|
+
}
|
|
534
|
+
const fixedSalt = Buffer.from(saltSource);
|
|
520
535
|
this.masterKey = scryptSync(secret, fixedSalt, KEY_LENGTH);
|
|
521
536
|
}
|
|
522
537
|
/** Encrypt a string value. Returns base64-encoded ciphertext. */
|
|
@@ -14952,7 +14967,7 @@ function isNativeAvailable() {
|
|
|
14952
14967
|
return nativeModule !== null;
|
|
14953
14968
|
}
|
|
14954
14969
|
function getNativeVersion() {
|
|
14955
|
-
return nativeModule ? "3.5.
|
|
14970
|
+
return nativeModule ? "3.5.2" : null;
|
|
14956
14971
|
}
|
|
14957
14972
|
function validateSsrf(url, allowPrivate = false) {
|
|
14958
14973
|
if (nativeModule) {
|
|
@@ -15857,7 +15872,12 @@ var init_docker = __esm({
|
|
|
15857
15872
|
this.timeoutMs = options.timeoutMs ?? 3e4;
|
|
15858
15873
|
this.memoryLimit = options.memoryLimit ?? `${config2.memoryLimitMb}m`;
|
|
15859
15874
|
this.cpuLimit = options.cpuLimit ?? config2.cpuLimitPercent / 100;
|
|
15860
|
-
this.networkEnabled = config2.networkPolicy
|
|
15875
|
+
this.networkEnabled = config2.networkPolicy === "restricted" || config2.networkPolicy === "full";
|
|
15876
|
+
if (config2.networkPolicy === void 0) {
|
|
15877
|
+
console.warn(
|
|
15878
|
+
'[nestor:sandbox] networkPolicy not set \u2014 defaulting to DISABLED for security. Set networkPolicy: "restricted" or "full" explicitly to allow network access.'
|
|
15879
|
+
);
|
|
15880
|
+
}
|
|
15861
15881
|
this.workDir = options.workDir ?? "/workspace";
|
|
15862
15882
|
}
|
|
15863
15883
|
/**
|
|
@@ -119701,7 +119721,7 @@ var SERVER_VERSION, startTime;
|
|
|
119701
119721
|
var init_health = __esm({
|
|
119702
119722
|
"../server/src/routes/health.ts"() {
|
|
119703
119723
|
"use strict";
|
|
119704
|
-
SERVER_VERSION = "3.5.
|
|
119724
|
+
SERVER_VERSION = "3.5.2";
|
|
119705
119725
|
startTime = Date.now();
|
|
119706
119726
|
}
|
|
119707
119727
|
});
|
|
@@ -121114,7 +121134,7 @@ var init_system = __esm({
|
|
|
121114
121134
|
init_error_handler();
|
|
121115
121135
|
init_broadcaster();
|
|
121116
121136
|
init_approval_service();
|
|
121117
|
-
SERVER_VERSION2 = "3.5.
|
|
121137
|
+
SERVER_VERSION2 = "3.5.2";
|
|
121118
121138
|
startTime2 = Date.now();
|
|
121119
121139
|
UpdateConfigSchema = z20.object({
|
|
121120
121140
|
server: z20.object({
|
|
@@ -158892,7 +158912,7 @@ var init_admin3 = __esm({
|
|
|
158892
158912
|
"../server/src/routes/admin.ts"() {
|
|
158893
158913
|
"use strict";
|
|
158894
158914
|
init_rate_limit();
|
|
158895
|
-
SERVER_VERSION3 = "3.5.
|
|
158915
|
+
SERVER_VERSION3 = "3.5.2";
|
|
158896
158916
|
startTime3 = Date.now();
|
|
158897
158917
|
}
|
|
158898
158918
|
});
|
|
@@ -162469,7 +162489,7 @@ var VERSION2, DATA_DIR3, TELEMETRY_ID_FILE, TELEMETRY_LOG_FILE, DEFAULT_FLUSH_TH
|
|
|
162469
162489
|
var init_telemetry2 = __esm({
|
|
162470
162490
|
"../server/src/services/telemetry.ts"() {
|
|
162471
162491
|
"use strict";
|
|
162472
|
-
VERSION2 = "3.5.
|
|
162492
|
+
VERSION2 = "3.5.2";
|
|
162473
162493
|
DATA_DIR3 = join27(homedir10(), ".nestor");
|
|
162474
162494
|
TELEMETRY_ID_FILE = join27(DATA_DIR3, "telemetry-id");
|
|
162475
162495
|
TELEMETRY_LOG_FILE = join27(DATA_DIR3, "telemetry.jsonl");
|
|
@@ -289643,438 +289663,14 @@ var require_chat_stream = __commonJS({
|
|
|
289643
289663
|
}
|
|
289644
289664
|
});
|
|
289645
289665
|
|
|
289646
|
-
// ../../node_modules/.pnpm/ms@2.0.0/node_modules/ms/index.js
|
|
289647
|
-
var require_ms2 = __commonJS({
|
|
289648
|
-
"../../node_modules/.pnpm/ms@2.0.0/node_modules/ms/index.js"(exports2, module2) {
|
|
289649
|
-
var s = 1e3;
|
|
289650
|
-
var m = s * 60;
|
|
289651
|
-
var h = m * 60;
|
|
289652
|
-
var d = h * 24;
|
|
289653
|
-
var y = d * 365.25;
|
|
289654
|
-
module2.exports = function(val, options) {
|
|
289655
|
-
options = options || {};
|
|
289656
|
-
var type = typeof val;
|
|
289657
|
-
if (type === "string" && val.length > 0) {
|
|
289658
|
-
return parse(val);
|
|
289659
|
-
} else if (type === "number" && isNaN(val) === false) {
|
|
289660
|
-
return options.long ? fmtLong(val) : fmtShort(val);
|
|
289661
|
-
}
|
|
289662
|
-
throw new Error(
|
|
289663
|
-
"val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
|
|
289664
|
-
);
|
|
289665
|
-
};
|
|
289666
|
-
function parse(str) {
|
|
289667
|
-
str = String(str);
|
|
289668
|
-
if (str.length > 100) {
|
|
289669
|
-
return;
|
|
289670
|
-
}
|
|
289671
|
-
var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(
|
|
289672
|
-
str
|
|
289673
|
-
);
|
|
289674
|
-
if (!match) {
|
|
289675
|
-
return;
|
|
289676
|
-
}
|
|
289677
|
-
var n = parseFloat(match[1]);
|
|
289678
|
-
var type = (match[2] || "ms").toLowerCase();
|
|
289679
|
-
switch (type) {
|
|
289680
|
-
case "years":
|
|
289681
|
-
case "year":
|
|
289682
|
-
case "yrs":
|
|
289683
|
-
case "yr":
|
|
289684
|
-
case "y":
|
|
289685
|
-
return n * y;
|
|
289686
|
-
case "days":
|
|
289687
|
-
case "day":
|
|
289688
|
-
case "d":
|
|
289689
|
-
return n * d;
|
|
289690
|
-
case "hours":
|
|
289691
|
-
case "hour":
|
|
289692
|
-
case "hrs":
|
|
289693
|
-
case "hr":
|
|
289694
|
-
case "h":
|
|
289695
|
-
return n * h;
|
|
289696
|
-
case "minutes":
|
|
289697
|
-
case "minute":
|
|
289698
|
-
case "mins":
|
|
289699
|
-
case "min":
|
|
289700
|
-
case "m":
|
|
289701
|
-
return n * m;
|
|
289702
|
-
case "seconds":
|
|
289703
|
-
case "second":
|
|
289704
|
-
case "secs":
|
|
289705
|
-
case "sec":
|
|
289706
|
-
case "s":
|
|
289707
|
-
return n * s;
|
|
289708
|
-
case "milliseconds":
|
|
289709
|
-
case "millisecond":
|
|
289710
|
-
case "msecs":
|
|
289711
|
-
case "msec":
|
|
289712
|
-
case "ms":
|
|
289713
|
-
return n;
|
|
289714
|
-
default:
|
|
289715
|
-
return void 0;
|
|
289716
|
-
}
|
|
289717
|
-
}
|
|
289718
|
-
function fmtShort(ms) {
|
|
289719
|
-
if (ms >= d) {
|
|
289720
|
-
return Math.round(ms / d) + "d";
|
|
289721
|
-
}
|
|
289722
|
-
if (ms >= h) {
|
|
289723
|
-
return Math.round(ms / h) + "h";
|
|
289724
|
-
}
|
|
289725
|
-
if (ms >= m) {
|
|
289726
|
-
return Math.round(ms / m) + "m";
|
|
289727
|
-
}
|
|
289728
|
-
if (ms >= s) {
|
|
289729
|
-
return Math.round(ms / s) + "s";
|
|
289730
|
-
}
|
|
289731
|
-
return ms + "ms";
|
|
289732
|
-
}
|
|
289733
|
-
function fmtLong(ms) {
|
|
289734
|
-
return plural(ms, d, "day") || plural(ms, h, "hour") || plural(ms, m, "minute") || plural(ms, s, "second") || ms + " ms";
|
|
289735
|
-
}
|
|
289736
|
-
function plural(ms, n, name) {
|
|
289737
|
-
if (ms < n) {
|
|
289738
|
-
return;
|
|
289739
|
-
}
|
|
289740
|
-
if (ms < n * 1.5) {
|
|
289741
|
-
return Math.floor(ms / n) + " " + name;
|
|
289742
|
-
}
|
|
289743
|
-
return Math.ceil(ms / n) + " " + name + "s";
|
|
289744
|
-
}
|
|
289745
|
-
}
|
|
289746
|
-
});
|
|
289747
|
-
|
|
289748
|
-
// ../../node_modules/.pnpm/debug@2.6.9/node_modules/debug/src/debug.js
|
|
289749
|
-
var require_debug3 = __commonJS({
|
|
289750
|
-
"../../node_modules/.pnpm/debug@2.6.9/node_modules/debug/src/debug.js"(exports2, module2) {
|
|
289751
|
-
exports2 = module2.exports = createDebug.debug = createDebug["default"] = createDebug;
|
|
289752
|
-
exports2.coerce = coerce;
|
|
289753
|
-
exports2.disable = disable;
|
|
289754
|
-
exports2.enable = enable;
|
|
289755
|
-
exports2.enabled = enabled;
|
|
289756
|
-
exports2.humanize = require_ms2();
|
|
289757
|
-
exports2.names = [];
|
|
289758
|
-
exports2.skips = [];
|
|
289759
|
-
exports2.formatters = {};
|
|
289760
|
-
var prevTime;
|
|
289761
|
-
function selectColor(namespace) {
|
|
289762
|
-
var hash = 0, i;
|
|
289763
|
-
for (i in namespace) {
|
|
289764
|
-
hash = (hash << 5) - hash + namespace.charCodeAt(i);
|
|
289765
|
-
hash |= 0;
|
|
289766
|
-
}
|
|
289767
|
-
return exports2.colors[Math.abs(hash) % exports2.colors.length];
|
|
289768
|
-
}
|
|
289769
|
-
function createDebug(namespace) {
|
|
289770
|
-
function debug5() {
|
|
289771
|
-
if (!debug5.enabled) return;
|
|
289772
|
-
var self2 = debug5;
|
|
289773
|
-
var curr = +/* @__PURE__ */ new Date();
|
|
289774
|
-
var ms = curr - (prevTime || curr);
|
|
289775
|
-
self2.diff = ms;
|
|
289776
|
-
self2.prev = prevTime;
|
|
289777
|
-
self2.curr = curr;
|
|
289778
|
-
prevTime = curr;
|
|
289779
|
-
var args = new Array(arguments.length);
|
|
289780
|
-
for (var i = 0; i < args.length; i++) {
|
|
289781
|
-
args[i] = arguments[i];
|
|
289782
|
-
}
|
|
289783
|
-
args[0] = exports2.coerce(args[0]);
|
|
289784
|
-
if ("string" !== typeof args[0]) {
|
|
289785
|
-
args.unshift("%O");
|
|
289786
|
-
}
|
|
289787
|
-
var index = 0;
|
|
289788
|
-
args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format3) {
|
|
289789
|
-
if (match === "%%") return match;
|
|
289790
|
-
index++;
|
|
289791
|
-
var formatter = exports2.formatters[format3];
|
|
289792
|
-
if ("function" === typeof formatter) {
|
|
289793
|
-
var val = args[index];
|
|
289794
|
-
match = formatter.call(self2, val);
|
|
289795
|
-
args.splice(index, 1);
|
|
289796
|
-
index--;
|
|
289797
|
-
}
|
|
289798
|
-
return match;
|
|
289799
|
-
});
|
|
289800
|
-
exports2.formatArgs.call(self2, args);
|
|
289801
|
-
var logFn = debug5.log || exports2.log || console.log.bind(console);
|
|
289802
|
-
logFn.apply(self2, args);
|
|
289803
|
-
}
|
|
289804
|
-
debug5.namespace = namespace;
|
|
289805
|
-
debug5.enabled = exports2.enabled(namespace);
|
|
289806
|
-
debug5.useColors = exports2.useColors();
|
|
289807
|
-
debug5.color = selectColor(namespace);
|
|
289808
|
-
if ("function" === typeof exports2.init) {
|
|
289809
|
-
exports2.init(debug5);
|
|
289810
|
-
}
|
|
289811
|
-
return debug5;
|
|
289812
|
-
}
|
|
289813
|
-
function enable(namespaces) {
|
|
289814
|
-
exports2.save(namespaces);
|
|
289815
|
-
exports2.names = [];
|
|
289816
|
-
exports2.skips = [];
|
|
289817
|
-
var split = (typeof namespaces === "string" ? namespaces : "").split(/[\s,]+/);
|
|
289818
|
-
var len = split.length;
|
|
289819
|
-
for (var i = 0; i < len; i++) {
|
|
289820
|
-
if (!split[i]) continue;
|
|
289821
|
-
namespaces = split[i].replace(/\*/g, ".*?");
|
|
289822
|
-
if (namespaces[0] === "-") {
|
|
289823
|
-
exports2.skips.push(new RegExp("^" + namespaces.substr(1) + "$"));
|
|
289824
|
-
} else {
|
|
289825
|
-
exports2.names.push(new RegExp("^" + namespaces + "$"));
|
|
289826
|
-
}
|
|
289827
|
-
}
|
|
289828
|
-
}
|
|
289829
|
-
function disable() {
|
|
289830
|
-
exports2.enable("");
|
|
289831
|
-
}
|
|
289832
|
-
function enabled(name) {
|
|
289833
|
-
var i, len;
|
|
289834
|
-
for (i = 0, len = exports2.skips.length; i < len; i++) {
|
|
289835
|
-
if (exports2.skips[i].test(name)) {
|
|
289836
|
-
return false;
|
|
289837
|
-
}
|
|
289838
|
-
}
|
|
289839
|
-
for (i = 0, len = exports2.names.length; i < len; i++) {
|
|
289840
|
-
if (exports2.names[i].test(name)) {
|
|
289841
|
-
return true;
|
|
289842
|
-
}
|
|
289843
|
-
}
|
|
289844
|
-
return false;
|
|
289845
|
-
}
|
|
289846
|
-
function coerce(val) {
|
|
289847
|
-
if (val instanceof Error) return val.stack || val.message;
|
|
289848
|
-
return val;
|
|
289849
|
-
}
|
|
289850
|
-
}
|
|
289851
|
-
});
|
|
289852
|
-
|
|
289853
|
-
// ../../node_modules/.pnpm/debug@2.6.9/node_modules/debug/src/browser.js
|
|
289854
|
-
var require_browser4 = __commonJS({
|
|
289855
|
-
"../../node_modules/.pnpm/debug@2.6.9/node_modules/debug/src/browser.js"(exports2, module2) {
|
|
289856
|
-
exports2 = module2.exports = require_debug3();
|
|
289857
|
-
exports2.log = log3;
|
|
289858
|
-
exports2.formatArgs = formatArgs;
|
|
289859
|
-
exports2.save = save;
|
|
289860
|
-
exports2.load = load;
|
|
289861
|
-
exports2.useColors = useColors;
|
|
289862
|
-
exports2.storage = "undefined" != typeof chrome && "undefined" != typeof chrome.storage ? chrome.storage.local : localstorage();
|
|
289863
|
-
exports2.colors = [
|
|
289864
|
-
"lightseagreen",
|
|
289865
|
-
"forestgreen",
|
|
289866
|
-
"goldenrod",
|
|
289867
|
-
"dodgerblue",
|
|
289868
|
-
"darkorchid",
|
|
289869
|
-
"crimson"
|
|
289870
|
-
];
|
|
289871
|
-
function useColors() {
|
|
289872
|
-
if (typeof window !== "undefined" && window.process && window.process.type === "renderer") {
|
|
289873
|
-
return true;
|
|
289874
|
-
}
|
|
289875
|
-
return typeof document !== "undefined" && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance || // is firebug? http://stackoverflow.com/a/398120/376773
|
|
289876
|
-
typeof window !== "undefined" && window.console && (window.console.firebug || window.console.exception && window.console.table) || // is firefox >= v31?
|
|
289877
|
-
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
|
|
289878
|
-
typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31 || // double check webkit in userAgent just in case we are in a worker
|
|
289879
|
-
typeof navigator !== "undefined" && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/);
|
|
289880
|
-
}
|
|
289881
|
-
exports2.formatters.j = function(v) {
|
|
289882
|
-
try {
|
|
289883
|
-
return JSON.stringify(v);
|
|
289884
|
-
} catch (err) {
|
|
289885
|
-
return "[UnexpectedJSONParseError]: " + err.message;
|
|
289886
|
-
}
|
|
289887
|
-
};
|
|
289888
|
-
function formatArgs(args) {
|
|
289889
|
-
var useColors2 = this.useColors;
|
|
289890
|
-
args[0] = (useColors2 ? "%c" : "") + this.namespace + (useColors2 ? " %c" : " ") + args[0] + (useColors2 ? "%c " : " ") + "+" + exports2.humanize(this.diff);
|
|
289891
|
-
if (!useColors2) return;
|
|
289892
|
-
var c = "color: " + this.color;
|
|
289893
|
-
args.splice(1, 0, c, "color: inherit");
|
|
289894
|
-
var index = 0;
|
|
289895
|
-
var lastC = 0;
|
|
289896
|
-
args[0].replace(/%[a-zA-Z%]/g, function(match) {
|
|
289897
|
-
if ("%%" === match) return;
|
|
289898
|
-
index++;
|
|
289899
|
-
if ("%c" === match) {
|
|
289900
|
-
lastC = index;
|
|
289901
|
-
}
|
|
289902
|
-
});
|
|
289903
|
-
args.splice(lastC, 0, c);
|
|
289904
|
-
}
|
|
289905
|
-
function log3() {
|
|
289906
|
-
return "object" === typeof console && console.log && Function.prototype.apply.call(console.log, console, arguments);
|
|
289907
|
-
}
|
|
289908
|
-
function save(namespaces) {
|
|
289909
|
-
try {
|
|
289910
|
-
if (null == namespaces) {
|
|
289911
|
-
exports2.storage.removeItem("debug");
|
|
289912
|
-
} else {
|
|
289913
|
-
exports2.storage.debug = namespaces;
|
|
289914
|
-
}
|
|
289915
|
-
} catch (e) {
|
|
289916
|
-
}
|
|
289917
|
-
}
|
|
289918
|
-
function load() {
|
|
289919
|
-
var r;
|
|
289920
|
-
try {
|
|
289921
|
-
r = exports2.storage.debug;
|
|
289922
|
-
} catch (e) {
|
|
289923
|
-
}
|
|
289924
|
-
if (!r && typeof process !== "undefined" && "env" in process) {
|
|
289925
|
-
r = process.env.DEBUG;
|
|
289926
|
-
}
|
|
289927
|
-
return r;
|
|
289928
|
-
}
|
|
289929
|
-
exports2.enable(load());
|
|
289930
|
-
function localstorage() {
|
|
289931
|
-
try {
|
|
289932
|
-
return window.localStorage;
|
|
289933
|
-
} catch (e) {
|
|
289934
|
-
}
|
|
289935
|
-
}
|
|
289936
|
-
}
|
|
289937
|
-
});
|
|
289938
|
-
|
|
289939
|
-
// ../../node_modules/.pnpm/debug@2.6.9/node_modules/debug/src/node.js
|
|
289940
|
-
var require_node15 = __commonJS({
|
|
289941
|
-
"../../node_modules/.pnpm/debug@2.6.9/node_modules/debug/src/node.js"(exports2, module2) {
|
|
289942
|
-
var tty = __require("tty");
|
|
289943
|
-
var util = __require("util");
|
|
289944
|
-
exports2 = module2.exports = require_debug3();
|
|
289945
|
-
exports2.init = init;
|
|
289946
|
-
exports2.log = log3;
|
|
289947
|
-
exports2.formatArgs = formatArgs;
|
|
289948
|
-
exports2.save = save;
|
|
289949
|
-
exports2.load = load;
|
|
289950
|
-
exports2.useColors = useColors;
|
|
289951
|
-
exports2.colors = [6, 2, 3, 4, 5, 1];
|
|
289952
|
-
exports2.inspectOpts = Object.keys(process.env).filter(function(key) {
|
|
289953
|
-
return /^debug_/i.test(key);
|
|
289954
|
-
}).reduce(function(obj2, key) {
|
|
289955
|
-
var prop = key.substring(6).toLowerCase().replace(/_([a-z])/g, function(_, k) {
|
|
289956
|
-
return k.toUpperCase();
|
|
289957
|
-
});
|
|
289958
|
-
var val = process.env[key];
|
|
289959
|
-
if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
|
|
289960
|
-
else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
|
|
289961
|
-
else if (val === "null") val = null;
|
|
289962
|
-
else val = Number(val);
|
|
289963
|
-
obj2[prop] = val;
|
|
289964
|
-
return obj2;
|
|
289965
|
-
}, {});
|
|
289966
|
-
var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
|
|
289967
|
-
if (1 !== fd && 2 !== fd) {
|
|
289968
|
-
util.deprecate(function() {
|
|
289969
|
-
}, "except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)")();
|
|
289970
|
-
}
|
|
289971
|
-
var stream = 1 === fd ? process.stdout : 2 === fd ? process.stderr : createWritableStdioStream(fd);
|
|
289972
|
-
function useColors() {
|
|
289973
|
-
return "colors" in exports2.inspectOpts ? Boolean(exports2.inspectOpts.colors) : tty.isatty(fd);
|
|
289974
|
-
}
|
|
289975
|
-
exports2.formatters.o = function(v) {
|
|
289976
|
-
this.inspectOpts.colors = this.useColors;
|
|
289977
|
-
return util.inspect(v, this.inspectOpts).split("\n").map(function(str) {
|
|
289978
|
-
return str.trim();
|
|
289979
|
-
}).join(" ");
|
|
289980
|
-
};
|
|
289981
|
-
exports2.formatters.O = function(v) {
|
|
289982
|
-
this.inspectOpts.colors = this.useColors;
|
|
289983
|
-
return util.inspect(v, this.inspectOpts);
|
|
289984
|
-
};
|
|
289985
|
-
function formatArgs(args) {
|
|
289986
|
-
var name = this.namespace;
|
|
289987
|
-
var useColors2 = this.useColors;
|
|
289988
|
-
if (useColors2) {
|
|
289989
|
-
var c = this.color;
|
|
289990
|
-
var prefix = " \x1B[3" + c + ";1m" + name + " \x1B[0m";
|
|
289991
|
-
args[0] = prefix + args[0].split("\n").join("\n" + prefix);
|
|
289992
|
-
args.push("\x1B[3" + c + "m+" + exports2.humanize(this.diff) + "\x1B[0m");
|
|
289993
|
-
} else {
|
|
289994
|
-
args[0] = (/* @__PURE__ */ new Date()).toUTCString() + " " + name + " " + args[0];
|
|
289995
|
-
}
|
|
289996
|
-
}
|
|
289997
|
-
function log3() {
|
|
289998
|
-
return stream.write(util.format.apply(util, arguments) + "\n");
|
|
289999
|
-
}
|
|
290000
|
-
function save(namespaces) {
|
|
290001
|
-
if (null == namespaces) {
|
|
290002
|
-
delete process.env.DEBUG;
|
|
290003
|
-
} else {
|
|
290004
|
-
process.env.DEBUG = namespaces;
|
|
290005
|
-
}
|
|
290006
|
-
}
|
|
290007
|
-
function load() {
|
|
290008
|
-
return process.env.DEBUG;
|
|
290009
|
-
}
|
|
290010
|
-
function createWritableStdioStream(fd2) {
|
|
290011
|
-
var stream2;
|
|
290012
|
-
var tty_wrap = process.binding("tty_wrap");
|
|
290013
|
-
switch (tty_wrap.guessHandleType(fd2)) {
|
|
290014
|
-
case "TTY":
|
|
290015
|
-
stream2 = new tty.WriteStream(fd2);
|
|
290016
|
-
stream2._type = "tty";
|
|
290017
|
-
if (stream2._handle && stream2._handle.unref) {
|
|
290018
|
-
stream2._handle.unref();
|
|
290019
|
-
}
|
|
290020
|
-
break;
|
|
290021
|
-
case "FILE":
|
|
290022
|
-
var fs32 = __require("fs");
|
|
290023
|
-
stream2 = new fs32.SyncWriteStream(fd2, { autoClose: false });
|
|
290024
|
-
stream2._type = "fs";
|
|
290025
|
-
break;
|
|
290026
|
-
case "PIPE":
|
|
290027
|
-
case "TCP":
|
|
290028
|
-
var net = __require("net");
|
|
290029
|
-
stream2 = new net.Socket({
|
|
290030
|
-
fd: fd2,
|
|
290031
|
-
readable: false,
|
|
290032
|
-
writable: true
|
|
290033
|
-
});
|
|
290034
|
-
stream2.readable = false;
|
|
290035
|
-
stream2.read = null;
|
|
290036
|
-
stream2._type = "pipe";
|
|
290037
|
-
if (stream2._handle && stream2._handle.unref) {
|
|
290038
|
-
stream2._handle.unref();
|
|
290039
|
-
}
|
|
290040
|
-
break;
|
|
290041
|
-
default:
|
|
290042
|
-
throw new Error("Implement me. Unknown stream file type!");
|
|
290043
|
-
}
|
|
290044
|
-
stream2.fd = fd2;
|
|
290045
|
-
stream2._isStdio = true;
|
|
290046
|
-
return stream2;
|
|
290047
|
-
}
|
|
290048
|
-
function init(debug5) {
|
|
290049
|
-
debug5.inspectOpts = {};
|
|
290050
|
-
var keys = Object.keys(exports2.inspectOpts);
|
|
290051
|
-
for (var i = 0; i < keys.length; i++) {
|
|
290052
|
-
debug5.inspectOpts[keys[i]] = exports2.inspectOpts[keys[i]];
|
|
290053
|
-
}
|
|
290054
|
-
}
|
|
290055
|
-
exports2.enable(load());
|
|
290056
|
-
}
|
|
290057
|
-
});
|
|
290058
|
-
|
|
290059
|
-
// ../../node_modules/.pnpm/debug@2.6.9/node_modules/debug/src/index.js
|
|
290060
|
-
var require_src19 = __commonJS({
|
|
290061
|
-
"../../node_modules/.pnpm/debug@2.6.9/node_modules/debug/src/index.js"(exports2, module2) {
|
|
290062
|
-
if (typeof process !== "undefined" && process.type === "renderer") {
|
|
290063
|
-
module2.exports = require_browser4();
|
|
290064
|
-
} else {
|
|
290065
|
-
module2.exports = require_node15();
|
|
290066
|
-
}
|
|
290067
|
-
}
|
|
290068
|
-
});
|
|
290069
|
-
|
|
290070
289666
|
// ../../node_modules/.pnpm/follow-redirects@1.15.11/node_modules/follow-redirects/debug.js
|
|
290071
|
-
var
|
|
289667
|
+
var require_debug3 = __commonJS({
|
|
290072
289668
|
"../../node_modules/.pnpm/follow-redirects@1.15.11/node_modules/follow-redirects/debug.js"(exports2, module2) {
|
|
290073
289669
|
var debug5;
|
|
290074
289670
|
module2.exports = function() {
|
|
290075
289671
|
if (!debug5) {
|
|
290076
289672
|
try {
|
|
290077
|
-
debug5 =
|
|
289673
|
+
debug5 = require_src()("follow-redirects");
|
|
290078
289674
|
} catch (error) {
|
|
290079
289675
|
}
|
|
290080
289676
|
if (typeof debug5 !== "function") {
|
|
@@ -290096,7 +289692,7 @@ var require_follow_redirects = __commonJS({
|
|
|
290096
289692
|
var https2 = __require("https");
|
|
290097
289693
|
var Writable = __require("stream").Writable;
|
|
290098
289694
|
var assert3 = __require("assert");
|
|
290099
|
-
var debug5 =
|
|
289695
|
+
var debug5 = require_debug3();
|
|
290100
289696
|
(function detectUnsupportedEnvironment() {
|
|
290101
289697
|
var looksLikeNode = typeof process !== "undefined";
|
|
290102
289698
|
var looksLikeBrowser = typeof window !== "undefined" && typeof document !== "undefined";
|
|
@@ -308158,7 +307754,7 @@ var require_SocketModeClient = __commonJS({
|
|
|
308158
307754
|
});
|
|
308159
307755
|
|
|
308160
307756
|
// ../../node_modules/.pnpm/@slack+socket-mode@2.0.6/node_modules/@slack/socket-mode/dist/src/index.js
|
|
308161
|
-
var
|
|
307757
|
+
var require_src19 = __commonJS({
|
|
308162
307758
|
"../../node_modules/.pnpm/@slack+socket-mode@2.0.6/node_modules/@slack/socket-mode/dist/src/index.js"(exports2) {
|
|
308163
307759
|
"use strict";
|
|
308164
307760
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -308244,7 +307840,7 @@ var require_SocketModeReceiver = __commonJS({
|
|
|
308244
307840
|
var node_url_1 = __require("node:url");
|
|
308245
307841
|
var logger_1 = require_dist21();
|
|
308246
307842
|
var oauth_1 = require_dist25();
|
|
308247
|
-
var socket_mode_1 =
|
|
307843
|
+
var socket_mode_1 = require_src19();
|
|
308248
307844
|
var path_to_regexp_1 = require_dist26();
|
|
308249
307845
|
var SocketModeFunctions_1 = require_SocketModeFunctions();
|
|
308250
307846
|
var SocketModeResponseAck_1 = require_SocketModeResponseAck();
|
|
@@ -311692,7 +311288,7 @@ var init_src8 = __esm({
|
|
|
311692
311288
|
await this._handle.listen();
|
|
311693
311289
|
const authMode = config2.apiKey ? "API key" : "open (no auth)";
|
|
311694
311290
|
console.log(`
|
|
311695
|
-
Nestor Server v3.5.
|
|
311291
|
+
Nestor Server v3.5.2`);
|
|
311696
311292
|
console.log(` \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
|
|
311697
311293
|
console.log(` HTTP : http://${this._host}:${this._port}`);
|
|
311698
311294
|
console.log(` WS : ws://${this._host}:${this._port}/ws`);
|
|
@@ -321481,7 +321077,7 @@ var init_server = __esm({
|
|
|
321481
321077
|
MCP_PROTOCOL_VERSION = "2024-11-05";
|
|
321482
321078
|
SERVER_INFO = {
|
|
321483
321079
|
name: "nestor",
|
|
321484
|
-
version: "3.5.
|
|
321080
|
+
version: "3.5.2"
|
|
321485
321081
|
};
|
|
321486
321082
|
SERVER_CAPABILITIES = {
|
|
321487
321083
|
tools: { listChanged: false },
|
|
@@ -322202,7 +321798,7 @@ function printWelcome() {
|
|
|
322202
321798
|
console.log(chalk15.cyan(` | .\` | | _| \\__ \\ | | | (_) | | / _ \\__ \\ | __ |`));
|
|
322203
321799
|
console.log(chalk15.cyan(` |_|\\_| |___| |___/ |_| \\___/ |_|_\\ (_) |___/ |_||_|`));
|
|
322204
321800
|
console.log("");
|
|
322205
|
-
console.log(chalk15.dim(" Interactive Shell \u2014 v3.5.
|
|
321801
|
+
console.log(chalk15.dim(" Interactive Shell \u2014 v3.5.2"));
|
|
322206
321802
|
console.log(chalk15.dim(" Type /help for commands, /exit to quit."));
|
|
322207
321803
|
console.log(chalk15.dim(" Multiline: end a line with \\ or use ``` code blocks."));
|
|
322208
321804
|
console.log("");
|
|
@@ -322871,11 +322467,190 @@ var init_plan_undo_commands = __esm({
|
|
|
322871
322467
|
}
|
|
322872
322468
|
});
|
|
322873
322469
|
|
|
322874
|
-
// src/commands/shell/
|
|
322470
|
+
// src/commands/shell/pair-command.ts
|
|
322471
|
+
import "node:readline";
|
|
322472
|
+
import { randomUUID as randomUUID66 } from "node:crypto";
|
|
322875
322473
|
import chalk20 from "chalk";
|
|
322474
|
+
async function askSingleKey(prompt, rl) {
|
|
322475
|
+
return new Promise((res) => {
|
|
322476
|
+
process.stdout.write(prompt);
|
|
322477
|
+
rl.once("line", (line) => {
|
|
322478
|
+
res(line.trim().toLowerCase());
|
|
322479
|
+
});
|
|
322480
|
+
});
|
|
322481
|
+
}
|
|
322482
|
+
async function cmdPairMode(args, session, rl, importAgentModule2, executeAgentTask2) {
|
|
322483
|
+
if (args.length === 0) {
|
|
322484
|
+
console.log(chalk20.yellow("Usage: /pair <task description>"));
|
|
322485
|
+
return;
|
|
322486
|
+
}
|
|
322487
|
+
if (!session.activeAgent) {
|
|
322488
|
+
console.log(chalk20.yellow("No agent active. Use /use <name> first."));
|
|
322489
|
+
return;
|
|
322490
|
+
}
|
|
322491
|
+
const task = args.join(" ");
|
|
322492
|
+
const agent = session.activeAgent;
|
|
322493
|
+
console.log(chalk20.cyan("\n\u{1F4CB} Planning...\n"));
|
|
322494
|
+
const agentModule = await importAgentModule2();
|
|
322495
|
+
if (!agentModule) {
|
|
322496
|
+
console.log(chalk20.yellow("Agent runtime not available. Cannot use pair mode."));
|
|
322497
|
+
return;
|
|
322498
|
+
}
|
|
322499
|
+
const { AgentRuntime: AgentRuntime2, RuntimeEventBus: RuntimeEventBus2, ToolRegistry: ToolRegistry4, ToolExecutor: ToolExecutor2, registerBuiltinTools: registerBuiltinTools2 } = agentModule;
|
|
322500
|
+
let llmAdapter;
|
|
322501
|
+
try {
|
|
322502
|
+
const router = await agentModule.createDefaultRouter();
|
|
322503
|
+
const modelId = agent.adapterConfig.model ?? "claude-sonnet-4-20250514";
|
|
322504
|
+
llmAdapter = router.resolve(modelId);
|
|
322505
|
+
} catch {
|
|
322506
|
+
console.log(chalk20.yellow("Could not initialize LLM adapter."));
|
|
322507
|
+
return;
|
|
322508
|
+
}
|
|
322509
|
+
let DryRunInterceptorCls;
|
|
322510
|
+
try {
|
|
322511
|
+
const mod2 = await Promise.resolve().then(() => (init_src5(), src_exports5));
|
|
322512
|
+
DryRunInterceptorCls = mod2.DryRunInterceptor;
|
|
322513
|
+
} catch {
|
|
322514
|
+
console.log(chalk20.yellow("DryRunInterceptor not available."));
|
|
322515
|
+
return;
|
|
322516
|
+
}
|
|
322517
|
+
const events = new RuntimeEventBus2();
|
|
322518
|
+
const tools = new ToolRegistry4();
|
|
322519
|
+
registerBuiltinTools2(tools);
|
|
322520
|
+
const interceptor = new DryRunInterceptorCls();
|
|
322521
|
+
const dryExecutor = new ToolExecutor2();
|
|
322522
|
+
dryExecutor.execute = async (tool, rawInput, ctx) => {
|
|
322523
|
+
return interceptor.execute(tool, rawInput, ctx);
|
|
322524
|
+
};
|
|
322525
|
+
const dryRuntime = new AgentRuntime2({
|
|
322526
|
+
adapter: llmAdapter,
|
|
322527
|
+
tools,
|
|
322528
|
+
toolExecutor: dryExecutor,
|
|
322529
|
+
role: {
|
|
322530
|
+
name: agent.name,
|
|
322531
|
+
description: agent.description ?? `Agent: ${agent.name}`,
|
|
322532
|
+
instructions: agent.adapterConfig.instructions ?? "You are a helpful AI assistant.",
|
|
322533
|
+
constraints: []
|
|
322534
|
+
},
|
|
322535
|
+
workingDir: process.cwd(),
|
|
322536
|
+
events,
|
|
322537
|
+
maxIterations: 20,
|
|
322538
|
+
signal: new AbortController().signal
|
|
322539
|
+
});
|
|
322540
|
+
const taskId = randomUUID66();
|
|
322541
|
+
try {
|
|
322542
|
+
const dryResult = await dryRuntime.run({ prompt: task, agentId: agent.id, taskId });
|
|
322543
|
+
const plan = interceptor.getPlan();
|
|
322544
|
+
if (plan.length === 0) {
|
|
322545
|
+
console.log(chalk20.yellow("No tool calls planned. The agent would only respond with text."));
|
|
322546
|
+
console.log("\n" + dryResult.output + "\n");
|
|
322547
|
+
return;
|
|
322548
|
+
}
|
|
322549
|
+
console.log(chalk20.cyan.bold(`\u{1F4CB} PLAN (${plan.length} steps):`));
|
|
322550
|
+
for (const step of plan) {
|
|
322551
|
+
console.log(formatPlanStep(step));
|
|
322552
|
+
}
|
|
322553
|
+
console.log("");
|
|
322554
|
+
console.log(chalk20.dim(` Estimated cost: $${dryResult.usage.estimatedCostUsd.toFixed(4)} | Iterations: ${dryResult.iterations}`));
|
|
322555
|
+
console.log("");
|
|
322556
|
+
const choice = await askSingleKey(
|
|
322557
|
+
" " + chalk20.cyan("[E]") + "xecute all | " + chalk20.cyan("[S]") + "tep-by-step | " + chalk20.cyan("[C]") + "ancel | " + chalk20.cyan("[R]") + "e-plan > ",
|
|
322558
|
+
rl
|
|
322559
|
+
);
|
|
322560
|
+
if (choice === "c") {
|
|
322561
|
+
console.log(chalk20.dim("\n Cancelled.\n"));
|
|
322562
|
+
return;
|
|
322563
|
+
}
|
|
322564
|
+
if (choice === "r") {
|
|
322565
|
+
const feedback = await askSingleKey(chalk20.cyan(" Feedback for re-planning: "), rl);
|
|
322566
|
+
const newArgs = [...args, "\n\nUser feedback:", feedback];
|
|
322567
|
+
return cmdPairMode(newArgs, session, rl, importAgentModule2, executeAgentTask2);
|
|
322568
|
+
}
|
|
322569
|
+
if (choice === "e") {
|
|
322570
|
+
console.log(chalk20.cyan("\n Executing all steps...\n"));
|
|
322571
|
+
await executeAgentTask2(agent, task, session);
|
|
322572
|
+
return;
|
|
322573
|
+
}
|
|
322574
|
+
console.log(chalk20.cyan("\n Step-by-step execution:\n"));
|
|
322575
|
+
const realTools = new ToolRegistry4();
|
|
322576
|
+
registerBuiltinTools2(realTools);
|
|
322577
|
+
const realExecutor = new ToolExecutor2();
|
|
322578
|
+
for (let i = 0; i < plan.length; i++) {
|
|
322579
|
+
const step = plan[i];
|
|
322580
|
+
console.log(chalk20.cyan.bold(`
|
|
322581
|
+
Step ${i + 1}/${plan.length}: ${step.toolName}`));
|
|
322582
|
+
if (step.toolName === "file_write" && step.args.path) {
|
|
322583
|
+
showDiffForStep(String(step.args.path), String(step.args.content ?? ""));
|
|
322584
|
+
} else if (step.toolName === "shell_exec") {
|
|
322585
|
+
console.log(chalk20.dim(` Command: ${chalk20.white(String(step.args.command ?? ""))}`));
|
|
322586
|
+
} else {
|
|
322587
|
+
console.log(chalk20.dim(` Args: ${JSON.stringify(step.args).slice(0, 200)}`));
|
|
322588
|
+
}
|
|
322589
|
+
const decision = await askSingleKey(
|
|
322590
|
+
" " + chalk20.cyan("[A]") + "ccept " + chalk20.cyan("[R]") + "eject " + chalk20.cyan("[M]") + "odify " + chalk20.cyan("[F]") + "eedback " + chalk20.cyan("[S]") + "kip > ",
|
|
322591
|
+
rl
|
|
322592
|
+
);
|
|
322593
|
+
const tool = realTools.get(step.toolName);
|
|
322594
|
+
const toolCtx = { agentId: agent.id, taskId, workingDir: process.cwd() };
|
|
322595
|
+
switch (decision) {
|
|
322596
|
+
case "a": {
|
|
322597
|
+
if (!tool) {
|
|
322598
|
+
console.log(chalk20.red(` Tool '${step.toolName}' not found.`));
|
|
322599
|
+
break;
|
|
322600
|
+
}
|
|
322601
|
+
const result = await realExecutor.execute(tool, step.args, toolCtx);
|
|
322602
|
+
console.log(result.isError ? chalk20.red(` \u2717 Error: ${result.output.slice(0, 200)}`) : chalk20.green(` \u2713 Done: ${result.output.slice(0, 200)}`));
|
|
322603
|
+
break;
|
|
322604
|
+
}
|
|
322605
|
+
case "r":
|
|
322606
|
+
console.log(chalk20.red(" \u2717 Rejected"));
|
|
322607
|
+
break;
|
|
322608
|
+
case "m": {
|
|
322609
|
+
if (!tool) {
|
|
322610
|
+
console.log(chalk20.red(` Tool '${step.toolName}' not found.`));
|
|
322611
|
+
break;
|
|
322612
|
+
}
|
|
322613
|
+
const modStr = await askSingleKey(chalk20.cyan(` Modified args JSON: `), rl);
|
|
322614
|
+
let modArgs = step.args;
|
|
322615
|
+
try {
|
|
322616
|
+
if (modStr.trim()) modArgs = JSON.parse(modStr);
|
|
322617
|
+
} catch {
|
|
322618
|
+
console.log(chalk20.yellow(" Invalid JSON, using original."));
|
|
322619
|
+
}
|
|
322620
|
+
const modResult = await realExecutor.execute(tool, modArgs, toolCtx);
|
|
322621
|
+
console.log(modResult.isError ? chalk20.red(` \u2717 Error: ${modResult.output.slice(0, 200)}`) : chalk20.green(` \u2713 Done: ${modResult.output.slice(0, 200)}`));
|
|
322622
|
+
break;
|
|
322623
|
+
}
|
|
322624
|
+
case "f": {
|
|
322625
|
+
const fb = await askSingleKey(chalk20.cyan(" Feedback: "), rl);
|
|
322626
|
+
console.log(chalk20.dim(` Noted: "${fb}"`));
|
|
322627
|
+
break;
|
|
322628
|
+
}
|
|
322629
|
+
case "s":
|
|
322630
|
+
console.log(chalk20.yellow(" \u23ED Skipped"));
|
|
322631
|
+
break;
|
|
322632
|
+
default:
|
|
322633
|
+
console.log(chalk20.yellow(" \u23ED Skipped"));
|
|
322634
|
+
break;
|
|
322635
|
+
}
|
|
322636
|
+
}
|
|
322637
|
+
console.log(chalk20.green("\n\u2705 Pair programming session complete.\n"));
|
|
322638
|
+
} catch (err) {
|
|
322639
|
+
console.error(chalk20.red("Pair mode error:"), err instanceof Error ? err.message : String(err));
|
|
322640
|
+
}
|
|
322641
|
+
}
|
|
322642
|
+
var init_pair_command = __esm({
|
|
322643
|
+
"src/commands/shell/pair-command.ts"() {
|
|
322644
|
+
"use strict";
|
|
322645
|
+
init_diff();
|
|
322646
|
+
}
|
|
322647
|
+
});
|
|
322648
|
+
|
|
322649
|
+
// src/commands/shell/replay-command.ts
|
|
322650
|
+
import chalk21 from "chalk";
|
|
322876
322651
|
async function cmdReplay(args) {
|
|
322877
322652
|
if (args.length === 0) {
|
|
322878
|
-
console.log(
|
|
322653
|
+
console.log(chalk21.yellow("Usage: /replay <runId>"));
|
|
322879
322654
|
return;
|
|
322880
322655
|
}
|
|
322881
322656
|
const runId = args[0];
|
|
@@ -322883,14 +322658,14 @@ async function cmdReplay(args) {
|
|
|
322883
322658
|
try {
|
|
322884
322659
|
const events = store.listRunEvents(runId);
|
|
322885
322660
|
if (!events || events.length === 0) {
|
|
322886
|
-
console.log(
|
|
322661
|
+
console.log(chalk21.yellow(`No events found for run ${runId}.`));
|
|
322887
322662
|
return;
|
|
322888
322663
|
}
|
|
322889
322664
|
console.log("");
|
|
322890
322665
|
console.log(
|
|
322891
|
-
|
|
322666
|
+
chalk21.cyan.bold("\u25B6 Replaying run ") + chalk21.cyan(runId.slice(0, 12) + "...") + chalk21.dim(` (${events.length} events)`)
|
|
322892
322667
|
);
|
|
322893
|
-
console.log(
|
|
322668
|
+
console.log(chalk21.dim("\u2500".repeat(60)));
|
|
322894
322669
|
console.log("");
|
|
322895
322670
|
let prevTimestamp = null;
|
|
322896
322671
|
for (const event of events) {
|
|
@@ -322899,7 +322674,7 @@ async function cmdReplay(args) {
|
|
|
322899
322674
|
if (prevTimestamp !== null) {
|
|
322900
322675
|
const gap = ts - prevTimestamp;
|
|
322901
322676
|
if (gap > 100) {
|
|
322902
|
-
process.stdout.write(
|
|
322677
|
+
process.stdout.write(chalk21.dim(` ... +${formatReplayDuration(gap)}
|
|
322903
322678
|
`));
|
|
322904
322679
|
}
|
|
322905
322680
|
}
|
|
@@ -322912,78 +322687,78 @@ async function cmdReplay(args) {
|
|
|
322912
322687
|
switch (event.type) {
|
|
322913
322688
|
case "node_started":
|
|
322914
322689
|
process.stdout.write(
|
|
322915
|
-
|
|
322690
|
+
chalk21.dim(` [${timeStr}] `) + chalk21.blue("\u25B6 ") + chalk21.blue.bold(data.nodeName ?? event.nodeId ?? "Step") + chalk21.dim(" started") + "\n"
|
|
322916
322691
|
);
|
|
322917
322692
|
break;
|
|
322918
322693
|
case "node_completed":
|
|
322919
322694
|
process.stdout.write(
|
|
322920
|
-
|
|
322695
|
+
chalk21.dim(` [${timeStr}] `) + chalk21.green("\u2714 ") + chalk21.green.bold(data.nodeName ?? event.nodeId ?? "Step") + chalk21.dim(" completed") + (data.durationMs ? chalk21.dim(` (${formatReplayDuration(data.durationMs)})`) : "") + "\n"
|
|
322921
322696
|
);
|
|
322922
322697
|
break;
|
|
322923
322698
|
case "node_failed":
|
|
322924
322699
|
process.stdout.write(
|
|
322925
|
-
|
|
322700
|
+
chalk21.dim(` [${timeStr}] `) + chalk21.red("\u2718 ") + chalk21.red.bold(data.nodeName ?? event.nodeId ?? "Step") + chalk21.dim(" failed") + "\n"
|
|
322926
322701
|
);
|
|
322927
322702
|
if (data.error) {
|
|
322928
|
-
process.stdout.write(
|
|
322703
|
+
process.stdout.write(chalk21.red(` Error: ${String(data.error).slice(0, 200)}`) + "\n");
|
|
322929
322704
|
}
|
|
322930
322705
|
break;
|
|
322931
322706
|
case "tool_call_requested":
|
|
322932
322707
|
process.stdout.write(
|
|
322933
|
-
|
|
322708
|
+
chalk21.dim(` [${timeStr}] `) + chalk21.yellow("\u{1F527} ") + chalk21.yellow.bold(data.tool ?? "tool") + "\n"
|
|
322934
322709
|
);
|
|
322935
322710
|
if (data.args) {
|
|
322936
322711
|
const argsStr = JSON.stringify(data.args);
|
|
322937
322712
|
const preview = argsStr.length > 120 ? argsStr.slice(0, 120) + "..." : argsStr;
|
|
322938
|
-
process.stdout.write(
|
|
322713
|
+
process.stdout.write(chalk21.dim(` args: ${preview}`) + "\n");
|
|
322939
322714
|
}
|
|
322940
322715
|
break;
|
|
322941
322716
|
case "tool_call_completed":
|
|
322942
322717
|
process.stdout.write(
|
|
322943
|
-
|
|
322718
|
+
chalk21.dim(` [${timeStr}] `) + chalk21.green("\u2714 ") + chalk21.yellow.bold(data.tool ?? "tool") + chalk21.green(" completed") + "\n"
|
|
322944
322719
|
);
|
|
322945
322720
|
if (data.output) {
|
|
322946
322721
|
const output = String(data.output);
|
|
322947
322722
|
const preview = output.length > 200 ? output.slice(0, 200) + "..." : output;
|
|
322948
|
-
process.stdout.write(
|
|
322723
|
+
process.stdout.write(chalk21.dim(` ${preview}`) + "\n");
|
|
322949
322724
|
}
|
|
322950
322725
|
break;
|
|
322951
322726
|
case "approval_requested":
|
|
322952
322727
|
process.stdout.write(
|
|
322953
|
-
|
|
322728
|
+
chalk21.dim(` [${timeStr}] `) + chalk21.yellow("\u{1F6E1}\uFE0F ") + chalk21.yellow("Approval requested: ") + chalk21.white(data.command ?? data.tool ?? "") + "\n"
|
|
322954
322729
|
);
|
|
322955
322730
|
break;
|
|
322956
322731
|
case "budget_warning":
|
|
322957
322732
|
process.stdout.write(
|
|
322958
|
-
|
|
322733
|
+
chalk21.dim(` [${timeStr}] `) + chalk21.yellow("\u26A0 Budget warning: ") + chalk21.white(`${data.usedPct ?? "?"}% used`) + "\n"
|
|
322959
322734
|
);
|
|
322960
322735
|
break;
|
|
322961
322736
|
case "reasoning": {
|
|
322962
322737
|
const entry = data.entry ?? data;
|
|
322963
322738
|
if (entry.reasoning) {
|
|
322964
|
-
const phaseTag = entry.phase ?
|
|
322739
|
+
const phaseTag = entry.phase ? chalk21.dim(`[${entry.phase}] `) : "";
|
|
322965
322740
|
process.stdout.write(
|
|
322966
|
-
|
|
322741
|
+
chalk21.dim(` [${timeStr}] `) + chalk21.dim.italic(`\u{1F4AD} ${phaseTag}${entry.reasoning}`) + "\n"
|
|
322967
322742
|
);
|
|
322968
322743
|
}
|
|
322969
322744
|
break;
|
|
322970
322745
|
}
|
|
322971
322746
|
default:
|
|
322972
322747
|
process.stdout.write(
|
|
322973
|
-
|
|
322748
|
+
chalk21.dim(` [${timeStr}] `) + chalk21.dim(`[${event.type}] `) + chalk21.dim(JSON.stringify(data).slice(0, 100)) + "\n"
|
|
322974
322749
|
);
|
|
322975
322750
|
break;
|
|
322976
322751
|
}
|
|
322977
322752
|
await new Promise((resolve20) => setTimeout(resolve20, 30));
|
|
322978
322753
|
}
|
|
322979
322754
|
console.log("");
|
|
322980
|
-
console.log(
|
|
322755
|
+
console.log(chalk21.dim("\u2500".repeat(60)));
|
|
322981
322756
|
console.log(
|
|
322982
|
-
|
|
322757
|
+
chalk21.cyan.bold("\u23F9 Replay complete") + chalk21.dim(` (${events.length} events)`)
|
|
322983
322758
|
);
|
|
322984
322759
|
console.log("");
|
|
322985
322760
|
} catch (err) {
|
|
322986
|
-
console.error(
|
|
322761
|
+
console.error(chalk21.red("Replay failed:"), err instanceof Error ? err.message : String(err));
|
|
322987
322762
|
} finally {
|
|
322988
322763
|
store.close();
|
|
322989
322764
|
}
|
|
@@ -323001,12 +322776,12 @@ var shell_exports = {};
|
|
|
323001
322776
|
__export(shell_exports, {
|
|
323002
322777
|
registerShellCommand: () => registerShellCommand
|
|
323003
322778
|
});
|
|
323004
|
-
import * as
|
|
322779
|
+
import * as readline5 from "node:readline";
|
|
323005
322780
|
import { existsSync as existsSync24, mkdirSync as mkdirSync16 } from "node:fs";
|
|
323006
322781
|
import { join as join31 } from "node:path";
|
|
323007
322782
|
import "node:fs";
|
|
323008
|
-
import { randomUUID as
|
|
323009
|
-
import
|
|
322783
|
+
import { randomUUID as randomUUID67 } from "node:crypto";
|
|
322784
|
+
import chalk22 from "chalk";
|
|
323010
322785
|
import * as p5 from "@clack/prompts";
|
|
323011
322786
|
function registerShellCommand(program2) {
|
|
323012
322787
|
program2.command("shell").description("Start an interactive REPL session").option("--fresh", "Start with a clean context, ignoring accumulated history").option("--max-iterations <n>", "Default max iterations for /mission commands").option("--max-runtime <seconds>", "Default max runtime in seconds for /mission commands").option("--hat <id>", "Activate a specialized persona hat (e.g. coder, researcher, security, writer, osint)").action(async (opts) => {
|
|
@@ -323053,13 +322828,13 @@ async function startShell(options) {
|
|
|
323053
322828
|
session.activeHat = hat;
|
|
323054
322829
|
} else {
|
|
323055
322830
|
const available = listHatsFn().map((h) => h.id).join(", ");
|
|
323056
|
-
console.log(
|
|
322831
|
+
console.log(chalk22.yellow(`Hat '${options.hat}' not found. Available hats: ${available}`));
|
|
323057
322832
|
}
|
|
323058
322833
|
} else {
|
|
323059
|
-
console.log(
|
|
322834
|
+
console.log(chalk22.dim("Hat system not available in this version of @nestor/agent."));
|
|
323060
322835
|
}
|
|
323061
322836
|
} catch {
|
|
323062
|
-
console.log(
|
|
322837
|
+
console.log(chalk22.dim("Hat system not available \u2014 @nestor/agent could not be loaded."));
|
|
323063
322838
|
}
|
|
323064
322839
|
}
|
|
323065
322840
|
if (!existsSync24(NESTOR_DIR)) {
|
|
@@ -323069,13 +322844,13 @@ async function startShell(options) {
|
|
|
323069
322844
|
const history = options?.fresh ? [] : loadHistory2();
|
|
323070
322845
|
printWelcome();
|
|
323071
322846
|
if (session.activeHat) {
|
|
323072
|
-
console.log(
|
|
322847
|
+
console.log(chalk22.cyan(` \u{1F3A9} Hat: ${chalk22.bold(session.activeHat.name)}`) + chalk22.dim(` \u2014 ${session.activeHat.description}`));
|
|
323073
322848
|
if (session.activeHat.modelPreference) {
|
|
323074
|
-
console.log(
|
|
322849
|
+
console.log(chalk22.dim(` Model preference: ${session.activeHat.modelPreference}`));
|
|
323075
322850
|
}
|
|
323076
322851
|
console.log("");
|
|
323077
322852
|
}
|
|
323078
|
-
const rl =
|
|
322853
|
+
const rl = readline5.createInterface({
|
|
323079
322854
|
input: process.stdin,
|
|
323080
322855
|
output: process.stdout,
|
|
323081
322856
|
prompt: buildPrompt(session),
|
|
@@ -323091,11 +322866,11 @@ async function startShell(options) {
|
|
|
323091
322866
|
const lastUserMsg = session.conversationHistory.filter((e) => e.role === "user").pop();
|
|
323092
322867
|
session.interruptedContext = lastUserMsg ? { prompt: lastUserMsg.content } : null;
|
|
323093
322868
|
process.stdout.write("\n");
|
|
323094
|
-
process.stdout.write(
|
|
322869
|
+
process.stdout.write(chalk22.yellow("^C Agent interrupted.") + "\n");
|
|
323095
322870
|
process.stdout.write(
|
|
323096
|
-
" " +
|
|
322871
|
+
" " + chalk22.cyan("[R]") + "esume " + chalk22.cyan("[N]") + "ew instruction " + chalk22.cyan("[C]") + "ancel\n"
|
|
323097
322872
|
);
|
|
323098
|
-
process.stdout.write(
|
|
322873
|
+
process.stdout.write(chalk22.dim("> "));
|
|
323099
322874
|
const onLine = async (answer) => {
|
|
323100
322875
|
const choice = answer.trim().toLowerCase();
|
|
323101
322876
|
if (choice === "r" && session.interruptedContext && session.activeAgent) {
|
|
@@ -323112,20 +322887,20 @@ async function startShell(options) {
|
|
|
323112
322887
|
rl.once("line", onLine);
|
|
323113
322888
|
return;
|
|
323114
322889
|
}
|
|
323115
|
-
process.stdout.write("\n" +
|
|
322890
|
+
process.stdout.write("\n" + chalk22.dim("(Use /exit or Ctrl+D to quit)") + "\n");
|
|
323116
322891
|
rl.prompt();
|
|
323117
322892
|
});
|
|
323118
322893
|
rl.on("close", () => {
|
|
323119
322894
|
saveHistory2(rl);
|
|
323120
322895
|
clearStatusBar();
|
|
323121
|
-
process.stdout.write("\n" +
|
|
322896
|
+
process.stdout.write("\n" + chalk22.dim("Goodbye.") + "\n");
|
|
323122
322897
|
process.exit(0);
|
|
323123
322898
|
});
|
|
323124
322899
|
rl.on("line", async (line) => {
|
|
323125
322900
|
if (line.trim().startsWith("```") && !session.inCodeBlock) {
|
|
323126
322901
|
session.inCodeBlock = true;
|
|
323127
322902
|
session.multilineBuffer.push(line);
|
|
323128
|
-
rl.setPrompt(
|
|
322903
|
+
rl.setPrompt(chalk22.dim("... "));
|
|
323129
322904
|
rl.prompt();
|
|
323130
322905
|
return;
|
|
323131
322906
|
}
|
|
@@ -323139,13 +322914,13 @@ async function startShell(options) {
|
|
|
323139
322914
|
await processInput(fullInput, session, rl);
|
|
323140
322915
|
return;
|
|
323141
322916
|
}
|
|
323142
|
-
rl.setPrompt(
|
|
322917
|
+
rl.setPrompt(chalk22.dim("... "));
|
|
323143
322918
|
rl.prompt();
|
|
323144
322919
|
return;
|
|
323145
322920
|
}
|
|
323146
322921
|
if (line.endsWith("\\")) {
|
|
323147
322922
|
session.multilineBuffer.push(line.slice(0, -1));
|
|
323148
|
-
rl.setPrompt(
|
|
322923
|
+
rl.setPrompt(chalk22.dim("... "));
|
|
323149
322924
|
rl.prompt();
|
|
323150
322925
|
return;
|
|
323151
322926
|
}
|
|
@@ -323175,10 +322950,10 @@ async function processInput(line, session, rl) {
|
|
|
323175
322950
|
} else if (session.activeAgent) {
|
|
323176
322951
|
await handleAgentMessage(trimmed, session, rl);
|
|
323177
322952
|
} else {
|
|
323178
|
-
console.log(
|
|
322953
|
+
console.log(chalk22.yellow("No agent active. Use /use <name> to activate one, or /help for commands."));
|
|
323179
322954
|
}
|
|
323180
322955
|
} catch (err) {
|
|
323181
|
-
console.error(
|
|
322956
|
+
console.error(chalk22.red("Error:"), err instanceof Error ? err.message : String(err));
|
|
323182
322957
|
}
|
|
323183
322958
|
rl.setPrompt(buildPrompt(session));
|
|
323184
322959
|
renderStatusBar(session);
|
|
@@ -323247,7 +323022,13 @@ async function handleSlashCommand(input, session, rl) {
|
|
|
323247
323022
|
cmdExport(args, session);
|
|
323248
323023
|
break;
|
|
323249
323024
|
case "/pair":
|
|
323250
|
-
await cmdPairMode(
|
|
323025
|
+
await cmdPairMode(
|
|
323026
|
+
args,
|
|
323027
|
+
session,
|
|
323028
|
+
rl,
|
|
323029
|
+
importAgentModule,
|
|
323030
|
+
(agent, task, sess) => executeAgentTask(agent, task, sess)
|
|
323031
|
+
);
|
|
323251
323032
|
break;
|
|
323252
323033
|
case "/annotate":
|
|
323253
323034
|
await cmdAnnotate2(args, session);
|
|
@@ -323277,12 +323058,12 @@ async function handleSlashCommand(input, session, rl) {
|
|
|
323277
323058
|
case "/quit":
|
|
323278
323059
|
saveHistory2(rl);
|
|
323279
323060
|
clearStatusBar();
|
|
323280
|
-
process.stdout.write(
|
|
323061
|
+
process.stdout.write(chalk22.dim("Goodbye.") + "\n");
|
|
323281
323062
|
process.exit(0);
|
|
323282
323063
|
break;
|
|
323283
323064
|
default:
|
|
323284
|
-
console.log(
|
|
323285
|
-
console.log(
|
|
323065
|
+
console.log(chalk22.red(`Unknown command: ${cmd}`));
|
|
323066
|
+
console.log(chalk22.dim("Type /help for available commands."));
|
|
323286
323067
|
break;
|
|
323287
323068
|
}
|
|
323288
323069
|
}
|
|
@@ -323292,9 +323073,9 @@ function printHelp2() {
|
|
|
323292
323073
|
async function cmdUseAgent(args, session) {
|
|
323293
323074
|
if (args.length === 0) {
|
|
323294
323075
|
if (session.activeAgent) {
|
|
323295
|
-
console.log(
|
|
323076
|
+
console.log(chalk22.dim(`Currently using: ${chalk22.bold(session.activeAgent.name)}`));
|
|
323296
323077
|
} else {
|
|
323297
|
-
console.log(
|
|
323078
|
+
console.log(chalk22.yellow("Usage: /use <agent-name>"));
|
|
323298
323079
|
}
|
|
323299
323080
|
return;
|
|
323300
323081
|
}
|
|
@@ -323303,8 +323084,8 @@ async function cmdUseAgent(args, session) {
|
|
|
323303
323084
|
try {
|
|
323304
323085
|
const agent = store.getAgentByName(name);
|
|
323305
323086
|
if (!agent) {
|
|
323306
|
-
console.log(
|
|
323307
|
-
console.log(
|
|
323087
|
+
console.log(chalk22.red(`Agent '${name}' not found.`));
|
|
323088
|
+
console.log(chalk22.dim("Use /agents to see available agents."));
|
|
323308
323089
|
return;
|
|
323309
323090
|
}
|
|
323310
323091
|
session.activeAgent = agent;
|
|
@@ -323314,10 +323095,10 @@ async function cmdUseAgent(args, session) {
|
|
|
323314
323095
|
session.totalTokensOut = 0;
|
|
323315
323096
|
session.totalCostUsd = 0;
|
|
323316
323097
|
session.totalToolCalls = 0;
|
|
323317
|
-
console.log(
|
|
323318
|
-
console.log(
|
|
323098
|
+
console.log(chalk22.green(`Activated agent: ${chalk22.bold(agent.name)}`));
|
|
323099
|
+
console.log(chalk22.dim(` Adapter: ${agent.adapterType} | Model: ${agent.adapterConfig.model ?? "default"}`));
|
|
323319
323100
|
if (agent.description) {
|
|
323320
|
-
console.log(
|
|
323101
|
+
console.log(chalk22.dim(` ${agent.description}`));
|
|
323321
323102
|
}
|
|
323322
323103
|
} finally {
|
|
323323
323104
|
store.close();
|
|
@@ -323336,7 +323117,7 @@ async function cmdNewAgent(args, session) {
|
|
|
323336
323117
|
validate: (v) => v.trim().length === 0 ? "Name is required" : void 0
|
|
323337
323118
|
});
|
|
323338
323119
|
if (p5.isCancel(result)) {
|
|
323339
|
-
console.log(
|
|
323120
|
+
console.log(chalk22.dim("Cancelled."));
|
|
323340
323121
|
return;
|
|
323341
323122
|
}
|
|
323342
323123
|
agentName = result;
|
|
@@ -323350,7 +323131,7 @@ async function cmdNewAgent(args, session) {
|
|
|
323350
323131
|
]
|
|
323351
323132
|
});
|
|
323352
323133
|
if (p5.isCancel(adapterResult)) {
|
|
323353
|
-
console.log(
|
|
323134
|
+
console.log(chalk22.dim("Cancelled."));
|
|
323354
323135
|
return;
|
|
323355
323136
|
}
|
|
323356
323137
|
adapter = adapterResult;
|
|
@@ -323359,7 +323140,7 @@ async function cmdNewAgent(args, session) {
|
|
|
323359
323140
|
placeholder: "claude-sonnet-4-20250514"
|
|
323360
323141
|
});
|
|
323361
323142
|
if (p5.isCancel(modelResult)) {
|
|
323362
|
-
console.log(
|
|
323143
|
+
console.log(chalk22.dim("Cancelled."));
|
|
323363
323144
|
return;
|
|
323364
323145
|
}
|
|
323365
323146
|
model = modelResult;
|
|
@@ -323370,7 +323151,7 @@ async function cmdNewAgent(args, session) {
|
|
|
323370
323151
|
if (!p5.isCancel(descResult)) {
|
|
323371
323152
|
description = descResult || void 0;
|
|
323372
323153
|
}
|
|
323373
|
-
const id =
|
|
323154
|
+
const id = randomUUID67();
|
|
323374
323155
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
323375
323156
|
const agentConfig = {
|
|
323376
323157
|
id,
|
|
@@ -323385,24 +323166,24 @@ async function cmdNewAgent(args, session) {
|
|
|
323385
323166
|
const store = await getStore();
|
|
323386
323167
|
try {
|
|
323387
323168
|
store.createAgent(agentConfig);
|
|
323388
|
-
console.log(
|
|
323169
|
+
console.log(chalk22.green(`Agent '${agentName}' created.`));
|
|
323389
323170
|
session.activeAgent = agentConfig;
|
|
323390
323171
|
session.conversationHistory = [];
|
|
323391
323172
|
session.totalTokensIn = 0;
|
|
323392
323173
|
session.totalTokensOut = 0;
|
|
323393
323174
|
session.totalCostUsd = 0;
|
|
323394
323175
|
session.totalToolCalls = 0;
|
|
323395
|
-
console.log(
|
|
323176
|
+
console.log(chalk22.dim(`Activated agent: ${agentName}`));
|
|
323396
323177
|
refreshAgentNameCache(session);
|
|
323397
323178
|
} catch (err) {
|
|
323398
|
-
console.error(
|
|
323179
|
+
console.error(chalk22.red("Failed to create agent:"), err instanceof Error ? err.message : String(err));
|
|
323399
323180
|
} finally {
|
|
323400
323181
|
store.close();
|
|
323401
323182
|
}
|
|
323402
323183
|
}
|
|
323403
323184
|
async function cmdRunAgent(args, session) {
|
|
323404
323185
|
if (args.length < 2) {
|
|
323405
|
-
console.log(
|
|
323186
|
+
console.log(chalk22.yellow("Usage: /run <agent-name> <task>"));
|
|
323406
323187
|
return;
|
|
323407
323188
|
}
|
|
323408
323189
|
const agentName = args[0];
|
|
@@ -323411,11 +323192,11 @@ async function cmdRunAgent(args, session) {
|
|
|
323411
323192
|
try {
|
|
323412
323193
|
const agent = store.getAgentByName(agentName);
|
|
323413
323194
|
if (!agent) {
|
|
323414
|
-
console.log(
|
|
323195
|
+
console.log(chalk22.red(`Agent '${agentName}' not found.`));
|
|
323415
323196
|
return;
|
|
323416
323197
|
}
|
|
323417
|
-
console.log(
|
|
323418
|
-
console.log(
|
|
323198
|
+
console.log(chalk22.cyan(`Running agent '${agentName}' on task...`));
|
|
323199
|
+
console.log(chalk22.dim(` Task: ${task}`));
|
|
323419
323200
|
console.log("");
|
|
323420
323201
|
await executeAgentTask(agent, task, session);
|
|
323421
323202
|
} finally {
|
|
@@ -323424,13 +323205,13 @@ async function cmdRunAgent(args, session) {
|
|
|
323424
323205
|
}
|
|
323425
323206
|
function cmdSwitchModel(args, session) {
|
|
323426
323207
|
if (!session.activeAgent) {
|
|
323427
|
-
console.log(
|
|
323208
|
+
console.log(chalk22.yellow("No agent active. Use /use <name> to activate one first."));
|
|
323428
323209
|
return;
|
|
323429
323210
|
}
|
|
323430
323211
|
if (args.length === 0) {
|
|
323431
323212
|
const current = session.activeAgent.adapterConfig.model ?? "default";
|
|
323432
|
-
console.log(
|
|
323433
|
-
console.log(
|
|
323213
|
+
console.log(chalk22.dim(`Current model: ${chalk22.bold(current)}`));
|
|
323214
|
+
console.log(chalk22.dim("Usage: /model <model-name>"));
|
|
323434
323215
|
return;
|
|
323435
323216
|
}
|
|
323436
323217
|
const newModel = args.join(" ");
|
|
@@ -323442,16 +323223,16 @@ function cmdSwitchModel(args, session) {
|
|
|
323442
323223
|
const hotSwap = runtime.getHotSwap();
|
|
323443
323224
|
const result = hotSwap.swap(newAdapter, `user requested /model ${newModel}`);
|
|
323444
323225
|
session.activeAgent.adapterConfig.model = newModel;
|
|
323445
|
-
console.log(
|
|
323226
|
+
console.log(chalk22.green(`Model hot-swapped: ${chalk22.dim(result.previous)} ${chalk22.bold("\u2192")} ${chalk22.bold(result.current)}`));
|
|
323446
323227
|
return;
|
|
323447
323228
|
} catch (err) {
|
|
323448
323229
|
const msg = err instanceof Error ? err.message : String(err);
|
|
323449
|
-
console.log(
|
|
323450
|
-
console.log(
|
|
323230
|
+
console.log(chalk22.yellow(`Hot-swap unavailable: ${msg}`));
|
|
323231
|
+
console.log(chalk22.dim("Falling back to config-level switch (takes effect on next request)."));
|
|
323451
323232
|
}
|
|
323452
323233
|
}
|
|
323453
323234
|
session.activeAgent.adapterConfig.model = newModel;
|
|
323454
|
-
console.log(
|
|
323235
|
+
console.log(chalk22.green(`Model switched to ${chalk22.bold(newModel)} (takes effect on next request)`));
|
|
323455
323236
|
}
|
|
323456
323237
|
async function cmdListTools() {
|
|
323457
323238
|
try {
|
|
@@ -323461,16 +323242,16 @@ async function cmdListTools() {
|
|
|
323461
323242
|
agentModule.registerBuiltinTools(tools);
|
|
323462
323243
|
const allTools = tools.list();
|
|
323463
323244
|
if (allTools.length === 0) {
|
|
323464
|
-
console.log(
|
|
323245
|
+
console.log(chalk22.yellow("No tools registered."));
|
|
323465
323246
|
return;
|
|
323466
323247
|
}
|
|
323467
323248
|
console.log("");
|
|
323468
|
-
console.log(
|
|
323469
|
-
console.log(
|
|
323249
|
+
console.log(chalk22.bold("Available Tools"));
|
|
323250
|
+
console.log(chalk22.dim("\u2500".repeat(50)));
|
|
323470
323251
|
for (const tool of allTools) {
|
|
323471
323252
|
const name = typeof tool === "string" ? tool : tool.name;
|
|
323472
323253
|
const desc = typeof tool === "string" ? "" : tool.description ?? "";
|
|
323473
|
-
console.log(` ${
|
|
323254
|
+
console.log(` ${chalk22.cyan(name)}${desc ? " " + chalk22.dim(desc) : ""}`);
|
|
323474
323255
|
}
|
|
323475
323256
|
console.log("");
|
|
323476
323257
|
return;
|
|
@@ -323481,14 +323262,14 @@ async function cmdListTools() {
|
|
|
323481
323262
|
try {
|
|
323482
323263
|
const skills = store.listSkills();
|
|
323483
323264
|
if (skills.length === 0) {
|
|
323484
|
-
console.log(
|
|
323265
|
+
console.log(chalk22.yellow("No tools available. Install skills to add tools."));
|
|
323485
323266
|
return;
|
|
323486
323267
|
}
|
|
323487
323268
|
console.log("");
|
|
323488
|
-
console.log(
|
|
323489
|
-
console.log(
|
|
323269
|
+
console.log(chalk22.bold("Available Tools (from installed skills)"));
|
|
323270
|
+
console.log(chalk22.dim("\u2500".repeat(50)));
|
|
323490
323271
|
for (const skill of skills) {
|
|
323491
|
-
console.log(` ${
|
|
323272
|
+
console.log(` ${chalk22.cyan(skill.name)} ${chalk22.dim(`v${skill.version}`)}`);
|
|
323492
323273
|
}
|
|
323493
323274
|
console.log("");
|
|
323494
323275
|
} finally {
|
|
@@ -323498,22 +323279,22 @@ async function cmdListTools() {
|
|
|
323498
323279
|
function cmdApprove(args, session) {
|
|
323499
323280
|
const validModes = ["off", "smart", "manual"];
|
|
323500
323281
|
if (args.length === 0) {
|
|
323501
|
-
console.log(`Approval mode: ${
|
|
323502
|
-
console.log(
|
|
323282
|
+
console.log(`Approval mode: ${chalk22.bold(session.approvalMode)}`);
|
|
323283
|
+
console.log(chalk22.dim(`Usage: /approve ${validModes.join("|")}`));
|
|
323503
323284
|
return;
|
|
323504
323285
|
}
|
|
323505
323286
|
const mode = args[0].toLowerCase();
|
|
323506
323287
|
if (!validModes.includes(mode)) {
|
|
323507
|
-
console.log(
|
|
323508
|
-
console.log(
|
|
323288
|
+
console.log(chalk22.red(`Invalid mode: ${mode}`));
|
|
323289
|
+
console.log(chalk22.dim(`Valid modes: ${validModes.join(", ")}`));
|
|
323509
323290
|
return;
|
|
323510
323291
|
}
|
|
323511
323292
|
session.approvalMode = mode;
|
|
323512
|
-
console.log(
|
|
323293
|
+
console.log(chalk22.green(`Approval mode set to ${chalk22.bold(mode)}`));
|
|
323513
323294
|
}
|
|
323514
323295
|
function cmdBack(session) {
|
|
323515
323296
|
if (session.conversationHistory.length < 2) {
|
|
323516
|
-
console.log(
|
|
323297
|
+
console.log(chalk22.yellow("Nothing to undo."));
|
|
323517
323298
|
return;
|
|
323518
323299
|
}
|
|
323519
323300
|
const last2 = session.conversationHistory[session.conversationHistory.length - 1];
|
|
@@ -323530,8 +323311,8 @@ function cmdBack(session) {
|
|
|
323530
323311
|
} else {
|
|
323531
323312
|
session.llmMessages = [];
|
|
323532
323313
|
}
|
|
323533
|
-
console.log(
|
|
323534
|
-
console.log(
|
|
323314
|
+
console.log(chalk22.green("Undid last message pair."));
|
|
323315
|
+
console.log(chalk22.dim(`History now has ${session.conversationHistory.length} entries.`));
|
|
323535
323316
|
}
|
|
323536
323317
|
function cmdFork(session) {
|
|
323537
323318
|
const forkName = `fork-${session.forks.length + 1}`;
|
|
@@ -323541,8 +323322,8 @@ function cmdFork(session) {
|
|
|
323541
323322
|
llmMessages: [...session.llmMessages],
|
|
323542
323323
|
timestamp: Date.now()
|
|
323543
323324
|
});
|
|
323544
|
-
console.log(
|
|
323545
|
-
console.log(
|
|
323325
|
+
console.log(chalk22.green(`Conversation forked as "${forkName}".`));
|
|
323326
|
+
console.log(chalk22.dim(`You now have ${session.forks.length} saved fork(s). Continue chatting from this point.`));
|
|
323546
323327
|
}
|
|
323547
323328
|
function cmdExport(args, session) {
|
|
323548
323329
|
exportConversation(args, session, NESTOR_DIR);
|
|
@@ -323560,7 +323341,7 @@ async function executeAgentTask(agent, prompt, session) {
|
|
|
323560
323341
|
const abortController = new AbortController();
|
|
323561
323342
|
session.abortController = abortController;
|
|
323562
323343
|
session.lastResponseStartMs = Date.now();
|
|
323563
|
-
const spinner3 = createSpinner(`${
|
|
323344
|
+
const spinner3 = createSpinner(`${chalk22.dim("Thinking...")}`);
|
|
323564
323345
|
spinner3.start();
|
|
323565
323346
|
try {
|
|
323566
323347
|
const agentModule = await importAgentModule();
|
|
@@ -323577,7 +323358,7 @@ Agent execution is not yet connected. The agent runtime will process your messag
|
|
|
323577
323358
|
|
|
323578
323359
|
Connect the LLM adapter to enable real responses.`;
|
|
323579
323360
|
console.log("");
|
|
323580
|
-
console.log(
|
|
323361
|
+
console.log(chalk22.white(placeholderResponse));
|
|
323581
323362
|
console.log("");
|
|
323582
323363
|
const simTokensIn = Math.floor(prompt.length * 1.3);
|
|
323583
323364
|
const simTokensOut = Math.floor(placeholderResponse.length * 1.1);
|
|
@@ -323599,7 +323380,7 @@ Connect the LLM adapter to enable real responses.`;
|
|
|
323599
323380
|
spinner3.fail("Aborted by user");
|
|
323600
323381
|
} else {
|
|
323601
323382
|
spinner3.fail("Error");
|
|
323602
|
-
console.error(
|
|
323383
|
+
console.error(chalk22.red(err instanceof Error ? err.message : String(err)));
|
|
323603
323384
|
}
|
|
323604
323385
|
} finally {
|
|
323605
323386
|
session.abortController = null;
|
|
@@ -323614,7 +323395,7 @@ async function runWithAgentRuntime(agentModule, agent, prompt, session, abortCon
|
|
|
323614
323395
|
const modelId = agent.adapterConfig.model ?? "claude-sonnet-4-20250514";
|
|
323615
323396
|
adapter = router.resolve(modelId);
|
|
323616
323397
|
} catch {
|
|
323617
|
-
console.log(
|
|
323398
|
+
console.log(chalk22.yellow("Could not initialize LLM adapter. Is the API key configured?"));
|
|
323618
323399
|
return;
|
|
323619
323400
|
}
|
|
323620
323401
|
const events = new RuntimeEventBus2();
|
|
@@ -323647,9 +323428,9 @@ async function runWithAgentRuntime(agentModule, agent, prompt, session, abortCon
|
|
|
323647
323428
|
session.currentRuntime = runtime;
|
|
323648
323429
|
session.currentRouter = router;
|
|
323649
323430
|
events.on("budget:warning", (payload) => {
|
|
323650
|
-
process.stdout.write("\n" +
|
|
323431
|
+
process.stdout.write("\n" + chalk22.yellow(` Budget warning: ${payload.usedPct.toFixed(0)}% used`) + "\n");
|
|
323651
323432
|
});
|
|
323652
|
-
const taskId =
|
|
323433
|
+
const taskId = randomUUID67();
|
|
323653
323434
|
console.log("");
|
|
323654
323435
|
let streamedOutput = "";
|
|
323655
323436
|
let receivedFirstToken = false;
|
|
@@ -323672,7 +323453,7 @@ async function runWithAgentRuntime(agentModule, agent, prompt, session, abortCon
|
|
|
323672
323453
|
process.stdout.write("\n");
|
|
323673
323454
|
}
|
|
323674
323455
|
process.stdout.write(
|
|
323675
|
-
|
|
323456
|
+
chalk22.dim(" ") + chalk22.yellow("\u25B6") + chalk22.dim(" Calling ") + chalk22.yellow.bold(event.name) + chalk22.dim("...") + "\n"
|
|
323676
323457
|
);
|
|
323677
323458
|
break;
|
|
323678
323459
|
case "tool_result": {
|
|
@@ -323680,32 +323461,32 @@ async function runWithAgentRuntime(agentModule, agent, prompt, session, abortCon
|
|
|
323680
323461
|
const toolOutput = event.result ?? "";
|
|
323681
323462
|
if (event.success) {
|
|
323682
323463
|
process.stdout.write(
|
|
323683
|
-
|
|
323464
|
+
chalk22.dim(" ") + chalk22.green("\u2714") + chalk22.dim(" ") + chalk22.yellow.bold(event.name) + chalk22.green(" completed") + "\n"
|
|
323684
323465
|
);
|
|
323685
323466
|
formatToolOutput(event.name, toolOutput);
|
|
323686
323467
|
} else {
|
|
323687
323468
|
process.stdout.write(
|
|
323688
|
-
|
|
323469
|
+
chalk22.dim(" ") + chalk22.red("\u2718") + chalk22.dim(" ") + chalk22.yellow.bold(event.name) + chalk22.red(" failed") + "\n"
|
|
323689
323470
|
);
|
|
323690
323471
|
if (toolOutput) {
|
|
323691
323472
|
const preview = toolOutput.length > 200 ? toolOutput.substring(0, 200) + "..." : toolOutput;
|
|
323692
|
-
process.stdout.write(
|
|
323473
|
+
process.stdout.write(chalk22.dim(" ") + chalk22.red(preview) + "\n");
|
|
323693
323474
|
}
|
|
323694
323475
|
}
|
|
323695
323476
|
receivedFirstToken = false;
|
|
323696
323477
|
break;
|
|
323697
323478
|
}
|
|
323698
323479
|
case "thinking":
|
|
323699
|
-
process.stdout.write(
|
|
323480
|
+
process.stdout.write(chalk22.dim.italic(event.text));
|
|
323700
323481
|
break;
|
|
323701
323482
|
case "reasoning":
|
|
323702
323483
|
if (session.verbose) {
|
|
323703
323484
|
const entry = event.entry;
|
|
323704
323485
|
if (entry?.reasoning) {
|
|
323705
|
-
const phaseTag = entry.phase ?
|
|
323706
|
-
const confTag = entry.confidence != null ?
|
|
323486
|
+
const phaseTag = entry.phase ? chalk22.dim(`[${entry.phase}] `) : "";
|
|
323487
|
+
const confTag = entry.confidence != null ? chalk22.dim(` (${(entry.confidence * 100).toFixed(0)}%)`) : "";
|
|
323707
323488
|
process.stdout.write(
|
|
323708
|
-
|
|
323489
|
+
chalk22.dim.italic(`
|
|
323709
323490
|
\u{1F4AD} ${phaseTag}${entry.reasoning}${confTag}
|
|
323710
323491
|
`)
|
|
323711
323492
|
);
|
|
@@ -323716,7 +323497,7 @@ async function runWithAgentRuntime(agentModule, agent, prompt, session, abortCon
|
|
|
323716
323497
|
if (receivedFirstToken) {
|
|
323717
323498
|
process.stdout.write("\n");
|
|
323718
323499
|
}
|
|
323719
|
-
process.stdout.write(
|
|
323500
|
+
process.stdout.write(chalk22.red("Error: ") + event.message + "\n");
|
|
323720
323501
|
break;
|
|
323721
323502
|
case "done": {
|
|
323722
323503
|
const result = event.result;
|
|
@@ -323734,9 +323515,9 @@ async function runWithAgentRuntime(agentModule, agent, prompt, session, abortCon
|
|
|
323734
323515
|
});
|
|
323735
323516
|
session.llmMessages = runtime.getMessages().filter((m) => m.role !== "system");
|
|
323736
323517
|
if (result.exitReason !== "completed") {
|
|
323737
|
-
console.log(
|
|
323518
|
+
console.log(chalk22.yellow(`Exit reason: ${result.exitReason}`));
|
|
323738
323519
|
if (result.error) {
|
|
323739
|
-
console.log(
|
|
323520
|
+
console.log(chalk22.red(`Error: ${result.error}`));
|
|
323740
323521
|
}
|
|
323741
323522
|
}
|
|
323742
323523
|
const turnTokens = result.usage.inputTokens + result.usage.outputTokens;
|
|
@@ -323758,177 +323539,9 @@ async function runWithAgentRuntime(agentModule, agent, prompt, session, abortCon
|
|
|
323758
323539
|
function cmdToggleVerbose(session) {
|
|
323759
323540
|
session.verbose = !session.verbose;
|
|
323760
323541
|
if (session.verbose) {
|
|
323761
|
-
console.log(
|
|
323542
|
+
console.log(chalk22.green("Verbose mode: ON") + chalk22.dim(" \u2014 Reasoning steps will be shown during agent runs."));
|
|
323762
323543
|
} else {
|
|
323763
|
-
console.log(
|
|
323764
|
-
}
|
|
323765
|
-
}
|
|
323766
|
-
async function askSingleKey(prompt, rl) {
|
|
323767
|
-
return new Promise((res) => {
|
|
323768
|
-
process.stdout.write(prompt);
|
|
323769
|
-
rl.once("line", (line) => {
|
|
323770
|
-
res(line.trim().toLowerCase());
|
|
323771
|
-
});
|
|
323772
|
-
});
|
|
323773
|
-
}
|
|
323774
|
-
async function cmdPairMode(args, session, rl) {
|
|
323775
|
-
if (args.length === 0) {
|
|
323776
|
-
console.log(chalk21.yellow("Usage: /pair <task description>"));
|
|
323777
|
-
return;
|
|
323778
|
-
}
|
|
323779
|
-
if (!session.activeAgent) {
|
|
323780
|
-
console.log(chalk21.yellow("No agent active. Use /use <name> first."));
|
|
323781
|
-
return;
|
|
323782
|
-
}
|
|
323783
|
-
const task = args.join(" ");
|
|
323784
|
-
const agent = session.activeAgent;
|
|
323785
|
-
console.log(chalk21.cyan("\n\u{1F4CB} Planning...\n"));
|
|
323786
|
-
const agentModule = await importAgentModule();
|
|
323787
|
-
if (!agentModule) {
|
|
323788
|
-
console.log(chalk21.yellow("Agent runtime not available. Cannot use pair mode."));
|
|
323789
|
-
return;
|
|
323790
|
-
}
|
|
323791
|
-
const { AgentRuntime: AgentRuntime2, RuntimeEventBus: RuntimeEventBus2, ToolRegistry: ToolRegistry4, ToolExecutor: ToolExecutor2, registerBuiltinTools: registerBuiltinTools2 } = agentModule;
|
|
323792
|
-
let llmAdapter;
|
|
323793
|
-
try {
|
|
323794
|
-
const router = await agentModule.createDefaultRouter();
|
|
323795
|
-
const modelId = agent.adapterConfig.model ?? "claude-sonnet-4-20250514";
|
|
323796
|
-
llmAdapter = router.resolve(modelId);
|
|
323797
|
-
} catch {
|
|
323798
|
-
console.log(chalk21.yellow("Could not initialize LLM adapter."));
|
|
323799
|
-
return;
|
|
323800
|
-
}
|
|
323801
|
-
let DryRunInterceptorCls;
|
|
323802
|
-
try {
|
|
323803
|
-
const mod2 = await Promise.resolve().then(() => (init_src5(), src_exports5));
|
|
323804
|
-
DryRunInterceptorCls = mod2.DryRunInterceptor;
|
|
323805
|
-
} catch {
|
|
323806
|
-
console.log(chalk21.yellow("DryRunInterceptor not available."));
|
|
323807
|
-
return;
|
|
323808
|
-
}
|
|
323809
|
-
const events = new RuntimeEventBus2();
|
|
323810
|
-
const tools = new ToolRegistry4();
|
|
323811
|
-
registerBuiltinTools2(tools);
|
|
323812
|
-
const interceptor = new DryRunInterceptorCls();
|
|
323813
|
-
const dryExecutor = new ToolExecutor2();
|
|
323814
|
-
dryExecutor.execute = async (tool, rawInput, ctx) => {
|
|
323815
|
-
return interceptor.execute(tool, rawInput, ctx);
|
|
323816
|
-
};
|
|
323817
|
-
const dryRuntime = new AgentRuntime2({
|
|
323818
|
-
adapter: llmAdapter,
|
|
323819
|
-
tools,
|
|
323820
|
-
toolExecutor: dryExecutor,
|
|
323821
|
-
role: {
|
|
323822
|
-
name: agent.name,
|
|
323823
|
-
description: agent.description ?? `Agent: ${agent.name}`,
|
|
323824
|
-
instructions: agent.adapterConfig.instructions ?? "You are a helpful AI assistant.",
|
|
323825
|
-
constraints: []
|
|
323826
|
-
},
|
|
323827
|
-
workingDir: process.cwd(),
|
|
323828
|
-
events,
|
|
323829
|
-
maxIterations: 20,
|
|
323830
|
-
signal: new AbortController().signal
|
|
323831
|
-
});
|
|
323832
|
-
const taskId = randomUUID66();
|
|
323833
|
-
try {
|
|
323834
|
-
const dryResult = await dryRuntime.run({ prompt: task, agentId: agent.id, taskId });
|
|
323835
|
-
const plan = interceptor.getPlan();
|
|
323836
|
-
if (plan.length === 0) {
|
|
323837
|
-
console.log(chalk21.yellow("No tool calls planned. The agent would only respond with text."));
|
|
323838
|
-
console.log("\n" + dryResult.output + "\n");
|
|
323839
|
-
return;
|
|
323840
|
-
}
|
|
323841
|
-
console.log(chalk21.cyan.bold(`\u{1F4CB} PLAN (${plan.length} steps):`));
|
|
323842
|
-
for (const step of plan) {
|
|
323843
|
-
console.log(formatPlanStep(step));
|
|
323844
|
-
}
|
|
323845
|
-
console.log("");
|
|
323846
|
-
console.log(chalk21.dim(` Estimated cost: $${dryResult.usage.estimatedCostUsd.toFixed(4)} | Iterations: ${dryResult.iterations}`));
|
|
323847
|
-
console.log("");
|
|
323848
|
-
const choice = await askSingleKey(
|
|
323849
|
-
" " + chalk21.cyan("[E]") + "xecute all | " + chalk21.cyan("[S]") + "tep-by-step | " + chalk21.cyan("[C]") + "ancel | " + chalk21.cyan("[R]") + "e-plan > ",
|
|
323850
|
-
rl
|
|
323851
|
-
);
|
|
323852
|
-
if (choice === "c") {
|
|
323853
|
-
console.log(chalk21.dim("\n Cancelled.\n"));
|
|
323854
|
-
return;
|
|
323855
|
-
}
|
|
323856
|
-
if (choice === "r") {
|
|
323857
|
-
const feedback = await askSingleKey(chalk21.cyan(" Feedback for re-planning: "), rl);
|
|
323858
|
-
const newArgs = [...args, "\n\nUser feedback:", feedback];
|
|
323859
|
-
return cmdPairMode(newArgs, session, rl);
|
|
323860
|
-
}
|
|
323861
|
-
if (choice === "e") {
|
|
323862
|
-
console.log(chalk21.cyan("\n Executing all steps...\n"));
|
|
323863
|
-
await executeAgentTask(agent, task, session);
|
|
323864
|
-
return;
|
|
323865
|
-
}
|
|
323866
|
-
console.log(chalk21.cyan("\n Step-by-step execution:\n"));
|
|
323867
|
-
const realTools = new ToolRegistry4();
|
|
323868
|
-
registerBuiltinTools2(realTools);
|
|
323869
|
-
const realExecutor = new ToolExecutor2();
|
|
323870
|
-
for (let i = 0; i < plan.length; i++) {
|
|
323871
|
-
const step = plan[i];
|
|
323872
|
-
console.log(chalk21.cyan.bold(`
|
|
323873
|
-
Step ${i + 1}/${plan.length}: ${step.toolName}`));
|
|
323874
|
-
if (step.toolName === "file_write" && step.args.path) {
|
|
323875
|
-
showDiffForStep(String(step.args.path), String(step.args.content ?? ""));
|
|
323876
|
-
} else if (step.toolName === "shell_exec") {
|
|
323877
|
-
console.log(chalk21.dim(` Command: ${chalk21.white(String(step.args.command ?? ""))}`));
|
|
323878
|
-
} else {
|
|
323879
|
-
console.log(chalk21.dim(` Args: ${JSON.stringify(step.args).slice(0, 200)}`));
|
|
323880
|
-
}
|
|
323881
|
-
const decision = await askSingleKey(
|
|
323882
|
-
" " + chalk21.cyan("[A]") + "ccept " + chalk21.cyan("[R]") + "eject " + chalk21.cyan("[M]") + "odify " + chalk21.cyan("[F]") + "eedback " + chalk21.cyan("[S]") + "kip > ",
|
|
323883
|
-
rl
|
|
323884
|
-
);
|
|
323885
|
-
const tool = realTools.get(step.toolName);
|
|
323886
|
-
const toolCtx = { agentId: agent.id, taskId, workingDir: process.cwd() };
|
|
323887
|
-
switch (decision) {
|
|
323888
|
-
case "a": {
|
|
323889
|
-
if (!tool) {
|
|
323890
|
-
console.log(chalk21.red(` Tool '${step.toolName}' not found.`));
|
|
323891
|
-
break;
|
|
323892
|
-
}
|
|
323893
|
-
const result = await realExecutor.execute(tool, step.args, toolCtx);
|
|
323894
|
-
console.log(result.isError ? chalk21.red(` \u2717 Error: ${result.output.slice(0, 200)}`) : chalk21.green(` \u2713 Done: ${result.output.slice(0, 200)}`));
|
|
323895
|
-
break;
|
|
323896
|
-
}
|
|
323897
|
-
case "r":
|
|
323898
|
-
console.log(chalk21.red(" \u2717 Rejected"));
|
|
323899
|
-
break;
|
|
323900
|
-
case "m": {
|
|
323901
|
-
if (!tool) {
|
|
323902
|
-
console.log(chalk21.red(` Tool '${step.toolName}' not found.`));
|
|
323903
|
-
break;
|
|
323904
|
-
}
|
|
323905
|
-
const modStr = await askSingleKey(chalk21.cyan(` Modified args JSON: `), rl);
|
|
323906
|
-
let modArgs = step.args;
|
|
323907
|
-
try {
|
|
323908
|
-
if (modStr.trim()) modArgs = JSON.parse(modStr);
|
|
323909
|
-
} catch {
|
|
323910
|
-
console.log(chalk21.yellow(" Invalid JSON, using original."));
|
|
323911
|
-
}
|
|
323912
|
-
const modResult = await realExecutor.execute(tool, modArgs, toolCtx);
|
|
323913
|
-
console.log(modResult.isError ? chalk21.red(` \u2717 Error: ${modResult.output.slice(0, 200)}`) : chalk21.green(` \u2713 Done: ${modResult.output.slice(0, 200)}`));
|
|
323914
|
-
break;
|
|
323915
|
-
}
|
|
323916
|
-
case "f": {
|
|
323917
|
-
const fb = await askSingleKey(chalk21.cyan(" Feedback: "), rl);
|
|
323918
|
-
console.log(chalk21.dim(` Noted: "${fb}"`));
|
|
323919
|
-
break;
|
|
323920
|
-
}
|
|
323921
|
-
case "s":
|
|
323922
|
-
console.log(chalk21.yellow(" \u23ED Skipped"));
|
|
323923
|
-
break;
|
|
323924
|
-
default:
|
|
323925
|
-
console.log(chalk21.yellow(" \u23ED Skipped"));
|
|
323926
|
-
break;
|
|
323927
|
-
}
|
|
323928
|
-
}
|
|
323929
|
-
console.log(chalk21.green("\n\u2705 Pair programming session complete.\n"));
|
|
323930
|
-
} catch (err) {
|
|
323931
|
-
console.error(chalk21.red("Pair mode error:"), err instanceof Error ? err.message : String(err));
|
|
323544
|
+
console.log(chalk22.yellow("Verbose mode: OFF") + chalk22.dim(" \u2014 Reasoning steps will be hidden."));
|
|
323932
323545
|
}
|
|
323933
323546
|
}
|
|
323934
323547
|
async function cmdAnnotate2(args, session) {
|
|
@@ -324010,6 +323623,7 @@ var init_shell = __esm({
|
|
|
324010
323623
|
init_handoffs_commands();
|
|
324011
323624
|
init_prompt_command();
|
|
324012
323625
|
init_plan_undo_commands();
|
|
323626
|
+
init_pair_command();
|
|
324013
323627
|
init_replay_command();
|
|
324014
323628
|
NESTOR_DIR = getNestorHome2();
|
|
324015
323629
|
HISTORY_FILE = join31(NESTOR_DIR, "shell_history");
|
|
@@ -324103,7 +323717,7 @@ var BANNER = `
|
|
|
324103
323717
|
function registerStartCommand(program2) {
|
|
324104
323718
|
program2.command("start").description("Start the Nestor server").option("-p, --port <port>", "Server port").option("-H, --host <host>", "Server host").option("--no-studio", "Disable the Studio web UI").action(async (options) => {
|
|
324105
323719
|
console.log(chalk.cyan(BANNER));
|
|
324106
|
-
console.log(chalk.dim(` v3.5.
|
|
323720
|
+
console.log(chalk.dim(` v3.5.2
|
|
324107
323721
|
`));
|
|
324108
323722
|
let config2 = readConfigFile();
|
|
324109
323723
|
if (!config2) {
|
|
@@ -326100,7 +325714,7 @@ import {
|
|
|
326100
325714
|
import { join as join32 } from "node:path";
|
|
326101
325715
|
import { fork as fork2, execSync as execSync3 } from "node:child_process";
|
|
326102
325716
|
import "node:readline";
|
|
326103
|
-
import
|
|
325717
|
+
import chalk23 from "chalk";
|
|
326104
325718
|
function desktopNotify(title, message) {
|
|
326105
325719
|
try {
|
|
326106
325720
|
if (process.platform === "win32") {
|
|
@@ -326150,26 +325764,26 @@ function registerDaemonCommand(program2) {
|
|
|
326150
325764
|
async function startForeground() {
|
|
326151
325765
|
const existingPid = readPid();
|
|
326152
325766
|
if (existingPid && isProcessAlive(existingPid)) {
|
|
326153
|
-
console.log(
|
|
326154
|
-
console.log(
|
|
325767
|
+
console.log(chalk23.yellow(`Daemon is already running (PID: ${existingPid}).`));
|
|
325768
|
+
console.log(chalk23.dim("Use `npx nestor-sh daemon stop` to stop it first."));
|
|
326155
325769
|
return;
|
|
326156
325770
|
}
|
|
326157
325771
|
ensureDirs();
|
|
326158
325772
|
writePid(process.pid);
|
|
326159
325773
|
console.log("");
|
|
326160
|
-
console.log(
|
|
326161
|
-
console.log(
|
|
326162
|
-
console.log(
|
|
326163
|
-
console.log(
|
|
325774
|
+
console.log(chalk23.cyan(` _ _ ___ ___ _____ ___ ___ ___ _ _`));
|
|
325775
|
+
console.log(chalk23.cyan(` | \\| | | __| / __| |_ _| / _ \\ | _ \\ / __| | || |`));
|
|
325776
|
+
console.log(chalk23.cyan(` | .\` | | _| \\__ \\ | | | (_) | | / _ \\__ \\ | __ |`));
|
|
325777
|
+
console.log(chalk23.cyan(` |_|\\_| |___| |___/ |_| \\___/ |_|_\\ (_) |___/ |_||_|`));
|
|
326164
325778
|
console.log("");
|
|
326165
|
-
console.log(
|
|
326166
|
-
console.log(
|
|
326167
|
-
console.log(
|
|
325779
|
+
console.log(chalk23.dim(" Daemon Mode \u2014 v3.5.2"));
|
|
325780
|
+
console.log(chalk23.dim(` PID: ${process.pid}`));
|
|
325781
|
+
console.log(chalk23.dim(` Log: ${LOG_FILE}`));
|
|
326168
325782
|
console.log("");
|
|
326169
325783
|
const daemonRunner = new DaemonRunner();
|
|
326170
325784
|
const shutdown = async (signal) => {
|
|
326171
325785
|
daemonLog(`Received ${signal}, shutting down...`);
|
|
326172
|
-
console.log(
|
|
325786
|
+
console.log(chalk23.yellow(`
|
|
326173
325787
|
Received ${signal}. Shutting down gracefully...`));
|
|
326174
325788
|
await daemonRunner.stop();
|
|
326175
325789
|
cleanupPid();
|
|
@@ -326182,8 +325796,8 @@ Received ${signal}. Shutting down gracefully...`));
|
|
|
326182
325796
|
async function startDetached() {
|
|
326183
325797
|
const existingPid = readPid();
|
|
326184
325798
|
if (existingPid && isProcessAlive(existingPid)) {
|
|
326185
|
-
console.log(
|
|
326186
|
-
console.log(
|
|
325799
|
+
console.log(chalk23.yellow(`Daemon is already running (PID: ${existingPid}).`));
|
|
325800
|
+
console.log(chalk23.dim("Use `npx nestor-sh daemon stop` to stop it first."));
|
|
326187
325801
|
return;
|
|
326188
325802
|
}
|
|
326189
325803
|
ensureDirs();
|
|
@@ -326197,22 +325811,22 @@ async function startDetached() {
|
|
|
326197
325811
|
child.unref();
|
|
326198
325812
|
if (child.pid) {
|
|
326199
325813
|
writePid(child.pid);
|
|
326200
|
-
console.log(
|
|
326201
|
-
console.log(
|
|
326202
|
-
console.log(
|
|
325814
|
+
console.log(chalk23.green(`Daemon started in background (PID: ${child.pid}).`));
|
|
325815
|
+
console.log(chalk23.dim(` Logs: ${LOG_FILE}`));
|
|
325816
|
+
console.log(chalk23.dim(` Stop: npx nestor-sh daemon stop`));
|
|
326203
325817
|
} else {
|
|
326204
|
-
console.error(
|
|
325818
|
+
console.error(chalk23.red("Failed to start daemon process."));
|
|
326205
325819
|
process.exit(1);
|
|
326206
325820
|
}
|
|
326207
325821
|
}
|
|
326208
325822
|
async function stopDaemon() {
|
|
326209
325823
|
const pid = readPid();
|
|
326210
325824
|
if (!pid) {
|
|
326211
|
-
console.log(
|
|
325825
|
+
console.log(chalk23.yellow("No daemon PID file found. Daemon is not running."));
|
|
326212
325826
|
return;
|
|
326213
325827
|
}
|
|
326214
325828
|
if (!isProcessAlive(pid)) {
|
|
326215
|
-
console.log(
|
|
325829
|
+
console.log(chalk23.yellow(`Daemon process (PID: ${pid}) is not running. Cleaning up PID file.`));
|
|
326216
325830
|
cleanupPid();
|
|
326217
325831
|
return;
|
|
326218
325832
|
}
|
|
@@ -326246,9 +325860,9 @@ async function showStatus() {
|
|
|
326246
325860
|
console.log("");
|
|
326247
325861
|
if (!pid || !alive) {
|
|
326248
325862
|
printBox([
|
|
326249
|
-
`${
|
|
326250
|
-
`Status: ${
|
|
326251
|
-
pid ?
|
|
325863
|
+
`${chalk23.bold("Nestor Daemon")}`,
|
|
325864
|
+
`Status: ${chalk23.red("STOPPED")}`,
|
|
325865
|
+
pid ? chalk23.dim(`(stale PID file: ${pid})`) : chalk23.dim("No PID file found")
|
|
326252
325866
|
]);
|
|
326253
325867
|
if (pid && !alive) {
|
|
326254
325868
|
cleanupPid();
|
|
@@ -326259,8 +325873,8 @@ async function showStatus() {
|
|
|
326259
325873
|
const uptimeStr = formatDuration(uptimeMs);
|
|
326260
325874
|
const lastBeat = heartbeat?.lastBeat ? timeSince(heartbeat.lastBeat) : "unknown";
|
|
326261
325875
|
const lines = [
|
|
326262
|
-
|
|
326263
|
-
`Status: ${
|
|
325876
|
+
chalk23.bold("Nestor Daemon"),
|
|
325877
|
+
`Status: ${chalk23.green("RUNNING")}`,
|
|
326264
325878
|
`PID: ${pid}`,
|
|
326265
325879
|
`Uptime: ${uptimeStr}`,
|
|
326266
325880
|
`Last heartbeat: ${lastBeat}`
|
|
@@ -326277,13 +325891,13 @@ async function showStatus() {
|
|
|
326277
325891
|
const agents = store.listAgents();
|
|
326278
325892
|
if (agents.length > 0) {
|
|
326279
325893
|
console.log("");
|
|
326280
|
-
console.log(
|
|
325894
|
+
console.log(chalk23.bold("Registered Agents:"));
|
|
326281
325895
|
const headers = ["Name", "Adapter", "Model", "Status"];
|
|
326282
325896
|
const rows = agents.map((a) => [
|
|
326283
325897
|
a.name,
|
|
326284
325898
|
a.adapterType,
|
|
326285
325899
|
a.adapterConfig.model ?? "-",
|
|
326286
|
-
|
|
325900
|
+
chalk23.dim("idle")
|
|
326287
325901
|
// We don't have live status without connecting to daemon
|
|
326288
325902
|
]);
|
|
326289
325903
|
printTable(headers, rows);
|
|
@@ -326295,8 +325909,8 @@ async function showStatus() {
|
|
|
326295
325909
|
}
|
|
326296
325910
|
async function showLogs(follow, lineCount) {
|
|
326297
325911
|
if (!existsSync25(LOG_FILE)) {
|
|
326298
|
-
console.log(
|
|
326299
|
-
console.log(
|
|
325912
|
+
console.log(chalk23.yellow("No daemon log file found."));
|
|
325913
|
+
console.log(chalk23.dim(`Expected at: ${LOG_FILE}`));
|
|
326300
325914
|
return;
|
|
326301
325915
|
}
|
|
326302
325916
|
if (!follow) {
|
|
@@ -326304,7 +325918,7 @@ async function showLogs(follow, lineCount) {
|
|
|
326304
325918
|
const lines = content.split("\n").filter((l) => l.length > 0);
|
|
326305
325919
|
const lastLines = lines.slice(-lineCount);
|
|
326306
325920
|
if (lastLines.length === 0) {
|
|
326307
|
-
console.log(
|
|
325921
|
+
console.log(chalk23.dim("(log is empty)"));
|
|
326308
325922
|
return;
|
|
326309
325923
|
}
|
|
326310
325924
|
for (const line of lastLines) {
|
|
@@ -326312,7 +325926,7 @@ async function showLogs(follow, lineCount) {
|
|
|
326312
325926
|
}
|
|
326313
325927
|
return;
|
|
326314
325928
|
}
|
|
326315
|
-
console.log(
|
|
325929
|
+
console.log(chalk23.dim(`Following ${LOG_FILE}... (Ctrl+C to stop)`));
|
|
326316
325930
|
console.log("");
|
|
326317
325931
|
if (existsSync25(LOG_FILE)) {
|
|
326318
325932
|
const content = readFileSync26(LOG_FILE, "utf-8");
|
|
@@ -326405,7 +326019,7 @@ var DaemonRunner = class {
|
|
|
326405
326019
|
}
|
|
326406
326020
|
}
|
|
326407
326021
|
daemonLog("Entering main loop");
|
|
326408
|
-
console.log(
|
|
326022
|
+
console.log(chalk23.green("Daemon is running. Press Ctrl+C to stop."));
|
|
326409
326023
|
while (this.running) {
|
|
326410
326024
|
try {
|
|
326411
326025
|
await this.tick();
|
|
@@ -326602,9 +326216,9 @@ var DaemonRunner = class {
|
|
|
326602
326216
|
try {
|
|
326603
326217
|
const store = await getStore();
|
|
326604
326218
|
try {
|
|
326605
|
-
const { randomUUID:
|
|
326219
|
+
const { randomUUID: randomUUID69 } = await import("node:crypto");
|
|
326606
326220
|
store.createRun({
|
|
326607
|
-
id:
|
|
326221
|
+
id: randomUUID69(),
|
|
326608
326222
|
workflowId: `agent:${agentId}`,
|
|
326609
326223
|
workflowVersion: 1,
|
|
326610
326224
|
status: result.exitReason === "completed" ? "completed" : "failed",
|
|
@@ -326640,9 +326254,9 @@ var DaemonRunner = class {
|
|
|
326640
326254
|
try {
|
|
326641
326255
|
const store = await getStore();
|
|
326642
326256
|
try {
|
|
326643
|
-
const { randomUUID:
|
|
326257
|
+
const { randomUUID: randomUUID69 } = await import("node:crypto");
|
|
326644
326258
|
store.createRun({
|
|
326645
|
-
id:
|
|
326259
|
+
id: randomUUID69(),
|
|
326646
326260
|
workflowId: `agent:${agentId}`,
|
|
326647
326261
|
workflowVersion: 1,
|
|
326648
326262
|
status: "failed",
|
|
@@ -326934,17 +326548,17 @@ function daemonLog(message) {
|
|
|
326934
326548
|
}
|
|
326935
326549
|
function colorizeLogLine(line) {
|
|
326936
326550
|
if (line.includes("error") || line.includes("Error") || line.includes("ERROR")) {
|
|
326937
|
-
return
|
|
326551
|
+
return chalk23.red(line);
|
|
326938
326552
|
}
|
|
326939
326553
|
if (line.includes("warn") || line.includes("Warning") || line.includes("WARN")) {
|
|
326940
|
-
return
|
|
326554
|
+
return chalk23.yellow(line);
|
|
326941
326555
|
}
|
|
326942
326556
|
if (line.includes("started") || line.includes("Started") || line.includes("completed")) {
|
|
326943
|
-
return
|
|
326557
|
+
return chalk23.green(line);
|
|
326944
326558
|
}
|
|
326945
326559
|
const match = line.match(/^(\[.*?\])\s(.*)$/);
|
|
326946
326560
|
if (match) {
|
|
326947
|
-
return
|
|
326561
|
+
return chalk23.dim(match[1]) + " " + match[2];
|
|
326948
326562
|
}
|
|
326949
326563
|
return line;
|
|
326950
326564
|
}
|
|
@@ -326997,7 +326611,7 @@ init_paths();
|
|
|
326997
326611
|
init_db();
|
|
326998
326612
|
import { existsSync as existsSync26, readFileSync as readFileSync27 } from "node:fs";
|
|
326999
326613
|
import { join as join33 } from "node:path";
|
|
327000
|
-
import
|
|
326614
|
+
import chalk24 from "chalk";
|
|
327001
326615
|
var NESTOR_DIR3 = getNestorHome2();
|
|
327002
326616
|
var HEARTBEAT_FILE2 = join33(NESTOR_DIR3, "daemon.heartbeat");
|
|
327003
326617
|
var LOG_FILE2 = join33(NESTOR_DIR3, "logs", "daemon.log");
|
|
@@ -327116,12 +326730,12 @@ function render(state) {
|
|
|
327116
326730
|
const headerText = " NESTOR MONITOR";
|
|
327117
326731
|
const timerText = `\u23F1 ${elapsed} `;
|
|
327118
326732
|
const headerPad = width - stripAnsi3(headerText).length - stripAnsi3(timerText).length;
|
|
327119
|
-
writeLn(
|
|
326733
|
+
writeLn(chalk24.bold.cyan("\u2554" + "\u2550".repeat(width) + "\u2557"));
|
|
327120
326734
|
writeLn(
|
|
327121
|
-
|
|
326735
|
+
chalk24.bold.cyan("\u2551") + chalk24.bold(headerText) + " ".repeat(Math.max(0, headerPad)) + chalk24.dim(timerText) + chalk24.bold.cyan("\u2551")
|
|
327122
326736
|
);
|
|
327123
|
-
writeLn(
|
|
327124
|
-
const daemonStatus = state.daemonRunning ?
|
|
326737
|
+
writeLn(chalk24.bold.cyan("\u2560" + "\u2550".repeat(width) + "\u2563"));
|
|
326738
|
+
const daemonStatus = state.daemonRunning ? chalk24.green("\u25CF RUNNING") + chalk24.dim(` (PID: ${state.daemonPid})`) : chalk24.red("\u25CB STOPPED");
|
|
327125
326739
|
writePadded(` Daemon: ${daemonStatus}`, width);
|
|
327126
326740
|
const totalAgents = state.agents.length;
|
|
327127
326741
|
const activeAgents = state.daemonRunning ? 0 : 0;
|
|
@@ -327132,47 +326746,47 @@ function render(state) {
|
|
|
327132
326746
|
if (agent) {
|
|
327133
326747
|
renderAgentDetail(agent, width, state);
|
|
327134
326748
|
} else {
|
|
327135
|
-
writePadded(
|
|
326749
|
+
writePadded(chalk24.yellow(` Agent '${state.focusedAgent}' not found.`), width);
|
|
327136
326750
|
}
|
|
327137
326751
|
} else {
|
|
327138
326752
|
for (const agent of state.agents) {
|
|
327139
326753
|
renderAgentRow(agent, width, state);
|
|
327140
326754
|
}
|
|
327141
326755
|
if (state.agents.length === 0) {
|
|
327142
|
-
writePadded(
|
|
326756
|
+
writePadded(chalk24.dim(" No agents registered."), width);
|
|
327143
326757
|
}
|
|
327144
326758
|
}
|
|
327145
326759
|
writePadded("", width);
|
|
327146
|
-
writePadded(
|
|
326760
|
+
writePadded(chalk24.bold(" Recent Events:"), width);
|
|
327147
326761
|
if (state.recentEvents.length === 0) {
|
|
327148
|
-
writePadded(
|
|
326762
|
+
writePadded(chalk24.dim(" (no events)"), width);
|
|
327149
326763
|
} else {
|
|
327150
326764
|
const eventsToShow = state.recentEvents.slice(-8);
|
|
327151
326765
|
for (const event of eventsToShow) {
|
|
327152
|
-
const colorFn = event.type === "error" ?
|
|
327153
|
-
const agentStr = event.agent ?
|
|
327154
|
-
const line = ` ${
|
|
326766
|
+
const colorFn = event.type === "error" ? chalk24.red : event.type === "warning" ? chalk24.yellow : event.type === "success" ? chalk24.green : chalk24.dim;
|
|
326767
|
+
const agentStr = event.agent ? chalk24.cyan(event.agent) + " \u2192 " : "";
|
|
326768
|
+
const line = ` ${chalk24.dim(event.time)} ${agentStr}${colorFn(truncate(event.message, width - 25))}`;
|
|
327155
326769
|
writePadded(line, width);
|
|
327156
326770
|
}
|
|
327157
326771
|
}
|
|
327158
|
-
writeLn(
|
|
326772
|
+
writeLn(chalk24.bold.cyan("\u2560" + "\u2550".repeat(width) + "\u2563"));
|
|
327159
326773
|
const helpText = " q:quit a:cycle agent r:refresh";
|
|
327160
|
-
writePadded(
|
|
327161
|
-
writeLn(
|
|
326774
|
+
writePadded(chalk24.dim(helpText), width);
|
|
326775
|
+
writeLn(chalk24.bold.cyan("\u255A" + "\u2550".repeat(width) + "\u255D"));
|
|
327162
326776
|
}
|
|
327163
326777
|
function renderAgentRow(agent, width, state) {
|
|
327164
|
-
const statusIcon2 = state.daemonRunning ?
|
|
327165
|
-
const statusText =
|
|
326778
|
+
const statusIcon2 = state.daemonRunning ? chalk24.dim("\u25CB") : chalk24.dim("\u25CB");
|
|
326779
|
+
const statusText = chalk24.dim("IDLE");
|
|
327166
326780
|
const model = agent.adapterConfig.model ?? "default";
|
|
327167
326781
|
const budget = agent.adapterConfig.budgetPerRunUsd;
|
|
327168
326782
|
const budgetStr = budget !== void 0 ? `$0.00/$${budget.toFixed(2)}` : "";
|
|
327169
326783
|
const nameStr = agent.name.padEnd(16).substring(0, 16);
|
|
327170
|
-
const line = ` ${nameStr} ${statusIcon2} ${statusText.padEnd(12)} ${budgetStr.padEnd(16)} ${
|
|
326784
|
+
const line = ` ${nameStr} ${statusIcon2} ${statusText.padEnd(12)} ${budgetStr.padEnd(16)} ${chalk24.dim(model)}`;
|
|
327171
326785
|
writePadded(line, width);
|
|
327172
326786
|
}
|
|
327173
326787
|
function renderAgentDetail(agent, width, state) {
|
|
327174
|
-
writePadded(
|
|
327175
|
-
writePadded(
|
|
326788
|
+
writePadded(chalk24.bold(` Agent: ${agent.name}`), width);
|
|
326789
|
+
writePadded(chalk24.dim(" " + "\u2500".repeat(width - 4)), width);
|
|
327176
326790
|
writePadded(` ID: ${agent.id}`, width);
|
|
327177
326791
|
writePadded(` Adapter: ${agent.adapterType}`, width);
|
|
327178
326792
|
writePadded(` Model: ${agent.adapterConfig.model ?? "default"}`, width);
|
|
@@ -327184,7 +326798,7 @@ function renderAgentDetail(agent, width, state) {
|
|
|
327184
326798
|
if (budget !== void 0) {
|
|
327185
326799
|
writePadded(` Budget: $${budget.toFixed(2)} per run`, width);
|
|
327186
326800
|
}
|
|
327187
|
-
writePadded(` Status: ${state.daemonRunning ?
|
|
326801
|
+
writePadded(` Status: ${state.daemonRunning ? chalk24.yellow("idle") : chalk24.dim("stopped")}`, width);
|
|
327188
326802
|
writePadded(` Created: ${agent.createdAt.substring(0, 19)}`, width);
|
|
327189
326803
|
}
|
|
327190
326804
|
function cycleAgentFocus(state) {
|
|
@@ -327207,7 +326821,7 @@ function writePadded(text7, totalWidth) {
|
|
|
327207
326821
|
const visible = stripAnsi3(text7).length;
|
|
327208
326822
|
const pad6 = Math.max(0, totalWidth - visible);
|
|
327209
326823
|
process.stdout.write(
|
|
327210
|
-
|
|
326824
|
+
chalk24.bold.cyan("\u2551") + text7 + " ".repeat(pad6) + chalk24.bold.cyan("\u2551") + "\n"
|
|
327211
326825
|
);
|
|
327212
326826
|
}
|
|
327213
326827
|
function stripAnsi3(str) {
|
|
@@ -327246,7 +326860,7 @@ function isDaemonAlive(pid) {
|
|
|
327246
326860
|
// src/commands/studio.ts
|
|
327247
326861
|
init_config2();
|
|
327248
326862
|
init_config();
|
|
327249
|
-
import
|
|
326863
|
+
import chalk25 from "chalk";
|
|
327250
326864
|
async function tryApiCall(method, path32, body) {
|
|
327251
326865
|
try {
|
|
327252
326866
|
const config2 = readConfigFile() ?? mergeWithDefaults({});
|
|
@@ -327284,22 +326898,22 @@ function registerStudioCommand(program2) {
|
|
|
327284
326898
|
const studio = program2.command("studio").description("Manage the Nestor Studio web UI");
|
|
327285
326899
|
studio.command("enable").description("Enable the Studio web UI").action(async () => {
|
|
327286
326900
|
updateConfigStudio(true);
|
|
327287
|
-
console.log(
|
|
326901
|
+
console.log(chalk25.green(" [ok]"), "Studio enabled in config file.");
|
|
327288
326902
|
const result = await tryApiCall("POST", "/api/admin/studio/toggle", { enabled: true });
|
|
327289
326903
|
if (result.ok) {
|
|
327290
|
-
console.log(
|
|
326904
|
+
console.log(chalk25.green(" [ok]"), "Running server updated (hot-reload).");
|
|
327291
326905
|
} else {
|
|
327292
|
-
console.log(
|
|
326906
|
+
console.log(chalk25.yellow(" [info]"), "Server not running or unreachable. Change will take effect on next start.");
|
|
327293
326907
|
}
|
|
327294
326908
|
});
|
|
327295
326909
|
studio.command("disable").description("Disable the Studio web UI").action(async () => {
|
|
327296
326910
|
updateConfigStudio(false);
|
|
327297
|
-
console.log(
|
|
326911
|
+
console.log(chalk25.green(" [ok]"), "Studio disabled in config file.");
|
|
327298
326912
|
const result = await tryApiCall("POST", "/api/admin/studio/toggle", { enabled: false });
|
|
327299
326913
|
if (result.ok) {
|
|
327300
|
-
console.log(
|
|
326914
|
+
console.log(chalk25.green(" [ok]"), "Running server updated (hot-reload).");
|
|
327301
326915
|
} else {
|
|
327302
|
-
console.log(
|
|
326916
|
+
console.log(chalk25.yellow(" [info]"), "Server not running or unreachable. Change will take effect on next start.");
|
|
327303
326917
|
}
|
|
327304
326918
|
});
|
|
327305
326919
|
studio.command("status").description("Show Studio status").action(async () => {
|
|
@@ -327310,25 +326924,25 @@ function registerStudioCommand(program2) {
|
|
|
327310
326924
|
const config3 = readConfigFile() ?? mergeWithDefaults({});
|
|
327311
326925
|
const url = `http://${config3.server.host}:${config3.server.port}/studio`;
|
|
327312
326926
|
console.log("");
|
|
327313
|
-
console.log(
|
|
327314
|
-
console.log(
|
|
327315
|
-
console.log(` Runtime : ${enabled ?
|
|
327316
|
-
console.log(` Config : ${config3.server.studio.enabled ?
|
|
327317
|
-
console.log(` URL : ${
|
|
326927
|
+
console.log(chalk25.bold(" Nestor Studio Status"));
|
|
326928
|
+
console.log(chalk25.dim(" \u2500".repeat(20)));
|
|
326929
|
+
console.log(` Runtime : ${enabled ? chalk25.green("enabled") : chalk25.red("disabled")}`);
|
|
326930
|
+
console.log(` Config : ${config3.server.studio.enabled ? chalk25.green("enabled") : chalk25.red("disabled")}`);
|
|
326931
|
+
console.log(` URL : ${chalk25.cyan(url)}`);
|
|
327318
326932
|
console.log("");
|
|
327319
326933
|
return;
|
|
327320
326934
|
}
|
|
327321
326935
|
const config2 = readConfigFile();
|
|
327322
326936
|
if (!config2) {
|
|
327323
|
-
console.log(
|
|
327324
|
-
console.log(
|
|
326937
|
+
console.log(chalk25.yellow(" No config file found."));
|
|
326938
|
+
console.log(chalk25.dim(" Studio is enabled by default."));
|
|
327325
326939
|
return;
|
|
327326
326940
|
}
|
|
327327
326941
|
console.log("");
|
|
327328
|
-
console.log(
|
|
327329
|
-
console.log(
|
|
327330
|
-
console.log(` Config : ${config2.server.studio.enabled ?
|
|
327331
|
-
console.log(` Server : ${
|
|
326942
|
+
console.log(chalk25.bold(" Nestor Studio Status"));
|
|
326943
|
+
console.log(chalk25.dim(" \u2500".repeat(20)));
|
|
326944
|
+
console.log(` Config : ${config2.server.studio.enabled ? chalk25.green("enabled") : chalk25.red("disabled")}`);
|
|
326945
|
+
console.log(` Server : ${chalk25.dim("not running")}`);
|
|
327332
326946
|
console.log("");
|
|
327333
326947
|
});
|
|
327334
326948
|
studio.command("open").description("Open Studio in your default browser").action(async () => {
|
|
@@ -327338,12 +326952,12 @@ function registerStudioCommand(program2) {
|
|
|
327338
326952
|
if (apiResult.ok) {
|
|
327339
326953
|
const data = apiResult.data?.data;
|
|
327340
326954
|
if (data && !data.enabled) {
|
|
327341
|
-
console.log(
|
|
327342
|
-
console.log(
|
|
326955
|
+
console.log(chalk25.yellow(" Studio is currently disabled on the running server."));
|
|
326956
|
+
console.log(chalk25.dim(" Use `npx nestor-sh studio enable` to enable it first."));
|
|
327343
326957
|
return;
|
|
327344
326958
|
}
|
|
327345
326959
|
}
|
|
327346
|
-
console.log(
|
|
326960
|
+
console.log(chalk25.green(" Opening Studio:"), chalk25.cyan(url));
|
|
327347
326961
|
try {
|
|
327348
326962
|
const { exec: exec2 } = await import("node:child_process");
|
|
327349
326963
|
const platform = process.platform;
|
|
@@ -327357,12 +326971,12 @@ function registerStudioCommand(program2) {
|
|
|
327357
326971
|
}
|
|
327358
326972
|
exec2(cmd, (err) => {
|
|
327359
326973
|
if (err) {
|
|
327360
|
-
console.log(
|
|
327361
|
-
console.log(
|
|
326974
|
+
console.log(chalk25.yellow(" Could not open browser automatically."));
|
|
326975
|
+
console.log(chalk25.dim(` Please open ${url} manually.`));
|
|
327362
326976
|
}
|
|
327363
326977
|
});
|
|
327364
326978
|
} catch {
|
|
327365
|
-
console.log(
|
|
326979
|
+
console.log(chalk25.dim(` Open ${url} in your browser.`));
|
|
327366
326980
|
}
|
|
327367
326981
|
});
|
|
327368
326982
|
}
|
|
@@ -327371,7 +326985,7 @@ function registerStudioCommand(program2) {
|
|
|
327371
326985
|
init_config();
|
|
327372
326986
|
init_config2();
|
|
327373
326987
|
init_paths();
|
|
327374
|
-
import
|
|
326988
|
+
import chalk26 from "chalk";
|
|
327375
326989
|
import fs28 from "node:fs";
|
|
327376
326990
|
import { join as join34 } from "node:path";
|
|
327377
326991
|
function registerTelemetryCommand(program2) {
|
|
@@ -327379,55 +326993,55 @@ function registerTelemetryCommand(program2) {
|
|
|
327379
326993
|
telemetry.command("on").description("Enable anonymous telemetry").action(() => {
|
|
327380
326994
|
setTelemetryEnabled(true);
|
|
327381
326995
|
console.log("");
|
|
327382
|
-
console.log(
|
|
326996
|
+
console.log(chalk26.green(" Telemetry enabled."));
|
|
327383
326997
|
console.log("");
|
|
327384
|
-
console.log(
|
|
327385
|
-
console.log(
|
|
327386
|
-
console.log(
|
|
327387
|
-
console.log(
|
|
327388
|
-
console.log(
|
|
326998
|
+
console.log(chalk26.dim(" What we collect (anonymized, aggregate only):"));
|
|
326999
|
+
console.log(chalk26.dim(" - Adapter type (claude/openai/ollama), model name"));
|
|
327000
|
+
console.log(chalk26.dim(" - Run duration, token count, tool count"));
|
|
327001
|
+
console.log(chalk26.dim(" - Exit reason, error class (no messages)"));
|
|
327002
|
+
console.log(chalk26.dim(" - OS platform, Node.js version"));
|
|
327389
327003
|
console.log("");
|
|
327390
|
-
console.log(
|
|
327391
|
-
console.log(
|
|
327004
|
+
console.log(chalk26.dim(" What we NEVER collect:"));
|
|
327005
|
+
console.log(chalk26.dim(" - API keys, file contents, prompts, personal data"));
|
|
327392
327006
|
console.log("");
|
|
327393
|
-
console.log(
|
|
327007
|
+
console.log(chalk26.dim(" Run `npx nestor-sh telemetry off` to disable at any time."));
|
|
327394
327008
|
console.log("");
|
|
327395
327009
|
});
|
|
327396
327010
|
telemetry.command("off").description("Disable anonymous telemetry").action(() => {
|
|
327397
327011
|
setTelemetryEnabled(false);
|
|
327398
327012
|
console.log("");
|
|
327399
|
-
console.log(
|
|
327400
|
-
console.log(
|
|
327013
|
+
console.log(chalk26.yellow(" Telemetry disabled."));
|
|
327014
|
+
console.log(chalk26.dim(" No data will be collected or sent."));
|
|
327401
327015
|
console.log("");
|
|
327402
327016
|
});
|
|
327403
327017
|
telemetry.command("status").description("Show current telemetry status").action(() => {
|
|
327404
327018
|
const config2 = readConfigFile();
|
|
327405
327019
|
console.log("");
|
|
327406
|
-
console.log(
|
|
327407
|
-
console.log(
|
|
327020
|
+
console.log(chalk26.bold(" Telemetry Status"));
|
|
327021
|
+
console.log(chalk26.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
327408
327022
|
if (!config2) {
|
|
327409
|
-
console.log(` ${
|
|
327410
|
-
console.log(
|
|
327023
|
+
console.log(` ${chalk26.dim("Enabled:")} ${chalk26.yellow("unknown")} (no config file)`);
|
|
327024
|
+
console.log(chalk26.dim(" Run `npx nestor-sh config init` to create a configuration."));
|
|
327411
327025
|
} else {
|
|
327412
327026
|
const enabled = config2.telemetry?.enabled ?? false;
|
|
327413
|
-
console.log(` ${
|
|
327027
|
+
console.log(` ${chalk26.dim("Enabled:")} ${enabled ? chalk26.green("true") : chalk26.dim("false (default)")}`);
|
|
327414
327028
|
if (config2.telemetry?.endpoint) {
|
|
327415
|
-
console.log(` ${
|
|
327029
|
+
console.log(` ${chalk26.dim("Endpoint:")} ${config2.telemetry.endpoint}`);
|
|
327416
327030
|
}
|
|
327417
|
-
console.log(` ${
|
|
327031
|
+
console.log(` ${chalk26.dim("Flush:")} every ${(config2.telemetry?.flushIntervalMs ?? 6e4) / 1e3}s`);
|
|
327418
327032
|
}
|
|
327419
327033
|
const telemetryFile = join34(getNestorHome2(), "telemetry.jsonl");
|
|
327420
327034
|
const idFile = join34(getNestorHome2(), "telemetry-id");
|
|
327421
327035
|
if (fs28.existsSync(idFile)) {
|
|
327422
327036
|
const installId = fs28.readFileSync(idFile, "utf-8").trim();
|
|
327423
|
-
console.log(` ${
|
|
327037
|
+
console.log(` ${chalk26.dim("Install ID:")} ${installId.slice(0, 8)}...`);
|
|
327424
327038
|
}
|
|
327425
327039
|
if (fs28.existsSync(telemetryFile)) {
|
|
327426
327040
|
const content = fs28.readFileSync(telemetryFile, "utf-8").trim();
|
|
327427
327041
|
const lineCount = content ? content.split("\n").length : 0;
|
|
327428
|
-
console.log(` ${
|
|
327042
|
+
console.log(` ${chalk26.dim("Events:")} ${lineCount} recorded locally`);
|
|
327429
327043
|
} else {
|
|
327430
|
-
console.log(` ${
|
|
327044
|
+
console.log(` ${chalk26.dim("Events:")} none recorded`);
|
|
327431
327045
|
}
|
|
327432
327046
|
console.log("");
|
|
327433
327047
|
});
|
|
@@ -327448,7 +327062,7 @@ function setTelemetryEnabled(enabled) {
|
|
|
327448
327062
|
const merged = mergeWithDefaults(config2);
|
|
327449
327063
|
fs28.writeFileSync(configPath, JSON.stringify(merged, null, 2) + "\n", "utf-8");
|
|
327450
327064
|
} catch (err) {
|
|
327451
|
-
console.error(
|
|
327065
|
+
console.error(chalk26.red(`Failed to update config: ${err instanceof Error ? err.message : String(err)}`));
|
|
327452
327066
|
process.exit(1);
|
|
327453
327067
|
}
|
|
327454
327068
|
}
|
|
@@ -327456,7 +327070,7 @@ function setTelemetryEnabled(enabled) {
|
|
|
327456
327070
|
// src/commands/memory.ts
|
|
327457
327071
|
init_db();
|
|
327458
327072
|
init_table();
|
|
327459
|
-
import
|
|
327073
|
+
import chalk27 from "chalk";
|
|
327460
327074
|
import { readFileSync as readFileSync28, writeFileSync as writeFileSync18 } from "node:fs";
|
|
327461
327075
|
function registerMemoryCommand(program2) {
|
|
327462
327076
|
const memory = program2.command("memory").description("Manage agent persistent memories");
|
|
@@ -327468,7 +327082,7 @@ function registerMemoryCommand(program2) {
|
|
|
327468
327082
|
if (!agentId) {
|
|
327469
327083
|
const agents = store.listAgents();
|
|
327470
327084
|
if (agents.length === 0) {
|
|
327471
|
-
console.log(
|
|
327085
|
+
console.log(chalk27.yellow("No agents found."));
|
|
327472
327086
|
return;
|
|
327473
327087
|
}
|
|
327474
327088
|
const headers2 = ["Agent", "Memories", "Avg Importance", "By Type"];
|
|
@@ -327489,7 +327103,7 @@ function registerMemoryCommand(program2) {
|
|
|
327489
327103
|
limit
|
|
327490
327104
|
});
|
|
327491
327105
|
if (memories.length === 0) {
|
|
327492
|
-
console.log(
|
|
327106
|
+
console.log(chalk27.yellow("No memories found."));
|
|
327493
327107
|
return;
|
|
327494
327108
|
}
|
|
327495
327109
|
const headers = ["ID", "Type", "Imp.", "Content", "Tags", "Created"];
|
|
@@ -327524,7 +327138,7 @@ function registerMemoryCommand(program2) {
|
|
|
327524
327138
|
allRows.sort((a, b) => b.imp - a.imp);
|
|
327525
327139
|
const limited = allRows.slice(0, limit);
|
|
327526
327140
|
if (limited.length === 0) {
|
|
327527
|
-
console.log(
|
|
327141
|
+
console.log(chalk27.yellow("No matching memories found."));
|
|
327528
327142
|
return;
|
|
327529
327143
|
}
|
|
327530
327144
|
printTable(
|
|
@@ -327535,7 +327149,7 @@ function registerMemoryCommand(program2) {
|
|
|
327535
327149
|
}
|
|
327536
327150
|
const results = store.recallMemories(agentId, query, { limit });
|
|
327537
327151
|
if (results.length === 0) {
|
|
327538
|
-
console.log(
|
|
327152
|
+
console.log(chalk27.yellow("No matching memories found."));
|
|
327539
327153
|
return;
|
|
327540
327154
|
}
|
|
327541
327155
|
printTable(
|
|
@@ -327555,41 +327169,41 @@ function registerMemoryCommand(program2) {
|
|
|
327555
327169
|
if (!agentId) {
|
|
327556
327170
|
const agents = store.listAgents();
|
|
327557
327171
|
if (agents.length === 0) {
|
|
327558
|
-
console.log(
|
|
327172
|
+
console.log(chalk27.yellow("No agents found."));
|
|
327559
327173
|
return;
|
|
327560
327174
|
}
|
|
327561
327175
|
let totalMemories = 0;
|
|
327562
327176
|
for (const agent of agents) {
|
|
327563
327177
|
const stats2 = store.getMemoryStats(agent.id);
|
|
327564
327178
|
totalMemories += stats2.total;
|
|
327565
|
-
console.log(
|
|
327179
|
+
console.log(chalk27.bold.white(`
|
|
327566
327180
|
${agent.name} (${agent.id.slice(0, 8)}...)`));
|
|
327567
|
-
console.log(` Total memories: ${
|
|
327568
|
-
console.log(` Avg importance: ${
|
|
327569
|
-
console.log(` FTS5 available: ${store.hasFts5() ?
|
|
327181
|
+
console.log(` Total memories: ${chalk27.cyan(String(stats2.total))}`);
|
|
327182
|
+
console.log(` Avg importance: ${chalk27.cyan(stats2.avgImportance.toFixed(2))}`);
|
|
327183
|
+
console.log(` FTS5 available: ${store.hasFts5() ? chalk27.green("yes") : chalk27.yellow("no (LIKE fallback)")}`);
|
|
327570
327184
|
const typeEntries2 = Object.entries(stats2.byType);
|
|
327571
327185
|
if (typeEntries2.length > 0) {
|
|
327572
327186
|
console.log(" By type:");
|
|
327573
327187
|
for (const [type, count] of typeEntries2) {
|
|
327574
|
-
console.log(` ${type}: ${
|
|
327188
|
+
console.log(` ${type}: ${chalk27.cyan(String(count))}`);
|
|
327575
327189
|
}
|
|
327576
327190
|
}
|
|
327577
327191
|
}
|
|
327578
|
-
console.log(
|
|
327579
|
-
Total across all agents: ${
|
|
327192
|
+
console.log(chalk27.bold.white(`
|
|
327193
|
+
Total across all agents: ${chalk27.cyan(String(totalMemories))}`));
|
|
327580
327194
|
return;
|
|
327581
327195
|
}
|
|
327582
327196
|
const stats = store.getMemoryStats(agentId);
|
|
327583
|
-
console.log(
|
|
327197
|
+
console.log(chalk27.bold.white(`
|
|
327584
327198
|
Memory Statistics for ${agentId}`));
|
|
327585
|
-
console.log(`Total memories: ${
|
|
327586
|
-
console.log(`Avg importance: ${
|
|
327587
|
-
console.log(`FTS5 available: ${store.hasFts5() ?
|
|
327199
|
+
console.log(`Total memories: ${chalk27.cyan(String(stats.total))}`);
|
|
327200
|
+
console.log(`Avg importance: ${chalk27.cyan(stats.avgImportance.toFixed(2))}`);
|
|
327201
|
+
console.log(`FTS5 available: ${store.hasFts5() ? chalk27.green("yes") : chalk27.yellow("no (LIKE fallback)")}`);
|
|
327588
327202
|
const typeEntries = Object.entries(stats.byType);
|
|
327589
327203
|
if (typeEntries.length > 0) {
|
|
327590
327204
|
console.log("\nBy type:");
|
|
327591
327205
|
for (const [type, count] of typeEntries) {
|
|
327592
|
-
console.log(` ${type}: ${
|
|
327206
|
+
console.log(` ${type}: ${chalk27.cyan(String(count))}`);
|
|
327593
327207
|
}
|
|
327594
327208
|
}
|
|
327595
327209
|
});
|
|
@@ -327600,14 +327214,14 @@ Memory Statistics for ${agentId}`));
|
|
|
327600
327214
|
const minImportance = parseFloat(options.minImportance);
|
|
327601
327215
|
const expired = store.pruneExpiredMemories();
|
|
327602
327216
|
if (expired > 0) {
|
|
327603
|
-
console.log(
|
|
327217
|
+
console.log(chalk27.green(`Pruned ${expired} expired memories.`));
|
|
327604
327218
|
}
|
|
327605
327219
|
if (agentId) {
|
|
327606
327220
|
const pruned = store.pruneMemories(agentId, {
|
|
327607
327221
|
maxAge: maxAgeDays * 86400,
|
|
327608
327222
|
minImportance
|
|
327609
327223
|
});
|
|
327610
|
-
console.log(
|
|
327224
|
+
console.log(chalk27.green(`Pruned ${pruned} old/low-importance memories for agent ${agentId}.`));
|
|
327611
327225
|
} else {
|
|
327612
327226
|
const agents = store.listAgents();
|
|
327613
327227
|
let total = 0;
|
|
@@ -327618,7 +327232,7 @@ Memory Statistics for ${agentId}`));
|
|
|
327618
327232
|
});
|
|
327619
327233
|
total += pruned;
|
|
327620
327234
|
}
|
|
327621
|
-
console.log(
|
|
327235
|
+
console.log(chalk27.green(`Pruned ${total} old/low-importance memories across all agents.`));
|
|
327622
327236
|
}
|
|
327623
327237
|
});
|
|
327624
327238
|
memory.command("export").description("Export memories to JSON").option("-a, --agent <id>", "Agent ID").option("-o, --output <file>", "Output file path", "memories-export.json").action(async (options) => {
|
|
@@ -327662,7 +327276,7 @@ Memory Statistics for ${agentId}`));
|
|
|
327662
327276
|
}
|
|
327663
327277
|
const json = JSON.stringify(allMemories, null, 2);
|
|
327664
327278
|
writeFileSync18(outputFile, json, "utf-8");
|
|
327665
|
-
console.log(
|
|
327279
|
+
console.log(chalk27.green(`Exported ${allMemories.length} memories to ${outputFile}`));
|
|
327666
327280
|
});
|
|
327667
327281
|
memory.command("import <file>").description("Import memories from JSON").action(async (file) => {
|
|
327668
327282
|
const store = await getStore();
|
|
@@ -327670,13 +327284,13 @@ Memory Statistics for ${agentId}`));
|
|
|
327670
327284
|
const raw = readFileSync28(file, "utf-8");
|
|
327671
327285
|
const entries = JSON.parse(raw);
|
|
327672
327286
|
if (!Array.isArray(entries)) {
|
|
327673
|
-
console.error(
|
|
327287
|
+
console.error(chalk27.red("Invalid format: expected a JSON array of memory entries."));
|
|
327674
327288
|
return;
|
|
327675
327289
|
}
|
|
327676
327290
|
let imported = 0;
|
|
327677
327291
|
for (const entry of entries) {
|
|
327678
327292
|
if (!entry.agentId || !entry.content) {
|
|
327679
|
-
console.warn(
|
|
327293
|
+
console.warn(chalk27.yellow("Skipping entry without agentId or content."));
|
|
327680
327294
|
continue;
|
|
327681
327295
|
}
|
|
327682
327296
|
store.storeMemory({
|
|
@@ -327688,9 +327302,9 @@ Memory Statistics for ${agentId}`));
|
|
|
327688
327302
|
});
|
|
327689
327303
|
imported++;
|
|
327690
327304
|
}
|
|
327691
|
-
console.log(
|
|
327305
|
+
console.log(chalk27.green(`Imported ${imported} memories from ${file}`));
|
|
327692
327306
|
} catch (err) {
|
|
327693
|
-
console.error(
|
|
327307
|
+
console.error(chalk27.red(`Failed to import: ${err instanceof Error ? err.message : String(err)}`));
|
|
327694
327308
|
}
|
|
327695
327309
|
});
|
|
327696
327310
|
}
|
|
@@ -327699,7 +327313,7 @@ Memory Statistics for ${agentId}`));
|
|
|
327699
327313
|
init_config2();
|
|
327700
327314
|
init_spinner();
|
|
327701
327315
|
init_table();
|
|
327702
|
-
import
|
|
327316
|
+
import chalk28 from "chalk";
|
|
327703
327317
|
function registerSandboxCommand(program2) {
|
|
327704
327318
|
const sandbox = program2.command("sandbox").description("Manage sandbox execution backends (Docker, SSH, local)");
|
|
327705
327319
|
sandbox.command("status").description("Show current sandbox mode and status").action(async () => {
|
|
@@ -327717,20 +327331,20 @@ async function cmdSandboxStatus() {
|
|
|
327717
327331
|
const sandboxMode = config2?.security?.sandboxMode ?? "none";
|
|
327718
327332
|
const sshConfig = config2?.security?.ssh;
|
|
327719
327333
|
const lines = [
|
|
327720
|
-
`Mode: ${
|
|
327334
|
+
`Mode: ${chalk28.bold(sandboxMode)}`
|
|
327721
327335
|
];
|
|
327722
327336
|
const dockerAvailable = await checkDockerAvailable();
|
|
327723
|
-
lines.push(`Docker: ${dockerAvailable ?
|
|
327337
|
+
lines.push(`Docker: ${dockerAvailable ? chalk28.green("available") : chalk28.red("not available")}`);
|
|
327724
327338
|
if (sshConfig) {
|
|
327725
|
-
lines.push(`SSH: ${
|
|
327339
|
+
lines.push(`SSH: ${chalk28.cyan(sshConfig.username)}@${chalk28.cyan(sshConfig.host)}:${sshConfig.port}`);
|
|
327726
327340
|
if (sshConfig.workDir) {
|
|
327727
327341
|
lines.push(`SSH workdir: ${sshConfig.workDir}`);
|
|
327728
327342
|
}
|
|
327729
327343
|
} else {
|
|
327730
|
-
lines.push(`SSH: ${
|
|
327344
|
+
lines.push(`SSH: ${chalk28.dim("not configured")}`);
|
|
327731
327345
|
}
|
|
327732
327346
|
console.log("");
|
|
327733
|
-
console.log(
|
|
327347
|
+
console.log(chalk28.bold("Sandbox Status"));
|
|
327734
327348
|
printBox(lines);
|
|
327735
327349
|
console.log("");
|
|
327736
327350
|
}
|
|
@@ -327738,8 +327352,8 @@ async function cmdSandboxTest() {
|
|
|
327738
327352
|
const config2 = readConfigFile();
|
|
327739
327353
|
const sandboxMode = config2?.security?.sandboxMode ?? "none";
|
|
327740
327354
|
console.log("");
|
|
327741
|
-
console.log(
|
|
327742
|
-
console.log(
|
|
327355
|
+
console.log(chalk28.bold("Sandbox Connectivity Test"));
|
|
327356
|
+
console.log(chalk28.dim("\u2500".repeat(40)));
|
|
327743
327357
|
const dockerSpinner = createSpinner("Testing Docker...");
|
|
327744
327358
|
dockerSpinner.start();
|
|
327745
327359
|
const dockerAvailable = await checkDockerAvailable();
|
|
@@ -327747,7 +327361,7 @@ async function cmdSandboxTest() {
|
|
|
327747
327361
|
dockerSpinner.succeed("Docker is available");
|
|
327748
327362
|
const version = await getDockerVersion();
|
|
327749
327363
|
if (version) {
|
|
327750
|
-
console.log(
|
|
327364
|
+
console.log(chalk28.dim(` Version: ${version}`));
|
|
327751
327365
|
}
|
|
327752
327366
|
} else {
|
|
327753
327367
|
dockerSpinner.fail("Docker is not available");
|
|
@@ -327760,43 +327374,43 @@ async function cmdSandboxTest() {
|
|
|
327760
327374
|
if (sshResult.ok) {
|
|
327761
327375
|
sshSpinner.succeed(`SSH connected to ${sshConfig.host}`);
|
|
327762
327376
|
if (sshResult.info) {
|
|
327763
|
-
console.log(
|
|
327377
|
+
console.log(chalk28.dim(` ${sshResult.info}`));
|
|
327764
327378
|
}
|
|
327765
327379
|
} else {
|
|
327766
327380
|
sshSpinner.fail(`SSH connection failed: ${sshResult.error}`);
|
|
327767
327381
|
}
|
|
327768
327382
|
} else {
|
|
327769
|
-
console.log(
|
|
327383
|
+
console.log(chalk28.dim(" SSH: not configured (use `npx nestor-sh sandbox ssh <host>`)"));
|
|
327770
327384
|
}
|
|
327771
|
-
console.log(
|
|
327385
|
+
console.log(chalk28.green("\u2714") + " Local execution: always available");
|
|
327772
327386
|
console.log("");
|
|
327773
327387
|
if (sandboxMode === "docker" && !dockerAvailable) {
|
|
327774
|
-
console.log(
|
|
327775
|
-
console.log(
|
|
327388
|
+
console.log(chalk28.yellow('Warning: Sandbox mode is "docker" but Docker is not available.'));
|
|
327389
|
+
console.log(chalk28.dim('Consider switching to "none" or "auto" in your config.'));
|
|
327776
327390
|
} else if (sandboxMode === "ssh" && !sshConfig) {
|
|
327777
|
-
console.log(
|
|
327778
|
-
console.log(
|
|
327391
|
+
console.log(chalk28.yellow('Warning: Sandbox mode is "ssh" but no SSH config found.'));
|
|
327392
|
+
console.log(chalk28.dim("Run `npx nestor-sh sandbox ssh <host>` to configure."));
|
|
327779
327393
|
} else {
|
|
327780
|
-
console.log(
|
|
327394
|
+
console.log(chalk28.green("Sandbox configuration looks good."));
|
|
327781
327395
|
}
|
|
327782
327396
|
console.log("");
|
|
327783
327397
|
}
|
|
327784
327398
|
async function cmdSandboxSSH(host, opts) {
|
|
327785
327399
|
const port = parseInt(opts.port, 10);
|
|
327786
327400
|
if (isNaN(port) || port < 1 || port > 65535) {
|
|
327787
|
-
console.log(
|
|
327401
|
+
console.log(chalk28.red(`Invalid port: ${opts.port}`));
|
|
327788
327402
|
return;
|
|
327789
327403
|
}
|
|
327790
327404
|
console.log("");
|
|
327791
|
-
console.log(
|
|
327792
|
-
console.log(
|
|
327793
|
-
console.log(` Host: ${
|
|
327794
|
-
console.log(` Port: ${
|
|
327795
|
-
console.log(` User: ${
|
|
327405
|
+
console.log(chalk28.bold("Configuring SSH Sandbox"));
|
|
327406
|
+
console.log(chalk28.dim("\u2500".repeat(40)));
|
|
327407
|
+
console.log(` Host: ${chalk28.cyan(host)}`);
|
|
327408
|
+
console.log(` Port: ${chalk28.cyan(String(port))}`);
|
|
327409
|
+
console.log(` User: ${chalk28.cyan(opts.user)}`);
|
|
327796
327410
|
if (opts.key) {
|
|
327797
|
-
console.log(` Key: ${
|
|
327411
|
+
console.log(` Key: ${chalk28.cyan(opts.key)}`);
|
|
327798
327412
|
}
|
|
327799
|
-
console.log(` Dir: ${
|
|
327413
|
+
console.log(` Dir: ${chalk28.cyan(opts.workdir)}`);
|
|
327800
327414
|
console.log("");
|
|
327801
327415
|
const testSpinner = createSpinner("Testing SSH connection...");
|
|
327802
327416
|
testSpinner.start();
|
|
@@ -327812,7 +327426,7 @@ async function cmdSandboxSSH(host, opts) {
|
|
|
327812
327426
|
testSpinner.succeed("SSH connection successful");
|
|
327813
327427
|
} else {
|
|
327814
327428
|
testSpinner.fail(`SSH connection failed: ${result.error}`);
|
|
327815
|
-
console.log(
|
|
327429
|
+
console.log(chalk28.yellow("Configuration saved anyway. Fix the connection issue and run `npx nestor-sh sandbox test`."));
|
|
327816
327430
|
}
|
|
327817
327431
|
try {
|
|
327818
327432
|
const config2 = readConfigFile() ?? {};
|
|
@@ -327826,10 +327440,10 @@ async function cmdSandboxSSH(host, opts) {
|
|
|
327826
327440
|
};
|
|
327827
327441
|
config2.security = security;
|
|
327828
327442
|
writeConfigFile(config2);
|
|
327829
|
-
console.log(
|
|
327830
|
-
console.log(
|
|
327443
|
+
console.log(chalk28.green("SSH configuration saved."));
|
|
327444
|
+
console.log(chalk28.dim('To use SSH as the default sandbox, set security.sandboxMode to "ssh" in your config.'));
|
|
327831
327445
|
} catch (err) {
|
|
327832
|
-
console.error(
|
|
327446
|
+
console.error(chalk28.red("Failed to save config:"), err instanceof Error ? err.message : String(err));
|
|
327833
327447
|
}
|
|
327834
327448
|
console.log("");
|
|
327835
327449
|
}
|
|
@@ -327918,7 +327532,7 @@ async function testSSHWithCli(config2) {
|
|
|
327918
327532
|
// src/commands/template.ts
|
|
327919
327533
|
init_db();
|
|
327920
327534
|
import * as p6 from "@clack/prompts";
|
|
327921
|
-
import
|
|
327535
|
+
import chalk29 from "chalk";
|
|
327922
327536
|
import fs29 from "node:fs";
|
|
327923
327537
|
import path29 from "node:path";
|
|
327924
327538
|
function registerTemplateCommand(program2) {
|
|
@@ -327935,13 +327549,13 @@ function registerTemplateCommand(program2) {
|
|
|
327935
327549
|
if (builtIn.length === 0) {
|
|
327936
327550
|
p6.log.info("No built-in templates found.");
|
|
327937
327551
|
} else {
|
|
327938
|
-
p6.log.info(
|
|
327552
|
+
p6.log.info(chalk29.bold("Built-in Templates:"));
|
|
327939
327553
|
for (const tmpl of builtIn) {
|
|
327940
327554
|
console.log(
|
|
327941
|
-
` ${
|
|
327555
|
+
` ${chalk29.cyan(tmpl.name)} ${chalk29.gray(`v${tmpl.version}`)} \u2014 ${tmpl.description}`
|
|
327942
327556
|
);
|
|
327943
327557
|
console.log(
|
|
327944
|
-
` ${
|
|
327558
|
+
` ${chalk29.gray(`${tmpl.agentCount} agents | by ${tmpl.author}`)}`
|
|
327945
327559
|
);
|
|
327946
327560
|
}
|
|
327947
327561
|
}
|
|
@@ -327966,7 +327580,7 @@ function registerTemplateCommand(program2) {
|
|
|
327966
327580
|
if (opts.output) {
|
|
327967
327581
|
const outputPath = path29.resolve(opts.output);
|
|
327968
327582
|
fs29.writeFileSync(outputPath, json, "utf-8");
|
|
327969
|
-
s.stop(`Template exported to ${
|
|
327583
|
+
s.stop(`Template exported to ${chalk29.green(outputPath)}`);
|
|
327970
327584
|
} else {
|
|
327971
327585
|
s.stop("Template exported:");
|
|
327972
327586
|
console.log(json);
|
|
@@ -327995,7 +327609,7 @@ function registerTemplateCommand(program2) {
|
|
|
327995
327609
|
if (!validation2.valid) {
|
|
327996
327610
|
p6.log.error("Template validation failed:");
|
|
327997
327611
|
for (const err of validation2.errors) {
|
|
327998
|
-
console.log(` ${
|
|
327612
|
+
console.log(` ${chalk29.red("\u2717")} ${err}`);
|
|
327999
327613
|
}
|
|
328000
327614
|
store.close();
|
|
328001
327615
|
process.exit(1);
|
|
@@ -328007,15 +327621,15 @@ function registerTemplateCommand(program2) {
|
|
|
328007
327621
|
overwrite: opts.overwrite
|
|
328008
327622
|
});
|
|
328009
327623
|
s.stop(opts.dryRun ? "Dry run complete:" : "Import complete:");
|
|
328010
|
-
console.log(` ${
|
|
327624
|
+
console.log(` ${chalk29.green("Created:")} ${result.created.agents} agents, ${result.created.workflows} workflows, ${result.created.skills} skills`);
|
|
328011
327625
|
if (result.skipped.length > 0) {
|
|
328012
|
-
console.log(` ${
|
|
327626
|
+
console.log(` ${chalk29.yellow("Skipped:")}`);
|
|
328013
327627
|
for (const skip of result.skipped) {
|
|
328014
327628
|
console.log(` ${skip.item}: ${skip.reason}`);
|
|
328015
327629
|
}
|
|
328016
327630
|
}
|
|
328017
327631
|
if (result.conflicts.length > 0) {
|
|
328018
|
-
console.log(` ${
|
|
327632
|
+
console.log(` ${chalk29.cyan("Conflicts:")}`);
|
|
328019
327633
|
for (const conflict of result.conflicts) {
|
|
328020
327634
|
console.log(` ${conflict.item}: ${conflict.resolution}`);
|
|
328021
327635
|
}
|
|
@@ -328039,7 +327653,7 @@ function registerTemplateCommand(program2) {
|
|
|
328039
327653
|
p6.log.info("Available templates:");
|
|
328040
327654
|
const available = service.listBuiltIn();
|
|
328041
327655
|
for (const t of available) {
|
|
328042
|
-
console.log(` ${
|
|
327656
|
+
console.log(` ${chalk29.cyan(t.name)} \u2014 ${t.description}`);
|
|
328043
327657
|
}
|
|
328044
327658
|
store.close();
|
|
328045
327659
|
process.exit(1);
|
|
@@ -328049,9 +327663,9 @@ function registerTemplateCommand(program2) {
|
|
|
328049
327663
|
dryRun: opts.dryRun
|
|
328050
327664
|
});
|
|
328051
327665
|
s.stop(opts.dryRun ? "Dry run complete:" : `Template "${name}" applied:`);
|
|
328052
|
-
console.log(` ${
|
|
327666
|
+
console.log(` ${chalk29.green("Created:")} ${result.created.agents} agents, ${result.created.workflows} workflows, ${result.created.skills} skills`);
|
|
328053
327667
|
if (result.skipped.length > 0) {
|
|
328054
|
-
console.log(` ${
|
|
327668
|
+
console.log(` ${chalk29.yellow("Skipped:")} ${result.skipped.length} items (already exist)`);
|
|
328055
327669
|
}
|
|
328056
327670
|
store.close();
|
|
328057
327671
|
} catch (err) {
|
|
@@ -328067,7 +327681,7 @@ init_db();
|
|
|
328067
327681
|
init_config2();
|
|
328068
327682
|
init_spinner();
|
|
328069
327683
|
import { resolve as resolve18 } from "node:path";
|
|
328070
|
-
import
|
|
327684
|
+
import chalk30 from "chalk";
|
|
328071
327685
|
function registerRagCommand(program2) {
|
|
328072
327686
|
const rag = program2.command("rag").description("RAG (Retrieval-Augmented Generation) commands");
|
|
328073
327687
|
rag.command("index [path]").description("Index a directory for code-context retrieval").option("-t, --tenant <id>", "Tenant ID", "default").option("--include <patterns...>", "Glob patterns to include").option("--exclude <patterns...>", "Glob patterns to exclude").option("--reindex", "Only re-index modified files", false).action(async (path32, opts) => {
|
|
@@ -328097,7 +327711,7 @@ function registerRagCommand(program2) {
|
|
|
328097
327711
|
}
|
|
328098
327712
|
});
|
|
328099
327713
|
spinner3.succeed(
|
|
328100
|
-
`Indexed ${
|
|
327714
|
+
`Indexed ${chalk30.bold(result.filesIndexed)} files, ${chalk30.bold(result.chunksCreated)} chunks in ${chalk30.dim((result.duration / 1e3).toFixed(1) + "s")} (provider: ${chalk30.cyan(provider.name)})`
|
|
328101
327715
|
);
|
|
328102
327716
|
} catch (err) {
|
|
328103
327717
|
spinner3.fail(`Indexing failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
@@ -328124,25 +327738,25 @@ function registerRagCommand(program2) {
|
|
|
328124
327738
|
filePath: opts.file
|
|
328125
327739
|
});
|
|
328126
327740
|
if (results.length === 0) {
|
|
328127
|
-
console.log(
|
|
327741
|
+
console.log(chalk30.yellow("No results found. Try indexing first: npx nestor-sh rag index"));
|
|
328128
327742
|
return;
|
|
328129
327743
|
}
|
|
328130
|
-
console.log(
|
|
327744
|
+
console.log(chalk30.bold(`
|
|
328131
327745
|
${results.length} results for "${query}":
|
|
328132
327746
|
`));
|
|
328133
327747
|
for (const chunk of results) {
|
|
328134
|
-
const nameLabel = chunk.name ?
|
|
328135
|
-
const scoreLabel = chunk.score >= 0.7 ?
|
|
327748
|
+
const nameLabel = chunk.name ? chalk30.cyan(` (${chunk.name})`) : "";
|
|
327749
|
+
const scoreLabel = chunk.score >= 0.7 ? chalk30.green(chunk.score.toFixed(2)) : chalk30.yellow(chunk.score.toFixed(2));
|
|
328136
327750
|
console.log(
|
|
328137
|
-
|
|
327751
|
+
chalk30.dim(" ") + chalk30.bold(chunk.filePath) + chalk30.dim(`:${chunk.startLine}-${chunk.endLine}`) + nameLabel + chalk30.dim(" [") + scoreLabel + chalk30.dim("]")
|
|
328138
327752
|
);
|
|
328139
327753
|
const preview = chunk.content.split("\n").slice(0, 3).join("\n");
|
|
328140
|
-
const indented = preview.split("\n").map((l) =>
|
|
327754
|
+
const indented = preview.split("\n").map((l) => chalk30.dim(" ") + l).join("\n");
|
|
328141
327755
|
console.log(indented);
|
|
328142
327756
|
console.log("");
|
|
328143
327757
|
}
|
|
328144
327758
|
} catch (err) {
|
|
328145
|
-
console.error(
|
|
327759
|
+
console.error(chalk30.red(`Search failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
328146
327760
|
process.exit(1);
|
|
328147
327761
|
}
|
|
328148
327762
|
});
|
|
@@ -328160,14 +327774,14 @@ ${results.length} results for "${query}":
|
|
|
328160
327774
|
});
|
|
328161
327775
|
const indexer = new agentModule.RagIndexer(store, provider);
|
|
328162
327776
|
const status = await indexer.status(opts.tenant);
|
|
328163
|
-
console.log(
|
|
328164
|
-
console.log(` Chunks: ${
|
|
328165
|
-
console.log(` Files: ${
|
|
328166
|
-
console.log(` Provider: ${
|
|
328167
|
-
console.log(` Last index: ${status.lastIndexedAt ?
|
|
327777
|
+
console.log(chalk30.bold("\nRAG Index Status:\n"));
|
|
327778
|
+
console.log(` Chunks: ${chalk30.bold(status.totalChunks)}`);
|
|
327779
|
+
console.log(` Files: ${chalk30.bold(status.totalFiles)}`);
|
|
327780
|
+
console.log(` Provider: ${chalk30.cyan(status.embeddingProvider)}`);
|
|
327781
|
+
console.log(` Last index: ${status.lastIndexedAt ? chalk30.dim(status.lastIndexedAt) : chalk30.yellow("never")}`);
|
|
328168
327782
|
console.log("");
|
|
328169
327783
|
} catch (err) {
|
|
328170
|
-
console.error(
|
|
327784
|
+
console.error(chalk30.red(`Status check failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
328171
327785
|
process.exit(1);
|
|
328172
327786
|
}
|
|
328173
327787
|
});
|
|
@@ -328178,9 +327792,9 @@ ${results.length} results for "${query}":
|
|
|
328178
327792
|
const provider = new agentModule.LocalEmbeddings();
|
|
328179
327793
|
const indexer = new agentModule.RagIndexer(store, provider);
|
|
328180
327794
|
const deleted = await indexer.clear(void 0, opts.tenant);
|
|
328181
|
-
console.log(
|
|
327795
|
+
console.log(chalk30.green(`Cleared ${deleted} chunks from the RAG index.`));
|
|
328182
327796
|
} catch (err) {
|
|
328183
|
-
console.error(
|
|
327797
|
+
console.error(chalk30.red(`Clear failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
328184
327798
|
process.exit(1);
|
|
328185
327799
|
}
|
|
328186
327800
|
});
|
|
@@ -328189,7 +327803,7 @@ ${results.length} results for "${query}":
|
|
|
328189
327803
|
// src/commands/test.ts
|
|
328190
327804
|
import { resolve as resolve19, relative as relative5 } from "node:path";
|
|
328191
327805
|
import { readdirSync as readdirSync8, statSync as statSync8, existsSync as existsSync27 } from "node:fs";
|
|
328192
|
-
import
|
|
327806
|
+
import chalk31 from "chalk";
|
|
328193
327807
|
var TEST_FILE_PATTERNS = [
|
|
328194
327808
|
".nestor-test.yaml",
|
|
328195
327809
|
".nestor-test.yml",
|
|
@@ -328202,7 +327816,7 @@ function registerTestCommand(program2) {
|
|
|
328202
327816
|
if (opts.file) {
|
|
328203
327817
|
const filePath = resolve19(opts.file);
|
|
328204
327818
|
if (!existsSync27(filePath)) {
|
|
328205
|
-
console.error(
|
|
327819
|
+
console.error(chalk31.red(`File not found: ${opts.file}`));
|
|
328206
327820
|
process.exit(1);
|
|
328207
327821
|
}
|
|
328208
327822
|
await runSkillTests([filePath], opts.verbose, opts.json);
|
|
@@ -328215,7 +327829,7 @@ function registerTestCommand(program2) {
|
|
|
328215
327829
|
}
|
|
328216
327830
|
if (opts.record) {
|
|
328217
327831
|
if (!opts.prompt) {
|
|
328218
|
-
console.error(
|
|
327832
|
+
console.error(chalk31.red("--prompt is required when using --record"));
|
|
328219
327833
|
process.exit(1);
|
|
328220
327834
|
}
|
|
328221
327835
|
await recordFixture(opts.record, opts.prompt);
|
|
@@ -328238,9 +327852,9 @@ function registerTestCommand(program2) {
|
|
|
328238
327852
|
}
|
|
328239
327853
|
const uniqueFiles = [...new Set(allFiles)];
|
|
328240
327854
|
if (uniqueFiles.length === 0) {
|
|
328241
|
-
console.log(
|
|
328242
|
-
console.log(
|
|
328243
|
-
console.log(
|
|
327855
|
+
console.log(chalk31.yellow("No test files found."));
|
|
327856
|
+
console.log(chalk31.dim(" Create files ending with .test.yaml or .nestor-test.yaml"));
|
|
327857
|
+
console.log(chalk31.dim(" Default search paths: ./ and .nestor/tests/"));
|
|
328244
327858
|
process.exit(1);
|
|
328245
327859
|
}
|
|
328246
327860
|
await runSkillTests(uniqueFiles, opts.verbose, opts.json);
|
|
@@ -328289,14 +327903,14 @@ async function listTestFiles(dir) {
|
|
|
328289
327903
|
}
|
|
328290
327904
|
const unique = [...new Set(files)];
|
|
328291
327905
|
if (unique.length === 0) {
|
|
328292
|
-
console.log(
|
|
327906
|
+
console.log(chalk31.yellow("No test files found. Create files ending with .test.yaml"));
|
|
328293
327907
|
return;
|
|
328294
327908
|
}
|
|
328295
|
-
console.log(
|
|
327909
|
+
console.log(chalk31.bold(`
|
|
328296
327910
|
Discovered ${unique.length} test file(s):
|
|
328297
327911
|
`));
|
|
328298
327912
|
for (const file of unique) {
|
|
328299
|
-
console.log(
|
|
327913
|
+
console.log(chalk31.dim(" ") + chalk31.cyan(relative5(dir, file)));
|
|
328300
327914
|
}
|
|
328301
327915
|
console.log("");
|
|
328302
327916
|
}
|
|
@@ -328307,7 +327921,7 @@ async function runSkillTests(files, verbose, json) {
|
|
|
328307
327921
|
const reporter = new skillTester.TestReporter();
|
|
328308
327922
|
const allResults = [];
|
|
328309
327923
|
if (!json) {
|
|
328310
|
-
console.log(
|
|
327924
|
+
console.log(chalk31.bold(`
|
|
328311
327925
|
Running ${files.length} test suite(s)...
|
|
328312
327926
|
`));
|
|
328313
327927
|
}
|
|
@@ -328317,7 +327931,7 @@ Running ${files.length} test suite(s)...
|
|
|
328317
327931
|
allResults.push(...suiteResults);
|
|
328318
327932
|
} catch (err) {
|
|
328319
327933
|
if (!json) {
|
|
328320
|
-
console.log(
|
|
327934
|
+
console.log(chalk31.red(` FAIL `) + chalk31.dim(file) + chalk31.red(` (${err instanceof Error ? err.message : String(err)})`));
|
|
328321
327935
|
}
|
|
328322
327936
|
}
|
|
328323
327937
|
}
|
|
@@ -328349,14 +327963,14 @@ async function runSkillTestsByName(skillName, verbose, json) {
|
|
|
328349
327963
|
}
|
|
328350
327964
|
}
|
|
328351
327965
|
if (matchingFiles.length === 0) {
|
|
328352
|
-
console.log(
|
|
328353
|
-
console.log(
|
|
327966
|
+
console.log(chalk31.yellow(`No test files found for skill: ${skillName}`));
|
|
327967
|
+
console.log(chalk31.dim(" Searched in: .nestor/tests/, tests/"));
|
|
328354
327968
|
process.exit(1);
|
|
328355
327969
|
}
|
|
328356
327970
|
await runSkillTests(matchingFiles, verbose, json);
|
|
328357
327971
|
}
|
|
328358
327972
|
async function runLegacyTests(files, verbose) {
|
|
328359
|
-
console.log(
|
|
327973
|
+
console.log(chalk31.bold(`
|
|
328360
327974
|
Running ${files.length} test suite(s) (legacy runner)...
|
|
328361
327975
|
`));
|
|
328362
327976
|
const agentModule = await Promise.resolve().then(() => (init_src5(), src_exports5));
|
|
@@ -328371,38 +327985,38 @@ Running ${files.length} test suite(s) (legacy runner)...
|
|
|
328371
327985
|
try {
|
|
328372
327986
|
suite = agentModule.AgentTestRunner.loadSuite(file);
|
|
328373
327987
|
} catch (err) {
|
|
328374
|
-
console.log(
|
|
327988
|
+
console.log(chalk31.red(` FAIL `) + chalk31.dim(relPath) + chalk31.red(` (parse error: ${err instanceof Error ? err.message : String(err)})`));
|
|
328375
327989
|
totalFailed++;
|
|
328376
327990
|
totalTests++;
|
|
328377
327991
|
continue;
|
|
328378
327992
|
}
|
|
328379
|
-
console.log(
|
|
327993
|
+
console.log(chalk31.bold(chalk31.dim(" ") + `${suite.name}`) + chalk31.dim(` (${relPath})`));
|
|
328380
327994
|
const result = await runner.runSuite(suite);
|
|
328381
327995
|
for (const testResult of result.results) {
|
|
328382
327996
|
totalTests++;
|
|
328383
327997
|
if (testResult.passed) {
|
|
328384
327998
|
totalPassed++;
|
|
328385
|
-
console.log(
|
|
327999
|
+
console.log(chalk31.green(" \u2714 ") + testResult.testName + chalk31.dim(` (${testResult.durationMs}ms)`));
|
|
328386
328000
|
} else {
|
|
328387
328001
|
totalFailed++;
|
|
328388
|
-
console.log(
|
|
328002
|
+
console.log(chalk31.red(" \u2718 ") + testResult.testName + chalk31.dim(` (${testResult.durationMs}ms)`));
|
|
328389
328003
|
for (const failure of testResult.failures) {
|
|
328390
|
-
console.log(
|
|
328004
|
+
console.log(chalk31.red(" ") + chalk31.dim(failure));
|
|
328391
328005
|
}
|
|
328392
328006
|
}
|
|
328393
328007
|
if (verbose && testResult.result) {
|
|
328394
|
-
console.log(
|
|
328008
|
+
console.log(chalk31.dim(" ") + `iterations: ${testResult.result.iterations}, cost: $${testResult.result.costUsd.toFixed(4)}, exit: ${testResult.result.exitReason}`);
|
|
328395
328009
|
}
|
|
328396
328010
|
}
|
|
328397
328011
|
console.log("");
|
|
328398
328012
|
}
|
|
328399
328013
|
const duration = ((Date.now() - startTime4) / 1e3).toFixed(1);
|
|
328400
|
-
console.log(
|
|
328014
|
+
console.log(chalk31.bold("\u2500".repeat(50)));
|
|
328401
328015
|
if (totalFailed === 0) {
|
|
328402
|
-
console.log(
|
|
328016
|
+
console.log(chalk31.green.bold(` All ${totalPassed} tests passed`) + chalk31.dim(` (${duration}s)`));
|
|
328403
328017
|
} else {
|
|
328404
328018
|
console.log(
|
|
328405
|
-
|
|
328019
|
+
chalk31.bold(` Tests: `) + chalk31.green.bold(`${totalPassed} passed`) + chalk31.dim(", ") + chalk31.red.bold(`${totalFailed} failed`) + chalk31.dim(`, ${totalTests} total (${duration}s)`)
|
|
328406
328020
|
);
|
|
328407
328021
|
}
|
|
328408
328022
|
console.log("");
|
|
@@ -328411,7 +328025,7 @@ Running ${files.length} test suite(s) (legacy runner)...
|
|
|
328411
328025
|
}
|
|
328412
328026
|
}
|
|
328413
328027
|
async function recordFixture(outputPath, prompt) {
|
|
328414
|
-
console.log(
|
|
328028
|
+
console.log(chalk31.bold("\nRecording LLM responses...\n"));
|
|
328415
328029
|
try {
|
|
328416
328030
|
const agentModule = await Promise.resolve().then(() => (init_src5(), src_exports5));
|
|
328417
328031
|
const router = await agentModule.createDefaultRouter();
|
|
@@ -328421,12 +328035,12 @@ async function recordFixture(outputPath, prompt) {
|
|
|
328421
328035
|
prompt,
|
|
328422
328036
|
outputPath: resolve19(outputPath)
|
|
328423
328037
|
});
|
|
328424
|
-
console.log(
|
|
328425
|
-
console.log(
|
|
328426
|
-
console.log(
|
|
328038
|
+
console.log(chalk31.green(` Recorded ${result.recordings} responses to ${outputPath}`));
|
|
328039
|
+
console.log(chalk31.dim(` Output: ${result.output.slice(0, 100)}...`));
|
|
328040
|
+
console.log(chalk31.dim(` Duration: ${(result.durationMs / 1e3).toFixed(1)}s, Iterations: ${result.iterations}`));
|
|
328427
328041
|
console.log("");
|
|
328428
328042
|
} catch (err) {
|
|
328429
|
-
console.error(
|
|
328043
|
+
console.error(chalk31.red(`Recording failed: ${err instanceof Error ? err.message : String(err)}`));
|
|
328430
328044
|
process.exit(1);
|
|
328431
328045
|
}
|
|
328432
328046
|
}
|
|
@@ -328434,7 +328048,7 @@ async function recordFixture(outputPath, prompt) {
|
|
|
328434
328048
|
// src/commands/guardrail.ts
|
|
328435
328049
|
init_db();
|
|
328436
328050
|
init_table();
|
|
328437
|
-
import
|
|
328051
|
+
import chalk32 from "chalk";
|
|
328438
328052
|
import * as p7 from "@clack/prompts";
|
|
328439
328053
|
import crypto21 from "node:crypto";
|
|
328440
328054
|
function registerGuardrailCommand(program2) {
|
|
@@ -328443,19 +328057,19 @@ function registerGuardrailCommand(program2) {
|
|
|
328443
328057
|
const store = await getStore();
|
|
328444
328058
|
const guardrails = store.listGuardrails();
|
|
328445
328059
|
if (guardrails.length === 0) {
|
|
328446
|
-
console.log(
|
|
328447
|
-
console.log(
|
|
328060
|
+
console.log(chalk32.dim("No guardrails configured."));
|
|
328061
|
+
console.log(chalk32.dim("Add one with: npx nestor-sh guardrail add"));
|
|
328448
328062
|
return;
|
|
328449
328063
|
}
|
|
328450
328064
|
printTable(
|
|
328451
328065
|
["ID", "Name", "Type", "Pattern", "Action", "Enabled"],
|
|
328452
328066
|
guardrails.map((g) => [
|
|
328453
|
-
|
|
328454
|
-
|
|
328455
|
-
|
|
328456
|
-
|
|
328457
|
-
g.action === "block" ?
|
|
328458
|
-
g.enabled ?
|
|
328067
|
+
chalk32.dim(g.id.slice(0, 12)),
|
|
328068
|
+
chalk32.white(g.name),
|
|
328069
|
+
chalk32.cyan(g.type),
|
|
328070
|
+
chalk32.dim(g.pattern.length > 30 ? g.pattern.slice(0, 30) + "..." : g.pattern),
|
|
328071
|
+
g.action === "block" ? chalk32.red(g.action) : g.action === "warn" ? chalk32.yellow(g.action) : chalk32.blue(g.action),
|
|
328072
|
+
g.enabled ? chalk32.green("yes") : chalk32.dim("no")
|
|
328459
328073
|
])
|
|
328460
328074
|
);
|
|
328461
328075
|
});
|
|
@@ -328512,35 +328126,35 @@ function registerGuardrailCommand(program2) {
|
|
|
328512
328126
|
config: config2,
|
|
328513
328127
|
enabled: true
|
|
328514
328128
|
});
|
|
328515
|
-
console.log(
|
|
328129
|
+
console.log(chalk32.green(`Guardrail "${name}" created (${id}).`));
|
|
328516
328130
|
});
|
|
328517
328131
|
guardrail.command("remove <id>").description("Remove a guardrail by ID").action(async (id) => {
|
|
328518
328132
|
const store = await getStore();
|
|
328519
328133
|
const deleted = store.deleteGuardrail(id);
|
|
328520
328134
|
if (deleted) {
|
|
328521
|
-
console.log(
|
|
328135
|
+
console.log(chalk32.green(`Guardrail ${id} removed.`));
|
|
328522
328136
|
} else {
|
|
328523
|
-
console.log(
|
|
328137
|
+
console.log(chalk32.red(`Guardrail ${id} not found.`));
|
|
328524
328138
|
}
|
|
328525
328139
|
});
|
|
328526
328140
|
guardrail.command("toggle <id>").description("Enable/disable a guardrail").action(async (id) => {
|
|
328527
328141
|
const store = await getStore();
|
|
328528
328142
|
const existing = store.getGuardrail(id);
|
|
328529
328143
|
if (!existing) {
|
|
328530
|
-
console.log(
|
|
328144
|
+
console.log(chalk32.red(`Guardrail ${id} not found.`));
|
|
328531
328145
|
return;
|
|
328532
328146
|
}
|
|
328533
328147
|
const newEnabled = !existing.enabled;
|
|
328534
328148
|
store.updateGuardrail(id, { enabled: newEnabled });
|
|
328535
|
-
console.log(
|
|
328149
|
+
console.log(chalk32.green(`Guardrail ${id} ${newEnabled ? "enabled" : "disabled"}.`));
|
|
328536
328150
|
});
|
|
328537
328151
|
}
|
|
328538
328152
|
|
|
328539
328153
|
// src/commands/loop.ts
|
|
328540
328154
|
init_db();
|
|
328541
328155
|
init_config2();
|
|
328542
|
-
import
|
|
328543
|
-
import { randomUUID as
|
|
328156
|
+
import chalk33 from "chalk";
|
|
328157
|
+
import { randomUUID as randomUUID68 } from "node:crypto";
|
|
328544
328158
|
import { readFileSync as readFileSync29, existsSync as existsSync28 } from "node:fs";
|
|
328545
328159
|
import { execSync as execSync4 } from "node:child_process";
|
|
328546
328160
|
function desktopNotify2(title, message) {
|
|
@@ -328634,13 +328248,13 @@ function registerLoopCommand(program2) {
|
|
|
328634
328248
|
let spec = opts.spec;
|
|
328635
328249
|
if (!spec && opts.specFile) {
|
|
328636
328250
|
if (!existsSync28(opts.specFile)) {
|
|
328637
|
-
console.error(
|
|
328251
|
+
console.error(chalk33.red(`Spec file not found: ${opts.specFile}`));
|
|
328638
328252
|
process.exit(1);
|
|
328639
328253
|
}
|
|
328640
328254
|
spec = readFileSync29(opts.specFile, "utf-8").trim();
|
|
328641
328255
|
}
|
|
328642
328256
|
if (!spec) {
|
|
328643
|
-
console.error(
|
|
328257
|
+
console.error(chalk33.red("Must provide --spec or --spec-file"));
|
|
328644
328258
|
process.exit(1);
|
|
328645
328259
|
}
|
|
328646
328260
|
const maxIterations = parseInt(opts.maxIterations, 10);
|
|
@@ -328663,27 +328277,27 @@ function registerLoopCommand(program2) {
|
|
|
328663
328277
|
} catch {
|
|
328664
328278
|
}
|
|
328665
328279
|
}
|
|
328666
|
-
console.log(
|
|
328667
|
-
console.log(
|
|
328668
|
-
console.log(
|
|
328669
|
-
console.log(
|
|
328670
|
-
console.log(
|
|
328280
|
+
console.log(chalk33.cyan("\n Ralph Fresh-Context Loop"));
|
|
328281
|
+
console.log(chalk33.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
328282
|
+
console.log(chalk33.white(" Spec:"), spec.slice(0, 100) + (spec.length > 100 ? "..." : ""));
|
|
328283
|
+
console.log(chalk33.white(" Agent:"), opts.agent);
|
|
328284
|
+
console.log(chalk33.white(" Max iterations:"), maxIterations);
|
|
328671
328285
|
if (maxRuntimeMs > 0) {
|
|
328672
|
-
console.log(
|
|
328286
|
+
console.log(chalk33.white(" Max runtime:"), `${maxRuntimeMs / 1e3}s`);
|
|
328673
328287
|
}
|
|
328674
|
-
console.log(
|
|
328288
|
+
console.log(chalk33.white(" Budget:"), `$${totalBudget}`);
|
|
328675
328289
|
if (gate) {
|
|
328676
|
-
console.log(
|
|
328677
|
-
console.log(
|
|
328290
|
+
console.log(chalk33.white(" Validators:"), validateCommands.join(", "));
|
|
328291
|
+
console.log(chalk33.white(" Strictness:"), `${opts.strictness} \u2192 strict (progressive)`);
|
|
328678
328292
|
} else if (opts.verify) {
|
|
328679
|
-
console.log(
|
|
328293
|
+
console.log(chalk33.white(" Verify cmd:"), opts.verify);
|
|
328680
328294
|
}
|
|
328681
328295
|
console.log("");
|
|
328682
328296
|
let agentModule;
|
|
328683
328297
|
try {
|
|
328684
328298
|
agentModule = await Promise.resolve().then(() => (init_src5(), src_exports5));
|
|
328685
328299
|
} catch {
|
|
328686
|
-
console.error(
|
|
328300
|
+
console.error(chalk33.red("Failed to import @nestor/agent. Is it installed?"));
|
|
328687
328301
|
process.exit(1);
|
|
328688
328302
|
}
|
|
328689
328303
|
const store = await getStore();
|
|
@@ -328694,7 +328308,7 @@ function registerLoopCommand(program2) {
|
|
|
328694
328308
|
} catch {
|
|
328695
328309
|
}
|
|
328696
328310
|
const agent = resolvedAgent ?? {
|
|
328697
|
-
id:
|
|
328311
|
+
id: randomUUID68(),
|
|
328698
328312
|
name: opts.agent,
|
|
328699
328313
|
adapterType: "claude",
|
|
328700
328314
|
adapterConfig: {
|
|
@@ -328709,7 +328323,7 @@ function registerLoopCommand(program2) {
|
|
|
328709
328323
|
try {
|
|
328710
328324
|
router = await agentModule.createDefaultRouter();
|
|
328711
328325
|
} catch {
|
|
328712
|
-
console.error(
|
|
328326
|
+
console.error(chalk33.red("Could not initialize LLM adapter. Is the API key configured?"));
|
|
328713
328327
|
process.exit(1);
|
|
328714
328328
|
}
|
|
328715
328329
|
const summary = {
|
|
@@ -328722,35 +328336,35 @@ function registerLoopCommand(program2) {
|
|
|
328722
328336
|
};
|
|
328723
328337
|
for (let i = 1; i <= maxIterations; i++) {
|
|
328724
328338
|
if (summary.totalCostUsd >= totalBudget) {
|
|
328725
|
-
console.log(
|
|
328339
|
+
console.log(chalk33.yellow(`
|
|
328726
328340
|
Budget exhausted ($${summary.totalCostUsd.toFixed(4)} / $${totalBudget}). Stopping.`));
|
|
328727
328341
|
break;
|
|
328728
328342
|
}
|
|
328729
328343
|
if (maxRuntimeMs > 0 && Date.now() - loopStartMs >= maxRuntimeMs) {
|
|
328730
|
-
console.log(
|
|
328344
|
+
console.log(chalk33.yellow(`
|
|
328731
328345
|
Max runtime reached (${maxRuntimeMs / 1e3}s). Stopping.`));
|
|
328732
328346
|
break;
|
|
328733
328347
|
}
|
|
328734
328348
|
const remainingBudget = totalBudget - summary.totalCostUsd;
|
|
328735
|
-
console.log(
|
|
328736
|
-
\u2500\u2500 Iteration ${i}/${maxIterations} `) +
|
|
328349
|
+
console.log(chalk33.cyan(`
|
|
328350
|
+
\u2500\u2500 Iteration ${i}/${maxIterations} `) + chalk33.dim(`(budget remaining: $${remainingBudget.toFixed(4)}) \u2500\u2500`));
|
|
328737
328351
|
let bpReport = null;
|
|
328738
328352
|
if (gate && i > 1) {
|
|
328739
328353
|
bpReport = gate.run();
|
|
328740
|
-
const strictTag =
|
|
328354
|
+
const strictTag = chalk33.dim(`[${bpReport.strictness}]`);
|
|
328741
328355
|
if (bpReport.passed && bpReport.score >= 0.95) {
|
|
328742
|
-
console.log(
|
|
328356
|
+
console.log(chalk33.green(` ${strictTag} All validators pass (score: ${(bpReport.score * 100).toFixed(0)}%). Specification met!`));
|
|
328743
328357
|
summary.specMet = true;
|
|
328744
328358
|
break;
|
|
328745
328359
|
}
|
|
328746
|
-
const passTag =
|
|
328747
|
-
const failTag = bpReport.failedCount > 0 ?
|
|
328748
|
-
const regTag = bpReport.regressionCount > 0 ?
|
|
328749
|
-
console.log(
|
|
328360
|
+
const passTag = chalk33.green(`${bpReport.passedCount} pass`);
|
|
328361
|
+
const failTag = bpReport.failedCount > 0 ? chalk33.red(` ${bpReport.failedCount} fail`) : "";
|
|
328362
|
+
const regTag = bpReport.regressionCount > 0 ? chalk33.bgRed(` ${bpReport.regressionCount} REGRESSION`) : "";
|
|
328363
|
+
console.log(chalk33.dim(` ${strictTag} Validators: ${passTag}${failTag}${regTag} (score: ${(bpReport.score * 100).toFixed(0)}%)`));
|
|
328750
328364
|
} else if (!gate && opts.verify && i > 1) {
|
|
328751
328365
|
const verifyResult = runShellCommand(opts.verify, cwd);
|
|
328752
328366
|
if (verifyResult.exitCode === 0) {
|
|
328753
|
-
console.log(
|
|
328367
|
+
console.log(chalk33.green(" Specification met! Verify command exited 0."));
|
|
328754
328368
|
summary.specMet = true;
|
|
328755
328369
|
break;
|
|
328756
328370
|
}
|
|
@@ -328790,7 +328404,7 @@ function registerLoopCommand(program2) {
|
|
|
328790
328404
|
contextRotation: { maxMessages: 40, maxTokensEstimate: 8e4 },
|
|
328791
328405
|
stuckDetection: { maxRepeatedCalls: 3, maxConsecutiveErrors: 3 }
|
|
328792
328406
|
});
|
|
328793
|
-
const taskId =
|
|
328407
|
+
const taskId = randomUUID68();
|
|
328794
328408
|
let iterOutput = "";
|
|
328795
328409
|
try {
|
|
328796
328410
|
for await (const event of runtime.runStreaming({
|
|
@@ -328804,16 +328418,16 @@ function registerLoopCommand(program2) {
|
|
|
328804
328418
|
iterOutput += event.text;
|
|
328805
328419
|
break;
|
|
328806
328420
|
case "tool_start":
|
|
328807
|
-
console.log(
|
|
328421
|
+
console.log(chalk33.dim(`
|
|
328808
328422
|
[tool] ${event.name}`));
|
|
328809
328423
|
break;
|
|
328810
328424
|
case "tool_result":
|
|
328811
328425
|
if (!event.success) {
|
|
328812
|
-
console.log(
|
|
328426
|
+
console.log(chalk33.red(` [tool error] ${event.name}: ${event.result.slice(0, 100)}`));
|
|
328813
328427
|
}
|
|
328814
328428
|
break;
|
|
328815
328429
|
case "error":
|
|
328816
|
-
console.log(
|
|
328430
|
+
console.log(chalk33.red(`
|
|
328817
328431
|
[error] ${event.message}`));
|
|
328818
328432
|
break;
|
|
328819
328433
|
case "done": {
|
|
@@ -328835,7 +328449,7 @@ function registerLoopCommand(program2) {
|
|
|
328835
328449
|
const postReport = gate.run();
|
|
328836
328450
|
iterResult.specMet = postReport.passed && postReport.score >= 0.95;
|
|
328837
328451
|
if (postReport.regressionCount > 0) {
|
|
328838
|
-
console.log(
|
|
328452
|
+
console.log(chalk33.bgRed(` REGRESSION detected in ${postReport.regressionCount} validator(s)`));
|
|
328839
328453
|
}
|
|
328840
328454
|
} else if (opts.verify) {
|
|
328841
328455
|
const postVerify = runShellCommand(opts.verify, cwd);
|
|
@@ -328843,9 +328457,9 @@ function registerLoopCommand(program2) {
|
|
|
328843
328457
|
}
|
|
328844
328458
|
summary.iterationResults.push(iterResult);
|
|
328845
328459
|
console.log("");
|
|
328846
|
-
console.log(
|
|
328460
|
+
console.log(chalk33.dim(` [${r.exitReason}] ${r.usage.totalTokens} tokens, $${r.usage.estimatedCostUsd.toFixed(4)}, ${(r.durationMs / 1e3).toFixed(1)}s`));
|
|
328847
328461
|
if (iterResult.specMet) {
|
|
328848
|
-
console.log(
|
|
328462
|
+
console.log(chalk33.green(" Specification met!"));
|
|
328849
328463
|
summary.specMet = true;
|
|
328850
328464
|
}
|
|
328851
328465
|
break;
|
|
@@ -328853,7 +328467,7 @@ function registerLoopCommand(program2) {
|
|
|
328853
328467
|
}
|
|
328854
328468
|
}
|
|
328855
328469
|
} catch (err) {
|
|
328856
|
-
console.error(
|
|
328470
|
+
console.error(chalk33.red(`
|
|
328857
328471
|
Iteration ${i} crashed: ${err instanceof Error ? err.message : String(err)}`));
|
|
328858
328472
|
summary.iterationResults.push({
|
|
328859
328473
|
iteration: i,
|
|
@@ -328867,14 +328481,14 @@ function registerLoopCommand(program2) {
|
|
|
328867
328481
|
}
|
|
328868
328482
|
if (summary.specMet) break;
|
|
328869
328483
|
}
|
|
328870
|
-
console.log(
|
|
328871
|
-
console.log(
|
|
328872
|
-
console.log(
|
|
328873
|
-
console.log(
|
|
328874
|
-
console.log(
|
|
328484
|
+
console.log(chalk33.cyan("\n \u2500\u2500 Loop Summary \u2500\u2500"));
|
|
328485
|
+
console.log(chalk33.white(" Iterations:"), summary.totalIterations);
|
|
328486
|
+
console.log(chalk33.white(" Total cost:"), `$${summary.totalCostUsd.toFixed(4)}`);
|
|
328487
|
+
console.log(chalk33.white(" Total tokens:"), summary.totalTokens.toLocaleString());
|
|
328488
|
+
console.log(chalk33.white(" Total time:"), `${(summary.totalDurationMs / 1e3).toFixed(1)}s`);
|
|
328875
328489
|
console.log(
|
|
328876
|
-
|
|
328877
|
-
summary.specMet ?
|
|
328490
|
+
chalk33.white(" Spec met:"),
|
|
328491
|
+
summary.specMet ? chalk33.green("YES") : chalk33.red("NO")
|
|
328878
328492
|
);
|
|
328879
328493
|
console.log("");
|
|
328880
328494
|
desktopNotify2(
|
|
@@ -328889,7 +328503,7 @@ function registerLoopCommand(program2) {
|
|
|
328889
328503
|
// src/commands/messaging.ts
|
|
328890
328504
|
init_config2();
|
|
328891
328505
|
init_config();
|
|
328892
|
-
import
|
|
328506
|
+
import chalk34 from "chalk";
|
|
328893
328507
|
function getAdapterEnvStatus2() {
|
|
328894
328508
|
return [
|
|
328895
328509
|
{
|
|
@@ -328921,25 +328535,25 @@ function registerMessagingCommand(program2) {
|
|
|
328921
328535
|
messaging.command("status").description("Show which messaging adapters are configured").action(async () => {
|
|
328922
328536
|
const config2 = readConfigFile() ?? mergeWithDefaults({});
|
|
328923
328537
|
console.log("");
|
|
328924
|
-
console.log(
|
|
328925
|
-
console.log(
|
|
328538
|
+
console.log(chalk34.bold(" Messaging Status"));
|
|
328539
|
+
console.log(chalk34.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
328926
328540
|
const msgConfig = config2.messaging;
|
|
328927
328541
|
const enabled = msgConfig?.enabled ?? false;
|
|
328928
|
-
console.log(` ${
|
|
328542
|
+
console.log(` ${chalk34.dim("Enabled:")} ${enabled ? chalk34.green("true") : chalk34.yellow("false")}`);
|
|
328929
328543
|
if (msgConfig?.defaultAgentId) {
|
|
328930
|
-
console.log(` ${
|
|
328544
|
+
console.log(` ${chalk34.dim("Default Agent:")} ${msgConfig.defaultAgentId}`);
|
|
328931
328545
|
}
|
|
328932
328546
|
console.log("");
|
|
328933
|
-
console.log(
|
|
328934
|
-
console.log(
|
|
328547
|
+
console.log(chalk34.bold(" Adapter Configuration"));
|
|
328548
|
+
console.log(chalk34.dim(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
328935
328549
|
const envStatus = getAdapterEnvStatus2();
|
|
328936
328550
|
for (const adapter of envStatus) {
|
|
328937
|
-
const icon = adapter.configured ?
|
|
328938
|
-
const label = adapter.configured ?
|
|
328939
|
-
console.log(` ${icon} ${
|
|
328551
|
+
const icon = adapter.configured ? chalk34.green("\u25CF") : chalk34.dim("\u25CB");
|
|
328552
|
+
const label = adapter.configured ? chalk34.green("ready") : chalk34.dim("not configured");
|
|
328553
|
+
console.log(` ${icon} ${chalk34.bold(adapter.platform.padEnd(12))} ${label}`);
|
|
328940
328554
|
for (const [varName, found] of Object.entries(adapter.envVars)) {
|
|
328941
|
-
const varIcon = found ?
|
|
328942
|
-
console.log(` ${varIcon} ${
|
|
328555
|
+
const varIcon = found ? chalk34.green(" \u2713") : chalk34.red(" \u2717");
|
|
328556
|
+
console.log(` ${varIcon} ${chalk34.dim(varName)}`);
|
|
328943
328557
|
}
|
|
328944
328558
|
}
|
|
328945
328559
|
const configTokens = [];
|
|
@@ -328948,30 +328562,30 @@ function registerMessagingCommand(program2) {
|
|
|
328948
328562
|
if (msgConfig?.slack?.botToken && msgConfig.slack.appToken) configTokens.push("slack");
|
|
328949
328563
|
if (configTokens.length > 0) {
|
|
328950
328564
|
console.log("");
|
|
328951
|
-
console.log(
|
|
328565
|
+
console.log(chalk34.dim(` Tokens also found in config file for: ${configTokens.join(", ")}`));
|
|
328952
328566
|
}
|
|
328953
328567
|
console.log("");
|
|
328954
|
-
console.log(
|
|
328955
|
-
console.log(
|
|
328956
|
-
console.log(
|
|
328957
|
-
console.log(
|
|
328958
|
-
console.log(
|
|
328568
|
+
console.log(chalk34.dim(" Required environment variables:"));
|
|
328569
|
+
console.log(chalk34.dim(" TELEGRAM_BOT_TOKEN \u2014 Telegram BotFather token"));
|
|
328570
|
+
console.log(chalk34.dim(" DISCORD_BOT_TOKEN \u2014 Discord bot token"));
|
|
328571
|
+
console.log(chalk34.dim(" SLACK_BOT_TOKEN \u2014 Slack Bot User OAuth Token (xoxb-...)"));
|
|
328572
|
+
console.log(chalk34.dim(" SLACK_APP_TOKEN \u2014 Slack App-Level Token (xapp-...)"));
|
|
328959
328573
|
console.log("");
|
|
328960
|
-
console.log(
|
|
328574
|
+
console.log(chalk34.dim(" Set messaging.enabled=true in nestor.config.json to activate."));
|
|
328961
328575
|
console.log("");
|
|
328962
328576
|
});
|
|
328963
328577
|
messaging.command("test").description("Send a test message via an adapter").argument("<adapter>", "Adapter to test: telegram, discord, or slack").option("-c, --channel <id>", "Channel/chat ID to send the test message to").option("-m, --message <text>", "Custom test message text").action(async (adapter, options) => {
|
|
328964
328578
|
const validAdapters = ["telegram", "discord", "slack"];
|
|
328965
328579
|
if (!validAdapters.includes(adapter)) {
|
|
328966
|
-
console.error(
|
|
328580
|
+
console.error(chalk34.red(` Unknown adapter "${adapter}". Must be one of: ${validAdapters.join(", ")}`));
|
|
328967
328581
|
process.exit(1);
|
|
328968
328582
|
}
|
|
328969
328583
|
if (!options.channel) {
|
|
328970
|
-
console.error(
|
|
328584
|
+
console.error(chalk34.red(" --channel is required. Provide the target channel/chat ID."));
|
|
328971
328585
|
process.exit(1);
|
|
328972
328586
|
}
|
|
328973
328587
|
console.log("");
|
|
328974
|
-
console.log(
|
|
328588
|
+
console.log(chalk34.dim(` Testing ${adapter} adapter...`));
|
|
328975
328589
|
const config2 = readConfigFile() ?? mergeWithDefaults({});
|
|
328976
328590
|
const host = config2.server.host ?? "127.0.0.1";
|
|
328977
328591
|
const port = config2.server.port ?? 3100;
|
|
@@ -328989,22 +328603,22 @@ function registerMessagingCommand(program2) {
|
|
|
328989
328603
|
const result = await response.json();
|
|
328990
328604
|
if (!response.ok) {
|
|
328991
328605
|
const error = result.error;
|
|
328992
|
-
console.error(
|
|
328606
|
+
console.error(chalk34.red(` Failed: ${error?.message ?? response.statusText}`));
|
|
328993
328607
|
if (response.status === 503) {
|
|
328994
|
-
console.log(
|
|
328995
|
-
console.log(
|
|
328608
|
+
console.log(chalk34.dim(" Make sure the Nestor server is running with messaging enabled."));
|
|
328609
|
+
console.log(chalk34.dim(" Run: npx nestor-sh start"));
|
|
328996
328610
|
}
|
|
328997
328611
|
process.exit(1);
|
|
328998
328612
|
}
|
|
328999
328613
|
const data = result.data;
|
|
329000
|
-
console.log(
|
|
329001
|
-
console.log(` ${
|
|
329002
|
-
console.log(` ${
|
|
329003
|
-
console.log(` ${
|
|
328614
|
+
console.log(chalk34.green(` Message sent successfully!`));
|
|
328615
|
+
console.log(` ${chalk34.dim("Platform:")} ${data.platform}`);
|
|
328616
|
+
console.log(` ${chalk34.dim("Channel:")} ${data.channelId}`);
|
|
328617
|
+
console.log(` ${chalk34.dim("Message ID:")} ${data.messageId}`);
|
|
329004
328618
|
console.log("");
|
|
329005
328619
|
} catch (err) {
|
|
329006
|
-
console.error(
|
|
329007
|
-
console.log(
|
|
328620
|
+
console.error(chalk34.red(` Failed to connect to Nestor server at ${baseUrl}`));
|
|
328621
|
+
console.log(chalk34.dim(" Make sure the server is running: npx nestor-sh start"));
|
|
329008
328622
|
console.log("");
|
|
329009
328623
|
process.exit(1);
|
|
329010
328624
|
}
|
|
@@ -329012,11 +328626,11 @@ function registerMessagingCommand(program2) {
|
|
|
329012
328626
|
messaging.command("send").description("Send a message to a specific channel via an adapter").argument("<adapter>", "Adapter: telegram, discord, or slack").argument("<channel>", "Channel or chat ID to send to").argument("<message>", "Message text to send").action(async (adapter, channel, message) => {
|
|
329013
328627
|
const validAdapters = ["telegram", "discord", "slack"];
|
|
329014
328628
|
if (!validAdapters.includes(adapter)) {
|
|
329015
|
-
console.error(
|
|
328629
|
+
console.error(chalk34.red(` Unknown adapter "${adapter}". Must be one of: ${validAdapters.join(", ")}`));
|
|
329016
328630
|
process.exit(1);
|
|
329017
328631
|
}
|
|
329018
328632
|
console.log("");
|
|
329019
|
-
console.log(
|
|
328633
|
+
console.log(chalk34.dim(` Sending message via ${adapter}...`));
|
|
329020
328634
|
const config2 = readConfigFile() ?? mergeWithDefaults({});
|
|
329021
328635
|
const host = config2.server.host ?? "127.0.0.1";
|
|
329022
328636
|
const port = config2.server.port ?? 3100;
|
|
@@ -329034,39 +328648,39 @@ function registerMessagingCommand(program2) {
|
|
|
329034
328648
|
const result = await response.json();
|
|
329035
328649
|
if (!response.ok) {
|
|
329036
328650
|
const error = result.error;
|
|
329037
|
-
console.error(
|
|
328651
|
+
console.error(chalk34.red(` Failed: ${error?.message ?? response.statusText}`));
|
|
329038
328652
|
if (response.status === 503) {
|
|
329039
|
-
console.log(
|
|
329040
|
-
console.log(
|
|
328653
|
+
console.log(chalk34.dim(" Make sure the Nestor server is running with messaging enabled."));
|
|
328654
|
+
console.log(chalk34.dim(" Run: npx nestor-sh start"));
|
|
329041
328655
|
}
|
|
329042
328656
|
process.exit(1);
|
|
329043
328657
|
}
|
|
329044
328658
|
const data = result.data;
|
|
329045
|
-
console.log(
|
|
329046
|
-
console.log(` ${
|
|
329047
|
-
console.log(` ${
|
|
329048
|
-
console.log(` ${
|
|
328659
|
+
console.log(chalk34.green(` Message sent!`));
|
|
328660
|
+
console.log(` ${chalk34.dim("Platform:")} ${data.platform}`);
|
|
328661
|
+
console.log(` ${chalk34.dim("Channel:")} ${data.channelId}`);
|
|
328662
|
+
console.log(` ${chalk34.dim("Message ID:")} ${data.messageId}`);
|
|
329049
328663
|
console.log("");
|
|
329050
328664
|
} catch (err) {
|
|
329051
|
-
console.error(
|
|
329052
|
-
console.log(
|
|
328665
|
+
console.error(chalk34.red(` Failed to connect to Nestor server at ${baseUrl}`));
|
|
328666
|
+
console.log(chalk34.dim(" Make sure the server is running: npx nestor-sh start"));
|
|
329053
328667
|
console.log("");
|
|
329054
328668
|
process.exit(1);
|
|
329055
328669
|
}
|
|
329056
328670
|
});
|
|
329057
328671
|
messaging.command("listen").description("Start listening for incoming messages (starts messaging bridge)").action(async () => {
|
|
329058
328672
|
console.log("");
|
|
329059
|
-
console.log(
|
|
328673
|
+
console.log(chalk34.bold(" Starting messaging bridge..."));
|
|
329060
328674
|
console.log("");
|
|
329061
328675
|
let config2 = readConfigFile();
|
|
329062
328676
|
if (!config2) {
|
|
329063
|
-
console.log(
|
|
328677
|
+
console.log(chalk34.yellow(" [warn]"), "No config file found, using defaults");
|
|
329064
328678
|
config2 = mergeWithDefaults({});
|
|
329065
328679
|
}
|
|
329066
328680
|
const msgConfig = config2.messaging;
|
|
329067
328681
|
if (!msgConfig?.enabled) {
|
|
329068
|
-
console.error(
|
|
329069
|
-
console.log(
|
|
328682
|
+
console.error(chalk34.red(" Messaging is not enabled in your configuration."));
|
|
328683
|
+
console.log(chalk34.dim(" Set messaging.enabled=true in nestor.config.json"));
|
|
329070
328684
|
console.log("");
|
|
329071
328685
|
process.exit(1);
|
|
329072
328686
|
}
|
|
@@ -329078,12 +328692,12 @@ function registerMessagingCommand(program2) {
|
|
|
329078
328692
|
const { bootstrapMessagingBridge: bootstrapMessagingBridge2 } = await Promise.resolve().then(() => (init_src8(), src_exports6));
|
|
329079
328693
|
const bridge = bootstrapMessagingBridge2(store, msgConfig, logger);
|
|
329080
328694
|
if (!bridge) {
|
|
329081
|
-
console.error(
|
|
328695
|
+
console.error(chalk34.red(" No adapter tokens found. Configure at least one platform."));
|
|
329082
328696
|
console.log("");
|
|
329083
|
-
console.log(
|
|
329084
|
-
console.log(
|
|
329085
|
-
console.log(
|
|
329086
|
-
console.log(
|
|
328697
|
+
console.log(chalk34.dim(" Required environment variables:"));
|
|
328698
|
+
console.log(chalk34.dim(" TELEGRAM_BOT_TOKEN"));
|
|
328699
|
+
console.log(chalk34.dim(" DISCORD_BOT_TOKEN"));
|
|
328700
|
+
console.log(chalk34.dim(" SLACK_BOT_TOKEN + SLACK_APP_TOKEN"));
|
|
329087
328701
|
console.log("");
|
|
329088
328702
|
store.close();
|
|
329089
328703
|
process.exit(1);
|
|
@@ -329091,28 +328705,28 @@ function registerMessagingCommand(program2) {
|
|
|
329091
328705
|
try {
|
|
329092
328706
|
await bridge.startAll();
|
|
329093
328707
|
const adapters = bridge.getStatus();
|
|
329094
|
-
console.log(
|
|
328708
|
+
console.log(chalk34.green(" Messaging bridge started"));
|
|
329095
328709
|
console.log("");
|
|
329096
328710
|
for (const a of adapters) {
|
|
329097
|
-
const icon = a.healthy ?
|
|
328711
|
+
const icon = a.healthy ? chalk34.green("\u25CF") : chalk34.red("\u25CB");
|
|
329098
328712
|
const label = a.healthy ? "connected" : "disconnected";
|
|
329099
328713
|
console.log(` ${icon} ${a.platform}: ${label}`);
|
|
329100
328714
|
}
|
|
329101
328715
|
console.log("");
|
|
329102
|
-
console.log(
|
|
328716
|
+
console.log(chalk34.dim(" Listening for messages. Press Ctrl+C to stop."));
|
|
329103
328717
|
console.log("");
|
|
329104
328718
|
const shutdown = async (signal) => {
|
|
329105
328719
|
console.log("");
|
|
329106
|
-
console.log(
|
|
328720
|
+
console.log(chalk34.yellow(` Received ${signal}, stopping...`));
|
|
329107
328721
|
await bridge.stopAll();
|
|
329108
328722
|
store.close();
|
|
329109
|
-
console.log(
|
|
328723
|
+
console.log(chalk34.green(" Messaging bridge stopped."));
|
|
329110
328724
|
process.exit(0);
|
|
329111
328725
|
};
|
|
329112
328726
|
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
329113
328727
|
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
329114
328728
|
} catch (err) {
|
|
329115
|
-
console.error(
|
|
328729
|
+
console.error(chalk34.red(` Failed to start messaging bridge: ${err instanceof Error ? err.message : String(err)}`));
|
|
329116
328730
|
store.close();
|
|
329117
328731
|
process.exit(1);
|
|
329118
328732
|
}
|
|
@@ -329122,7 +328736,7 @@ function registerMessagingCommand(program2) {
|
|
|
329122
328736
|
// src/commands/schedule.ts
|
|
329123
328737
|
init_db();
|
|
329124
328738
|
init_config2();
|
|
329125
|
-
import
|
|
328739
|
+
import chalk35 from "chalk";
|
|
329126
328740
|
import fs30 from "node:fs";
|
|
329127
328741
|
import path30 from "node:path";
|
|
329128
328742
|
function legacyJsonPath() {
|
|
@@ -329185,7 +328799,7 @@ async function migrateLegacyJsonIfPresent() {
|
|
|
329185
328799
|
}
|
|
329186
328800
|
return;
|
|
329187
328801
|
}
|
|
329188
|
-
console.log(
|
|
328802
|
+
console.log(chalk35.dim(`Migrating ${legacy.length} legacy schedule(s) from ${jsonPath} to server DB...`));
|
|
329189
328803
|
let migrated = 0;
|
|
329190
328804
|
let failed = 0;
|
|
329191
328805
|
for (const entry of legacy) {
|
|
@@ -329194,7 +328808,7 @@ async function migrateLegacyJsonIfPresent() {
|
|
|
329194
328808
|
migrated++;
|
|
329195
328809
|
} catch (err) {
|
|
329196
328810
|
failed++;
|
|
329197
|
-
console.log(
|
|
328811
|
+
console.log(chalk35.yellow(
|
|
329198
328812
|
` ${entry.agentName}: migration failed (${err instanceof Error ? err.message : String(err)})`
|
|
329199
328813
|
));
|
|
329200
328814
|
}
|
|
@@ -329204,14 +328818,14 @@ async function migrateLegacyJsonIfPresent() {
|
|
|
329204
328818
|
fs30.unlinkSync(jsonPath);
|
|
329205
328819
|
} catch {
|
|
329206
328820
|
}
|
|
329207
|
-
console.log(
|
|
328821
|
+
console.log(chalk35.green(` Migrated ${migrated}/${legacy.length}. Legacy file removed.`));
|
|
329208
328822
|
} else {
|
|
329209
328823
|
const backup = jsonPath + ".bak";
|
|
329210
328824
|
try {
|
|
329211
328825
|
fs30.renameSync(jsonPath, backup);
|
|
329212
328826
|
} catch {
|
|
329213
328827
|
}
|
|
329214
|
-
console.log(
|
|
328828
|
+
console.log(chalk35.yellow(
|
|
329215
328829
|
` Migrated ${migrated}/${legacy.length}. ${failed} failed. Original kept as ${backup}.`
|
|
329216
328830
|
));
|
|
329217
328831
|
}
|
|
@@ -329269,8 +328883,8 @@ function pad4(s, width) {
|
|
|
329269
328883
|
return s + " ".repeat(width - s.length);
|
|
329270
328884
|
}
|
|
329271
328885
|
function handleServerError(err) {
|
|
329272
|
-
console.error(
|
|
329273
|
-
console.log(
|
|
328886
|
+
console.error(chalk35.red(` ${err instanceof Error ? err.message : String(err)}`));
|
|
328887
|
+
console.log(chalk35.dim(" Is the server running? Start it with: npx nestor-sh start"));
|
|
329274
328888
|
console.log("");
|
|
329275
328889
|
process.exit(1);
|
|
329276
328890
|
}
|
|
@@ -329281,8 +328895,8 @@ function registerScheduleCommand(program2) {
|
|
|
329281
328895
|
await migrateLegacyJsonIfPresent();
|
|
329282
328896
|
const schedules = await listSchedulesFromServer();
|
|
329283
328897
|
if (schedules.length === 0) {
|
|
329284
|
-
console.log(
|
|
329285
|
-
console.log(
|
|
328898
|
+
console.log(chalk35.yellow("No scheduled agents."));
|
|
328899
|
+
console.log(chalk35.dim("Use `npx nestor-sh schedule add <agent> <cron>` to schedule one."));
|
|
329286
328900
|
return;
|
|
329287
328901
|
}
|
|
329288
328902
|
if (options.json) {
|
|
@@ -329291,15 +328905,15 @@ function registerScheduleCommand(program2) {
|
|
|
329291
328905
|
}
|
|
329292
328906
|
const nameW = 20, cronW = 20, nextW = 25, lastW = 22, statusW = 10;
|
|
329293
328907
|
console.log("");
|
|
329294
|
-
console.log(
|
|
328908
|
+
console.log(chalk35.bold(
|
|
329295
328909
|
pad4("Agent", nameW) + pad4("Cron", cronW) + pad4("Next Run", nextW) + pad4("Last Run", lastW) + pad4("Status", statusW)
|
|
329296
328910
|
));
|
|
329297
|
-
console.log(
|
|
328911
|
+
console.log(chalk35.dim("-".repeat(nameW + cronW + nextW + lastW + statusW)));
|
|
329298
328912
|
for (const s of schedules) {
|
|
329299
|
-
const statusColor2 = s.enabled ?
|
|
328913
|
+
const statusColor2 = s.enabled ? chalk35.green : chalk35.yellow;
|
|
329300
328914
|
const statusLabel = s.enabled ? "active" : "paused";
|
|
329301
328915
|
const nextRun = computeNextRun(s.cron);
|
|
329302
|
-
const lastRun = s.lastRunAt ? s.lastRunAt.substring(0, 19).replace("T", " ") :
|
|
328916
|
+
const lastRun = s.lastRunAt ? s.lastRunAt.substring(0, 19).replace("T", " ") : chalk35.dim("never");
|
|
329303
328917
|
console.log(
|
|
329304
328918
|
pad4(s.agentName, nameW) + pad4(s.cron, cronW) + pad4(nextRun, nextW) + pad4(String(lastRun), lastW) + statusColor2(pad4(statusLabel, statusW))
|
|
329305
328919
|
);
|
|
@@ -329311,9 +328925,9 @@ function registerScheduleCommand(program2) {
|
|
|
329311
328925
|
});
|
|
329312
328926
|
schedule.command("add").description("Schedule an agent with a cron expression").argument("<agent>", "Agent name").argument("<cron>", 'Cron expression (5-field, e.g. "0 9 * * 1-5")').option("-p, --prompt <text>", "Prompt to run on each tick", "Execute scheduled task.").action(async (agentName, cronExpr, options) => {
|
|
329313
328927
|
if (!isValidCron(cronExpr)) {
|
|
329314
|
-
console.error(
|
|
329315
|
-
console.log(
|
|
329316
|
-
console.log(
|
|
328928
|
+
console.error(chalk35.red(`Invalid cron expression: "${cronExpr}"`));
|
|
328929
|
+
console.log(chalk35.dim(" Format: minute hour day-of-month month day-of-week"));
|
|
328930
|
+
console.log(chalk35.dim(' Examples: "0 9 * * 1-5" (weekdays at 9am), "*/15 * * * *" (every 15min)'));
|
|
329317
328931
|
process.exit(1);
|
|
329318
328932
|
}
|
|
329319
328933
|
const store = await getStore();
|
|
@@ -329321,8 +328935,8 @@ function registerScheduleCommand(program2) {
|
|
|
329321
328935
|
try {
|
|
329322
328936
|
const agentCfg = store.getAgentByName(agentName);
|
|
329323
328937
|
if (!agentCfg) {
|
|
329324
|
-
console.error(
|
|
329325
|
-
console.log(
|
|
328938
|
+
console.error(chalk35.red(`Agent '${agentName}' not found.`));
|
|
328939
|
+
console.log(chalk35.dim("Use `npx nestor-sh agent list` to see available agents."));
|
|
329326
328940
|
process.exit(1);
|
|
329327
328941
|
}
|
|
329328
328942
|
agentId = agentCfg.id;
|
|
@@ -329332,13 +328946,13 @@ function registerScheduleCommand(program2) {
|
|
|
329332
328946
|
try {
|
|
329333
328947
|
await migrateLegacyJsonIfPresent();
|
|
329334
328948
|
await setScheduleOnServer(agentId, cronExpr, options.prompt, true);
|
|
329335
|
-
console.log(
|
|
329336
|
-
console.log(` ${
|
|
329337
|
-
console.log(` ${
|
|
329338
|
-
console.log(` ${
|
|
328949
|
+
console.log(chalk35.green(`Agent '${agentName}' scheduled.`));
|
|
328950
|
+
console.log(` ${chalk35.dim("Cron:")} ${cronExpr}`);
|
|
328951
|
+
console.log(` ${chalk35.dim("Schedule:")} ${computeNextRun(cronExpr)}`);
|
|
328952
|
+
console.log(` ${chalk35.dim("Prompt:")} ${options.prompt}`);
|
|
329339
328953
|
console.log("");
|
|
329340
|
-
console.log(
|
|
329341
|
-
console.log(
|
|
328954
|
+
console.log(chalk35.dim(" The schedule fires when the server is running."));
|
|
328955
|
+
console.log(chalk35.dim(" Start it with: npx nestor-sh start"));
|
|
329342
328956
|
} catch (err) {
|
|
329343
328957
|
handleServerError(err);
|
|
329344
328958
|
}
|
|
@@ -329349,7 +328963,7 @@ function registerScheduleCommand(program2) {
|
|
|
329349
328963
|
try {
|
|
329350
328964
|
const agentCfg = store.getAgentByName(agentName);
|
|
329351
328965
|
if (!agentCfg) {
|
|
329352
|
-
console.error(
|
|
328966
|
+
console.error(chalk35.red(`Agent '${agentName}' not found.`));
|
|
329353
328967
|
process.exit(1);
|
|
329354
328968
|
}
|
|
329355
328969
|
agentId = agentCfg.id;
|
|
@@ -329359,7 +328973,7 @@ function registerScheduleCommand(program2) {
|
|
|
329359
328973
|
try {
|
|
329360
328974
|
await migrateLegacyJsonIfPresent();
|
|
329361
328975
|
await deleteScheduleOnServer(agentId);
|
|
329362
|
-
console.log(
|
|
328976
|
+
console.log(chalk35.green(`Schedule for '${agentName}' removed.`));
|
|
329363
328977
|
} catch (err) {
|
|
329364
328978
|
handleServerError(err);
|
|
329365
328979
|
}
|
|
@@ -329376,22 +328990,22 @@ function registerScheduleCommand(program2) {
|
|
|
329376
328990
|
const schedules = await listSchedulesFromServer();
|
|
329377
328991
|
const entry = schedules.find((s) => s.agentName === agentName);
|
|
329378
328992
|
if (!entry) {
|
|
329379
|
-
console.error(
|
|
328993
|
+
console.error(chalk35.red(`No schedule found for agent '${agentName}'.`));
|
|
329380
328994
|
process.exit(1);
|
|
329381
328995
|
}
|
|
329382
|
-
console.log(
|
|
328996
|
+
console.log(chalk35.cyan(` Triggering immediate run for '${agentName}'...`));
|
|
329383
328997
|
const res = await apiCall("POST", `/agents/${entry.agentId}/run`, {
|
|
329384
328998
|
prompt: entry.prompt ?? "Execute scheduled task."
|
|
329385
328999
|
});
|
|
329386
329000
|
if (!res.ok) {
|
|
329387
329001
|
const body2 = await res.json().catch(() => ({}));
|
|
329388
329002
|
const err = body2.error;
|
|
329389
|
-
console.error(
|
|
329003
|
+
console.error(chalk35.red(` Failed: ${err?.message ?? res.statusText}`));
|
|
329390
329004
|
process.exit(1);
|
|
329391
329005
|
}
|
|
329392
329006
|
const body = await res.json();
|
|
329393
|
-
console.log(
|
|
329394
|
-
if (body.data?.runId) console.log(` ${
|
|
329007
|
+
console.log(chalk35.green(` Agent '${agentName}' triggered successfully.`));
|
|
329008
|
+
if (body.data?.runId) console.log(` ${chalk35.dim("Run ID:")} ${String(body.data.runId)}`);
|
|
329395
329009
|
console.log("");
|
|
329396
329010
|
} catch (err) {
|
|
329397
329011
|
handleServerError(err);
|
|
@@ -329404,7 +329018,7 @@ async function setEnabledByName(agentName, enabled) {
|
|
|
329404
329018
|
try {
|
|
329405
329019
|
const agentCfg = store.getAgentByName(agentName);
|
|
329406
329020
|
if (!agentCfg) {
|
|
329407
|
-
console.error(
|
|
329021
|
+
console.error(chalk35.red(`Agent '${agentName}' not found.`));
|
|
329408
329022
|
process.exit(1);
|
|
329409
329023
|
}
|
|
329410
329024
|
agentId = agentCfg.id;
|
|
@@ -329416,15 +329030,15 @@ async function setEnabledByName(agentName, enabled) {
|
|
|
329416
329030
|
const schedules = await listSchedulesFromServer();
|
|
329417
329031
|
const current = schedules.find((s) => s.agentId === agentId);
|
|
329418
329032
|
if (!current) {
|
|
329419
|
-
console.error(
|
|
329033
|
+
console.error(chalk35.red(`No schedule found for agent '${agentName}'.`));
|
|
329420
329034
|
process.exit(1);
|
|
329421
329035
|
}
|
|
329422
329036
|
if (current.enabled === enabled) {
|
|
329423
|
-
console.log(
|
|
329037
|
+
console.log(chalk35.yellow(`Schedule for '${agentName}' is already ${enabled ? "active" : "paused"}.`));
|
|
329424
329038
|
return;
|
|
329425
329039
|
}
|
|
329426
329040
|
await setScheduleOnServer(agentId, current.cron, current.prompt ?? void 0, enabled);
|
|
329427
|
-
console.log(
|
|
329041
|
+
console.log(chalk35.green(`Schedule for '${agentName}' ${enabled ? "resumed" : "paused"}.`));
|
|
329428
329042
|
} catch (err) {
|
|
329429
329043
|
handleServerError(err);
|
|
329430
329044
|
}
|
|
@@ -329434,7 +329048,7 @@ async function setEnabledByName(agentName, enabled) {
|
|
|
329434
329048
|
init_db();
|
|
329435
329049
|
init_paths();
|
|
329436
329050
|
import * as p8 from "@clack/prompts";
|
|
329437
|
-
import
|
|
329051
|
+
import chalk36 from "chalk";
|
|
329438
329052
|
import fs31 from "node:fs";
|
|
329439
329053
|
import path31 from "node:path";
|
|
329440
329054
|
function getSkillsDir2() {
|
|
@@ -329455,36 +329069,36 @@ function truncate2(s, max) {
|
|
|
329455
329069
|
function statusColor(status) {
|
|
329456
329070
|
switch (status) {
|
|
329457
329071
|
case "pending":
|
|
329458
|
-
return
|
|
329072
|
+
return chalk36.yellow;
|
|
329459
329073
|
case "approved":
|
|
329460
329074
|
case "auto_approved":
|
|
329461
|
-
return
|
|
329075
|
+
return chalk36.green;
|
|
329462
329076
|
case "rejected":
|
|
329463
|
-
return
|
|
329077
|
+
return chalk36.red;
|
|
329464
329078
|
default:
|
|
329465
|
-
return
|
|
329079
|
+
return chalk36.dim;
|
|
329466
329080
|
}
|
|
329467
329081
|
}
|
|
329468
329082
|
function confidenceColor(confidence) {
|
|
329469
|
-
if (confidence >= 0.8) return
|
|
329470
|
-
if (confidence >= 0.5) return
|
|
329471
|
-
return
|
|
329083
|
+
if (confidence >= 0.8) return chalk36.green;
|
|
329084
|
+
if (confidence >= 0.5) return chalk36.yellow;
|
|
329085
|
+
return chalk36.red;
|
|
329472
329086
|
}
|
|
329473
329087
|
function formatCandidate(c) {
|
|
329474
329088
|
console.log("");
|
|
329475
|
-
console.log(
|
|
329476
|
-
console.log(
|
|
329477
|
-
console.log(` ${
|
|
329478
|
-
console.log(` ${
|
|
329479
|
-
console.log(` ${
|
|
329480
|
-
console.log(` ${
|
|
329481
|
-
console.log(` ${
|
|
329482
|
-
console.log(` ${
|
|
329089
|
+
console.log(chalk36.bold(` Candidate: ${c.skillName}`));
|
|
329090
|
+
console.log(chalk36.dim(" " + "\u2500".repeat(50)));
|
|
329091
|
+
console.log(` ${chalk36.cyan("ID:")} ${c.id}`);
|
|
329092
|
+
console.log(` ${chalk36.cyan("Pattern:")} ${truncate2(c.pattern, 60)}`);
|
|
329093
|
+
console.log(` ${chalk36.cyan("Description:")} ${truncate2(c.skillDescription, 60)}`);
|
|
329094
|
+
console.log(` ${chalk36.cyan("Confidence:")} ${confidenceColor(c.confidence)((c.confidence * 100).toFixed(0) + "%")}`);
|
|
329095
|
+
console.log(` ${chalk36.cyan("Status:")} ${statusColor(c.status)(c.status)}`);
|
|
329096
|
+
console.log(` ${chalk36.cyan("Created:")} ${c.createdAt}`);
|
|
329483
329097
|
if (c.sourceAgentId) {
|
|
329484
|
-
console.log(` ${
|
|
329098
|
+
console.log(` ${chalk36.cyan("Source Agent:")} ${c.sourceAgentId}`);
|
|
329485
329099
|
}
|
|
329486
329100
|
if (c.reviewedAt) {
|
|
329487
|
-
console.log(` ${
|
|
329101
|
+
console.log(` ${chalk36.cyan("Reviewed:")} ${c.reviewedAt} by ${c.reviewedBy ?? "unknown"}`);
|
|
329488
329102
|
}
|
|
329489
329103
|
}
|
|
329490
329104
|
function installCandidate(candidate) {
|
|
@@ -329509,8 +329123,8 @@ function registerEvolveCommand(program2) {
|
|
|
329509
329123
|
limit
|
|
329510
329124
|
});
|
|
329511
329125
|
if (candidates.length === 0) {
|
|
329512
|
-
console.log(
|
|
329513
|
-
console.log(
|
|
329126
|
+
console.log(chalk36.yellow("No skill candidates found."));
|
|
329127
|
+
console.log(chalk36.dim("Candidates are generated automatically during agent runs when evolve is enabled."));
|
|
329514
329128
|
return;
|
|
329515
329129
|
}
|
|
329516
329130
|
if (options.json) {
|
|
@@ -329524,22 +329138,22 @@ function registerEvolveCommand(program2) {
|
|
|
329524
329138
|
const patternW = 30;
|
|
329525
329139
|
console.log("");
|
|
329526
329140
|
console.log(
|
|
329527
|
-
|
|
329141
|
+
chalk36.bold(
|
|
329528
329142
|
pad5("ID", idW) + pad5("Skill Name", nameW) + pad5("Confidence", confW) + pad5("Status", statusW) + pad5("Pattern", patternW)
|
|
329529
329143
|
)
|
|
329530
329144
|
);
|
|
329531
|
-
console.log(
|
|
329145
|
+
console.log(chalk36.dim("-".repeat(idW + nameW + confW + statusW + patternW)));
|
|
329532
329146
|
for (const c of candidates) {
|
|
329533
329147
|
const shortId = c.id.substring(0, 8);
|
|
329534
329148
|
const confStr = (c.confidence * 100).toFixed(0) + "%";
|
|
329535
329149
|
console.log(
|
|
329536
|
-
pad5(shortId, idW) + pad5(c.skillName, nameW) + confidenceColor(c.confidence)(pad5(confStr, confW)) + statusColor(c.status)(pad5(c.status, statusW)) +
|
|
329150
|
+
pad5(shortId, idW) + pad5(c.skillName, nameW) + confidenceColor(c.confidence)(pad5(confStr, confW)) + statusColor(c.status)(pad5(c.status, statusW)) + chalk36.dim(pad5(truncate2(c.pattern, patternW - 1), patternW))
|
|
329537
329151
|
);
|
|
329538
329152
|
}
|
|
329539
329153
|
const pendingCount = candidates.filter((c) => c.status === "pending").length;
|
|
329540
329154
|
console.log("");
|
|
329541
329155
|
if (pendingCount > 0) {
|
|
329542
|
-
console.log(
|
|
329156
|
+
console.log(chalk36.dim(` ${pendingCount} pending candidate(s). Use \`npx nestor-sh evolve review\` to review them.`));
|
|
329543
329157
|
}
|
|
329544
329158
|
console.log("");
|
|
329545
329159
|
} finally {
|
|
@@ -329556,25 +329170,25 @@ function registerEvolveCommand(program2) {
|
|
|
329556
329170
|
if (matches.length === 1) {
|
|
329557
329171
|
candidate = matches[0];
|
|
329558
329172
|
} else if (matches.length > 1) {
|
|
329559
|
-
console.error(
|
|
329173
|
+
console.error(chalk36.red(`Ambiguous ID prefix '${candidateId}'. Matches ${matches.length} candidates.`));
|
|
329560
329174
|
for (const m of matches) {
|
|
329561
|
-
console.log(` ${
|
|
329175
|
+
console.log(` ${chalk36.dim(m.id)} \u2014 ${m.skillName}`);
|
|
329562
329176
|
}
|
|
329563
329177
|
process.exit(1);
|
|
329564
329178
|
}
|
|
329565
329179
|
}
|
|
329566
329180
|
if (!candidate) {
|
|
329567
|
-
console.error(
|
|
329181
|
+
console.error(chalk36.red(`Candidate '${candidateId}' not found.`));
|
|
329568
329182
|
process.exit(1);
|
|
329569
329183
|
}
|
|
329570
329184
|
if (candidate.status !== "pending") {
|
|
329571
|
-
console.error(
|
|
329185
|
+
console.error(chalk36.yellow(`Candidate is already ${candidate.status}.`));
|
|
329572
329186
|
process.exit(1);
|
|
329573
329187
|
}
|
|
329574
329188
|
const skillDir = installCandidate(candidate);
|
|
329575
329189
|
store.updateSkillCandidateStatus(candidate.id, "approved", "cli-user");
|
|
329576
|
-
console.log(
|
|
329577
|
-
console.log(` ${
|
|
329190
|
+
console.log(chalk36.green(`Candidate '${candidate.skillName}' approved and installed.`));
|
|
329191
|
+
console.log(` ${chalk36.dim("Skill path:")} ${skillDir}`);
|
|
329578
329192
|
console.log("");
|
|
329579
329193
|
} finally {
|
|
329580
329194
|
store.close();
|
|
@@ -329590,20 +329204,20 @@ function registerEvolveCommand(program2) {
|
|
|
329590
329204
|
if (matches.length === 1) {
|
|
329591
329205
|
candidate = matches[0];
|
|
329592
329206
|
} else if (matches.length > 1) {
|
|
329593
|
-
console.error(
|
|
329207
|
+
console.error(chalk36.red(`Ambiguous ID prefix '${candidateId}'. Matches ${matches.length} candidates.`));
|
|
329594
329208
|
process.exit(1);
|
|
329595
329209
|
}
|
|
329596
329210
|
}
|
|
329597
329211
|
if (!candidate) {
|
|
329598
|
-
console.error(
|
|
329212
|
+
console.error(chalk36.red(`Candidate '${candidateId}' not found.`));
|
|
329599
329213
|
process.exit(1);
|
|
329600
329214
|
}
|
|
329601
329215
|
if (candidate.status !== "pending") {
|
|
329602
|
-
console.error(
|
|
329216
|
+
console.error(chalk36.yellow(`Candidate is already ${candidate.status}.`));
|
|
329603
329217
|
process.exit(1);
|
|
329604
329218
|
}
|
|
329605
329219
|
store.updateSkillCandidateStatus(candidate.id, "rejected", "cli-user");
|
|
329606
|
-
console.log(
|
|
329220
|
+
console.log(chalk36.green(`Candidate '${candidate.skillName}' rejected.`));
|
|
329607
329221
|
} finally {
|
|
329608
329222
|
store.close();
|
|
329609
329223
|
}
|
|
@@ -329613,10 +329227,10 @@ function registerEvolveCommand(program2) {
|
|
|
329613
329227
|
try {
|
|
329614
329228
|
const candidates = store.listSkillCandidates({ status: "pending", limit: 100 });
|
|
329615
329229
|
if (candidates.length === 0) {
|
|
329616
|
-
console.log(
|
|
329230
|
+
console.log(chalk36.yellow("No pending candidates to review."));
|
|
329617
329231
|
return;
|
|
329618
329232
|
}
|
|
329619
|
-
p8.intro(
|
|
329233
|
+
p8.intro(chalk36.bgCyan(` Review ${candidates.length} Skill Candidate(s) `));
|
|
329620
329234
|
let approved = 0;
|
|
329621
329235
|
let rejected = 0;
|
|
329622
329236
|
for (let i = 0; i < candidates.length; i++) {
|
|
@@ -329625,12 +329239,12 @@ function registerEvolveCommand(program2) {
|
|
|
329625
329239
|
const lines = c.skillMd.split("\n");
|
|
329626
329240
|
const previewLines = lines.slice(0, 12);
|
|
329627
329241
|
console.log("");
|
|
329628
|
-
console.log(
|
|
329242
|
+
console.log(chalk36.dim(" SKILL.md preview:"));
|
|
329629
329243
|
for (const line of previewLines) {
|
|
329630
|
-
console.log(
|
|
329244
|
+
console.log(chalk36.dim(` ${line}`));
|
|
329631
329245
|
}
|
|
329632
329246
|
if (lines.length > 12) {
|
|
329633
|
-
console.log(
|
|
329247
|
+
console.log(chalk36.dim(` ... (${lines.length - 12} more lines)`));
|
|
329634
329248
|
}
|
|
329635
329249
|
console.log("");
|
|
329636
329250
|
const action = await p8.select({
|
|
@@ -329649,19 +329263,19 @@ function registerEvolveCommand(program2) {
|
|
|
329649
329263
|
if (action === "approve") {
|
|
329650
329264
|
const skillDir = installCandidate(c);
|
|
329651
329265
|
store.updateSkillCandidateStatus(c.id, "approved", "cli-user");
|
|
329652
|
-
console.log(
|
|
329266
|
+
console.log(chalk36.green(` Approved and installed to ${skillDir}`));
|
|
329653
329267
|
approved++;
|
|
329654
329268
|
} else if (action === "reject") {
|
|
329655
329269
|
store.updateSkillCandidateStatus(c.id, "rejected", "cli-user");
|
|
329656
|
-
console.log(
|
|
329270
|
+
console.log(chalk36.dim(` Rejected.`));
|
|
329657
329271
|
rejected++;
|
|
329658
329272
|
} else {
|
|
329659
|
-
console.log(
|
|
329273
|
+
console.log(chalk36.dim(` Skipped.`));
|
|
329660
329274
|
}
|
|
329661
329275
|
}
|
|
329662
329276
|
console.log("");
|
|
329663
329277
|
p8.outro(
|
|
329664
|
-
|
|
329278
|
+
chalk36.bold(`Review complete: ${chalk36.green(`${approved} approved`)}, ${chalk36.red(`${rejected} rejected`)}, ${candidates.length - approved - rejected} skipped`)
|
|
329665
329279
|
);
|
|
329666
329280
|
} finally {
|
|
329667
329281
|
store.close();
|
|
@@ -329671,7 +329285,7 @@ function registerEvolveCommand(program2) {
|
|
|
329671
329285
|
|
|
329672
329286
|
// src/index.ts
|
|
329673
329287
|
var program = new Command();
|
|
329674
|
-
program.name("nestor-sh").description("Nestor AI Agent Platform \u2014 orchestrate, secure and monitor AI agents").version("3.5.
|
|
329288
|
+
program.name("nestor-sh").description("Nestor AI Agent Platform \u2014 orchestrate, secure and monitor AI agents").version("3.5.2");
|
|
329675
329289
|
registerStartCommand(program);
|
|
329676
329290
|
registerInstallCommand(program);
|
|
329677
329291
|
registerAgentCommand(program);
|