nestor-sh 2.9.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/nestor.mjs +1174 -457
- package/dist/studio/assets/index-Cw42VG9E.js +596 -0
- package/dist/studio/index.html +1 -1
- package/package.json +1 -1
package/dist/nestor.mjs
CHANGED
|
@@ -7809,9 +7809,9 @@ var init_request_validator = __esm({
|
|
|
7809
7809
|
});
|
|
7810
7810
|
|
|
7811
7811
|
// ../server/src/security/input-sanitizer.ts
|
|
7812
|
-
function resolvePath(base,
|
|
7813
|
-
if (
|
|
7814
|
-
const parts = (base + "/" +
|
|
7812
|
+
function resolvePath(base, relative7) {
|
|
7813
|
+
if (relative7.startsWith("/")) return relative7;
|
|
7814
|
+
const parts = (base + "/" + relative7).split("/");
|
|
7815
7815
|
const resolved = [];
|
|
7816
7816
|
for (const part of parts) {
|
|
7817
7817
|
if (part === "..") {
|
|
@@ -9350,7 +9350,7 @@ import path from "node:path";
|
|
|
9350
9350
|
import fs2 from "node:fs";
|
|
9351
9351
|
function validateSkillFile(filePath, content) {
|
|
9352
9352
|
const ext = path.extname(filePath).toLowerCase();
|
|
9353
|
-
const
|
|
9353
|
+
const basename6 = path.basename(filePath);
|
|
9354
9354
|
const extensionlessAllowed = /* @__PURE__ */ new Set([
|
|
9355
9355
|
"LICENSE",
|
|
9356
9356
|
"LICENCE",
|
|
@@ -9366,14 +9366,14 @@ function validateSkillFile(filePath, content) {
|
|
|
9366
9366
|
".prettierrc",
|
|
9367
9367
|
".eslintrc"
|
|
9368
9368
|
]);
|
|
9369
|
-
if (!ext && !extensionlessAllowed.has(
|
|
9369
|
+
if (!ext && !extensionlessAllowed.has(basename6)) {
|
|
9370
9370
|
return {
|
|
9371
9371
|
valid: false,
|
|
9372
|
-
reason: `File without extension is not in the allowlist: ${
|
|
9372
|
+
reason: `File without extension is not in the allowlist: ${basename6}`,
|
|
9373
9373
|
extension: ""
|
|
9374
9374
|
};
|
|
9375
9375
|
}
|
|
9376
|
-
if (!ext && extensionlessAllowed.has(
|
|
9376
|
+
if (!ext && extensionlessAllowed.has(basename6)) {
|
|
9377
9377
|
if (content && content.length >= 4) {
|
|
9378
9378
|
const binaryCheck = checkForBinaryContent(content, "");
|
|
9379
9379
|
if (binaryCheck) {
|
|
@@ -11501,7 +11501,7 @@ var SERVER_VERSION, startTime;
|
|
|
11501
11501
|
var init_health = __esm({
|
|
11502
11502
|
"../server/src/routes/health.ts"() {
|
|
11503
11503
|
"use strict";
|
|
11504
|
-
SERVER_VERSION = "
|
|
11504
|
+
SERVER_VERSION = "3.0.0";
|
|
11505
11505
|
startTime = Date.now();
|
|
11506
11506
|
}
|
|
11507
11507
|
});
|
|
@@ -12914,7 +12914,7 @@ var init_system = __esm({
|
|
|
12914
12914
|
init_error_handler();
|
|
12915
12915
|
init_broadcaster();
|
|
12916
12916
|
init_approval_service();
|
|
12917
|
-
SERVER_VERSION2 = "
|
|
12917
|
+
SERVER_VERSION2 = "3.0.0";
|
|
12918
12918
|
startTime2 = Date.now();
|
|
12919
12919
|
UpdateConfigSchema = z9.object({
|
|
12920
12920
|
server: z9.object({
|
|
@@ -20344,7 +20344,7 @@ function isNativeAvailable() {
|
|
|
20344
20344
|
return nativeModule !== null;
|
|
20345
20345
|
}
|
|
20346
20346
|
function getNativeVersion() {
|
|
20347
|
-
return nativeModule ? "
|
|
20347
|
+
return nativeModule ? "3.0.0" : null;
|
|
20348
20348
|
}
|
|
20349
20349
|
function validateSsrf(url, allowPrivate = false) {
|
|
20350
20350
|
if (nativeModule) {
|
|
@@ -71110,7 +71110,7 @@ var require_util2 = __commonJS({
|
|
|
71110
71110
|
return path30;
|
|
71111
71111
|
}
|
|
71112
71112
|
exports2.normalize = normalize4;
|
|
71113
|
-
function
|
|
71113
|
+
function join31(aRoot, aPath) {
|
|
71114
71114
|
if (aRoot === "") {
|
|
71115
71115
|
aRoot = ".";
|
|
71116
71116
|
}
|
|
@@ -71142,11 +71142,11 @@ var require_util2 = __commonJS({
|
|
|
71142
71142
|
}
|
|
71143
71143
|
return joined;
|
|
71144
71144
|
}
|
|
71145
|
-
exports2.join =
|
|
71145
|
+
exports2.join = join31;
|
|
71146
71146
|
exports2.isAbsolute = function(aPath) {
|
|
71147
71147
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
71148
71148
|
};
|
|
71149
|
-
function
|
|
71149
|
+
function relative7(aRoot, aPath) {
|
|
71150
71150
|
if (aRoot === "") {
|
|
71151
71151
|
aRoot = ".";
|
|
71152
71152
|
}
|
|
@@ -71165,7 +71165,7 @@ var require_util2 = __commonJS({
|
|
|
71165
71165
|
}
|
|
71166
71166
|
return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
|
|
71167
71167
|
}
|
|
71168
|
-
exports2.relative =
|
|
71168
|
+
exports2.relative = relative7;
|
|
71169
71169
|
var supportsNullProto = function() {
|
|
71170
71170
|
var obj = /* @__PURE__ */ Object.create(null);
|
|
71171
71171
|
return !("__proto__" in obj);
|
|
@@ -71315,7 +71315,7 @@ var require_util2 = __commonJS({
|
|
|
71315
71315
|
parsed.path = parsed.path.substring(0, index + 1);
|
|
71316
71316
|
}
|
|
71317
71317
|
}
|
|
71318
|
-
sourceURL =
|
|
71318
|
+
sourceURL = join31(urlGenerate(parsed), sourceURL);
|
|
71319
71319
|
}
|
|
71320
71320
|
return normalize4(sourceURL);
|
|
71321
71321
|
}
|
|
@@ -73117,7 +73117,7 @@ var require_escodegen = __commonJS({
|
|
|
73117
73117
|
function noEmptySpace() {
|
|
73118
73118
|
return space ? space : " ";
|
|
73119
73119
|
}
|
|
73120
|
-
function
|
|
73120
|
+
function join31(left2, right2) {
|
|
73121
73121
|
var leftSource, rightSource, leftCharCode, rightCharCode;
|
|
73122
73122
|
leftSource = toSourceNodeWhenNeeded(left2).toString();
|
|
73123
73123
|
if (leftSource.length === 0) {
|
|
@@ -73448,8 +73448,8 @@ var require_escodegen = __commonJS({
|
|
|
73448
73448
|
} else {
|
|
73449
73449
|
result.push(that.generateExpression(stmt.left, Precedence.Call, E_TTT));
|
|
73450
73450
|
}
|
|
73451
|
-
result =
|
|
73452
|
-
result = [
|
|
73451
|
+
result = join31(result, operator);
|
|
73452
|
+
result = [join31(
|
|
73453
73453
|
result,
|
|
73454
73454
|
that.generateExpression(stmt.right, Precedence.Assignment, E_TTT)
|
|
73455
73455
|
), ")"];
|
|
@@ -73592,11 +73592,11 @@ var require_escodegen = __commonJS({
|
|
|
73592
73592
|
var result, fragment;
|
|
73593
73593
|
result = ["class"];
|
|
73594
73594
|
if (stmt.id) {
|
|
73595
|
-
result =
|
|
73595
|
+
result = join31(result, this.generateExpression(stmt.id, Precedence.Sequence, E_TTT));
|
|
73596
73596
|
}
|
|
73597
73597
|
if (stmt.superClass) {
|
|
73598
|
-
fragment =
|
|
73599
|
-
result =
|
|
73598
|
+
fragment = join31("extends", this.generateExpression(stmt.superClass, Precedence.Unary, E_TTT));
|
|
73599
|
+
result = join31(result, fragment);
|
|
73600
73600
|
}
|
|
73601
73601
|
result.push(space);
|
|
73602
73602
|
result.push(this.generateStatement(stmt.body, S_TFFT));
|
|
@@ -73609,9 +73609,9 @@ var require_escodegen = __commonJS({
|
|
|
73609
73609
|
return escapeDirective(stmt.directive) + this.semicolon(flags);
|
|
73610
73610
|
},
|
|
73611
73611
|
DoWhileStatement: function(stmt, flags) {
|
|
73612
|
-
var result =
|
|
73612
|
+
var result = join31("do", this.maybeBlock(stmt.body, S_TFFF));
|
|
73613
73613
|
result = this.maybeBlockSuffix(stmt.body, result);
|
|
73614
|
-
return
|
|
73614
|
+
return join31(result, [
|
|
73615
73615
|
"while" + space + "(",
|
|
73616
73616
|
this.generateExpression(stmt.test, Precedence.Sequence, E_TTT),
|
|
73617
73617
|
")" + this.semicolon(flags)
|
|
@@ -73647,11 +73647,11 @@ var require_escodegen = __commonJS({
|
|
|
73647
73647
|
ExportDefaultDeclaration: function(stmt, flags) {
|
|
73648
73648
|
var result = ["export"], bodyFlags;
|
|
73649
73649
|
bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
|
|
73650
|
-
result =
|
|
73650
|
+
result = join31(result, "default");
|
|
73651
73651
|
if (isStatement(stmt.declaration)) {
|
|
73652
|
-
result =
|
|
73652
|
+
result = join31(result, this.generateStatement(stmt.declaration, bodyFlags));
|
|
73653
73653
|
} else {
|
|
73654
|
-
result =
|
|
73654
|
+
result = join31(result, this.generateExpression(stmt.declaration, Precedence.Assignment, E_TTT) + this.semicolon(flags));
|
|
73655
73655
|
}
|
|
73656
73656
|
return result;
|
|
73657
73657
|
},
|
|
@@ -73659,15 +73659,15 @@ var require_escodegen = __commonJS({
|
|
|
73659
73659
|
var result = ["export"], bodyFlags, that = this;
|
|
73660
73660
|
bodyFlags = flags & F_SEMICOLON_OPT ? S_TFFT : S_TFFF;
|
|
73661
73661
|
if (stmt.declaration) {
|
|
73662
|
-
return
|
|
73662
|
+
return join31(result, this.generateStatement(stmt.declaration, bodyFlags));
|
|
73663
73663
|
}
|
|
73664
73664
|
if (stmt.specifiers) {
|
|
73665
73665
|
if (stmt.specifiers.length === 0) {
|
|
73666
|
-
result =
|
|
73666
|
+
result = join31(result, "{" + space + "}");
|
|
73667
73667
|
} else if (stmt.specifiers[0].type === Syntax.ExportBatchSpecifier) {
|
|
73668
|
-
result =
|
|
73668
|
+
result = join31(result, this.generateExpression(stmt.specifiers[0], Precedence.Sequence, E_TTT));
|
|
73669
73669
|
} else {
|
|
73670
|
-
result =
|
|
73670
|
+
result = join31(result, "{");
|
|
73671
73671
|
withIndent(function(indent2) {
|
|
73672
73672
|
var i, iz;
|
|
73673
73673
|
result.push(newline);
|
|
@@ -73685,7 +73685,7 @@ var require_escodegen = __commonJS({
|
|
|
73685
73685
|
result.push(base + "}");
|
|
73686
73686
|
}
|
|
73687
73687
|
if (stmt.source) {
|
|
73688
|
-
result =
|
|
73688
|
+
result = join31(result, [
|
|
73689
73689
|
"from" + space,
|
|
73690
73690
|
// ModuleSpecifier
|
|
73691
73691
|
this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
|
|
@@ -73773,7 +73773,7 @@ var require_escodegen = __commonJS({
|
|
|
73773
73773
|
];
|
|
73774
73774
|
cursor = 0;
|
|
73775
73775
|
if (stmt.specifiers[cursor].type === Syntax.ImportDefaultSpecifier) {
|
|
73776
|
-
result =
|
|
73776
|
+
result = join31(result, [
|
|
73777
73777
|
this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
|
|
73778
73778
|
]);
|
|
73779
73779
|
++cursor;
|
|
@@ -73783,7 +73783,7 @@ var require_escodegen = __commonJS({
|
|
|
73783
73783
|
result.push(",");
|
|
73784
73784
|
}
|
|
73785
73785
|
if (stmt.specifiers[cursor].type === Syntax.ImportNamespaceSpecifier) {
|
|
73786
|
-
result =
|
|
73786
|
+
result = join31(result, [
|
|
73787
73787
|
space,
|
|
73788
73788
|
this.generateExpression(stmt.specifiers[cursor], Precedence.Sequence, E_TTT)
|
|
73789
73789
|
]);
|
|
@@ -73812,7 +73812,7 @@ var require_escodegen = __commonJS({
|
|
|
73812
73812
|
}
|
|
73813
73813
|
}
|
|
73814
73814
|
}
|
|
73815
|
-
result =
|
|
73815
|
+
result = join31(result, [
|
|
73816
73816
|
"from" + space,
|
|
73817
73817
|
// ModuleSpecifier
|
|
73818
73818
|
this.generateExpression(stmt.source, Precedence.Sequence, E_TTT),
|
|
@@ -73866,7 +73866,7 @@ var require_escodegen = __commonJS({
|
|
|
73866
73866
|
return result;
|
|
73867
73867
|
},
|
|
73868
73868
|
ThrowStatement: function(stmt, flags) {
|
|
73869
|
-
return [
|
|
73869
|
+
return [join31(
|
|
73870
73870
|
"throw",
|
|
73871
73871
|
this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
|
|
73872
73872
|
), this.semicolon(flags)];
|
|
@@ -73877,7 +73877,7 @@ var require_escodegen = __commonJS({
|
|
|
73877
73877
|
result = this.maybeBlockSuffix(stmt.block, result);
|
|
73878
73878
|
if (stmt.handlers) {
|
|
73879
73879
|
for (i = 0, iz = stmt.handlers.length; i < iz; ++i) {
|
|
73880
|
-
result =
|
|
73880
|
+
result = join31(result, this.generateStatement(stmt.handlers[i], S_TFFF));
|
|
73881
73881
|
if (stmt.finalizer || i + 1 !== iz) {
|
|
73882
73882
|
result = this.maybeBlockSuffix(stmt.handlers[i].body, result);
|
|
73883
73883
|
}
|
|
@@ -73885,7 +73885,7 @@ var require_escodegen = __commonJS({
|
|
|
73885
73885
|
} else {
|
|
73886
73886
|
guardedHandlers = stmt.guardedHandlers || [];
|
|
73887
73887
|
for (i = 0, iz = guardedHandlers.length; i < iz; ++i) {
|
|
73888
|
-
result =
|
|
73888
|
+
result = join31(result, this.generateStatement(guardedHandlers[i], S_TFFF));
|
|
73889
73889
|
if (stmt.finalizer || i + 1 !== iz) {
|
|
73890
73890
|
result = this.maybeBlockSuffix(guardedHandlers[i].body, result);
|
|
73891
73891
|
}
|
|
@@ -73893,13 +73893,13 @@ var require_escodegen = __commonJS({
|
|
|
73893
73893
|
if (stmt.handler) {
|
|
73894
73894
|
if (Array.isArray(stmt.handler)) {
|
|
73895
73895
|
for (i = 0, iz = stmt.handler.length; i < iz; ++i) {
|
|
73896
|
-
result =
|
|
73896
|
+
result = join31(result, this.generateStatement(stmt.handler[i], S_TFFF));
|
|
73897
73897
|
if (stmt.finalizer || i + 1 !== iz) {
|
|
73898
73898
|
result = this.maybeBlockSuffix(stmt.handler[i].body, result);
|
|
73899
73899
|
}
|
|
73900
73900
|
}
|
|
73901
73901
|
} else {
|
|
73902
|
-
result =
|
|
73902
|
+
result = join31(result, this.generateStatement(stmt.handler, S_TFFF));
|
|
73903
73903
|
if (stmt.finalizer) {
|
|
73904
73904
|
result = this.maybeBlockSuffix(stmt.handler.body, result);
|
|
73905
73905
|
}
|
|
@@ -73907,7 +73907,7 @@ var require_escodegen = __commonJS({
|
|
|
73907
73907
|
}
|
|
73908
73908
|
}
|
|
73909
73909
|
if (stmt.finalizer) {
|
|
73910
|
-
result =
|
|
73910
|
+
result = join31(result, ["finally", this.maybeBlock(stmt.finalizer, S_TFFF)]);
|
|
73911
73911
|
}
|
|
73912
73912
|
return result;
|
|
73913
73913
|
},
|
|
@@ -73941,7 +73941,7 @@ var require_escodegen = __commonJS({
|
|
|
73941
73941
|
withIndent(function() {
|
|
73942
73942
|
if (stmt.test) {
|
|
73943
73943
|
result = [
|
|
73944
|
-
|
|
73944
|
+
join31("case", that.generateExpression(stmt.test, Precedence.Sequence, E_TTT)),
|
|
73945
73945
|
":"
|
|
73946
73946
|
];
|
|
73947
73947
|
} else {
|
|
@@ -73989,9 +73989,9 @@ var require_escodegen = __commonJS({
|
|
|
73989
73989
|
result.push(this.maybeBlock(stmt.consequent, S_TFFF));
|
|
73990
73990
|
result = this.maybeBlockSuffix(stmt.consequent, result);
|
|
73991
73991
|
if (stmt.alternate.type === Syntax.IfStatement) {
|
|
73992
|
-
result =
|
|
73992
|
+
result = join31(result, ["else ", this.generateStatement(stmt.alternate, bodyFlags)]);
|
|
73993
73993
|
} else {
|
|
73994
|
-
result =
|
|
73994
|
+
result = join31(result, join31("else", this.maybeBlock(stmt.alternate, bodyFlags)));
|
|
73995
73995
|
}
|
|
73996
73996
|
} else {
|
|
73997
73997
|
result.push(this.maybeBlock(stmt.consequent, bodyFlags));
|
|
@@ -74092,7 +74092,7 @@ var require_escodegen = __commonJS({
|
|
|
74092
74092
|
},
|
|
74093
74093
|
ReturnStatement: function(stmt, flags) {
|
|
74094
74094
|
if (stmt.argument) {
|
|
74095
|
-
return [
|
|
74095
|
+
return [join31(
|
|
74096
74096
|
"return",
|
|
74097
74097
|
this.generateExpression(stmt.argument, Precedence.Sequence, E_TTT)
|
|
74098
74098
|
), this.semicolon(flags)];
|
|
@@ -74181,14 +74181,14 @@ var require_escodegen = __commonJS({
|
|
|
74181
74181
|
if (leftSource.charCodeAt(leftSource.length - 1) === 47 && esutils.code.isIdentifierPartES5(expr.operator.charCodeAt(0))) {
|
|
74182
74182
|
result = [fragment, noEmptySpace(), expr.operator];
|
|
74183
74183
|
} else {
|
|
74184
|
-
result =
|
|
74184
|
+
result = join31(fragment, expr.operator);
|
|
74185
74185
|
}
|
|
74186
74186
|
fragment = this.generateExpression(expr.right, rightPrecedence, flags);
|
|
74187
74187
|
if (expr.operator === "/" && fragment.toString().charAt(0) === "/" || expr.operator.slice(-1) === "<" && fragment.toString().slice(0, 3) === "!--") {
|
|
74188
74188
|
result.push(noEmptySpace());
|
|
74189
74189
|
result.push(fragment);
|
|
74190
74190
|
} else {
|
|
74191
|
-
result =
|
|
74191
|
+
result = join31(result, fragment);
|
|
74192
74192
|
}
|
|
74193
74193
|
if (expr.operator === "in" && !(flags & F_ALLOW_IN)) {
|
|
74194
74194
|
return ["(", result, ")"];
|
|
@@ -74228,7 +74228,7 @@ var require_escodegen = __commonJS({
|
|
|
74228
74228
|
var result, length, i, iz, itemFlags;
|
|
74229
74229
|
length = expr["arguments"].length;
|
|
74230
74230
|
itemFlags = flags & F_ALLOW_UNPARATH_NEW && !parentheses && length === 0 ? E_TFT : E_TFF;
|
|
74231
|
-
result =
|
|
74231
|
+
result = join31(
|
|
74232
74232
|
"new",
|
|
74233
74233
|
this.generateExpression(expr.callee, Precedence.New, itemFlags)
|
|
74234
74234
|
);
|
|
@@ -74278,11 +74278,11 @@ var require_escodegen = __commonJS({
|
|
|
74278
74278
|
var result, fragment, rightCharCode, leftSource, leftCharCode;
|
|
74279
74279
|
fragment = this.generateExpression(expr.argument, Precedence.Unary, E_TTT);
|
|
74280
74280
|
if (space === "") {
|
|
74281
|
-
result =
|
|
74281
|
+
result = join31(expr.operator, fragment);
|
|
74282
74282
|
} else {
|
|
74283
74283
|
result = [expr.operator];
|
|
74284
74284
|
if (expr.operator.length > 2) {
|
|
74285
|
-
result =
|
|
74285
|
+
result = join31(result, fragment);
|
|
74286
74286
|
} else {
|
|
74287
74287
|
leftSource = toSourceNodeWhenNeeded(result).toString();
|
|
74288
74288
|
leftCharCode = leftSource.charCodeAt(leftSource.length - 1);
|
|
@@ -74305,7 +74305,7 @@ var require_escodegen = __commonJS({
|
|
|
74305
74305
|
result = "yield";
|
|
74306
74306
|
}
|
|
74307
74307
|
if (expr.argument) {
|
|
74308
|
-
result =
|
|
74308
|
+
result = join31(
|
|
74309
74309
|
result,
|
|
74310
74310
|
this.generateExpression(expr.argument, Precedence.Yield, E_TTT)
|
|
74311
74311
|
);
|
|
@@ -74313,7 +74313,7 @@ var require_escodegen = __commonJS({
|
|
|
74313
74313
|
return parenthesize(result, Precedence.Yield, precedence);
|
|
74314
74314
|
},
|
|
74315
74315
|
AwaitExpression: function(expr, precedence, flags) {
|
|
74316
|
-
var result =
|
|
74316
|
+
var result = join31(
|
|
74317
74317
|
expr.all ? "await*" : "await",
|
|
74318
74318
|
this.generateExpression(expr.argument, Precedence.Await, E_TTT)
|
|
74319
74319
|
);
|
|
@@ -74396,11 +74396,11 @@ var require_escodegen = __commonJS({
|
|
|
74396
74396
|
var result, fragment;
|
|
74397
74397
|
result = ["class"];
|
|
74398
74398
|
if (expr.id) {
|
|
74399
|
-
result =
|
|
74399
|
+
result = join31(result, this.generateExpression(expr.id, Precedence.Sequence, E_TTT));
|
|
74400
74400
|
}
|
|
74401
74401
|
if (expr.superClass) {
|
|
74402
|
-
fragment =
|
|
74403
|
-
result =
|
|
74402
|
+
fragment = join31("extends", this.generateExpression(expr.superClass, Precedence.Unary, E_TTT));
|
|
74403
|
+
result = join31(result, fragment);
|
|
74404
74404
|
}
|
|
74405
74405
|
result.push(space);
|
|
74406
74406
|
result.push(this.generateStatement(expr.body, S_TFFT));
|
|
@@ -74415,7 +74415,7 @@ var require_escodegen = __commonJS({
|
|
|
74415
74415
|
}
|
|
74416
74416
|
if (expr.kind === "get" || expr.kind === "set") {
|
|
74417
74417
|
fragment = [
|
|
74418
|
-
|
|
74418
|
+
join31(expr.kind, this.generatePropertyKey(expr.key, expr.computed)),
|
|
74419
74419
|
this.generateFunctionBody(expr.value)
|
|
74420
74420
|
];
|
|
74421
74421
|
} else {
|
|
@@ -74425,7 +74425,7 @@ var require_escodegen = __commonJS({
|
|
|
74425
74425
|
this.generateFunctionBody(expr.value)
|
|
74426
74426
|
];
|
|
74427
74427
|
}
|
|
74428
|
-
return
|
|
74428
|
+
return join31(result, fragment);
|
|
74429
74429
|
},
|
|
74430
74430
|
Property: function(expr, precedence, flags) {
|
|
74431
74431
|
if (expr.kind === "get" || expr.kind === "set") {
|
|
@@ -74620,7 +74620,7 @@ var require_escodegen = __commonJS({
|
|
|
74620
74620
|
for (i = 0, iz = expr.blocks.length; i < iz; ++i) {
|
|
74621
74621
|
fragment = that.generateExpression(expr.blocks[i], Precedence.Sequence, E_TTT);
|
|
74622
74622
|
if (i > 0 || extra.moz.comprehensionExpressionStartsWithAssignment) {
|
|
74623
|
-
result =
|
|
74623
|
+
result = join31(result, fragment);
|
|
74624
74624
|
} else {
|
|
74625
74625
|
result.push(fragment);
|
|
74626
74626
|
}
|
|
@@ -74628,13 +74628,13 @@ var require_escodegen = __commonJS({
|
|
|
74628
74628
|
});
|
|
74629
74629
|
}
|
|
74630
74630
|
if (expr.filter) {
|
|
74631
|
-
result =
|
|
74631
|
+
result = join31(result, "if" + space);
|
|
74632
74632
|
fragment = this.generateExpression(expr.filter, Precedence.Sequence, E_TTT);
|
|
74633
|
-
result =
|
|
74633
|
+
result = join31(result, ["(", fragment, ")"]);
|
|
74634
74634
|
}
|
|
74635
74635
|
if (!extra.moz.comprehensionExpressionStartsWithAssignment) {
|
|
74636
74636
|
fragment = this.generateExpression(expr.body, Precedence.Assignment, E_TTT);
|
|
74637
|
-
result =
|
|
74637
|
+
result = join31(result, fragment);
|
|
74638
74638
|
}
|
|
74639
74639
|
result.push(expr.type === Syntax.GeneratorExpression ? ")" : "]");
|
|
74640
74640
|
return result;
|
|
@@ -74650,8 +74650,8 @@ var require_escodegen = __commonJS({
|
|
|
74650
74650
|
} else {
|
|
74651
74651
|
fragment = this.generateExpression(expr.left, Precedence.Call, E_TTT);
|
|
74652
74652
|
}
|
|
74653
|
-
fragment =
|
|
74654
|
-
fragment =
|
|
74653
|
+
fragment = join31(fragment, expr.of ? "of" : "in");
|
|
74654
|
+
fragment = join31(fragment, this.generateExpression(expr.right, Precedence.Sequence, E_TTT));
|
|
74655
74655
|
return ["for" + space + "(", fragment, ")"];
|
|
74656
74656
|
},
|
|
74657
74657
|
SpreadElement: function(expr, precedence, flags) {
|
|
@@ -102210,8 +102210,8 @@ function findChromePath() {
|
|
|
102210
102210
|
for (const p8 of paths) {
|
|
102211
102211
|
if (p8) {
|
|
102212
102212
|
try {
|
|
102213
|
-
const { existsSync:
|
|
102214
|
-
if (
|
|
102213
|
+
const { existsSync: existsSync28 } = __require("node:fs");
|
|
102214
|
+
if (existsSync28(p8)) return p8;
|
|
102215
102215
|
} catch {
|
|
102216
102216
|
}
|
|
102217
102217
|
}
|
|
@@ -102226,8 +102226,8 @@ function findChromePath() {
|
|
|
102226
102226
|
];
|
|
102227
102227
|
for (const p8 of paths) {
|
|
102228
102228
|
try {
|
|
102229
|
-
const { existsSync:
|
|
102230
|
-
if (
|
|
102229
|
+
const { existsSync: existsSync28 } = __require("node:fs");
|
|
102230
|
+
if (existsSync28(p8)) return p8;
|
|
102231
102231
|
} catch {
|
|
102232
102232
|
}
|
|
102233
102233
|
}
|
|
@@ -102242,8 +102242,8 @@ function findChromePath() {
|
|
|
102242
102242
|
];
|
|
102243
102243
|
for (const p8 of linuxPaths) {
|
|
102244
102244
|
try {
|
|
102245
|
-
const { existsSync:
|
|
102246
|
-
if (
|
|
102245
|
+
const { existsSync: existsSync28 } = __require("node:fs");
|
|
102246
|
+
if (existsSync28(p8)) return p8;
|
|
102247
102247
|
} catch {
|
|
102248
102248
|
}
|
|
102249
102249
|
}
|
|
@@ -103615,11 +103615,197 @@ var init_layered_memory = __esm({
|
|
|
103615
103615
|
}
|
|
103616
103616
|
});
|
|
103617
103617
|
|
|
103618
|
+
// ../agent/src/integrations/obsidian.ts
|
|
103619
|
+
import { existsSync as existsSync5, readFileSync as readFileSync8, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, readdirSync as readdirSync2, statSync as statSync3 } from "node:fs";
|
|
103620
|
+
import { join as join8, basename as basename3, relative as relative3 } from "node:path";
|
|
103621
|
+
var ObsidianIntegration;
|
|
103622
|
+
var init_obsidian = __esm({
|
|
103623
|
+
"../agent/src/integrations/obsidian.ts"() {
|
|
103624
|
+
"use strict";
|
|
103625
|
+
ObsidianIntegration = class {
|
|
103626
|
+
constructor(config2) {
|
|
103627
|
+
this.config = config2;
|
|
103628
|
+
this.nestorDir = join8(config2.vaultPath, config2.nestorFolder || "Nestor");
|
|
103629
|
+
if (!existsSync5(this.nestorDir)) {
|
|
103630
|
+
mkdirSync3(this.nestorDir, { recursive: true });
|
|
103631
|
+
}
|
|
103632
|
+
}
|
|
103633
|
+
nestorDir;
|
|
103634
|
+
/** Check if vault exists and is accessible */
|
|
103635
|
+
isAvailable() {
|
|
103636
|
+
return existsSync5(this.config.vaultPath);
|
|
103637
|
+
}
|
|
103638
|
+
/** Write a note to the vault */
|
|
103639
|
+
writeNote(opts) {
|
|
103640
|
+
const folder5 = opts.folder ? join8(this.nestorDir, opts.folder) : this.nestorDir;
|
|
103641
|
+
if (!existsSync5(folder5)) mkdirSync3(folder5, { recursive: true });
|
|
103642
|
+
const filename = this.sanitizeFilename(opts.title) + ".md";
|
|
103643
|
+
const filepath = join8(folder5, filename);
|
|
103644
|
+
const fm = {
|
|
103645
|
+
created: (/* @__PURE__ */ new Date()).toISOString(),
|
|
103646
|
+
source: "nestor",
|
|
103647
|
+
tags: [...this.config.defaultTags || [], ...opts.tags || []],
|
|
103648
|
+
...opts.frontmatter
|
|
103649
|
+
};
|
|
103650
|
+
const frontmatter = `---
|
|
103651
|
+
${Object.entries(fm).map(
|
|
103652
|
+
([k, v]) => `${k}: ${typeof v === "object" ? JSON.stringify(v) : v}`
|
|
103653
|
+
).join("\n")}
|
|
103654
|
+
---
|
|
103655
|
+
|
|
103656
|
+
`;
|
|
103657
|
+
writeFileSync3(filepath, frontmatter + opts.content);
|
|
103658
|
+
return filepath;
|
|
103659
|
+
}
|
|
103660
|
+
/** Read a note from the vault */
|
|
103661
|
+
readNote(path30) {
|
|
103662
|
+
const fullPath = path30.startsWith("/") || path30.includes(":") ? path30 : join8(this.nestorDir, path30);
|
|
103663
|
+
if (!existsSync5(fullPath)) return null;
|
|
103664
|
+
const raw = readFileSync8(fullPath, "utf-8");
|
|
103665
|
+
const fmMatch = raw.match(/^---\n([\s\S]*?)\n---\n\n?([\s\S]*)$/);
|
|
103666
|
+
if (fmMatch) {
|
|
103667
|
+
const frontmatter = {};
|
|
103668
|
+
for (const line of fmMatch[1].split("\n")) {
|
|
103669
|
+
const [key, ...rest] = line.split(": ");
|
|
103670
|
+
if (key) frontmatter[key.trim()] = rest.join(": ").trim();
|
|
103671
|
+
}
|
|
103672
|
+
return { frontmatter, content: fmMatch[2] };
|
|
103673
|
+
}
|
|
103674
|
+
return { frontmatter: {}, content: raw };
|
|
103675
|
+
}
|
|
103676
|
+
/** Search notes in the vault */
|
|
103677
|
+
searchNotes(query, limit = 10) {
|
|
103678
|
+
const results = [];
|
|
103679
|
+
const q = query.toLowerCase();
|
|
103680
|
+
this.walkDir(this.nestorDir, (filepath) => {
|
|
103681
|
+
if (!filepath.endsWith(".md") || results.length >= limit) return;
|
|
103682
|
+
try {
|
|
103683
|
+
const content = readFileSync8(filepath, "utf-8");
|
|
103684
|
+
if (content.toLowerCase().includes(q)) {
|
|
103685
|
+
const relPath = relative3(this.nestorDir, filepath);
|
|
103686
|
+
const title = basename3(filepath, ".md");
|
|
103687
|
+
const idx = content.toLowerCase().indexOf(q);
|
|
103688
|
+
const snippet = content.substring(Math.max(0, idx - 50), idx + 100).replace(/\n/g, " ");
|
|
103689
|
+
results.push({ path: relPath, title, snippet });
|
|
103690
|
+
}
|
|
103691
|
+
} catch {
|
|
103692
|
+
}
|
|
103693
|
+
});
|
|
103694
|
+
return results;
|
|
103695
|
+
}
|
|
103696
|
+
/** List all notes in a folder */
|
|
103697
|
+
listNotes(folder5) {
|
|
103698
|
+
const dir = folder5 ? join8(this.nestorDir, folder5) : this.nestorDir;
|
|
103699
|
+
if (!existsSync5(dir)) return [];
|
|
103700
|
+
const notes = [];
|
|
103701
|
+
this.walkDir(dir, (filepath) => {
|
|
103702
|
+
if (!filepath.endsWith(".md")) return;
|
|
103703
|
+
const stat = statSync3(filepath);
|
|
103704
|
+
notes.push({
|
|
103705
|
+
path: relative3(this.nestorDir, filepath),
|
|
103706
|
+
title: basename3(filepath, ".md"),
|
|
103707
|
+
modified: stat.mtime
|
|
103708
|
+
});
|
|
103709
|
+
});
|
|
103710
|
+
return notes.sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
103711
|
+
}
|
|
103712
|
+
/** Write a mission report to the vault */
|
|
103713
|
+
writeMissionReport(mission) {
|
|
103714
|
+
return this.writeNote({
|
|
103715
|
+
title: mission.title,
|
|
103716
|
+
content: mission.report,
|
|
103717
|
+
folder: `missions/${mission.type}`,
|
|
103718
|
+
tags: ["mission", mission.type],
|
|
103719
|
+
frontmatter: {
|
|
103720
|
+
type: mission.type,
|
|
103721
|
+
quality: mission.evaluation?.overall
|
|
103722
|
+
}
|
|
103723
|
+
});
|
|
103724
|
+
}
|
|
103725
|
+
sanitizeFilename(name) {
|
|
103726
|
+
return name.replace(/[<>:"/\\|?*]/g, "-").substring(0, 100);
|
|
103727
|
+
}
|
|
103728
|
+
walkDir(dir, callback) {
|
|
103729
|
+
if (!existsSync5(dir)) return;
|
|
103730
|
+
for (const entry of readdirSync2(dir, { withFileTypes: true })) {
|
|
103731
|
+
const fullPath = join8(dir, entry.name);
|
|
103732
|
+
if (entry.isDirectory()) {
|
|
103733
|
+
this.walkDir(fullPath, callback);
|
|
103734
|
+
} else {
|
|
103735
|
+
callback(fullPath);
|
|
103736
|
+
}
|
|
103737
|
+
}
|
|
103738
|
+
}
|
|
103739
|
+
};
|
|
103740
|
+
}
|
|
103741
|
+
});
|
|
103742
|
+
|
|
103743
|
+
// ../agent/src/integrations/n8n.ts
|
|
103744
|
+
var N8nIntegration;
|
|
103745
|
+
var init_n8n = __esm({
|
|
103746
|
+
"../agent/src/integrations/n8n.ts"() {
|
|
103747
|
+
"use strict";
|
|
103748
|
+
N8nIntegration = class {
|
|
103749
|
+
constructor(config2) {
|
|
103750
|
+
this.config = config2;
|
|
103751
|
+
}
|
|
103752
|
+
/** Check if n8n is accessible */
|
|
103753
|
+
async isAvailable() {
|
|
103754
|
+
try {
|
|
103755
|
+
const res = await fetch(`${this.config.baseUrl}/api/v1/workflows`, {
|
|
103756
|
+
headers: this.headers(),
|
|
103757
|
+
signal: AbortSignal.timeout(5e3)
|
|
103758
|
+
});
|
|
103759
|
+
return res.ok;
|
|
103760
|
+
} catch {
|
|
103761
|
+
return false;
|
|
103762
|
+
}
|
|
103763
|
+
}
|
|
103764
|
+
/** Trigger a webhook workflow */
|
|
103765
|
+
async triggerWebhook(webhookPath, data) {
|
|
103766
|
+
const url = `${this.config.baseUrl}/webhook/${webhookPath}`;
|
|
103767
|
+
const res = await fetch(url, {
|
|
103768
|
+
method: "POST",
|
|
103769
|
+
headers: { "Content-Type": "application/json" },
|
|
103770
|
+
body: JSON.stringify(data),
|
|
103771
|
+
signal: AbortSignal.timeout(3e4)
|
|
103772
|
+
});
|
|
103773
|
+
return res.json();
|
|
103774
|
+
}
|
|
103775
|
+
/** List workflows */
|
|
103776
|
+
async listWorkflows() {
|
|
103777
|
+
const res = await fetch(`${this.config.baseUrl}/api/v1/workflows`, {
|
|
103778
|
+
headers: this.headers(),
|
|
103779
|
+
signal: AbortSignal.timeout(1e4)
|
|
103780
|
+
});
|
|
103781
|
+
if (!res.ok) return [];
|
|
103782
|
+
const data = await res.json();
|
|
103783
|
+
return data.data || [];
|
|
103784
|
+
}
|
|
103785
|
+
/** Execute a workflow by ID */
|
|
103786
|
+
async executeWorkflow(id, data) {
|
|
103787
|
+
const res = await fetch(`${this.config.baseUrl}/api/v1/workflows/${id}/execute`, {
|
|
103788
|
+
method: "POST",
|
|
103789
|
+
headers: this.headers(),
|
|
103790
|
+
body: data ? JSON.stringify(data) : void 0,
|
|
103791
|
+
signal: AbortSignal.timeout(6e4)
|
|
103792
|
+
});
|
|
103793
|
+
return res.json();
|
|
103794
|
+
}
|
|
103795
|
+
headers() {
|
|
103796
|
+
const h = { "Content-Type": "application/json" };
|
|
103797
|
+
if (this.config.apiKey) h["X-N8N-API-KEY"] = this.config.apiKey;
|
|
103798
|
+
return h;
|
|
103799
|
+
}
|
|
103800
|
+
};
|
|
103801
|
+
}
|
|
103802
|
+
});
|
|
103803
|
+
|
|
103618
103804
|
// ../agent/src/tools/system-tools.ts
|
|
103619
103805
|
import { z as z28 } from "zod";
|
|
103620
103806
|
import { randomUUID as randomUUID23 } from "node:crypto";
|
|
103621
|
-
import { readFileSync as
|
|
103622
|
-
import { join as
|
|
103807
|
+
import { readFileSync as readFileSync9 } from "node:fs";
|
|
103808
|
+
import { join as join9 } from "node:path";
|
|
103623
103809
|
import { homedir as homedir3 } from "node:os";
|
|
103624
103810
|
function registerSystemTools(registry, store, defaultTenantId = "default") {
|
|
103625
103811
|
const tid = defaultTenantId;
|
|
@@ -103859,9 +104045,9 @@ Direct sub-agent execution from chat is not yet supported. Use the Studio UI or
|
|
|
103859
104045
|
description: "Read the current Nestor configuration from ~/.nestor/nestor.config.json.",
|
|
103860
104046
|
inputSchema: emptySchema,
|
|
103861
104047
|
handler: async (_input, _ctx) => {
|
|
103862
|
-
const configPath =
|
|
104048
|
+
const configPath = join9(homedir3(), ".nestor", "nestor.config.json");
|
|
103863
104049
|
try {
|
|
103864
|
-
const config2 =
|
|
104050
|
+
const config2 = readFileSync9(configPath, "utf-8");
|
|
103865
104051
|
return { output: config2, isError: false };
|
|
103866
104052
|
} catch {
|
|
103867
104053
|
return { output: "No config file found at ~/.nestor/nestor.config.json", isError: false };
|
|
@@ -104124,12 +104310,245 @@ ${mission.report}`;
|
|
|
104124
104310
|
}
|
|
104125
104311
|
}
|
|
104126
104312
|
});
|
|
104313
|
+
function loadIntegrationConfig() {
|
|
104314
|
+
const configPath = join9(homedir3(), ".nestor", "nestor.config.json");
|
|
104315
|
+
try {
|
|
104316
|
+
const raw = readFileSync9(configPath, "utf-8");
|
|
104317
|
+
const config2 = JSON.parse(raw);
|
|
104318
|
+
return {
|
|
104319
|
+
obsidian: config2.obsidian,
|
|
104320
|
+
n8n: config2.n8n
|
|
104321
|
+
};
|
|
104322
|
+
} catch {
|
|
104323
|
+
return {};
|
|
104324
|
+
}
|
|
104325
|
+
}
|
|
104326
|
+
const obsidianWriteNoteSchema = z28.object({
|
|
104327
|
+
title: z28.string().describe("Note title (used as filename)"),
|
|
104328
|
+
content: z28.string().describe("Markdown content of the note"),
|
|
104329
|
+
folder: z28.string().optional().describe('Subfolder within Nestor dir (e.g., "research", "missions/osint")'),
|
|
104330
|
+
tags: z28.array(z28.string()).optional().describe("Tags to add to the note frontmatter")
|
|
104331
|
+
});
|
|
104332
|
+
const obsidianSearchSchema = z28.object({
|
|
104333
|
+
query: z28.string().describe("Search query (full-text search across note titles and content)"),
|
|
104334
|
+
limit: z28.number().optional().describe("Max results (default: 10)")
|
|
104335
|
+
});
|
|
104336
|
+
const obsidianReadNoteSchema = z28.object({
|
|
104337
|
+
path: z28.string().describe('Relative path within the Nestor folder (e.g., "research/AI Frameworks.md") or absolute path')
|
|
104338
|
+
});
|
|
104339
|
+
const obsidianListNotesSchema = z28.object({
|
|
104340
|
+
folder: z28.string().optional().describe('Subfolder to list (e.g., "missions"). Omit for root Nestor folder.')
|
|
104341
|
+
});
|
|
104342
|
+
registry.register({
|
|
104343
|
+
name: "obsidian_write_note",
|
|
104344
|
+
description: 'Write a note to the connected Obsidian vault. Creates a .md file with YAML frontmatter in the Nestor subfolder. Configure vault path in nestor.config.json under "obsidian.vaultPath".',
|
|
104345
|
+
inputSchema: obsidianWriteNoteSchema,
|
|
104346
|
+
handler: async (input, _ctx) => {
|
|
104347
|
+
const args2 = input;
|
|
104348
|
+
const cfg = loadIntegrationConfig();
|
|
104349
|
+
if (!cfg.obsidian?.vaultPath) {
|
|
104350
|
+
return {
|
|
104351
|
+
output: 'Obsidian integration not configured. Add "obsidian": { "vaultPath": "/path/to/vault" } to ~/.nestor/nestor.config.json',
|
|
104352
|
+
isError: true
|
|
104353
|
+
};
|
|
104354
|
+
}
|
|
104355
|
+
try {
|
|
104356
|
+
const obsidian = new ObsidianIntegration(cfg.obsidian);
|
|
104357
|
+
if (!obsidian.isAvailable()) {
|
|
104358
|
+
return { output: `Obsidian vault not found at: ${cfg.obsidian.vaultPath}`, isError: true };
|
|
104359
|
+
}
|
|
104360
|
+
const filepath = obsidian.writeNote({
|
|
104361
|
+
title: args2.title,
|
|
104362
|
+
content: args2.content,
|
|
104363
|
+
folder: args2.folder,
|
|
104364
|
+
tags: args2.tags
|
|
104365
|
+
});
|
|
104366
|
+
return { output: `Note written: ${filepath}`, isError: false };
|
|
104367
|
+
} catch (err) {
|
|
104368
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
104369
|
+
return { output: `Failed to write note: ${msg}`, isError: true };
|
|
104370
|
+
}
|
|
104371
|
+
}
|
|
104372
|
+
});
|
|
104373
|
+
registry.register({
|
|
104374
|
+
name: "obsidian_search",
|
|
104375
|
+
description: "Search notes in the connected Obsidian vault. Full-text search across all .md files in the Nestor subfolder.",
|
|
104376
|
+
inputSchema: obsidianSearchSchema,
|
|
104377
|
+
handler: async (input, _ctx) => {
|
|
104378
|
+
const args2 = input;
|
|
104379
|
+
const cfg = loadIntegrationConfig();
|
|
104380
|
+
if (!cfg.obsidian?.vaultPath) {
|
|
104381
|
+
return {
|
|
104382
|
+
output: 'Obsidian integration not configured. Add "obsidian": { "vaultPath": "/path/to/vault" } to ~/.nestor/nestor.config.json',
|
|
104383
|
+
isError: true
|
|
104384
|
+
};
|
|
104385
|
+
}
|
|
104386
|
+
try {
|
|
104387
|
+
const obsidian = new ObsidianIntegration(cfg.obsidian);
|
|
104388
|
+
if (!obsidian.isAvailable()) {
|
|
104389
|
+
return { output: `Obsidian vault not found at: ${cfg.obsidian.vaultPath}`, isError: true };
|
|
104390
|
+
}
|
|
104391
|
+
const results = obsidian.searchNotes(args2.query, args2.limit ?? 10);
|
|
104392
|
+
if (results.length === 0) {
|
|
104393
|
+
return { output: `No notes found matching "${args2.query}".`, isError: false };
|
|
104394
|
+
}
|
|
104395
|
+
return { output: JSON.stringify(results, null, 2), isError: false };
|
|
104396
|
+
} catch (err) {
|
|
104397
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
104398
|
+
return { output: `Search failed: ${msg}`, isError: true };
|
|
104399
|
+
}
|
|
104400
|
+
}
|
|
104401
|
+
});
|
|
104402
|
+
registry.register({
|
|
104403
|
+
name: "obsidian_read_note",
|
|
104404
|
+
description: "Read a note from the connected Obsidian vault. Returns frontmatter and content.",
|
|
104405
|
+
inputSchema: obsidianReadNoteSchema,
|
|
104406
|
+
handler: async (input, _ctx) => {
|
|
104407
|
+
const args2 = input;
|
|
104408
|
+
const cfg = loadIntegrationConfig();
|
|
104409
|
+
if (!cfg.obsidian?.vaultPath) {
|
|
104410
|
+
return {
|
|
104411
|
+
output: 'Obsidian integration not configured. Add "obsidian": { "vaultPath": "/path/to/vault" } to ~/.nestor/nestor.config.json',
|
|
104412
|
+
isError: true
|
|
104413
|
+
};
|
|
104414
|
+
}
|
|
104415
|
+
try {
|
|
104416
|
+
const obsidian = new ObsidianIntegration(cfg.obsidian);
|
|
104417
|
+
const note2 = obsidian.readNote(args2.path);
|
|
104418
|
+
if (!note2) {
|
|
104419
|
+
return { output: `Note not found: ${args2.path}`, isError: true };
|
|
104420
|
+
}
|
|
104421
|
+
return { output: JSON.stringify(note2, null, 2), isError: false };
|
|
104422
|
+
} catch (err) {
|
|
104423
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
104424
|
+
return { output: `Failed to read note: ${msg}`, isError: true };
|
|
104425
|
+
}
|
|
104426
|
+
}
|
|
104427
|
+
});
|
|
104428
|
+
registry.register({
|
|
104429
|
+
name: "obsidian_list_notes",
|
|
104430
|
+
description: "List all notes in the Obsidian vault Nestor folder, sorted by most recently modified.",
|
|
104431
|
+
inputSchema: obsidianListNotesSchema,
|
|
104432
|
+
handler: async (input, _ctx) => {
|
|
104433
|
+
const args2 = input;
|
|
104434
|
+
const cfg = loadIntegrationConfig();
|
|
104435
|
+
if (!cfg.obsidian?.vaultPath) {
|
|
104436
|
+
return {
|
|
104437
|
+
output: 'Obsidian integration not configured. Add "obsidian": { "vaultPath": "/path/to/vault" } to ~/.nestor/nestor.config.json',
|
|
104438
|
+
isError: true
|
|
104439
|
+
};
|
|
104440
|
+
}
|
|
104441
|
+
try {
|
|
104442
|
+
const obsidian = new ObsidianIntegration(cfg.obsidian);
|
|
104443
|
+
if (!obsidian.isAvailable()) {
|
|
104444
|
+
return { output: `Obsidian vault not found at: ${cfg.obsidian.vaultPath}`, isError: true };
|
|
104445
|
+
}
|
|
104446
|
+
const notes = obsidian.listNotes(args2.folder);
|
|
104447
|
+
if (notes.length === 0) {
|
|
104448
|
+
return { output: "No notes found.", isError: false };
|
|
104449
|
+
}
|
|
104450
|
+
const list = notes.map((n) => `- ${n.title} (${n.path}) \u2014 modified: ${n.modified.toISOString()}`).join("\n");
|
|
104451
|
+
return { output: `Found ${notes.length} note(s):
|
|
104452
|
+
${list}`, isError: false };
|
|
104453
|
+
} catch (err) {
|
|
104454
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
104455
|
+
return { output: `Failed to list notes: ${msg}`, isError: true };
|
|
104456
|
+
}
|
|
104457
|
+
}
|
|
104458
|
+
});
|
|
104459
|
+
const n8nTriggerSchema = z28.object({
|
|
104460
|
+
webhook: z28.string().describe('Webhook path (e.g., "nestor-report" \u2014 will call {baseUrl}/webhook/nestor-report)'),
|
|
104461
|
+
data: z28.record(z28.unknown()).optional().describe("JSON data to send to the webhook")
|
|
104462
|
+
});
|
|
104463
|
+
const n8nExecuteWorkflowSchema = z28.object({
|
|
104464
|
+
workflowId: z28.string().describe("n8n workflow ID to execute"),
|
|
104465
|
+
data: z28.record(z28.unknown()).optional().describe("Input data for the workflow")
|
|
104466
|
+
});
|
|
104467
|
+
registry.register({
|
|
104468
|
+
name: "n8n_trigger",
|
|
104469
|
+
description: 'Trigger an n8n webhook workflow. Sends JSON data to a webhook endpoint. Configure n8n in nestor.config.json under "n8n": { "baseUrl": "http://localhost:5678", "apiKey": "..." }.',
|
|
104470
|
+
inputSchema: n8nTriggerSchema,
|
|
104471
|
+
handler: async (input, _ctx) => {
|
|
104472
|
+
const args2 = input;
|
|
104473
|
+
const cfg = loadIntegrationConfig();
|
|
104474
|
+
if (!cfg.n8n?.baseUrl) {
|
|
104475
|
+
return {
|
|
104476
|
+
output: 'n8n integration not configured. Add "n8n": { "baseUrl": "http://localhost:5678" } to ~/.nestor/nestor.config.json',
|
|
104477
|
+
isError: true
|
|
104478
|
+
};
|
|
104479
|
+
}
|
|
104480
|
+
try {
|
|
104481
|
+
const n8n = new N8nIntegration(cfg.n8n);
|
|
104482
|
+
const result = await n8n.triggerWebhook(args2.webhook, args2.data || {});
|
|
104483
|
+
return { output: JSON.stringify(result, null, 2), isError: false };
|
|
104484
|
+
} catch (err) {
|
|
104485
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
104486
|
+
return { output: `n8n webhook trigger failed: ${msg}`, isError: true };
|
|
104487
|
+
}
|
|
104488
|
+
}
|
|
104489
|
+
});
|
|
104490
|
+
registry.register({
|
|
104491
|
+
name: "n8n_list_workflows",
|
|
104492
|
+
description: "List available n8n workflows with their ID, name, and active status.",
|
|
104493
|
+
inputSchema: emptySchema,
|
|
104494
|
+
handler: async (_input, _ctx) => {
|
|
104495
|
+
const cfg = loadIntegrationConfig();
|
|
104496
|
+
if (!cfg.n8n?.baseUrl) {
|
|
104497
|
+
return {
|
|
104498
|
+
output: 'n8n integration not configured. Add "n8n": { "baseUrl": "http://localhost:5678" } to ~/.nestor/nestor.config.json',
|
|
104499
|
+
isError: true
|
|
104500
|
+
};
|
|
104501
|
+
}
|
|
104502
|
+
try {
|
|
104503
|
+
const n8n = new N8nIntegration(cfg.n8n);
|
|
104504
|
+
const available = await n8n.isAvailable();
|
|
104505
|
+
if (!available) {
|
|
104506
|
+
return { output: `n8n is not reachable at: ${cfg.n8n.baseUrl}`, isError: true };
|
|
104507
|
+
}
|
|
104508
|
+
const workflows = await n8n.listWorkflows();
|
|
104509
|
+
if (workflows.length === 0) {
|
|
104510
|
+
return { output: "No workflows found.", isError: false };
|
|
104511
|
+
}
|
|
104512
|
+
const list = workflows.map((w) => `- [${w.active ? "ACTIVE" : "inactive"}] ${w.name} (id: ${w.id})`).join("\n");
|
|
104513
|
+
return { output: `Found ${workflows.length} workflow(s):
|
|
104514
|
+
${list}`, isError: false };
|
|
104515
|
+
} catch (err) {
|
|
104516
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
104517
|
+
return { output: `Failed to list n8n workflows: ${msg}`, isError: true };
|
|
104518
|
+
}
|
|
104519
|
+
}
|
|
104520
|
+
});
|
|
104521
|
+
registry.register({
|
|
104522
|
+
name: "n8n_execute_workflow",
|
|
104523
|
+
description: "Execute an n8n workflow by its ID. Optionally pass input data.",
|
|
104524
|
+
inputSchema: n8nExecuteWorkflowSchema,
|
|
104525
|
+
handler: async (input, _ctx) => {
|
|
104526
|
+
const args2 = input;
|
|
104527
|
+
const cfg = loadIntegrationConfig();
|
|
104528
|
+
if (!cfg.n8n?.baseUrl) {
|
|
104529
|
+
return {
|
|
104530
|
+
output: 'n8n integration not configured. Add "n8n": { "baseUrl": "http://localhost:5678" } to ~/.nestor/nestor.config.json',
|
|
104531
|
+
isError: true
|
|
104532
|
+
};
|
|
104533
|
+
}
|
|
104534
|
+
try {
|
|
104535
|
+
const n8n = new N8nIntegration(cfg.n8n);
|
|
104536
|
+
const result = await n8n.executeWorkflow(args2.workflowId, args2.data);
|
|
104537
|
+
return { output: JSON.stringify(result, null, 2), isError: false };
|
|
104538
|
+
} catch (err) {
|
|
104539
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
104540
|
+
return { output: `n8n workflow execution failed: ${msg}`, isError: true };
|
|
104541
|
+
}
|
|
104542
|
+
}
|
|
104543
|
+
});
|
|
104127
104544
|
}
|
|
104128
104545
|
var emptySchema, createAgentSchema, runAgentSchema, deleteAgentSchema, createWorkflowSchema, searchMemorySchema, storeMemorySchema, createGuardrailSchema, createMissionSchema, missionIdSchema, queryMemorySchema;
|
|
104129
104546
|
var init_system_tools = __esm({
|
|
104130
104547
|
"../agent/src/tools/system-tools.ts"() {
|
|
104131
104548
|
"use strict";
|
|
104132
104549
|
init_layered_memory();
|
|
104550
|
+
init_obsidian();
|
|
104551
|
+
init_n8n();
|
|
104133
104552
|
emptySchema = z28.object({}).passthrough();
|
|
104134
104553
|
createAgentSchema = z28.object({
|
|
104135
104554
|
name: z28.string().describe("Agent name"),
|
|
@@ -104187,7 +104606,7 @@ var init_system_tools = __esm({
|
|
|
104187
104606
|
import { z as z29 } from "zod";
|
|
104188
104607
|
import { promises as fs14 } from "node:fs";
|
|
104189
104608
|
import { execFile as execFile6 } from "node:child_process";
|
|
104190
|
-
import { resolve as resolve10, join as
|
|
104609
|
+
import { resolve as resolve10, join as join10 } from "node:path";
|
|
104191
104610
|
function buildSandboxConfig(context3) {
|
|
104192
104611
|
const s = context3.sandbox;
|
|
104193
104612
|
return {
|
|
@@ -104468,11 +104887,11 @@ async function fileListHandler(input, context3) {
|
|
|
104468
104887
|
const items = await fs14.readdir(dir, { withFileTypes: true });
|
|
104469
104888
|
for (const item of items) {
|
|
104470
104889
|
if (item.name.startsWith(".") || item.name === "node_modules") continue;
|
|
104471
|
-
const relativePath =
|
|
104890
|
+
const relativePath = join10(dir, item.name).replace(absolutePath, "").replace(/^[/\\]/, "");
|
|
104472
104891
|
if (item.isDirectory()) {
|
|
104473
104892
|
entries.push(`${relativePath}/`);
|
|
104474
104893
|
if (recursive) {
|
|
104475
|
-
await listDir(
|
|
104894
|
+
await listDir(join10(dir, item.name), depth + 1);
|
|
104476
104895
|
}
|
|
104477
104896
|
} else {
|
|
104478
104897
|
entries.push(relativePath);
|
|
@@ -104565,32 +104984,19 @@ async function webFetchHandler(input, context3) {
|
|
|
104565
104984
|
return { output: `Fetch failed: ${message}`, isError: true };
|
|
104566
104985
|
}
|
|
104567
104986
|
}
|
|
104568
|
-
|
|
104569
|
-
|
|
104570
|
-
|
|
104571
|
-
|
|
104572
|
-
|
|
104573
|
-
|
|
104574
|
-
|
|
104575
|
-
|
|
104576
|
-
break;
|
|
104577
|
-
case "bing":
|
|
104578
|
-
searchUrl = `https://www.bing.com/search?q=${encodeURIComponent(query)}&count=${max}`;
|
|
104579
|
-
break;
|
|
104580
|
-
case "duckduckgo":
|
|
104581
|
-
default:
|
|
104582
|
-
searchUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
|
|
104583
|
-
break;
|
|
104987
|
+
function pickUserAgent(attempt = 0) {
|
|
104988
|
+
return SEARCH_USER_AGENTS[attempt % SEARCH_USER_AGENTS.length];
|
|
104989
|
+
}
|
|
104990
|
+
async function fetchSearchHtml(searchUrl, context3, userAgent, timeoutMs = 15e3) {
|
|
104991
|
+
const controller = new AbortController();
|
|
104992
|
+
const timer2 = setTimeout(() => controller.abort(), timeoutMs);
|
|
104993
|
+
if (context3.signal) {
|
|
104994
|
+
context3.signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
104584
104995
|
}
|
|
104585
104996
|
try {
|
|
104586
|
-
const controller = new AbortController();
|
|
104587
|
-
const timer2 = setTimeout(() => controller.abort(), 15e3);
|
|
104588
|
-
if (context3.signal) {
|
|
104589
|
-
context3.signal.addEventListener("abort", () => controller.abort(), { once: true });
|
|
104590
|
-
}
|
|
104591
104997
|
const resp = await fetch(searchUrl, {
|
|
104592
104998
|
headers: {
|
|
104593
|
-
"User-Agent":
|
|
104999
|
+
"User-Agent": userAgent,
|
|
104594
105000
|
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
|
104595
105001
|
"Accept-Language": "en-US,en;q=0.9,fr;q=0.8"
|
|
104596
105002
|
},
|
|
@@ -104598,96 +105004,217 @@ async function webSearchHandler(input, context3) {
|
|
|
104598
105004
|
redirect: "follow"
|
|
104599
105005
|
});
|
|
104600
105006
|
clearTimeout(timer2);
|
|
104601
|
-
if (!resp.ok) {
|
|
104602
|
-
return { output: `Search failed: HTTP ${resp.status}. Try a different search engine with engine:"google" or engine:"bing".`, isError: true };
|
|
104603
|
-
}
|
|
104604
105007
|
const html = await resp.text();
|
|
104605
|
-
|
|
104606
|
-
|
|
104607
|
-
|
|
104608
|
-
|
|
104609
|
-
|
|
104610
|
-
|
|
104611
|
-
|
|
104612
|
-
|
|
104613
|
-
|
|
104614
|
-
|
|
104615
|
-
|
|
104616
|
-
|
|
104617
|
-
|
|
104618
|
-
|
|
104619
|
-
|
|
104620
|
-
|
|
104621
|
-
|
|
104622
|
-
|
|
104623
|
-
|
|
104624
|
-
|
|
104625
|
-
|
|
104626
|
-
|
|
104627
|
-
|
|
104628
|
-
|
|
104629
|
-
|
|
104630
|
-
|
|
104631
|
-
|
|
104632
|
-
|
|
104633
|
-
|
|
104634
|
-
|
|
104635
|
-
|
|
104636
|
-
|
|
104637
|
-
|
|
104638
|
-
|
|
104639
|
-
|
|
104640
|
-
|
|
104641
|
-
|
|
104642
|
-
|
|
104643
|
-
|
|
104644
|
-
|
|
104645
|
-
|
|
104646
|
-
|
|
104647
|
-
|
|
104648
|
-
|
|
104649
|
-
|
|
104650
|
-
|
|
104651
|
-
|
|
104652
|
-
|
|
105008
|
+
return { ok: resp.ok, status: resp.status, html };
|
|
105009
|
+
} catch {
|
|
105010
|
+
clearTimeout(timer2);
|
|
105011
|
+
return { ok: false, status: 0, html: "" };
|
|
105012
|
+
}
|
|
105013
|
+
}
|
|
105014
|
+
function parseDuckDuckGo(html, max) {
|
|
105015
|
+
const results = [];
|
|
105016
|
+
const linkRegex = /<a[^>]*class="result__a"[^>]*href="([^"]*)"[^>]*>(.*?)<\/a>/gi;
|
|
105017
|
+
const snippetRegex = /<a[^>]*class="result__snippet"[^>]*>(.*?)<\/a>/gi;
|
|
105018
|
+
let linkMatch;
|
|
105019
|
+
const links = [];
|
|
105020
|
+
while ((linkMatch = linkRegex.exec(html)) !== null && links.length < max) {
|
|
105021
|
+
let url = linkMatch[1];
|
|
105022
|
+
const uddg = url.match(/uddg=([^&]*)/);
|
|
105023
|
+
if (uddg) url = decodeURIComponent(uddg[1]);
|
|
105024
|
+
const title = linkMatch[2].replace(/<[^>]*>/g, "").trim();
|
|
105025
|
+
if (url.startsWith("http") && !url.includes("duckduckgo.com/y.js") && !url.includes("ad_domain=")) {
|
|
105026
|
+
links.push({ url, title });
|
|
105027
|
+
}
|
|
105028
|
+
}
|
|
105029
|
+
let snippetMatch;
|
|
105030
|
+
const snippets = [];
|
|
105031
|
+
while ((snippetMatch = snippetRegex.exec(html)) !== null) {
|
|
105032
|
+
snippets.push(snippetMatch[1].replace(/<[^>]*>/g, "").trim());
|
|
105033
|
+
}
|
|
105034
|
+
for (let i = 0; i < links.length; i++) {
|
|
105035
|
+
results.push({
|
|
105036
|
+
title: links[i].title,
|
|
105037
|
+
url: links[i].url,
|
|
105038
|
+
snippet: snippets[i] || ""
|
|
105039
|
+
});
|
|
105040
|
+
}
|
|
105041
|
+
return results;
|
|
105042
|
+
}
|
|
105043
|
+
function parseGoogle(html, max) {
|
|
105044
|
+
const results = [];
|
|
105045
|
+
const googleRegex = /<a[^>]*href="(https?:\/\/[^"]*)"[^>]*><h3[^>]*>([^<]+)<\/h3>/gi;
|
|
105046
|
+
let gMatch;
|
|
105047
|
+
while ((gMatch = googleRegex.exec(html)) !== null && results.length < max) {
|
|
105048
|
+
const url = gMatch[1];
|
|
105049
|
+
const title = gMatch[2].trim();
|
|
105050
|
+
if (title.length > 3 && !url.includes("google.com")) {
|
|
105051
|
+
results.push({ title, url, snippet: "" });
|
|
105052
|
+
}
|
|
105053
|
+
}
|
|
105054
|
+
if (results.length > 0) {
|
|
105055
|
+
const snippetRegex = /<div[^>]*class="[^"]*VwiC3b[^"]*"[^>]*>([\s\S]*?)<\/div>/gi;
|
|
105056
|
+
let sMatch;
|
|
105057
|
+
let idx = 0;
|
|
105058
|
+
while ((sMatch = snippetRegex.exec(html)) !== null && idx < results.length) {
|
|
105059
|
+
const snippet = sMatch[1].replace(/<[^>]*>/g, "").trim();
|
|
105060
|
+
if (snippet.length > 10) {
|
|
105061
|
+
results[idx].snippet = snippet;
|
|
105062
|
+
idx++;
|
|
104653
105063
|
}
|
|
104654
105064
|
}
|
|
104655
|
-
|
|
104656
|
-
|
|
104657
|
-
|
|
104658
|
-
|
|
104659
|
-
|
|
104660
|
-
|
|
104661
|
-
|
|
104662
|
-
|
|
104663
|
-
|
|
105065
|
+
return results;
|
|
105066
|
+
}
|
|
105067
|
+
const resultBlockRegex = /<div class="[^"]*g[^"]*"[^>]*>[\s\S]*?<a[^>]*href="(https?:\/\/[^"]*)"[^>]*>([\s\S]*?)<\/a>[\s\S]*?(?:<span[^>]*>([\s\S]*?)<\/span>)?/gi;
|
|
105068
|
+
let blockMatch;
|
|
105069
|
+
while ((blockMatch = resultBlockRegex.exec(html)) !== null && results.length < max) {
|
|
105070
|
+
const url = blockMatch[1];
|
|
105071
|
+
const title = blockMatch[2].replace(/<[^>]*>/g, "").trim();
|
|
105072
|
+
const snippet = (blockMatch[3] || "").replace(/<[^>]*>/g, "").trim();
|
|
105073
|
+
if (title.length > 3 && !url.includes("google.com")) {
|
|
105074
|
+
results.push({ title, url, snippet });
|
|
105075
|
+
}
|
|
105076
|
+
}
|
|
105077
|
+
return results;
|
|
105078
|
+
}
|
|
105079
|
+
function parseBing(html, max) {
|
|
105080
|
+
const results = [];
|
|
105081
|
+
const bingRegex = /<li[^>]*class="b_algo"[^>]*>[\s\S]*?<a[^>]*href="([^"]*)"[^>]*>([^<]+)<\/a>[\s\S]*?<p[^>]*>([^<]*)/gi;
|
|
105082
|
+
let bingMatch;
|
|
105083
|
+
while ((bingMatch = bingRegex.exec(html)) !== null && results.length < max) {
|
|
105084
|
+
const url = bingMatch[1];
|
|
105085
|
+
const title = bingMatch[2].replace(/<[^>]*>/g, "").trim();
|
|
105086
|
+
const snippet = bingMatch[3].replace(/<[^>]*>/g, "").trim();
|
|
105087
|
+
if (title.length > 3) {
|
|
105088
|
+
results.push({ title, url, snippet });
|
|
105089
|
+
}
|
|
105090
|
+
}
|
|
105091
|
+
if (results.length === 0) {
|
|
105092
|
+
const fallbackRegex = /<li class="b_algo"[^>]*>[\s\S]*?<a[^>]*href="(https?:\/\/[^"]*)"[^>]*>([\s\S]*?)<\/a>[\s\S]*?<p[^>]*>([\s\S]*?)<\/p>/gi;
|
|
105093
|
+
let fbMatch;
|
|
105094
|
+
while ((fbMatch = fallbackRegex.exec(html)) !== null && results.length < max) {
|
|
105095
|
+
const url = fbMatch[1];
|
|
105096
|
+
const title = fbMatch[2].replace(/<[^>]*>/g, "").trim();
|
|
105097
|
+
const snippet = fbMatch[3].replace(/<[^>]*>/g, "").trim();
|
|
105098
|
+
if (title.length > 3) {
|
|
105099
|
+
results.push({ title, url, snippet });
|
|
104664
105100
|
}
|
|
104665
105101
|
}
|
|
105102
|
+
}
|
|
105103
|
+
return results;
|
|
105104
|
+
}
|
|
105105
|
+
function parseAnyLinks(html, max) {
|
|
105106
|
+
const results = [];
|
|
105107
|
+
const anyLinkRegex = /<a[^>]*href="(https?:\/\/[^"]*)"[^>]*>(.*?)<\/a>/gi;
|
|
105108
|
+
let anyMatch;
|
|
105109
|
+
while ((anyMatch = anyLinkRegex.exec(html)) !== null && results.length < max) {
|
|
105110
|
+
const url = anyMatch[1];
|
|
105111
|
+
const title = anyMatch[2].replace(/<[^>]*>/g, "").trim();
|
|
105112
|
+
if (title.length > 5 && !url.includes("duckduckgo.com") && !url.includes("google.com") && !url.includes("bing.com")) {
|
|
105113
|
+
results.push({ title, url, snippet: "" });
|
|
105114
|
+
}
|
|
105115
|
+
}
|
|
105116
|
+
return results;
|
|
105117
|
+
}
|
|
105118
|
+
async function searchSingleEngine(engineName, query, max, context3) {
|
|
105119
|
+
let searchUrl;
|
|
105120
|
+
let parser2;
|
|
105121
|
+
switch (engineName) {
|
|
105122
|
+
case "google":
|
|
105123
|
+
searchUrl = `https://www.google.com/search?q=${encodeURIComponent(query)}&num=${max}`;
|
|
105124
|
+
parser2 = parseGoogle;
|
|
105125
|
+
break;
|
|
105126
|
+
case "bing":
|
|
105127
|
+
searchUrl = `https://www.bing.com/search?q=${encodeURIComponent(query)}&count=${max}`;
|
|
105128
|
+
parser2 = parseBing;
|
|
105129
|
+
break;
|
|
105130
|
+
case "duckduckgo":
|
|
105131
|
+
default:
|
|
105132
|
+
searchUrl = `https://html.duckduckgo.com/html/?q=${encodeURIComponent(query)}`;
|
|
105133
|
+
parser2 = parseDuckDuckGo;
|
|
105134
|
+
break;
|
|
105135
|
+
}
|
|
105136
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
105137
|
+
const ua = pickUserAgent(attempt);
|
|
105138
|
+
const { ok, status, html } = await fetchSearchHtml(searchUrl, context3, ua);
|
|
105139
|
+
if (!ok) {
|
|
105140
|
+
if (attempt === 0) continue;
|
|
105141
|
+
return { results: [], engineUsed: engineName, error: `HTTP ${status}` };
|
|
105142
|
+
}
|
|
105143
|
+
let results = parser2(html, max);
|
|
104666
105144
|
if (results.length === 0) {
|
|
105145
|
+
results = parseAnyLinks(html, max);
|
|
105146
|
+
}
|
|
105147
|
+
if (results.length > 0) {
|
|
105148
|
+
return { results, engineUsed: engineName };
|
|
105149
|
+
}
|
|
105150
|
+
}
|
|
105151
|
+
return { results: [], engineUsed: engineName, error: "0 results after UA rotation" };
|
|
105152
|
+
}
|
|
105153
|
+
async function webSearchHandler(input, context3) {
|
|
105154
|
+
const { query, engine, maxResults } = input;
|
|
105155
|
+
const max = maxResults || 5;
|
|
105156
|
+
const searchEngine = engine || "auto";
|
|
105157
|
+
if (searchEngine !== "auto") {
|
|
105158
|
+
try {
|
|
105159
|
+
const { results, error } = await searchSingleEngine(searchEngine, query, max, context3);
|
|
105160
|
+
if (results.length === 0) {
|
|
105161
|
+
return {
|
|
105162
|
+
output: `No results found for "${query}" on ${searchEngine}${error ? ` (${error})` : ""}. Try a different query or use engine:"auto" for multi-engine fallback. You can also try web_fetch directly on a relevant URL.`,
|
|
105163
|
+
isError: false
|
|
105164
|
+
};
|
|
105165
|
+
}
|
|
105166
|
+
const formatted = results.map(
|
|
105167
|
+
(r, i) => `${i + 1}. ${r.title}
|
|
105168
|
+
${r.url}
|
|
105169
|
+
${r.snippet}`
|
|
105170
|
+
).join("\n\n");
|
|
104667
105171
|
return {
|
|
104668
|
-
output: `
|
|
105172
|
+
output: `Search results for "${query}" (${searchEngine}):
|
|
105173
|
+
|
|
105174
|
+
${formatted}
|
|
105175
|
+
|
|
105176
|
+
Use web_fetch on any URL above to get the full page content.`,
|
|
104669
105177
|
isError: false
|
|
104670
105178
|
};
|
|
105179
|
+
} catch (err) {
|
|
105180
|
+
if (err.name === "AbortError") {
|
|
105181
|
+
return { output: `Search timed out for "${query}". Try a simpler query or different engine.`, isError: true };
|
|
105182
|
+
}
|
|
105183
|
+
return { output: `Search error: ${err.message}. Try engine:"auto" for multi-engine fallback.`, isError: true };
|
|
104671
105184
|
}
|
|
104672
|
-
|
|
104673
|
-
|
|
105185
|
+
}
|
|
105186
|
+
const fallbackChain = ["duckduckgo", "google", "bing"];
|
|
105187
|
+
const errors = [];
|
|
105188
|
+
for (const eng of fallbackChain) {
|
|
105189
|
+
try {
|
|
105190
|
+
const { results, engineUsed, error } = await searchSingleEngine(eng, query, max, context3);
|
|
105191
|
+
if (results.length > 0) {
|
|
105192
|
+
const formatted = results.map(
|
|
105193
|
+
(r, i) => `${i + 1}. ${r.title}
|
|
104674
105194
|
${r.url}
|
|
104675
105195
|
${r.snippet}`
|
|
104676
|
-
|
|
104677
|
-
|
|
104678
|
-
|
|
105196
|
+
).join("\n\n");
|
|
105197
|
+
const fallbackNote = eng !== "duckduckgo" ? `
|
|
105198
|
+
|
|
105199
|
+
(Note: Results from ${engineUsed} \u2014 earlier engines returned 0 results)` : "";
|
|
105200
|
+
return {
|
|
105201
|
+
output: `Search results for "${query}" (${engineUsed}):
|
|
104679
105202
|
|
|
104680
105203
|
${formatted}
|
|
104681
105204
|
|
|
104682
|
-
Use web_fetch on any URL above to get the full page content
|
|
104683
|
-
|
|
104684
|
-
|
|
104685
|
-
|
|
104686
|
-
|
|
104687
|
-
|
|
105205
|
+
Use web_fetch on any URL above to get the full page content.${fallbackNote}`,
|
|
105206
|
+
isError: false
|
|
105207
|
+
};
|
|
105208
|
+
}
|
|
105209
|
+
errors.push(`${eng}: ${error || "0 results"}`);
|
|
105210
|
+
} catch (err) {
|
|
105211
|
+
errors.push(`${eng}: ${err.message || "unknown error"}`);
|
|
104688
105212
|
}
|
|
104689
|
-
return { output: `Search error: ${err.message}. Try a different search engine with engine:"google" or engine:"bing".`, isError: true };
|
|
104690
105213
|
}
|
|
105214
|
+
return {
|
|
105215
|
+
output: `All search engines failed for "${query}". Tried: ${errors.join("; ")}. Try web_fetch directly on known URLs (e.g., Wikipedia, company sites, social profiles) instead of searching.`,
|
|
105216
|
+
isError: true
|
|
105217
|
+
};
|
|
104691
105218
|
}
|
|
104692
105219
|
async function messageSendHandler(input, context3) {
|
|
104693
105220
|
const { to, subject, body } = input;
|
|
@@ -104826,7 +105353,7 @@ function registerBrowserTools(registry, config2) {
|
|
|
104826
105353
|
}
|
|
104827
105354
|
return manager;
|
|
104828
105355
|
}
|
|
104829
|
-
var shellExecSchema, sandboxCache, DANGEROUS_METACHARACTERS, shellExecTool, fileReadSchema, fileReadTool, fileWriteSchema, fileWriteTool, fileListSchema, fileListTool, webFetchSchema, webFetchTool, webSearchSchema, webSearchTool, messageSendSchema, messageSendTool, messageReadSchema, messageReadTool, handoffSchema, handoffTool, undoSchema;
|
|
105356
|
+
var shellExecSchema, sandboxCache, DANGEROUS_METACHARACTERS, shellExecTool, fileReadSchema, fileReadTool, fileWriteSchema, fileWriteTool, fileListSchema, fileListTool, webFetchSchema, webFetchTool, webSearchSchema, SEARCH_USER_AGENTS, webSearchTool, messageSendSchema, messageSendTool, messageReadSchema, messageReadTool, handoffSchema, handoffTool, undoSchema;
|
|
104830
105357
|
var init_builtin = __esm({
|
|
104831
105358
|
"../agent/src/tools/builtin.ts"() {
|
|
104832
105359
|
"use strict";
|
|
@@ -104906,12 +105433,17 @@ var init_builtin = __esm({
|
|
|
104906
105433
|
};
|
|
104907
105434
|
webSearchSchema = z29.object({
|
|
104908
105435
|
query: z29.string().describe("The search query"),
|
|
104909
|
-
engine: z29.string().optional().describe(
|
|
105436
|
+
engine: z29.string().optional().describe('Search engine: google, duckduckgo, bing, or "auto" for multi-engine fallback (default). Default: auto'),
|
|
104910
105437
|
maxResults: z29.number().optional().describe("Max results to return. Default: 5")
|
|
104911
105438
|
});
|
|
105439
|
+
SEARCH_USER_AGENTS = [
|
|
105440
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
105441
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15",
|
|
105442
|
+
"Mozilla/5.0 (X11; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0"
|
|
105443
|
+
];
|
|
104912
105444
|
webSearchTool = {
|
|
104913
105445
|
name: "web_search",
|
|
104914
|
-
description:
|
|
105446
|
+
description: 'Search the internet using DuckDuckGo, Google, or Bing with automatic multi-engine fallback. Returns titles, URLs, and snippets. Use web_fetch on result URLs to read full page content. Default mode "auto" tries DuckDuckGo first, then Google, then Bing if previous engines return 0 results.',
|
|
104915
105447
|
inputSchema: webSearchSchema,
|
|
104916
105448
|
handler: webSearchHandler
|
|
104917
105449
|
};
|
|
@@ -106835,8 +107367,8 @@ var init_store2 = __esm({
|
|
|
106835
107367
|
});
|
|
106836
107368
|
|
|
106837
107369
|
// ../agent/src/memory/files.ts
|
|
106838
|
-
import { readFileSync as
|
|
106839
|
-
import { join as
|
|
107370
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync4, existsSync as existsSync6, mkdirSync as mkdirSync4 } from "node:fs";
|
|
107371
|
+
import { join as join11, dirname as dirname5 } from "node:path";
|
|
106840
107372
|
var MemoryFiles;
|
|
106841
107373
|
var init_files = __esm({
|
|
106842
107374
|
"../agent/src/memory/files.ts"() {
|
|
@@ -106844,8 +107376,8 @@ var init_files = __esm({
|
|
|
106844
107376
|
MemoryFiles = class {
|
|
106845
107377
|
constructor(workDir) {
|
|
106846
107378
|
this.workDir = workDir;
|
|
106847
|
-
this.memoryPath =
|
|
106848
|
-
this.userPath =
|
|
107379
|
+
this.memoryPath = join11(workDir, "MEMORY.md");
|
|
107380
|
+
this.userPath = join11(workDir, "USER.md");
|
|
106849
107381
|
}
|
|
106850
107382
|
memoryPath;
|
|
106851
107383
|
userPath;
|
|
@@ -106854,8 +107386,8 @@ var init_files = __esm({
|
|
|
106854
107386
|
*/
|
|
106855
107387
|
readMemoryFile() {
|
|
106856
107388
|
try {
|
|
106857
|
-
if (!
|
|
106858
|
-
return
|
|
107389
|
+
if (!existsSync6(this.memoryPath)) return null;
|
|
107390
|
+
return readFileSync10(this.memoryPath, "utf-8");
|
|
106859
107391
|
} catch {
|
|
106860
107392
|
return null;
|
|
106861
107393
|
}
|
|
@@ -106865,8 +107397,8 @@ var init_files = __esm({
|
|
|
106865
107397
|
*/
|
|
106866
107398
|
readUserFile() {
|
|
106867
107399
|
try {
|
|
106868
|
-
if (!
|
|
106869
|
-
return
|
|
107400
|
+
if (!existsSync6(this.userPath)) return null;
|
|
107401
|
+
return readFileSync10(this.userPath, "utf-8");
|
|
106870
107402
|
} catch {
|
|
106871
107403
|
return null;
|
|
106872
107404
|
}
|
|
@@ -106876,16 +107408,16 @@ var init_files = __esm({
|
|
|
106876
107408
|
*/
|
|
106877
107409
|
appendMemory(observation) {
|
|
106878
107410
|
const dir = dirname5(this.memoryPath);
|
|
106879
|
-
if (!
|
|
106880
|
-
|
|
107411
|
+
if (!existsSync6(dir)) {
|
|
107412
|
+
mkdirSync4(dir, { recursive: true });
|
|
106881
107413
|
}
|
|
106882
107414
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
106883
107415
|
const entry = `
|
|
106884
107416
|
- [${timestamp}] ${observation}
|
|
106885
107417
|
`;
|
|
106886
|
-
if (
|
|
106887
|
-
const existing =
|
|
106888
|
-
|
|
107418
|
+
if (existsSync6(this.memoryPath)) {
|
|
107419
|
+
const existing = readFileSync10(this.memoryPath, "utf-8");
|
|
107420
|
+
writeFileSync4(this.memoryPath, existing + entry, "utf-8");
|
|
106889
107421
|
} else {
|
|
106890
107422
|
const header = `# Agent Memory
|
|
106891
107423
|
|
|
@@ -106893,7 +107425,7 @@ Persistent observations and notes.
|
|
|
106893
107425
|
|
|
106894
107426
|
## Observations
|
|
106895
107427
|
`;
|
|
106896
|
-
|
|
107428
|
+
writeFileSync4(this.memoryPath, header + entry, "utf-8");
|
|
106897
107429
|
}
|
|
106898
107430
|
}
|
|
106899
107431
|
/**
|
|
@@ -106901,8 +107433,8 @@ Persistent observations and notes.
|
|
|
106901
107433
|
*/
|
|
106902
107434
|
updateUserProfile(info) {
|
|
106903
107435
|
const dir = dirname5(this.userPath);
|
|
106904
|
-
if (!
|
|
106905
|
-
|
|
107436
|
+
if (!existsSync6(dir)) {
|
|
107437
|
+
mkdirSync4(dir, { recursive: true });
|
|
106906
107438
|
}
|
|
106907
107439
|
const lines = ["# User Profile\n"];
|
|
106908
107440
|
for (const [key, value] of Object.entries(info)) {
|
|
@@ -106911,7 +107443,7 @@ Persistent observations and notes.
|
|
|
106911
107443
|
}
|
|
106912
107444
|
}
|
|
106913
107445
|
lines.push("");
|
|
106914
|
-
|
|
107446
|
+
writeFileSync4(this.userPath, lines.join("\n"), "utf-8");
|
|
106915
107447
|
}
|
|
106916
107448
|
/**
|
|
106917
107449
|
* Parse MEMORY.md into structured entries.
|
|
@@ -111124,8 +111656,8 @@ var init_embeddings = __esm({
|
|
|
111124
111656
|
});
|
|
111125
111657
|
|
|
111126
111658
|
// ../agent/src/rag/indexer.ts
|
|
111127
|
-
import { readFileSync as
|
|
111128
|
-
import { join as
|
|
111659
|
+
import { readFileSync as readFileSync11, statSync as statSync4, existsSync as existsSync7 } from "node:fs";
|
|
111660
|
+
import { join as join12, relative as relative4, resolve as resolve11 } from "node:path";
|
|
111129
111661
|
function matchesGlob(filePath, pattern) {
|
|
111130
111662
|
const regexStr = pattern.replace(/\./g, "\\.").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\{\{GLOBSTAR\}\}/g, ".*");
|
|
111131
111663
|
return new RegExp(`^${regexStr}$`).test(filePath) || new RegExp(`(^|/)${regexStr}$`).test(filePath);
|
|
@@ -111151,14 +111683,14 @@ function walkDirectory2(dir, excludePatterns) {
|
|
|
111151
111683
|
const currentDir = stack.pop();
|
|
111152
111684
|
let entries;
|
|
111153
111685
|
try {
|
|
111154
|
-
const { readdirSync:
|
|
111155
|
-
entries =
|
|
111686
|
+
const { readdirSync: readdirSync8 } = __require("node:fs");
|
|
111687
|
+
entries = readdirSync8(currentDir);
|
|
111156
111688
|
} catch {
|
|
111157
111689
|
continue;
|
|
111158
111690
|
}
|
|
111159
111691
|
for (const entry of entries) {
|
|
111160
|
-
const fullPath =
|
|
111161
|
-
const relFromRoot =
|
|
111692
|
+
const fullPath = join12(currentDir, entry);
|
|
111693
|
+
const relFromRoot = relative4(dir, fullPath).replace(/\\/g, "/");
|
|
111162
111694
|
let excluded = false;
|
|
111163
111695
|
for (const pattern of excludePatterns) {
|
|
111164
111696
|
if (!pattern.includes("*") && !pattern.includes(".")) {
|
|
@@ -111170,7 +111702,7 @@ function walkDirectory2(dir, excludePatterns) {
|
|
|
111170
111702
|
}
|
|
111171
111703
|
if (excluded) continue;
|
|
111172
111704
|
try {
|
|
111173
|
-
const stat =
|
|
111705
|
+
const stat = statSync4(fullPath);
|
|
111174
111706
|
if (stat.isDirectory()) {
|
|
111175
111707
|
stack.push(fullPath);
|
|
111176
111708
|
} else if (stat.isFile()) {
|
|
@@ -111262,13 +111794,13 @@ var init_indexer = __esm({
|
|
|
111262
111794
|
const tenantId = opts?.tenantId ?? "default";
|
|
111263
111795
|
const onProgress = opts?.onProgress;
|
|
111264
111796
|
const absDir = resolve11(dir);
|
|
111265
|
-
if (!
|
|
111797
|
+
if (!existsSync7(absDir)) {
|
|
111266
111798
|
throw new Error(`Directory not found: ${absDir}`);
|
|
111267
111799
|
}
|
|
111268
111800
|
const allFiles = walkDirectory2(absDir, excludePatterns);
|
|
111269
111801
|
const matchingFiles = [];
|
|
111270
111802
|
for (const file of allFiles) {
|
|
111271
|
-
const relPath =
|
|
111803
|
+
const relPath = relative4(absDir, file).replace(/\\/g, "/");
|
|
111272
111804
|
if (shouldInclude(relPath, includePatterns, excludePatterns)) {
|
|
111273
111805
|
matchingFiles.push(file);
|
|
111274
111806
|
}
|
|
@@ -111284,11 +111816,11 @@ var init_indexer = __esm({
|
|
|
111284
111816
|
let totalFilesIndexed = 0;
|
|
111285
111817
|
const allChunks = [];
|
|
111286
111818
|
for (const filePath of matchingFiles) {
|
|
111287
|
-
const relPath =
|
|
111819
|
+
const relPath = relative4(absDir, filePath).replace(/\\/g, "/");
|
|
111288
111820
|
progress.currentFile = relPath;
|
|
111289
111821
|
onProgress?.(progress);
|
|
111290
111822
|
try {
|
|
111291
|
-
const content =
|
|
111823
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
111292
111824
|
if (content.includes("\0")) {
|
|
111293
111825
|
progress.processedFiles++;
|
|
111294
111826
|
continue;
|
|
@@ -111297,7 +111829,7 @@ var init_indexer = __esm({
|
|
|
111297
111829
|
progress.processedFiles++;
|
|
111298
111830
|
continue;
|
|
111299
111831
|
}
|
|
111300
|
-
const mtime =
|
|
111832
|
+
const mtime = statSync4(filePath).mtimeMs;
|
|
111301
111833
|
const chunks = this.chunker.chunk(relPath, content);
|
|
111302
111834
|
for (const chunk of chunks) {
|
|
111303
111835
|
allChunks.push({ ...chunk, fileMtime: Math.floor(mtime) });
|
|
@@ -111359,7 +111891,7 @@ ${c.content}`);
|
|
|
111359
111891
|
const tenantId = opts?.tenantId ?? "default";
|
|
111360
111892
|
const onProgress = opts?.onProgress;
|
|
111361
111893
|
const absDir = resolve11(dir);
|
|
111362
|
-
if (!
|
|
111894
|
+
if (!existsSync7(absDir)) {
|
|
111363
111895
|
throw new Error(`Directory not found: ${absDir}`);
|
|
111364
111896
|
}
|
|
111365
111897
|
const existingMtimes = this.store.getChunkMtimes(tenantId);
|
|
@@ -111370,16 +111902,16 @@ ${c.content}`);
|
|
|
111370
111902
|
const allFiles = walkDirectory2(absDir, excludePatterns);
|
|
111371
111903
|
const matchingFiles = [];
|
|
111372
111904
|
for (const file of allFiles) {
|
|
111373
|
-
const relPath =
|
|
111905
|
+
const relPath = relative4(absDir, file).replace(/\\/g, "/");
|
|
111374
111906
|
if (shouldInclude(relPath, includePatterns, excludePatterns)) {
|
|
111375
111907
|
matchingFiles.push(file);
|
|
111376
111908
|
}
|
|
111377
111909
|
}
|
|
111378
111910
|
const filesToProcess = [];
|
|
111379
111911
|
for (const filePath of matchingFiles) {
|
|
111380
|
-
const relPath =
|
|
111912
|
+
const relPath = relative4(absDir, filePath).replace(/\\/g, "/");
|
|
111381
111913
|
try {
|
|
111382
|
-
const mtime = Math.floor(
|
|
111914
|
+
const mtime = Math.floor(statSync4(filePath).mtimeMs);
|
|
111383
111915
|
const existingMtime = mtimeMap.get(relPath);
|
|
111384
111916
|
if (existingMtime === void 0 || mtime > existingMtime) {
|
|
111385
111917
|
filesToProcess.push(filePath);
|
|
@@ -111401,16 +111933,16 @@ ${c.content}`);
|
|
|
111401
111933
|
let totalChunksCreated = 0;
|
|
111402
111934
|
let totalFilesIndexed = 0;
|
|
111403
111935
|
for (const filePath of filesToProcess) {
|
|
111404
|
-
const relPath =
|
|
111936
|
+
const relPath = relative4(absDir, filePath).replace(/\\/g, "/");
|
|
111405
111937
|
progress.currentFile = relPath;
|
|
111406
111938
|
onProgress?.(progress);
|
|
111407
111939
|
try {
|
|
111408
|
-
const content =
|
|
111940
|
+
const content = readFileSync11(filePath, "utf-8");
|
|
111409
111941
|
if (content.includes("\0") || content.length > 5e5) {
|
|
111410
111942
|
progress.processedFiles++;
|
|
111411
111943
|
continue;
|
|
111412
111944
|
}
|
|
111413
|
-
const mtime = Math.floor(
|
|
111945
|
+
const mtime = Math.floor(statSync4(filePath).mtimeMs);
|
|
111414
111946
|
this.store.clearChunksByFile(relPath, tenantId);
|
|
111415
111947
|
const chunks = this.chunker.chunk(relPath, content);
|
|
111416
111948
|
const texts = chunks.map((c) => `${c.name ?? c.type} in ${c.filePath}
|
|
@@ -111593,8 +112125,8 @@ var init_search = __esm({
|
|
|
111593
112125
|
});
|
|
111594
112126
|
|
|
111595
112127
|
// ../agent/src/rag/mental-model.ts
|
|
111596
|
-
import { readFileSync as
|
|
111597
|
-
import { join as
|
|
112128
|
+
import { readFileSync as readFileSync12, statSync as statSync5, readdirSync as readdirSync3, writeFileSync as writeFileSync5, existsSync as existsSync8 } from "node:fs";
|
|
112129
|
+
import { join as join13, relative as relative5, resolve as resolve12, extname as extname3, basename as basename4, dirname as dirname6 } from "node:path";
|
|
111598
112130
|
var EXCLUDE_DIRS, SOURCE_EXTENSIONS, MentalModelBuilder;
|
|
111599
112131
|
var init_mental_model = __esm({
|
|
111600
112132
|
"../agent/src/rag/mental-model.ts"() {
|
|
@@ -111658,10 +112190,10 @@ var init_mental_model = __esm({
|
|
|
111658
112190
|
const files = await this.findSourceFiles(absRoot);
|
|
111659
112191
|
const nodes = /* @__PURE__ */ new Map();
|
|
111660
112192
|
for (const file of files) {
|
|
111661
|
-
const relPath =
|
|
112193
|
+
const relPath = relative5(absRoot, file).replace(/\\/g, "/");
|
|
111662
112194
|
let content;
|
|
111663
112195
|
try {
|
|
111664
|
-
content =
|
|
112196
|
+
content = readFileSync12(file, "utf-8");
|
|
111665
112197
|
} catch {
|
|
111666
112198
|
continue;
|
|
111667
112199
|
}
|
|
@@ -111669,14 +112201,14 @@ var init_mental_model = __esm({
|
|
|
111669
112201
|
const imports = this.extractImports(content, file, absRoot);
|
|
111670
112202
|
let mtime;
|
|
111671
112203
|
try {
|
|
111672
|
-
mtime =
|
|
112204
|
+
mtime = statSync5(file).mtimeMs;
|
|
111673
112205
|
} catch {
|
|
111674
112206
|
mtime = Date.now();
|
|
111675
112207
|
}
|
|
111676
112208
|
nodes.set(relPath, {
|
|
111677
112209
|
path: relPath,
|
|
111678
112210
|
type: "file",
|
|
111679
|
-
name:
|
|
112211
|
+
name: basename4(file),
|
|
111680
112212
|
dependencies: imports,
|
|
111681
112213
|
dependents: [],
|
|
111682
112214
|
lastModified: mtime,
|
|
@@ -111709,7 +112241,7 @@ var init_mental_model = __esm({
|
|
|
111709
112241
|
);
|
|
111710
112242
|
const hubs = [...graph.nodes.values()].sort((a, b) => b.dependents.length - a.dependents.length).slice(0, 5);
|
|
111711
112243
|
const lines = [];
|
|
111712
|
-
lines.push(`Project: ${
|
|
112244
|
+
lines.push(`Project: ${basename4(graph.rootDir)}`);
|
|
111713
112245
|
lines.push(`Language: ${graph.language}`);
|
|
111714
112246
|
if (graph.framework) lines.push(`Framework: ${graph.framework}`);
|
|
111715
112247
|
lines.push(`Files: ${moduleCount}`);
|
|
@@ -111796,15 +112328,15 @@ var init_mental_model = __esm({
|
|
|
111796
112328
|
*/
|
|
111797
112329
|
save(graph, filePath) {
|
|
111798
112330
|
const json = this.toJson(graph);
|
|
111799
|
-
|
|
112331
|
+
writeFileSync5(filePath, JSON.stringify(json, null, 2), "utf-8");
|
|
111800
112332
|
}
|
|
111801
112333
|
/**
|
|
111802
112334
|
* Load a graph from a JSON file.
|
|
111803
112335
|
*/
|
|
111804
112336
|
load(filePath) {
|
|
111805
|
-
if (!
|
|
112337
|
+
if (!existsSync8(filePath)) return null;
|
|
111806
112338
|
try {
|
|
111807
|
-
const content =
|
|
112339
|
+
const content = readFileSync12(filePath, "utf-8");
|
|
111808
112340
|
const json = JSON.parse(content);
|
|
111809
112341
|
return this.fromJson(json);
|
|
111810
112342
|
} catch {
|
|
@@ -111883,7 +112415,7 @@ var init_mental_model = __esm({
|
|
|
111883
112415
|
}
|
|
111884
112416
|
const fromDir = dirname6(fromFile);
|
|
111885
112417
|
const resolved = resolve12(fromDir, specifier);
|
|
111886
|
-
const relPath =
|
|
112418
|
+
const relPath = relative5(rootDir, resolved).replace(/\\/g, "/");
|
|
111887
112419
|
const candidates = [
|
|
111888
112420
|
relPath,
|
|
111889
112421
|
relPath + ".ts",
|
|
@@ -111904,7 +112436,7 @@ var init_mental_model = __esm({
|
|
|
111904
112436
|
for (const candidate of candidates) {
|
|
111905
112437
|
const fullPath = resolve12(rootDir, candidate);
|
|
111906
112438
|
try {
|
|
111907
|
-
const stat =
|
|
112439
|
+
const stat = statSync5(fullPath);
|
|
111908
112440
|
if (stat.isFile()) {
|
|
111909
112441
|
return candidate;
|
|
111910
112442
|
}
|
|
@@ -111914,7 +112446,7 @@ var init_mental_model = __esm({
|
|
|
111914
112446
|
return relPath;
|
|
111915
112447
|
}
|
|
111916
112448
|
resolveRelativePy(modulePath, fromFile, rootDir) {
|
|
111917
|
-
const relPath =
|
|
112449
|
+
const relPath = relative5(rootDir, resolve12(dirname6(fromFile), modulePath)).replace(/\\/g, "/");
|
|
111918
112450
|
const candidates = [
|
|
111919
112451
|
relPath + ".py",
|
|
111920
112452
|
relPath + "/__init__.py"
|
|
@@ -111922,7 +112454,7 @@ var init_mental_model = __esm({
|
|
|
111922
112454
|
for (const candidate of candidates) {
|
|
111923
112455
|
const fullPath = resolve12(rootDir, candidate);
|
|
111924
112456
|
try {
|
|
111925
|
-
if (
|
|
112457
|
+
if (statSync5(fullPath).isFile()) return candidate;
|
|
111926
112458
|
} catch {
|
|
111927
112459
|
}
|
|
111928
112460
|
}
|
|
@@ -111997,10 +112529,10 @@ var init_mental_model = __esm({
|
|
|
111997
112529
|
return "Unknown";
|
|
111998
112530
|
}
|
|
111999
112531
|
detectFramework(rootDir) {
|
|
112000
|
-
const pkgPath =
|
|
112001
|
-
if (
|
|
112532
|
+
const pkgPath = join13(rootDir, "package.json");
|
|
112533
|
+
if (existsSync8(pkgPath)) {
|
|
112002
112534
|
try {
|
|
112003
|
-
const pkg = JSON.parse(
|
|
112535
|
+
const pkg = JSON.parse(readFileSync12(pkgPath, "utf-8"));
|
|
112004
112536
|
const deps = {
|
|
112005
112537
|
...pkg.dependencies ?? {},
|
|
112006
112538
|
...pkg.devDependencies ?? {}
|
|
@@ -112019,10 +112551,10 @@ var init_mental_model = __esm({
|
|
|
112019
112551
|
} catch {
|
|
112020
112552
|
}
|
|
112021
112553
|
}
|
|
112022
|
-
const cargoPath =
|
|
112023
|
-
if (
|
|
112554
|
+
const cargoPath = join13(rootDir, "Cargo.toml");
|
|
112555
|
+
if (existsSync8(cargoPath)) {
|
|
112024
112556
|
try {
|
|
112025
|
-
const cargo =
|
|
112557
|
+
const cargo = readFileSync12(cargoPath, "utf-8");
|
|
112026
112558
|
if (cargo.includes("actix-web")) return "Actix";
|
|
112027
112559
|
if (cargo.includes("axum")) return "Axum";
|
|
112028
112560
|
if (cargo.includes("rocket")) return "Rocket";
|
|
@@ -112030,10 +112562,10 @@ var init_mental_model = __esm({
|
|
|
112030
112562
|
} catch {
|
|
112031
112563
|
}
|
|
112032
112564
|
}
|
|
112033
|
-
const goModPath =
|
|
112034
|
-
if (
|
|
112565
|
+
const goModPath = join13(rootDir, "go.mod");
|
|
112566
|
+
if (existsSync8(goModPath)) {
|
|
112035
112567
|
try {
|
|
112036
|
-
const goMod =
|
|
112568
|
+
const goMod = readFileSync12(goModPath, "utf-8");
|
|
112037
112569
|
if (goMod.includes("gin-gonic")) return "Gin";
|
|
112038
112570
|
if (goMod.includes("echo")) return "Echo";
|
|
112039
112571
|
if (goMod.includes("fiber")) return "Fiber";
|
|
@@ -112041,10 +112573,10 @@ var init_mental_model = __esm({
|
|
|
112041
112573
|
}
|
|
112042
112574
|
}
|
|
112043
112575
|
for (const pyFile of ["requirements.txt", "pyproject.toml"]) {
|
|
112044
|
-
const pyPath =
|
|
112045
|
-
if (
|
|
112576
|
+
const pyPath = join13(rootDir, pyFile);
|
|
112577
|
+
if (existsSync8(pyPath)) {
|
|
112046
112578
|
try {
|
|
112047
|
-
const content =
|
|
112579
|
+
const content = readFileSync12(pyPath, "utf-8");
|
|
112048
112580
|
if (content.includes("django")) return "Django";
|
|
112049
112581
|
if (content.includes("flask")) return "Flask";
|
|
112050
112582
|
if (content.includes("fastapi")) return "FastAPI";
|
|
@@ -112098,16 +112630,16 @@ var init_mental_model = __esm({
|
|
|
112098
112630
|
const currentDir = stack.pop();
|
|
112099
112631
|
let entries;
|
|
112100
112632
|
try {
|
|
112101
|
-
entries =
|
|
112633
|
+
entries = readdirSync3(currentDir);
|
|
112102
112634
|
} catch {
|
|
112103
112635
|
continue;
|
|
112104
112636
|
}
|
|
112105
112637
|
for (const entry of entries) {
|
|
112106
112638
|
if (EXCLUDE_DIRS.has(entry)) continue;
|
|
112107
112639
|
if (entry.startsWith(".") && entry !== ".") continue;
|
|
112108
|
-
const fullPath =
|
|
112640
|
+
const fullPath = join13(currentDir, entry);
|
|
112109
112641
|
try {
|
|
112110
|
-
const stat =
|
|
112642
|
+
const stat = statSync5(fullPath);
|
|
112111
112643
|
if (stat.isDirectory()) {
|
|
112112
112644
|
stack.push(fullPath);
|
|
112113
112645
|
} else if (stat.isFile()) {
|
|
@@ -112140,7 +112672,7 @@ var init_rag = __esm({
|
|
|
112140
112672
|
});
|
|
112141
112673
|
|
|
112142
112674
|
// ../agent/src/testing/mock-adapter.ts
|
|
112143
|
-
import { readFileSync as
|
|
112675
|
+
import { readFileSync as readFileSync13, writeFileSync as writeFileSync6 } from "node:fs";
|
|
112144
112676
|
var MockLlmAdapter, RecordingAdapter;
|
|
112145
112677
|
var init_mock_adapter = __esm({
|
|
112146
112678
|
"../agent/src/testing/mock-adapter.ts"() {
|
|
@@ -112192,7 +112724,7 @@ var init_mock_adapter = __esm({
|
|
|
112192
112724
|
}
|
|
112193
112725
|
/** Create from a JSON file of recorded responses. */
|
|
112194
112726
|
static fromFile(filePath) {
|
|
112195
|
-
const data = JSON.parse(
|
|
112727
|
+
const data = JSON.parse(readFileSync13(filePath, "utf-8"));
|
|
112196
112728
|
return new _MockLlmAdapter2(data);
|
|
112197
112729
|
}
|
|
112198
112730
|
};
|
|
@@ -112224,11 +112756,11 @@ var init_mock_adapter = __esm({
|
|
|
112224
112756
|
/** Save recordings to a JSON file. */
|
|
112225
112757
|
save(filePath) {
|
|
112226
112758
|
const responses = this.recordings.map((r) => r.response);
|
|
112227
|
-
|
|
112759
|
+
writeFileSync6(filePath, JSON.stringify(responses, null, 2), "utf-8");
|
|
112228
112760
|
}
|
|
112229
112761
|
/** Load responses from a JSON file (returns the responses array for MockLlmAdapter). */
|
|
112230
112762
|
static load(filePath) {
|
|
112231
|
-
return JSON.parse(
|
|
112763
|
+
return JSON.parse(readFileSync13(filePath, "utf-8"));
|
|
112232
112764
|
}
|
|
112233
112765
|
/** Get just the response objects for replaying. */
|
|
112234
112766
|
getResponses() {
|
|
@@ -112390,8 +112922,8 @@ var init_assertions = __esm({
|
|
|
112390
112922
|
});
|
|
112391
112923
|
|
|
112392
112924
|
// ../agent/src/testing/runner.ts
|
|
112393
|
-
import { readFileSync as
|
|
112394
|
-
import { join as
|
|
112925
|
+
import { readFileSync as readFileSync14, mkdirSync as mkdirSync5, writeFileSync as writeFileSync7, rmSync, existsSync as existsSync9 } from "node:fs";
|
|
112926
|
+
import { join as join14 } from "node:path";
|
|
112395
112927
|
import { tmpdir as tmpdir3 } from "node:os";
|
|
112396
112928
|
import { randomUUID as randomUUID27 } from "node:crypto";
|
|
112397
112929
|
function parseYaml(content) {
|
|
@@ -112493,7 +113025,7 @@ var init_runner = __esm({
|
|
|
112493
113025
|
AgentTestRunner = class {
|
|
112494
113026
|
/** Load test suite from a YAML or JSON file. */
|
|
112495
113027
|
static loadSuite(filePath) {
|
|
112496
|
-
const content =
|
|
113028
|
+
const content = readFileSync14(filePath, "utf-8");
|
|
112497
113029
|
const parsed = parseYaml(content);
|
|
112498
113030
|
return {
|
|
112499
113031
|
name: parsed.name ?? "Unnamed Suite",
|
|
@@ -112516,18 +113048,18 @@ var init_runner = __esm({
|
|
|
112516
113048
|
async runTest(testCase) {
|
|
112517
113049
|
const startTime4 = Date.now();
|
|
112518
113050
|
try {
|
|
112519
|
-
const tempDir =
|
|
112520
|
-
|
|
113051
|
+
const tempDir = join14(tmpdir3(), `nestor-test-${randomUUID27()}`);
|
|
113052
|
+
mkdirSync5(tempDir, { recursive: true });
|
|
112521
113053
|
if (testCase.files) {
|
|
112522
113054
|
for (const [path30, content] of Object.entries(testCase.files)) {
|
|
112523
|
-
const fullPath =
|
|
112524
|
-
|
|
112525
|
-
|
|
113055
|
+
const fullPath = join14(tempDir, path30);
|
|
113056
|
+
mkdirSync5(join14(fullPath, ".."), { recursive: true });
|
|
113057
|
+
writeFileSync7(fullPath, content, "utf-8");
|
|
112526
113058
|
}
|
|
112527
113059
|
}
|
|
112528
113060
|
let responses;
|
|
112529
|
-
if (testCase.recordings &&
|
|
112530
|
-
responses = JSON.parse(
|
|
113061
|
+
if (testCase.recordings && existsSync9(testCase.recordings)) {
|
|
113062
|
+
responses = JSON.parse(readFileSync14(testCase.recordings, "utf-8"));
|
|
112531
113063
|
} else {
|
|
112532
113064
|
responses = [{
|
|
112533
113065
|
content: "Test completed successfully.",
|
|
@@ -115301,11 +115833,11 @@ var init_safety = __esm({
|
|
|
115301
115833
|
|
|
115302
115834
|
// ../agent/src/mission/tool-factory.ts
|
|
115303
115835
|
import { randomUUID as randomUUID33 } from "node:crypto";
|
|
115304
|
-
import { writeFileSync as
|
|
115836
|
+
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync6, existsSync as existsSync11 } from "node:fs";
|
|
115305
115837
|
import { homedir as homedir4 } from "node:os";
|
|
115306
|
-
import { join as
|
|
115838
|
+
import { join as join17 } from "node:path";
|
|
115307
115839
|
function getDefaultToolsDir() {
|
|
115308
|
-
return
|
|
115840
|
+
return join17(homedir4(), ".nestor", "tools");
|
|
115309
115841
|
}
|
|
115310
115842
|
function createDefaultToolFactory(adapter, toolsDir) {
|
|
115311
115843
|
return new ToolFactory(adapter, toolsDir ?? getDefaultToolsDir());
|
|
@@ -115318,7 +115850,7 @@ var init_tool_factory = __esm({
|
|
|
115318
115850
|
constructor(adapter, toolsDir) {
|
|
115319
115851
|
this.adapter = adapter;
|
|
115320
115852
|
this.toolsDir = toolsDir;
|
|
115321
|
-
if (!
|
|
115853
|
+
if (!existsSync11(toolsDir)) mkdirSync6(toolsDir, { recursive: true });
|
|
115322
115854
|
}
|
|
115323
115855
|
/**
|
|
115324
115856
|
* Generate a new tool from a natural language description.
|
|
@@ -115495,13 +116027,13 @@ Fix the tool code so it passes its test. Respond ONLY with valid JSON:
|
|
|
115495
116027
|
* Save tool to disk: source, compiled JS, test, and manifest.
|
|
115496
116028
|
*/
|
|
115497
116029
|
saveTool(tool) {
|
|
115498
|
-
const toolDir =
|
|
115499
|
-
if (!
|
|
115500
|
-
|
|
115501
|
-
|
|
115502
|
-
|
|
115503
|
-
|
|
115504
|
-
|
|
116030
|
+
const toolDir = join17(this.toolsDir, tool.name);
|
|
116031
|
+
if (!existsSync11(toolDir)) mkdirSync6(toolDir, { recursive: true });
|
|
116032
|
+
writeFileSync8(join17(toolDir, "tool.ts"), tool.code);
|
|
116033
|
+
writeFileSync8(join17(toolDir, "tool.js"), tool.compiledCode);
|
|
116034
|
+
writeFileSync8(join17(toolDir, "test.js"), tool.testCode);
|
|
116035
|
+
writeFileSync8(
|
|
116036
|
+
join17(toolDir, "manifest.json"),
|
|
115505
116037
|
JSON.stringify(
|
|
115506
116038
|
{
|
|
115507
116039
|
id: tool.id,
|
|
@@ -116076,13 +116608,172 @@ Analyze and return the JSON structure described in the system prompt.`;
|
|
|
116076
116608
|
}
|
|
116077
116609
|
});
|
|
116078
116610
|
|
|
116611
|
+
// ../agent/src/mission/capability-research.ts
|
|
116612
|
+
var capability_research_exports = {};
|
|
116613
|
+
__export(capability_research_exports, {
|
|
116614
|
+
CapabilityResearchEngine: () => CapabilityResearchEngine
|
|
116615
|
+
});
|
|
116616
|
+
var CapabilityResearchEngine;
|
|
116617
|
+
var init_capability_research = __esm({
|
|
116618
|
+
"../agent/src/mission/capability-research.ts"() {
|
|
116619
|
+
"use strict";
|
|
116620
|
+
CapabilityResearchEngine = class {
|
|
116621
|
+
constructor(adapter, orchestratorStore) {
|
|
116622
|
+
this.adapter = adapter;
|
|
116623
|
+
this.orchestratorStore = orchestratorStore;
|
|
116624
|
+
}
|
|
116625
|
+
cache = /* @__PURE__ */ new Map();
|
|
116626
|
+
/**
|
|
116627
|
+
* Research capabilities for a mission type.
|
|
116628
|
+
* Returns cached results if still valid, otherwise does fresh research.
|
|
116629
|
+
*/
|
|
116630
|
+
async research(type, objective) {
|
|
116631
|
+
const cached = this.cache.get(type);
|
|
116632
|
+
if (cached && Date.now() - cached.timestamp < cached.ttlMs) {
|
|
116633
|
+
return cached;
|
|
116634
|
+
}
|
|
116635
|
+
if (this.orchestratorStore) {
|
|
116636
|
+
const orch = this.orchestratorStore.get(type);
|
|
116637
|
+
if (orch.toolRecommendations.length > 0 && orch.missionCount > 3) {
|
|
116638
|
+
const fromOrch = {
|
|
116639
|
+
domain: type,
|
|
116640
|
+
recommendedTools: orch.toolRecommendations.map((t) => ({
|
|
116641
|
+
name: t,
|
|
116642
|
+
description: "",
|
|
116643
|
+
source: "builtin",
|
|
116644
|
+
priority: "recommended"
|
|
116645
|
+
})),
|
|
116646
|
+
methodologies: [],
|
|
116647
|
+
pitfalls: orch.knowledgeBase.failedPatterns.map(
|
|
116648
|
+
(p8) => `Previously failed pattern: ${p8.subObjectiveNames.join(" \u2192 ")} (used ${p8.usageCount} time${p8.usageCount > 1 ? "s" : ""}, score: ${p8.score.toFixed(2)})`
|
|
116649
|
+
),
|
|
116650
|
+
resources: [],
|
|
116651
|
+
timestamp: Date.now(),
|
|
116652
|
+
ttlMs: 7 * 24 * 60 * 60 * 1e3
|
|
116653
|
+
};
|
|
116654
|
+
this.cache.set(type, fromOrch);
|
|
116655
|
+
return fromOrch;
|
|
116656
|
+
}
|
|
116657
|
+
}
|
|
116658
|
+
const result = await this.doResearch(type, objective);
|
|
116659
|
+
this.cache.set(type, result);
|
|
116660
|
+
return result;
|
|
116661
|
+
}
|
|
116662
|
+
async doResearch(type, objective) {
|
|
116663
|
+
const domainHints = this.getDomainHints(type);
|
|
116664
|
+
const prompt = `You are a capability researcher for an AI agent platform.
|
|
116665
|
+
Given a mission type and objective, recommend the best tools, methodologies, and resources.
|
|
116666
|
+
|
|
116667
|
+
Mission type: ${type}
|
|
116668
|
+
Objective: ${objective}
|
|
116669
|
+
|
|
116670
|
+
Based on your knowledge of ${type} best practices, respond with JSON:
|
|
116671
|
+
{
|
|
116672
|
+
"recommendedTools": [
|
|
116673
|
+
{ "name": "tool_name", "description": "what it does", "source": "builtin|npm|github|api", "url": "optional", "priority": "essential|recommended|optional" }
|
|
116674
|
+
],
|
|
116675
|
+
"methodologies": [
|
|
116676
|
+
{ "name": "method name", "description": "brief description", "steps": ["step1", "step2"] }
|
|
116677
|
+
],
|
|
116678
|
+
"pitfalls": ["common mistake 1", "common mistake 2"],
|
|
116679
|
+
"resources": [
|
|
116680
|
+
{ "title": "resource title", "url": "https://...", "type": "article|repo|docs|tutorial" }
|
|
116681
|
+
]
|
|
116682
|
+
}
|
|
116683
|
+
|
|
116684
|
+
${domainHints}
|
|
116685
|
+
|
|
116686
|
+
Focus on tools that work locally (no cloud-only services) and can be used by an AI agent.
|
|
116687
|
+
Respond ONLY with JSON.`;
|
|
116688
|
+
try {
|
|
116689
|
+
const response = await this.adapter.chat([
|
|
116690
|
+
{
|
|
116691
|
+
role: "system",
|
|
116692
|
+
content: "You are a capability researcher. Respond only with JSON."
|
|
116693
|
+
},
|
|
116694
|
+
{ role: "user", content: prompt }
|
|
116695
|
+
]);
|
|
116696
|
+
let jsonStr = response.content;
|
|
116697
|
+
const codeBlockMatch = jsonStr.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
116698
|
+
if (codeBlockMatch) jsonStr = codeBlockMatch[1].trim();
|
|
116699
|
+
const match = jsonStr.match(/\{[\s\S]*\}/);
|
|
116700
|
+
if (match) jsonStr = match[0];
|
|
116701
|
+
const parsed = JSON.parse(jsonStr);
|
|
116702
|
+
return {
|
|
116703
|
+
domain: type,
|
|
116704
|
+
recommendedTools: Array.isArray(parsed.recommendedTools) ? parsed.recommendedTools : [],
|
|
116705
|
+
methodologies: Array.isArray(parsed.methodologies) ? parsed.methodologies : [],
|
|
116706
|
+
pitfalls: Array.isArray(parsed.pitfalls) ? parsed.pitfalls : [],
|
|
116707
|
+
resources: Array.isArray(parsed.resources) ? parsed.resources : [],
|
|
116708
|
+
timestamp: Date.now(),
|
|
116709
|
+
ttlMs: 7 * 24 * 60 * 60 * 1e3
|
|
116710
|
+
// 7 days
|
|
116711
|
+
};
|
|
116712
|
+
} catch {
|
|
116713
|
+
return {
|
|
116714
|
+
domain: type,
|
|
116715
|
+
recommendedTools: [],
|
|
116716
|
+
methodologies: [],
|
|
116717
|
+
pitfalls: [],
|
|
116718
|
+
resources: [],
|
|
116719
|
+
timestamp: Date.now(),
|
|
116720
|
+
ttlMs: 24 * 60 * 60 * 1e3
|
|
116721
|
+
// retry after 1 day on failure
|
|
116722
|
+
};
|
|
116723
|
+
}
|
|
116724
|
+
}
|
|
116725
|
+
/**
|
|
116726
|
+
* Inject research results into the mission planning context.
|
|
116727
|
+
* Returns a context block to prepend to the decomposition prompt.
|
|
116728
|
+
*/
|
|
116729
|
+
toContextBlock(result) {
|
|
116730
|
+
if (result.recommendedTools.length === 0 && result.methodologies.length === 0) {
|
|
116731
|
+
return "";
|
|
116732
|
+
}
|
|
116733
|
+
const sections = ["CAPABILITY RESEARCH (pre-mission analysis):"];
|
|
116734
|
+
if (result.recommendedTools.length > 0) {
|
|
116735
|
+
sections.push("Recommended tools:");
|
|
116736
|
+
for (const t of result.recommendedTools.slice(0, 8)) {
|
|
116737
|
+
sections.push(` - ${t.name} (${t.priority}): ${t.description}`);
|
|
116738
|
+
}
|
|
116739
|
+
}
|
|
116740
|
+
if (result.methodologies.length > 0) {
|
|
116741
|
+
sections.push("Recommended methodology:");
|
|
116742
|
+
const best = result.methodologies[0];
|
|
116743
|
+
sections.push(` ${best.name}: ${best.steps.join(" \u2192 ")}`);
|
|
116744
|
+
}
|
|
116745
|
+
if (result.pitfalls.length > 0) {
|
|
116746
|
+
sections.push("Known pitfalls to avoid:");
|
|
116747
|
+
for (const p8 of result.pitfalls.slice(0, 5)) {
|
|
116748
|
+
sections.push(` - ${p8}`);
|
|
116749
|
+
}
|
|
116750
|
+
}
|
|
116751
|
+
return sections.join("\n");
|
|
116752
|
+
}
|
|
116753
|
+
// ─── Private Helpers ────────────────────────────────────────────────
|
|
116754
|
+
getDomainHints(type) {
|
|
116755
|
+
const hints = {
|
|
116756
|
+
osint: "For osint missions, consider: OSINT tools like Maltego alternatives, Wayback Machine, WHOIS, social media scrapers, SIRENE, public records databases",
|
|
116757
|
+
research: "For research missions, consider: Google Scholar, arxiv, Semantic Scholar, news aggregators, RSS feeds, citation graphs",
|
|
116758
|
+
code: "For code missions, consider: linters, formatters, test frameworks, build tools, CI/CD, static analysis",
|
|
116759
|
+
audit: "For audit missions, consider: static analyzers, dependency checkers, fuzzing tools, CVE databases, SAST/DAST",
|
|
116760
|
+
creation: "For creation missions, consider: writing assistants, image generators, template engines, CMS tools, Markdown processors",
|
|
116761
|
+
analysis: "For analysis missions, consider: data processing libraries, visualization tools, statistical frameworks, ML frameworks",
|
|
116762
|
+
custom: "Consider what specialized tools and methods would best serve this specific objective."
|
|
116763
|
+
};
|
|
116764
|
+
return hints[type] || hints.custom;
|
|
116765
|
+
}
|
|
116766
|
+
};
|
|
116767
|
+
}
|
|
116768
|
+
});
|
|
116769
|
+
|
|
116079
116770
|
// ../agent/src/mission/orchestrator-store.ts
|
|
116080
116771
|
var orchestrator_store_exports = {};
|
|
116081
116772
|
__export(orchestrator_store_exports, {
|
|
116082
116773
|
OrchestratorStore: () => OrchestratorStore
|
|
116083
116774
|
});
|
|
116084
|
-
import { existsSync as
|
|
116085
|
-
import { join as
|
|
116775
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync7, readFileSync as readFileSync16, writeFileSync as writeFileSync9 } from "node:fs";
|
|
116776
|
+
import { join as join18 } from "node:path";
|
|
116086
116777
|
import { homedir as homedir5 } from "node:os";
|
|
116087
116778
|
function arraysEqual(a, b) {
|
|
116088
116779
|
if (a.length !== b.length) return false;
|
|
@@ -116092,11 +116783,11 @@ var ORCHESTRATORS_DIR, OrchestratorStore;
|
|
|
116092
116783
|
var init_orchestrator_store = __esm({
|
|
116093
116784
|
"../agent/src/mission/orchestrator-store.ts"() {
|
|
116094
116785
|
"use strict";
|
|
116095
|
-
ORCHESTRATORS_DIR =
|
|
116786
|
+
ORCHESTRATORS_DIR = join18(homedir5(), ".nestor", "orchestrators");
|
|
116096
116787
|
OrchestratorStore = class {
|
|
116097
116788
|
constructor(baseDir = ORCHESTRATORS_DIR) {
|
|
116098
116789
|
this.baseDir = baseDir;
|
|
116099
|
-
if (!
|
|
116790
|
+
if (!existsSync12(baseDir)) mkdirSync7(baseDir, { recursive: true });
|
|
116100
116791
|
}
|
|
116101
116792
|
cache = /* @__PURE__ */ new Map();
|
|
116102
116793
|
/**
|
|
@@ -116106,9 +116797,9 @@ var init_orchestrator_store = __esm({
|
|
|
116106
116797
|
get(type) {
|
|
116107
116798
|
if (this.cache.has(type)) return this.cache.get(type);
|
|
116108
116799
|
const filePath = this.filePath(type);
|
|
116109
|
-
if (
|
|
116800
|
+
if (existsSync12(filePath)) {
|
|
116110
116801
|
try {
|
|
116111
|
-
const data = JSON.parse(
|
|
116802
|
+
const data = JSON.parse(readFileSync16(filePath, "utf-8"));
|
|
116112
116803
|
this.cache.set(type, data);
|
|
116113
116804
|
return data;
|
|
116114
116805
|
} catch {
|
|
@@ -116206,7 +116897,7 @@ var init_orchestrator_store = __esm({
|
|
|
116206
116897
|
];
|
|
116207
116898
|
return types.map((type) => {
|
|
116208
116899
|
const filePath = this.filePath(type);
|
|
116209
|
-
if (!
|
|
116900
|
+
if (!existsSync12(filePath)) return null;
|
|
116210
116901
|
const orch = this.get(type);
|
|
116211
116902
|
return {
|
|
116212
116903
|
type: orch.type,
|
|
@@ -116243,12 +116934,12 @@ var init_orchestrator_store = __esm({
|
|
|
116243
116934
|
}
|
|
116244
116935
|
// ─── Private ──────────────────────────────────────────────────────────
|
|
116245
116936
|
filePath(type) {
|
|
116246
|
-
return
|
|
116937
|
+
return join18(this.baseDir, type, "orchestrator.json");
|
|
116247
116938
|
}
|
|
116248
116939
|
save(orch) {
|
|
116249
|
-
const dir =
|
|
116250
|
-
if (!
|
|
116251
|
-
|
|
116940
|
+
const dir = join18(this.baseDir, orch.type);
|
|
116941
|
+
if (!existsSync12(dir)) mkdirSync7(dir, { recursive: true });
|
|
116942
|
+
writeFileSync9(this.filePath(orch.type), JSON.stringify(orch, null, 2));
|
|
116252
116943
|
this.cache.set(orch.type, orch);
|
|
116253
116944
|
}
|
|
116254
116945
|
createDefault(type) {
|
|
@@ -116463,8 +117154,19 @@ var init_controller = __esm({
|
|
|
116463
117154
|
async plan(input, options) {
|
|
116464
117155
|
const tenantId = options?.tenantId ?? "default";
|
|
116465
117156
|
const type = this.detectMissionType(input);
|
|
117157
|
+
let capabilityContext = "";
|
|
117158
|
+
try {
|
|
117159
|
+
const { CapabilityResearchEngine: CapabilityResearchEngine2 } = await Promise.resolve().then(() => (init_capability_research(), capability_research_exports));
|
|
117160
|
+
const researcher = new CapabilityResearchEngine2(
|
|
117161
|
+
this.agentFactory.getDefaultAdapter()
|
|
117162
|
+
// orchestratorStore could be wired here if available on the controller
|
|
117163
|
+
);
|
|
117164
|
+
const research = await researcher.research(type, input);
|
|
117165
|
+
capabilityContext = researcher.toContextBlock(research);
|
|
117166
|
+
} catch {
|
|
117167
|
+
}
|
|
116466
117168
|
const similar = await this.inventory.findSimilarMissions(input);
|
|
116467
|
-
const decomposition = await this.decompose(input, type, similar);
|
|
117169
|
+
const decomposition = await this.decompose(input, type, similar, capabilityContext);
|
|
116468
117170
|
const defaultMaxIterations = (() => {
|
|
116469
117171
|
switch (type) {
|
|
116470
117172
|
case "osint":
|
|
@@ -116832,7 +117534,7 @@ Report generation failed. Mission completed with ${mission.findings.length} find
|
|
|
116832
117534
|
return "custom";
|
|
116833
117535
|
}
|
|
116834
117536
|
// ─── Decompose ─────────────────────────────────────────────────────
|
|
116835
|
-
async decompose(input, type, similar) {
|
|
117537
|
+
async decompose(input, type, similar, capabilityContext) {
|
|
116836
117538
|
const methodGuide = {
|
|
116837
117539
|
osint: `For OSINT missions, structure sub-objectives by METHOD, not by category:
|
|
116838
117540
|
1. Entity disambiguation \u2014 multi-engine search to find the correct subject among homonyms
|
|
@@ -116895,7 +117597,8 @@ ${methodGuide[type] || methodGuide.custom}
|
|
|
116895
117597
|
${similar.length > 0 ? `Similar past missions found (learn from their structure):
|
|
116896
117598
|
${similar.map((m) => `- ${m.title} (${m.subObjectives.length} sub-objectives, score: ${m.evaluation?.overall ?? "N/A"})`).join("\n")}` : "No similar past missions found."}
|
|
116897
117599
|
|
|
116898
|
-
|
|
117600
|
+
${capabilityContext ? `${capabilityContext}
|
|
117601
|
+
` : ""}The "type" field of each sub-objective should be one of:
|
|
116899
117602
|
search \u2014 broad web search with multiple engines
|
|
116900
117603
|
scrape \u2014 detailed scrape of specific page(s)
|
|
116901
117604
|
analyze \u2014 analysis of data already collected (no external fetch)
|
|
@@ -117710,8 +118413,8 @@ var init_inventory = __esm({
|
|
|
117710
118413
|
});
|
|
117711
118414
|
|
|
117712
118415
|
// ../agent/src/mission/mcp-factory.ts
|
|
117713
|
-
import { writeFileSync as
|
|
117714
|
-
import { join as
|
|
118416
|
+
import { writeFileSync as writeFileSync10, mkdirSync as mkdirSync8, existsSync as existsSync13 } from "node:fs";
|
|
118417
|
+
import { join as join19 } from "node:path";
|
|
117715
118418
|
var McpFactory;
|
|
117716
118419
|
var init_mcp_factory = __esm({
|
|
117717
118420
|
"../agent/src/mission/mcp-factory.ts"() {
|
|
@@ -117719,7 +118422,7 @@ var init_mcp_factory = __esm({
|
|
|
117719
118422
|
McpFactory = class {
|
|
117720
118423
|
constructor(mcpDir) {
|
|
117721
118424
|
this.mcpDir = mcpDir;
|
|
117722
|
-
if (!
|
|
118425
|
+
if (!existsSync13(mcpDir)) mkdirSync8(mcpDir, { recursive: true });
|
|
117723
118426
|
}
|
|
117724
118427
|
/**
|
|
117725
118428
|
* Generate an MCP server that exposes one or more custom tools.
|
|
@@ -117727,13 +118430,13 @@ var init_mcp_factory = __esm({
|
|
|
117727
118430
|
*/
|
|
117728
118431
|
generate(tools, serverName) {
|
|
117729
118432
|
const safeName = this.sanitizeName(serverName);
|
|
117730
|
-
const serverDir =
|
|
117731
|
-
if (!
|
|
118433
|
+
const serverDir = join19(this.mcpDir, safeName);
|
|
118434
|
+
if (!existsSync13(serverDir)) mkdirSync8(serverDir, { recursive: true });
|
|
117732
118435
|
const serverCode = this.generateServerCode(tools, safeName);
|
|
117733
|
-
const entrypoint =
|
|
117734
|
-
|
|
117735
|
-
|
|
117736
|
-
|
|
118436
|
+
const entrypoint = join19(serverDir, "server.mjs");
|
|
118437
|
+
writeFileSync10(entrypoint, serverCode);
|
|
118438
|
+
writeFileSync10(
|
|
118439
|
+
join19(serverDir, "package.json"),
|
|
117737
118440
|
JSON.stringify(
|
|
117738
118441
|
{
|
|
117739
118442
|
name: `@nestor/mcp-${safeName}`,
|
|
@@ -117747,11 +118450,11 @@ var init_mcp_factory = __esm({
|
|
|
117747
118450
|
2
|
|
117748
118451
|
)
|
|
117749
118452
|
);
|
|
117750
|
-
|
|
117751
|
-
|
|
118453
|
+
writeFileSync10(join19(serverDir, "Dockerfile"), this.generateDockerfile(safeName));
|
|
118454
|
+
writeFileSync10(join19(serverDir, "README.md"), this.generateReadme(tools, safeName));
|
|
117752
118455
|
for (const tool of tools) {
|
|
117753
118456
|
const toolModuleCode = this.wrapToolAsModule(tool);
|
|
117754
|
-
|
|
118457
|
+
writeFileSync10(join19(serverDir, `${tool.name}.js`), toolModuleCode);
|
|
117755
118458
|
}
|
|
117756
118459
|
return {
|
|
117757
118460
|
id: safeName,
|
|
@@ -117985,8 +118688,8 @@ npx nestor-sh mcp add ${serverName} --command "node ${serverName}/server.mjs"
|
|
|
117985
118688
|
// ../agent/src/mission/docker-deployer.ts
|
|
117986
118689
|
import { execFile as execFile7 } from "node:child_process";
|
|
117987
118690
|
import { promisify as promisify5 } from "node:util";
|
|
117988
|
-
import { existsSync as
|
|
117989
|
-
import { join as
|
|
118691
|
+
import { existsSync as existsSync14 } from "node:fs";
|
|
118692
|
+
import { join as join20 } from "node:path";
|
|
117990
118693
|
var execFileAsync4, DockerDeployer;
|
|
117991
118694
|
var init_docker_deployer = __esm({
|
|
117992
118695
|
"../agent/src/mission/docker-deployer.ts"() {
|
|
@@ -118023,9 +118726,9 @@ var init_docker_deployer = __esm({
|
|
|
118023
118726
|
* Returns the image name (tag).
|
|
118024
118727
|
*/
|
|
118025
118728
|
async build(server) {
|
|
118026
|
-
const serverDir =
|
|
118729
|
+
const serverDir = join20(server.entrypoint, "..");
|
|
118027
118730
|
const imageName = `nestor-mcp-${server.name}:latest`;
|
|
118028
|
-
if (!
|
|
118731
|
+
if (!existsSync14(join20(serverDir, "Dockerfile"))) {
|
|
118029
118732
|
throw new Error(`No Dockerfile found in ${serverDir}`);
|
|
118030
118733
|
}
|
|
118031
118734
|
const container = {
|
|
@@ -118248,6 +118951,7 @@ var init_mission = __esm({
|
|
|
118248
118951
|
init_mcp_factory();
|
|
118249
118952
|
init_docker_deployer();
|
|
118250
118953
|
init_orchestrator_store();
|
|
118954
|
+
init_capability_research();
|
|
118251
118955
|
}
|
|
118252
118956
|
});
|
|
118253
118957
|
|
|
@@ -118498,6 +119202,15 @@ var init_intent = __esm({
|
|
|
118498
119202
|
}
|
|
118499
119203
|
});
|
|
118500
119204
|
|
|
119205
|
+
// ../agent/src/integrations/index.ts
|
|
119206
|
+
var init_integrations = __esm({
|
|
119207
|
+
"../agent/src/integrations/index.ts"() {
|
|
119208
|
+
"use strict";
|
|
119209
|
+
init_obsidian();
|
|
119210
|
+
init_n8n();
|
|
119211
|
+
}
|
|
119212
|
+
});
|
|
119213
|
+
|
|
118501
119214
|
// ../agent/src/index.ts
|
|
118502
119215
|
var src_exports3 = {};
|
|
118503
119216
|
__export(src_exports3, {
|
|
@@ -118512,6 +119225,7 @@ __export(src_exports3, {
|
|
|
118512
119225
|
AutoDowngradeAdapter: () => AutoDowngradeAdapter,
|
|
118513
119226
|
AutoDowngradeMonitor: () => AutoDowngradeMonitor,
|
|
118514
119227
|
BrowserManager: () => BrowserManager,
|
|
119228
|
+
CapabilityResearchEngine: () => CapabilityResearchEngine,
|
|
118515
119229
|
CircuitBreaker: () => CircuitBreaker,
|
|
118516
119230
|
ClaudeAdapter: () => ClaudeAdapter,
|
|
118517
119231
|
CodeChunker: () => CodeChunker,
|
|
@@ -118547,6 +119261,8 @@ __export(src_exports3, {
|
|
|
118547
119261
|
MistralAdapter: () => MistralAdapter,
|
|
118548
119262
|
MockLlmAdapter: () => MockLlmAdapter,
|
|
118549
119263
|
ModelRouter: () => ModelRouter,
|
|
119264
|
+
N8nIntegration: () => N8nIntegration,
|
|
119265
|
+
ObsidianIntegration: () => ObsidianIntegration,
|
|
118550
119266
|
OllamaAdapter: () => OllamaAdapter,
|
|
118551
119267
|
OllamaEmbeddingProvider: () => OllamaEmbeddingProvider,
|
|
118552
119268
|
OllamaEmbeddings: () => OllamaEmbeddings,
|
|
@@ -118702,6 +119418,7 @@ var init_src5 = __esm({
|
|
|
118702
119418
|
init_mission();
|
|
118703
119419
|
init_meta_tool_factory();
|
|
118704
119420
|
init_intent();
|
|
119421
|
+
init_integrations();
|
|
118705
119422
|
}
|
|
118706
119423
|
});
|
|
118707
119424
|
|
|
@@ -119971,8 +120688,8 @@ var init_experiments = __esm({
|
|
|
119971
120688
|
|
|
119972
120689
|
// ../server/src/services/telemetry-anon.ts
|
|
119973
120690
|
import { randomUUID as randomUUID38 } from "node:crypto";
|
|
119974
|
-
import { existsSync as
|
|
119975
|
-
import { join as
|
|
120691
|
+
import { existsSync as existsSync15, readFileSync as readFileSync17, writeFileSync as writeFileSync11, mkdirSync as mkdirSync9 } from "node:fs";
|
|
120692
|
+
import { join as join21 } from "node:path";
|
|
119976
120693
|
import { homedir as homedir6 } from "node:os";
|
|
119977
120694
|
function getAnonTelemetry(config2) {
|
|
119978
120695
|
if (!_anonInstance) {
|
|
@@ -119988,8 +120705,8 @@ var init_telemetry_anon = __esm({
|
|
|
119988
120705
|
"../server/src/services/telemetry-anon.ts"() {
|
|
119989
120706
|
"use strict";
|
|
119990
120707
|
NESTOR_VERSION = "0.4.1";
|
|
119991
|
-
DATA_DIR2 =
|
|
119992
|
-
ANON_ID_FILE =
|
|
120708
|
+
DATA_DIR2 = join21(homedir6(), ".nestor");
|
|
120709
|
+
ANON_ID_FILE = join21(DATA_DIR2, "anon-telemetry-id");
|
|
119993
120710
|
DEFAULT_ENDPOINT = "https://telemetry.nestor.sh/v1/events";
|
|
119994
120711
|
FLUSH_BATCH_SIZE = 25;
|
|
119995
120712
|
AnonTelemetryService = class {
|
|
@@ -120093,18 +120810,18 @@ var init_telemetry_anon = __esm({
|
|
|
120093
120810
|
// ─── Private ──────────────────────────────────────────────────────────
|
|
120094
120811
|
getOrCreateInstallId() {
|
|
120095
120812
|
try {
|
|
120096
|
-
if (
|
|
120097
|
-
const id =
|
|
120813
|
+
if (existsSync15(ANON_ID_FILE)) {
|
|
120814
|
+
const id = readFileSync17(ANON_ID_FILE, "utf-8").trim();
|
|
120098
120815
|
if (id.length > 0) return id;
|
|
120099
120816
|
}
|
|
120100
120817
|
} catch {
|
|
120101
120818
|
}
|
|
120102
120819
|
const newId = randomUUID38();
|
|
120103
120820
|
try {
|
|
120104
|
-
if (!
|
|
120105
|
-
|
|
120821
|
+
if (!existsSync15(DATA_DIR2)) {
|
|
120822
|
+
mkdirSync9(DATA_DIR2, { recursive: true });
|
|
120106
120823
|
}
|
|
120107
|
-
|
|
120824
|
+
writeFileSync11(ANON_ID_FILE, newId + "\n", "utf-8");
|
|
120108
120825
|
} catch {
|
|
120109
120826
|
}
|
|
120110
120827
|
return newId;
|
|
@@ -150434,7 +151151,7 @@ var init_admin2 = __esm({
|
|
|
150434
151151
|
"../server/src/routes/admin.ts"() {
|
|
150435
151152
|
"use strict";
|
|
150436
151153
|
init_rate_limit();
|
|
150437
|
-
SERVER_VERSION3 = "
|
|
151154
|
+
SERVER_VERSION3 = "3.0.0";
|
|
150438
151155
|
startTime3 = Date.now();
|
|
150439
151156
|
}
|
|
150440
151157
|
});
|
|
@@ -152122,19 +152839,19 @@ var init_providers = __esm({
|
|
|
152122
152839
|
|
|
152123
152840
|
// ../server/src/services/key-vault.ts
|
|
152124
152841
|
import { createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, randomBytes as randomBytes7, scryptSync as scryptSync2 } from "node:crypto";
|
|
152125
|
-
import { readFileSync as
|
|
152126
|
-
import { join as
|
|
152842
|
+
import { readFileSync as readFileSync18, writeFileSync as writeFileSync12, existsSync as existsSync16, mkdirSync as mkdirSync10 } from "node:fs";
|
|
152843
|
+
import { join as join22, dirname as dirname8 } from "node:path";
|
|
152127
152844
|
import { homedir as homedir7 } from "node:os";
|
|
152128
152845
|
function getVaultKey() {
|
|
152129
|
-
if (!
|
|
152846
|
+
if (!existsSync16(KEY_FILE)) {
|
|
152130
152847
|
const dir = dirname8(KEY_FILE);
|
|
152131
|
-
if (!
|
|
152132
|
-
|
|
152848
|
+
if (!existsSync16(dir)) {
|
|
152849
|
+
mkdirSync10(dir, { recursive: true });
|
|
152133
152850
|
}
|
|
152134
152851
|
const masterSecret = randomBytes7(32).toString("hex");
|
|
152135
|
-
|
|
152852
|
+
writeFileSync12(KEY_FILE, masterSecret, { mode: 384 });
|
|
152136
152853
|
}
|
|
152137
|
-
const secret =
|
|
152854
|
+
const secret = readFileSync18(KEY_FILE, "utf-8").trim();
|
|
152138
152855
|
return scryptSync2(secret, "nestor-vault-salt", 32);
|
|
152139
152856
|
}
|
|
152140
152857
|
function encryptApiKey(plainKey) {
|
|
@@ -152186,7 +152903,7 @@ var init_key_vault = __esm({
|
|
|
152186
152903
|
"../server/src/services/key-vault.ts"() {
|
|
152187
152904
|
"use strict";
|
|
152188
152905
|
ALGORITHM2 = "aes-256-gcm";
|
|
152189
|
-
KEY_FILE =
|
|
152906
|
+
KEY_FILE = join22(homedir7(), ".nestor", ".vault-key");
|
|
152190
152907
|
PROVIDER_ENV_MAP = {
|
|
152191
152908
|
claude: "ANTHROPIC_API_KEY",
|
|
152192
152909
|
openai: "OPENAI_API_KEY",
|
|
@@ -153171,8 +153888,8 @@ var init_seed_defaults = __esm({
|
|
|
153171
153888
|
|
|
153172
153889
|
// ../server/src/app.ts
|
|
153173
153890
|
import express from "express";
|
|
153174
|
-
import { resolve as resolve13, join as
|
|
153175
|
-
import { existsSync as
|
|
153891
|
+
import { resolve as resolve13, join as join23 } from "node:path";
|
|
153892
|
+
import { existsSync as existsSync17 } from "node:fs";
|
|
153176
153893
|
import compression from "compression";
|
|
153177
153894
|
import cors from "cors";
|
|
153178
153895
|
function getStudioState() {
|
|
@@ -153502,7 +154219,7 @@ function createApp(config2) {
|
|
|
153502
154219
|
}
|
|
153503
154220
|
for (const dir of candidateDirs) {
|
|
153504
154221
|
try {
|
|
153505
|
-
if (
|
|
154222
|
+
if (existsSync17(join23(dir, "index.html"))) {
|
|
153506
154223
|
studioDistDir = dir;
|
|
153507
154224
|
break;
|
|
153508
154225
|
}
|
|
@@ -153526,7 +154243,7 @@ function createApp(config2) {
|
|
|
153526
154243
|
if (!studioState.enabled) {
|
|
153527
154244
|
return res.status(403).json({ error: { code: "STUDIO_DISABLED", message: "Studio is disabled." } });
|
|
153528
154245
|
}
|
|
153529
|
-
res.sendFile(
|
|
154246
|
+
res.sendFile(join23(studioDistDir, "index.html"));
|
|
153530
154247
|
});
|
|
153531
154248
|
app.use("/studio", express.static(studioDistDir, { index: false }));
|
|
153532
154249
|
app.use(express.static(studioDistDir, { index: false }));
|
|
@@ -153534,7 +154251,7 @@ function createApp(config2) {
|
|
|
153534
154251
|
if (!studioState.enabled) {
|
|
153535
154252
|
return res.status(403).json({ error: { code: "STUDIO_DISABLED", message: "Studio is disabled." } });
|
|
153536
154253
|
}
|
|
153537
|
-
res.sendFile(
|
|
154254
|
+
res.sendFile(join23(studioDistDir, "index.html"));
|
|
153538
154255
|
});
|
|
153539
154256
|
} else {
|
|
153540
154257
|
app.get("/studio", (_req, res) => {
|
|
@@ -153562,7 +154279,7 @@ function createApp(config2) {
|
|
|
153562
154279
|
if (!studioState.enabled) {
|
|
153563
154280
|
return res.status(403).json({ error: { code: "STUDIO_DISABLED", message: "Studio is disabled." } });
|
|
153564
154281
|
}
|
|
153565
|
-
res.sendFile(
|
|
154282
|
+
res.sendFile(join23(studioDistDir, "index.html"));
|
|
153566
154283
|
});
|
|
153567
154284
|
}
|
|
153568
154285
|
app.use(errorHandler());
|
|
@@ -153641,7 +154358,7 @@ var init_app = __esm({
|
|
|
153641
154358
|
});
|
|
153642
154359
|
|
|
153643
154360
|
// ../server/src/services/config-watcher.ts
|
|
153644
|
-
import { watch, existsSync as
|
|
154361
|
+
import { watch, existsSync as existsSync18 } from "node:fs";
|
|
153645
154362
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
153646
154363
|
var ConfigWatcher;
|
|
153647
154364
|
var init_config_watcher = __esm({
|
|
@@ -153665,7 +154382,7 @@ var init_config_watcher = __esm({
|
|
|
153665
154382
|
*/
|
|
153666
154383
|
async start() {
|
|
153667
154384
|
await this.reload();
|
|
153668
|
-
if (
|
|
154385
|
+
if (existsSync18(this.configPath)) {
|
|
153669
154386
|
this.watcher = watch(this.configPath, { persistent: false }, (eventType) => {
|
|
153670
154387
|
if (eventType === "change") {
|
|
153671
154388
|
if (this.debounceTimer) clearTimeout(this.debounceTimer);
|
|
@@ -153701,7 +154418,7 @@ var init_config_watcher = __esm({
|
|
|
153701
154418
|
// ─── Internal ───────────────────────────────────────────────────────
|
|
153702
154419
|
async reload() {
|
|
153703
154420
|
try {
|
|
153704
|
-
if (!
|
|
154421
|
+
if (!existsSync18(this.configPath)) {
|
|
153705
154422
|
console.warn("[config-watcher] Config file not found, keeping current config.");
|
|
153706
154423
|
return;
|
|
153707
154424
|
}
|
|
@@ -153745,8 +154462,8 @@ __export(telemetry_exports, {
|
|
|
153745
154462
|
resetTelemetry: () => resetTelemetry
|
|
153746
154463
|
});
|
|
153747
154464
|
import { randomUUID as randomUUID42 } from "node:crypto";
|
|
153748
|
-
import { existsSync as
|
|
153749
|
-
import { join as
|
|
154465
|
+
import { existsSync as existsSync19, readFileSync as readFileSync19, writeFileSync as writeFileSync13, appendFileSync as appendFileSync2, mkdirSync as mkdirSync11 } from "node:fs";
|
|
154466
|
+
import { join as join24 } from "node:path";
|
|
153750
154467
|
import { homedir as homedir8 } from "node:os";
|
|
153751
154468
|
function getTelemetry(config2) {
|
|
153752
154469
|
if (!_instance2) {
|
|
@@ -153761,10 +154478,10 @@ var VERSION2, DATA_DIR3, TELEMETRY_ID_FILE, TELEMETRY_LOG_FILE, DEFAULT_FLUSH_TH
|
|
|
153761
154478
|
var init_telemetry2 = __esm({
|
|
153762
154479
|
"../server/src/services/telemetry.ts"() {
|
|
153763
154480
|
"use strict";
|
|
153764
|
-
VERSION2 = "
|
|
153765
|
-
DATA_DIR3 =
|
|
153766
|
-
TELEMETRY_ID_FILE =
|
|
153767
|
-
TELEMETRY_LOG_FILE =
|
|
154481
|
+
VERSION2 = "3.0.0";
|
|
154482
|
+
DATA_DIR3 = join24(homedir8(), ".nestor");
|
|
154483
|
+
TELEMETRY_ID_FILE = join24(DATA_DIR3, "telemetry-id");
|
|
154484
|
+
TELEMETRY_LOG_FILE = join24(DATA_DIR3, "telemetry.jsonl");
|
|
153768
154485
|
DEFAULT_FLUSH_THRESHOLD = 10;
|
|
153769
154486
|
TelemetryService = class {
|
|
153770
154487
|
enabled;
|
|
@@ -153857,8 +154574,8 @@ var init_telemetry2 = __esm({
|
|
|
153857
154574
|
// ─── Private ─────────────────────────────────────────────────────────
|
|
153858
154575
|
getOrCreateInstallId() {
|
|
153859
154576
|
try {
|
|
153860
|
-
if (
|
|
153861
|
-
const id =
|
|
154577
|
+
if (existsSync19(TELEMETRY_ID_FILE)) {
|
|
154578
|
+
const id = readFileSync19(TELEMETRY_ID_FILE, "utf-8").trim();
|
|
153862
154579
|
if (id.length > 0) return id;
|
|
153863
154580
|
}
|
|
153864
154581
|
} catch {
|
|
@@ -153866,14 +154583,14 @@ var init_telemetry2 = __esm({
|
|
|
153866
154583
|
const newId = randomUUID42();
|
|
153867
154584
|
try {
|
|
153868
154585
|
this.ensureDataDir();
|
|
153869
|
-
|
|
154586
|
+
writeFileSync13(TELEMETRY_ID_FILE, newId + "\n", "utf-8");
|
|
153870
154587
|
} catch {
|
|
153871
154588
|
}
|
|
153872
154589
|
return newId;
|
|
153873
154590
|
}
|
|
153874
154591
|
ensureDataDir() {
|
|
153875
|
-
if (!
|
|
153876
|
-
|
|
154592
|
+
if (!existsSync19(DATA_DIR3)) {
|
|
154593
|
+
mkdirSync11(DATA_DIR3, { recursive: true });
|
|
153877
154594
|
}
|
|
153878
154595
|
}
|
|
153879
154596
|
startFlushTimer() {
|
|
@@ -158080,7 +158797,7 @@ var init_src6 = __esm({
|
|
|
158080
158797
|
await this._handle.listen();
|
|
158081
158798
|
const authMode = config2.apiKey ? "API key" : "open (no auth)";
|
|
158082
158799
|
console.log(`
|
|
158083
|
-
Nestor Server
|
|
158800
|
+
Nestor Server v3.0.0`);
|
|
158084
158801
|
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`);
|
|
158085
158802
|
console.log(` HTTP : http://${this._host}:${this._port}`);
|
|
158086
158803
|
console.log(` WS : ws://${this._host}:${this._port}/ws`);
|
|
@@ -165459,7 +166176,7 @@ var require_dist12 = __commonJS({
|
|
|
165459
166176
|
});
|
|
165460
166177
|
|
|
165461
166178
|
// ../skill-tester/src/yaml-loader.ts
|
|
165462
|
-
import { readFileSync as
|
|
166179
|
+
import { readFileSync as readFileSync20 } from "node:fs";
|
|
165463
166180
|
function parseYamlContent(content) {
|
|
165464
166181
|
try {
|
|
165465
166182
|
return JSON.parse(content);
|
|
@@ -165575,7 +166292,7 @@ var init_yaml_loader = __esm({
|
|
|
165575
166292
|
* Load a YAML test suite from a file path.
|
|
165576
166293
|
*/
|
|
165577
166294
|
static loadFile(filePath) {
|
|
165578
|
-
const content =
|
|
166295
|
+
const content = readFileSync20(filePath, "utf-8");
|
|
165579
166296
|
return _YamlTestLoader.parse(content);
|
|
165580
166297
|
}
|
|
165581
166298
|
/**
|
|
@@ -165654,8 +166371,8 @@ var init_yaml_loader = __esm({
|
|
|
165654
166371
|
});
|
|
165655
166372
|
|
|
165656
166373
|
// ../skill-tester/src/runner.ts
|
|
165657
|
-
import { readFileSync as
|
|
165658
|
-
import { join as
|
|
166374
|
+
import { readFileSync as readFileSync21, readdirSync as readdirSync5, statSync as statSync6, existsSync as existsSync21, mkdirSync as mkdirSync13, rmSync as rmSync2 } from "node:fs";
|
|
166375
|
+
import { join as join26, resolve as resolve14 } from "node:path";
|
|
165659
166376
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
165660
166377
|
import { randomUUID as randomUUID44 } from "node:crypto";
|
|
165661
166378
|
var SequentialMockAdapter, SkillTestRunner;
|
|
@@ -165730,25 +166447,25 @@ var init_runner2 = __esm({
|
|
|
165730
166447
|
try {
|
|
165731
166448
|
const mockResponses = test.mockResponses.length > 0 ? test.mockResponses : [{ content: "Test completed." }];
|
|
165732
166449
|
const adapter = new SequentialMockAdapter(mockResponses);
|
|
165733
|
-
const tempDir =
|
|
165734
|
-
|
|
166450
|
+
const tempDir = join26(tmpdir4(), `nestor-skill-test-${randomUUID44()}`);
|
|
166451
|
+
mkdirSync13(tempDir, { recursive: true });
|
|
165735
166452
|
try {
|
|
165736
166453
|
const agentModule = await Promise.resolve().then(() => (init_src5(), src_exports3));
|
|
165737
166454
|
const events = new agentModule.RuntimeEventBus();
|
|
165738
166455
|
const tools = new agentModule.ToolRegistry();
|
|
165739
166456
|
const toolExecutor = new agentModule.ToolExecutor();
|
|
165740
166457
|
let instructions = "You are a helpful AI assistant.";
|
|
165741
|
-
if (test.skill &&
|
|
165742
|
-
instructions =
|
|
166458
|
+
if (test.skill && existsSync21(test.skill)) {
|
|
166459
|
+
instructions = readFileSync21(test.skill, "utf-8");
|
|
165743
166460
|
} else if (test.skill) {
|
|
165744
166461
|
const skillPaths = [
|
|
165745
|
-
|
|
165746
|
-
|
|
165747
|
-
|
|
166462
|
+
join26(process.cwd(), ".nestor", "skills", test.skill, "SKILL.md"),
|
|
166463
|
+
join26(process.cwd(), "skills", test.skill, "SKILL.md"),
|
|
166464
|
+
join26(process.cwd(), "skills-registry", test.skill, "SKILL.md")
|
|
165748
166465
|
];
|
|
165749
166466
|
for (const p8 of skillPaths) {
|
|
165750
|
-
if (
|
|
165751
|
-
instructions =
|
|
166467
|
+
if (existsSync21(p8)) {
|
|
166468
|
+
instructions = readFileSync21(p8, "utf-8");
|
|
165752
166469
|
break;
|
|
165753
166470
|
}
|
|
165754
166471
|
}
|
|
@@ -165958,23 +166675,23 @@ var init_runner2 = __esm({
|
|
|
165958
166675
|
discoverTestFiles(dir) {
|
|
165959
166676
|
const files = [];
|
|
165960
166677
|
const resolvedDir = resolve14(dir);
|
|
165961
|
-
if (!
|
|
165962
|
-
const stat =
|
|
166678
|
+
if (!existsSync21(resolvedDir)) return files;
|
|
166679
|
+
const stat = statSync6(resolvedDir);
|
|
165963
166680
|
if (!stat.isDirectory()) {
|
|
165964
166681
|
return [resolvedDir];
|
|
165965
166682
|
}
|
|
165966
166683
|
function walk(current) {
|
|
165967
166684
|
let entries;
|
|
165968
166685
|
try {
|
|
165969
|
-
entries =
|
|
166686
|
+
entries = readdirSync5(current);
|
|
165970
166687
|
} catch {
|
|
165971
166688
|
return;
|
|
165972
166689
|
}
|
|
165973
166690
|
for (const entry of entries) {
|
|
165974
166691
|
if (entry === "node_modules" || entry === ".git" || entry === "dist") continue;
|
|
165975
|
-
const fullPath =
|
|
166692
|
+
const fullPath = join26(current, entry);
|
|
165976
166693
|
try {
|
|
165977
|
-
const s =
|
|
166694
|
+
const s = statSync6(fullPath);
|
|
165978
166695
|
if (s.isDirectory()) {
|
|
165979
166696
|
walk(fullPath);
|
|
165980
166697
|
} else if (s.isFile() && entry.endsWith(".test.yaml")) {
|
|
@@ -167842,7 +168559,7 @@ var init_server = __esm({
|
|
|
167842
168559
|
MCP_PROTOCOL_VERSION = "2024-11-05";
|
|
167843
168560
|
SERVER_INFO = {
|
|
167844
168561
|
name: "nestor",
|
|
167845
|
-
version: "
|
|
168562
|
+
version: "3.0.0"
|
|
167846
168563
|
};
|
|
167847
168564
|
SERVER_CAPABILITIES = {
|
|
167848
168565
|
tools: { listChanged: false },
|
|
@@ -168028,10 +168745,10 @@ __export(shell_exports, {
|
|
|
168028
168745
|
registerShellCommand: () => registerShellCommand
|
|
168029
168746
|
});
|
|
168030
168747
|
import * as readline3 from "node:readline";
|
|
168031
|
-
import { existsSync as
|
|
168032
|
-
import { join as
|
|
168748
|
+
import { existsSync as existsSync22, readFileSync as readFileSync22, writeFileSync as writeFileSync15, mkdirSync as mkdirSync14, appendFileSync as appendFileSync3 } from "node:fs";
|
|
168749
|
+
import { join as join27, resolve as resolve15, dirname as dirname10, basename as basename5 } from "node:path";
|
|
168033
168750
|
import { homedir as homedir9 } from "node:os";
|
|
168034
|
-
import { readdirSync as
|
|
168751
|
+
import { readdirSync as readdirSync6 } from "node:fs";
|
|
168035
168752
|
import { randomUUID as randomUUID50 } from "node:crypto";
|
|
168036
168753
|
import chalk11 from "chalk";
|
|
168037
168754
|
import * as p5 from "@clack/prompts";
|
|
@@ -168062,8 +168779,8 @@ async function startShell() {
|
|
|
168062
168779
|
currentRouter: null,
|
|
168063
168780
|
verbose: false
|
|
168064
168781
|
};
|
|
168065
|
-
if (!
|
|
168066
|
-
|
|
168782
|
+
if (!existsSync22(NESTOR_DIR)) {
|
|
168783
|
+
mkdirSync14(NESTOR_DIR, { recursive: true });
|
|
168067
168784
|
}
|
|
168068
168785
|
refreshAgentNameCache(session);
|
|
168069
168786
|
const history = loadHistory();
|
|
@@ -168286,7 +169003,7 @@ function printWelcome() {
|
|
|
168286
169003
|
console.log(chalk11.cyan(` | .\` | | _| \\__ \\ | | | (_) | | / _ \\__ \\ | __ |`));
|
|
168287
169004
|
console.log(chalk11.cyan(` |_|\\_| |___| |___/ |_| \\___/ |_|_\\ (_) |___/ |_||_|`));
|
|
168288
169005
|
console.log("");
|
|
168289
|
-
console.log(chalk11.dim(" Interactive Shell \u2014
|
|
169006
|
+
console.log(chalk11.dim(" Interactive Shell \u2014 v3.0.0"));
|
|
168290
169007
|
console.log(chalk11.dim(" Type /help for commands, /exit to quit."));
|
|
168291
169008
|
console.log(chalk11.dim(" Multiline: end a line with \\ or use ``` code blocks."));
|
|
168292
169009
|
console.log("");
|
|
@@ -168783,8 +169500,8 @@ function cmdExport(args2, session) {
|
|
|
168783
169500
|
timestamp: new Date(e.timestamp).toISOString()
|
|
168784
169501
|
}))
|
|
168785
169502
|
};
|
|
168786
|
-
const filename =
|
|
168787
|
-
|
|
169503
|
+
const filename = join27(NESTOR_DIR, `conversation-${timestamp}.json`);
|
|
169504
|
+
writeFileSync15(filename, JSON.stringify(data, null, 2), "utf-8");
|
|
168788
169505
|
console.log(chalk11.green(`Exported to: ${filename}`));
|
|
168789
169506
|
return;
|
|
168790
169507
|
}
|
|
@@ -168808,8 +169525,8 @@ function cmdExport(args2, session) {
|
|
|
168808
169525
|
lines.push(entry.content);
|
|
168809
169526
|
lines.push("");
|
|
168810
169527
|
}
|
|
168811
|
-
const filename =
|
|
168812
|
-
|
|
169528
|
+
const filename = join27(NESTOR_DIR, `conversation-${timestamp}.md`);
|
|
169529
|
+
writeFileSync15(filename, lines.join("\n"), "utf-8");
|
|
168813
169530
|
console.log(chalk11.green(`Exported to: ${filename}`));
|
|
168814
169531
|
return;
|
|
168815
169532
|
}
|
|
@@ -168845,8 +169562,8 @@ ${rows}
|
|
|
168845
169562
|
<div class="stats">Tokens: ${fmtNum(session.totalTokensIn)} in / ${fmtNum(session.totalTokensOut)} out | Cost: $${session.totalCostUsd.toFixed(4)} | Tool calls: ${session.totalToolCalls}</div>
|
|
168846
169563
|
</body>
|
|
168847
169564
|
</html>`;
|
|
168848
|
-
const filename =
|
|
168849
|
-
|
|
169565
|
+
const filename = join27(NESTOR_DIR, `conversation-${timestamp}.html`);
|
|
169566
|
+
writeFileSync15(filename, html, "utf-8");
|
|
168850
169567
|
console.log(chalk11.green(`Exported to: ${filename}`));
|
|
168851
169568
|
}
|
|
168852
169569
|
}
|
|
@@ -169353,7 +170070,7 @@ function createUnifiedDiff(oldText, newText, fileName) {
|
|
|
169353
170070
|
function showDiffForStep(filePath, newContent) {
|
|
169354
170071
|
try {
|
|
169355
170072
|
const absolutePath = resolve15(process.cwd(), filePath);
|
|
169356
|
-
const oldContent =
|
|
170073
|
+
const oldContent = readFileSync22(absolutePath, "utf-8");
|
|
169357
170074
|
const diff = createUnifiedDiff(oldContent, newContent, filePath);
|
|
169358
170075
|
for (const line of diff.split("\n")) {
|
|
169359
170076
|
if (line.startsWith("+") && !line.startsWith("+++")) {
|
|
@@ -169766,8 +170483,8 @@ function completeFilePath(partial) {
|
|
|
169766
170483
|
dir = dirname10(resolved);
|
|
169767
170484
|
prefix = partial.substring(0, Math.max(partial.lastIndexOf("/"), partial.lastIndexOf("\\")) + 1);
|
|
169768
170485
|
}
|
|
169769
|
-
const entries =
|
|
169770
|
-
const base =
|
|
170486
|
+
const entries = readdirSync6(dir, { withFileTypes: true });
|
|
170487
|
+
const base = basename5(partial);
|
|
169771
170488
|
const matches = [];
|
|
169772
170489
|
for (const entry of entries) {
|
|
169773
170490
|
if (entry.name.startsWith(".")) continue;
|
|
@@ -169797,8 +170514,8 @@ function refreshAgentNameCache(session) {
|
|
|
169797
170514
|
}
|
|
169798
170515
|
function loadHistory() {
|
|
169799
170516
|
try {
|
|
169800
|
-
if (
|
|
169801
|
-
const raw =
|
|
170517
|
+
if (existsSync22(HISTORY_FILE)) {
|
|
170518
|
+
const raw = readFileSync22(HISTORY_FILE, "utf-8");
|
|
169802
170519
|
return raw.split("\n").filter((l) => l.trim().length > 0).slice(-MAX_HISTORY);
|
|
169803
170520
|
}
|
|
169804
170521
|
} catch {
|
|
@@ -169809,8 +170526,8 @@ function saveHistory(rl) {
|
|
|
169809
170526
|
}
|
|
169810
170527
|
function appendToHistoryFile(line) {
|
|
169811
170528
|
try {
|
|
169812
|
-
if (!
|
|
169813
|
-
|
|
170529
|
+
if (!existsSync22(NESTOR_DIR)) {
|
|
170530
|
+
mkdirSync14(NESTOR_DIR, { recursive: true });
|
|
169814
170531
|
}
|
|
169815
170532
|
appendFileSync3(HISTORY_FILE, line + "\n", "utf-8");
|
|
169816
170533
|
} catch {
|
|
@@ -170152,8 +170869,8 @@ var init_shell = __esm({
|
|
|
170152
170869
|
init_config2();
|
|
170153
170870
|
init_spinner();
|
|
170154
170871
|
init_table();
|
|
170155
|
-
NESTOR_DIR =
|
|
170156
|
-
HISTORY_FILE =
|
|
170872
|
+
NESTOR_DIR = join27(homedir9(), ".nestor");
|
|
170873
|
+
HISTORY_FILE = join27(NESTOR_DIR, "shell_history");
|
|
170157
170874
|
MAX_HISTORY = 1e3;
|
|
170158
170875
|
SLASH_COMMANDS = {
|
|
170159
170876
|
"/help": { description: "Show all commands", usage: "/help" },
|
|
@@ -170205,8 +170922,8 @@ var init_shell = __esm({
|
|
|
170205
170922
|
|
|
170206
170923
|
// src/index.ts
|
|
170207
170924
|
import { Command } from "commander";
|
|
170208
|
-
import { existsSync as
|
|
170209
|
-
import { join as
|
|
170925
|
+
import { existsSync as existsSync27, readFileSync as readFileSync27 } from "node:fs";
|
|
170926
|
+
import { join as join30 } from "node:path";
|
|
170210
170927
|
import { homedir as homedir12 } from "node:os";
|
|
170211
170928
|
|
|
170212
170929
|
// src/commands/start.ts
|
|
@@ -170226,7 +170943,7 @@ var BANNER = `
|
|
|
170226
170943
|
function registerStartCommand(program2) {
|
|
170227
170944
|
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) => {
|
|
170228
170945
|
console.log(chalk.cyan(BANNER));
|
|
170229
|
-
console.log(chalk.dim(`
|
|
170946
|
+
console.log(chalk.dim(` v3.0.0
|
|
170230
170947
|
`));
|
|
170231
170948
|
let config2 = readConfigFile();
|
|
170232
170949
|
if (!config2) {
|
|
@@ -170351,8 +171068,8 @@ init_config();
|
|
|
170351
171068
|
init_config2();
|
|
170352
171069
|
import * as p from "@clack/prompts";
|
|
170353
171070
|
import chalk2 from "chalk";
|
|
170354
|
-
import { mkdirSync as
|
|
170355
|
-
import { join as
|
|
171071
|
+
import { mkdirSync as mkdirSync12, existsSync as existsSync20 } from "node:fs";
|
|
171072
|
+
import { join as join25 } from "node:path";
|
|
170356
171073
|
import { randomBytes as randomBytes8 } from "node:crypto";
|
|
170357
171074
|
function generateApiKey() {
|
|
170358
171075
|
return `nst_${randomBytes8(32).toString("hex")}`;
|
|
@@ -170371,7 +171088,7 @@ function generateBetaKey() {
|
|
|
170371
171088
|
}
|
|
170372
171089
|
async function initializeDatabase(dataDir) {
|
|
170373
171090
|
const { NestorStore: NestorStore2 } = await Promise.resolve().then(() => (init_src2(), src_exports));
|
|
170374
|
-
const dbPath =
|
|
171091
|
+
const dbPath = join25(dataDir, "nestor.db");
|
|
170375
171092
|
const store = await NestorStore2.open(dbPath);
|
|
170376
171093
|
store.close();
|
|
170377
171094
|
}
|
|
@@ -170419,31 +171136,31 @@ async function runNonInteractiveInstall() {
|
|
|
170419
171136
|
console.log();
|
|
170420
171137
|
const config2 = buildConfigFromDefaults();
|
|
170421
171138
|
const dataDir = expandPath(config2.server.dataDir);
|
|
170422
|
-
if (!
|
|
170423
|
-
|
|
171139
|
+
if (!existsSync20(dataDir)) {
|
|
171140
|
+
mkdirSync12(dataDir, { recursive: true });
|
|
170424
171141
|
console.log(chalk2.green(" Created data directory:"), dataDir);
|
|
170425
171142
|
}
|
|
170426
171143
|
for (const sub of ["adapters", "skills", "plugins", "logs"]) {
|
|
170427
|
-
const subDir =
|
|
170428
|
-
if (!
|
|
170429
|
-
|
|
171144
|
+
const subDir = join25(dataDir, sub);
|
|
171145
|
+
if (!existsSync20(subDir)) {
|
|
171146
|
+
mkdirSync12(subDir, { recursive: true });
|
|
170430
171147
|
}
|
|
170431
171148
|
}
|
|
170432
171149
|
writeConfigFile(config2);
|
|
170433
171150
|
console.log(chalk2.green(" Configuration saved:"), getConfigPath());
|
|
170434
171151
|
try {
|
|
170435
171152
|
await initializeDatabase(dataDir);
|
|
170436
|
-
console.log(chalk2.green(" Database initialized:"),
|
|
171153
|
+
console.log(chalk2.green(" Database initialized:"), join25(dataDir, "nestor.db"));
|
|
170437
171154
|
} catch (err) {
|
|
170438
171155
|
console.log(chalk2.yellow(" Database initialization skipped (install @nestor/db first)"));
|
|
170439
171156
|
}
|
|
170440
171157
|
const apiKey = generateApiKey();
|
|
170441
|
-
const apiKeyPath =
|
|
170442
|
-
const { writeFileSync:
|
|
170443
|
-
|
|
171158
|
+
const apiKeyPath = join25(dataDir, ".api-keys");
|
|
171159
|
+
const { writeFileSync: writeFileSync18 } = await import("node:fs");
|
|
171160
|
+
writeFileSync18(apiKeyPath, JSON.stringify({ admin: apiKey }, null, 2) + "\n", "utf-8");
|
|
170444
171161
|
console.log(chalk2.green(" Admin API key created"));
|
|
170445
171162
|
const betaKey = generateBetaKey();
|
|
170446
|
-
|
|
171163
|
+
writeFileSync18(join25(dataDir, "license.key"), betaKey, "utf-8");
|
|
170447
171164
|
console.log(chalk2.green(" Beta key created"));
|
|
170448
171165
|
console.log();
|
|
170449
171166
|
console.log(chalk2.bold("Admin API Key:"), chalk2.yellow(apiKey));
|
|
@@ -170539,9 +171256,9 @@ async function runInteractiveInstall() {
|
|
|
170539
171256
|
const dataDir = expandPath(config2.server.dataDir);
|
|
170540
171257
|
const spinner3 = p.spinner();
|
|
170541
171258
|
spinner3.start("Creating directories...");
|
|
170542
|
-
for (const dir of [dataDir,
|
|
170543
|
-
if (!
|
|
170544
|
-
|
|
171259
|
+
for (const dir of [dataDir, join25(dataDir, "adapters"), join25(dataDir, "skills"), join25(dataDir, "plugins"), join25(dataDir, "logs")]) {
|
|
171260
|
+
if (!existsSync20(dir)) {
|
|
171261
|
+
mkdirSync12(dir, { recursive: true });
|
|
170545
171262
|
}
|
|
170546
171263
|
}
|
|
170547
171264
|
spinner3.stop("Directories created");
|
|
@@ -170566,14 +171283,14 @@ async function runInteractiveInstall() {
|
|
|
170566
171283
|
const spinner4 = p.spinner();
|
|
170567
171284
|
spinner4.start("Generating admin API key...");
|
|
170568
171285
|
const apiKey = generateApiKey();
|
|
170569
|
-
const apiKeyPath =
|
|
170570
|
-
const { writeFileSync:
|
|
170571
|
-
|
|
171286
|
+
const apiKeyPath = join25(dataDir, ".api-keys");
|
|
171287
|
+
const { writeFileSync: writeFileSync18 } = await import("node:fs");
|
|
171288
|
+
writeFileSync18(apiKeyPath, JSON.stringify({ admin: apiKey }, null, 2) + "\n", "utf-8");
|
|
170572
171289
|
spinner4.stop("Admin API key created!");
|
|
170573
171290
|
const spinner5 = p.spinner();
|
|
170574
171291
|
spinner5.start("Generating beta key...");
|
|
170575
171292
|
const betaKey = generateBetaKey();
|
|
170576
|
-
|
|
171293
|
+
writeFileSync18(join25(dataDir, "license.key"), betaKey, "utf-8");
|
|
170577
171294
|
spinner5.stop("Beta key created!");
|
|
170578
171295
|
p.note(
|
|
170579
171296
|
`Config file: ${getConfigPath()}
|
|
@@ -171866,23 +172583,23 @@ init_db();
|
|
|
171866
172583
|
init_spinner();
|
|
171867
172584
|
init_table();
|
|
171868
172585
|
import {
|
|
171869
|
-
existsSync as
|
|
171870
|
-
readFileSync as
|
|
171871
|
-
writeFileSync as
|
|
171872
|
-
mkdirSync as
|
|
172586
|
+
existsSync as existsSync23,
|
|
172587
|
+
readFileSync as readFileSync23,
|
|
172588
|
+
writeFileSync as writeFileSync16,
|
|
172589
|
+
mkdirSync as mkdirSync15,
|
|
171873
172590
|
unlinkSync,
|
|
171874
172591
|
appendFileSync as appendFileSync4
|
|
171875
172592
|
} from "node:fs";
|
|
171876
|
-
import { join as
|
|
172593
|
+
import { join as join28 } from "node:path";
|
|
171877
172594
|
import { homedir as homedir10 } from "node:os";
|
|
171878
172595
|
import { fork as fork2 } from "node:child_process";
|
|
171879
172596
|
import "node:readline";
|
|
171880
172597
|
import chalk12 from "chalk";
|
|
171881
|
-
var NESTOR_DIR2 =
|
|
171882
|
-
var PID_FILE =
|
|
171883
|
-
var LOG_DIR =
|
|
171884
|
-
var LOG_FILE =
|
|
171885
|
-
var HEARTBEAT_FILE =
|
|
172598
|
+
var NESTOR_DIR2 = join28(homedir10(), ".nestor");
|
|
172599
|
+
var PID_FILE = join28(NESTOR_DIR2, "daemon.pid");
|
|
172600
|
+
var LOG_DIR = join28(NESTOR_DIR2, "logs");
|
|
172601
|
+
var LOG_FILE = join28(LOG_DIR, "daemon.log");
|
|
172602
|
+
var HEARTBEAT_FILE = join28(NESTOR_DIR2, "daemon.heartbeat");
|
|
171886
172603
|
var HEARTBEAT_INTERVAL_MS2 = 3e4;
|
|
171887
172604
|
function registerDaemonCommand(program2) {
|
|
171888
172605
|
const daemon = program2.command("daemon").description("Manage the Nestor background daemon");
|
|
@@ -171918,7 +172635,7 @@ async function startForeground() {
|
|
|
171918
172635
|
console.log(chalk12.cyan(` | .\` | | _| \\__ \\ | | | (_) | | / _ \\__ \\ | __ |`));
|
|
171919
172636
|
console.log(chalk12.cyan(` |_|\\_| |___| |___/ |_| \\___/ |_|_\\ (_) |___/ |_||_|`));
|
|
171920
172637
|
console.log("");
|
|
171921
|
-
console.log(chalk12.dim(" Daemon Mode \u2014
|
|
172638
|
+
console.log(chalk12.dim(" Daemon Mode \u2014 v3.0.0"));
|
|
171922
172639
|
console.log(chalk12.dim(` PID: ${process.pid}`));
|
|
171923
172640
|
console.log(chalk12.dim(` Log: ${LOG_FILE}`));
|
|
171924
172641
|
console.log("");
|
|
@@ -172050,13 +172767,13 @@ async function showStatus() {
|
|
|
172050
172767
|
console.log("");
|
|
172051
172768
|
}
|
|
172052
172769
|
async function showLogs(follow, lineCount) {
|
|
172053
|
-
if (!
|
|
172770
|
+
if (!existsSync23(LOG_FILE)) {
|
|
172054
172771
|
console.log(chalk12.yellow("No daemon log file found."));
|
|
172055
172772
|
console.log(chalk12.dim(`Expected at: ${LOG_FILE}`));
|
|
172056
172773
|
return;
|
|
172057
172774
|
}
|
|
172058
172775
|
if (!follow) {
|
|
172059
|
-
const content =
|
|
172776
|
+
const content = readFileSync23(LOG_FILE, "utf-8");
|
|
172060
172777
|
const lines = content.split("\n").filter((l) => l.length > 0);
|
|
172061
172778
|
const lastLines = lines.slice(-lineCount);
|
|
172062
172779
|
if (lastLines.length === 0) {
|
|
@@ -172070,19 +172787,19 @@ async function showLogs(follow, lineCount) {
|
|
|
172070
172787
|
}
|
|
172071
172788
|
console.log(chalk12.dim(`Following ${LOG_FILE}... (Ctrl+C to stop)`));
|
|
172072
172789
|
console.log("");
|
|
172073
|
-
if (
|
|
172074
|
-
const content =
|
|
172790
|
+
if (existsSync23(LOG_FILE)) {
|
|
172791
|
+
const content = readFileSync23(LOG_FILE, "utf-8");
|
|
172075
172792
|
const lines = content.split("\n").filter((l) => l.length > 0);
|
|
172076
172793
|
const lastLines = lines.slice(-10);
|
|
172077
172794
|
for (const line of lastLines) {
|
|
172078
172795
|
console.log(colorizeLogLine(line));
|
|
172079
172796
|
}
|
|
172080
172797
|
}
|
|
172081
|
-
let lastSize =
|
|
172798
|
+
let lastSize = existsSync23(LOG_FILE) ? readFileSync23(LOG_FILE).length : 0;
|
|
172082
172799
|
const watcher = setInterval(() => {
|
|
172083
172800
|
try {
|
|
172084
|
-
if (!
|
|
172085
|
-
const content =
|
|
172801
|
+
if (!existsSync23(LOG_FILE)) return;
|
|
172802
|
+
const content = readFileSync23(LOG_FILE, "utf-8");
|
|
172086
172803
|
if (content.length > lastSize) {
|
|
172087
172804
|
const newContent = content.substring(lastSize);
|
|
172088
172805
|
const newLines = newContent.split("\n").filter((l) => l.length > 0);
|
|
@@ -172394,7 +173111,7 @@ var DaemonRunner = class {
|
|
|
172394
173111
|
activeAgents: this.runningAgents.size,
|
|
172395
173112
|
nextScheduledRun: void 0
|
|
172396
173113
|
};
|
|
172397
|
-
|
|
173114
|
+
writeFileSync16(HEARTBEAT_FILE, JSON.stringify(data), "utf-8");
|
|
172398
173115
|
} catch {
|
|
172399
173116
|
}
|
|
172400
173117
|
}
|
|
@@ -172412,8 +173129,8 @@ async function importDaemonAgentModule() {
|
|
|
172412
173129
|
}
|
|
172413
173130
|
function readHeartbeat() {
|
|
172414
173131
|
try {
|
|
172415
|
-
if (
|
|
172416
|
-
const raw =
|
|
173132
|
+
if (existsSync23(HEARTBEAT_FILE)) {
|
|
173133
|
+
const raw = readFileSync23(HEARTBEAT_FILE, "utf-8");
|
|
172417
173134
|
return JSON.parse(raw);
|
|
172418
173135
|
}
|
|
172419
173136
|
} catch {
|
|
@@ -172422,8 +173139,8 @@ function readHeartbeat() {
|
|
|
172422
173139
|
}
|
|
172423
173140
|
function readPid() {
|
|
172424
173141
|
try {
|
|
172425
|
-
if (
|
|
172426
|
-
const raw =
|
|
173142
|
+
if (existsSync23(PID_FILE)) {
|
|
173143
|
+
const raw = readFileSync23(PID_FILE, "utf-8").trim();
|
|
172427
173144
|
const pid = parseInt(raw, 10);
|
|
172428
173145
|
return isNaN(pid) ? null : pid;
|
|
172429
173146
|
}
|
|
@@ -172433,11 +173150,11 @@ function readPid() {
|
|
|
172433
173150
|
}
|
|
172434
173151
|
function writePid(pid) {
|
|
172435
173152
|
ensureDirs();
|
|
172436
|
-
|
|
173153
|
+
writeFileSync16(PID_FILE, String(pid), "utf-8");
|
|
172437
173154
|
}
|
|
172438
173155
|
function cleanupPid() {
|
|
172439
173156
|
try {
|
|
172440
|
-
if (
|
|
173157
|
+
if (existsSync23(PID_FILE)) {
|
|
172441
173158
|
unlinkSync(PID_FILE);
|
|
172442
173159
|
}
|
|
172443
173160
|
} catch {
|
|
@@ -172477,11 +173194,11 @@ function colorizeLogLine(line) {
|
|
|
172477
173194
|
return line;
|
|
172478
173195
|
}
|
|
172479
173196
|
function ensureDirs() {
|
|
172480
|
-
if (!
|
|
172481
|
-
|
|
173197
|
+
if (!existsSync23(NESTOR_DIR2)) {
|
|
173198
|
+
mkdirSync15(NESTOR_DIR2, { recursive: true });
|
|
172482
173199
|
}
|
|
172483
|
-
if (!
|
|
172484
|
-
|
|
173200
|
+
if (!existsSync23(LOG_DIR)) {
|
|
173201
|
+
mkdirSync15(LOG_DIR, { recursive: true });
|
|
172485
173202
|
}
|
|
172486
173203
|
}
|
|
172487
173204
|
function delay(ms) {
|
|
@@ -172522,13 +173239,13 @@ if (process.argv[2] === "__daemon_child__" || process.env.NESTOR_DAEMON_MODE ===
|
|
|
172522
173239
|
|
|
172523
173240
|
// src/commands/watch.ts
|
|
172524
173241
|
init_db();
|
|
172525
|
-
import { existsSync as
|
|
172526
|
-
import { join as
|
|
173242
|
+
import { existsSync as existsSync24, readFileSync as readFileSync24 } from "node:fs";
|
|
173243
|
+
import { join as join29 } from "node:path";
|
|
172527
173244
|
import { homedir as homedir11 } from "node:os";
|
|
172528
173245
|
import chalk13 from "chalk";
|
|
172529
|
-
var NESTOR_DIR3 =
|
|
172530
|
-
var HEARTBEAT_FILE2 =
|
|
172531
|
-
var LOG_FILE2 =
|
|
173246
|
+
var NESTOR_DIR3 = join29(homedir11(), ".nestor");
|
|
173247
|
+
var HEARTBEAT_FILE2 = join29(NESTOR_DIR3, "daemon.heartbeat");
|
|
173248
|
+
var LOG_FILE2 = join29(NESTOR_DIR3, "logs", "daemon.log");
|
|
172532
173249
|
var REFRESH_INTERVAL_MS = 1e3;
|
|
172533
173250
|
var MAX_EVENTS = 12;
|
|
172534
173251
|
function registerWatchCommand(program2) {
|
|
@@ -172596,8 +173313,8 @@ async function refreshData(state) {
|
|
|
172596
173313
|
} catch {
|
|
172597
173314
|
}
|
|
172598
173315
|
try {
|
|
172599
|
-
if (
|
|
172600
|
-
const raw =
|
|
173316
|
+
if (existsSync24(HEARTBEAT_FILE2)) {
|
|
173317
|
+
const raw = readFileSync24(HEARTBEAT_FILE2, "utf-8");
|
|
172601
173318
|
const heartbeat = JSON.parse(raw);
|
|
172602
173319
|
state.daemonRunning = isDaemonAlive(heartbeat.pid);
|
|
172603
173320
|
state.daemonPid = heartbeat.pid;
|
|
@@ -172614,8 +173331,8 @@ async function refreshData(state) {
|
|
|
172614
173331
|
}
|
|
172615
173332
|
function loadRecentEvents(state) {
|
|
172616
173333
|
try {
|
|
172617
|
-
if (!
|
|
172618
|
-
const content =
|
|
173334
|
+
if (!existsSync24(LOG_FILE2)) return;
|
|
173335
|
+
const content = readFileSync24(LOG_FILE2, "utf-8");
|
|
172619
173336
|
const lines = content.split("\n").filter((l) => l.length > 0);
|
|
172620
173337
|
const recent = lines.slice(-MAX_EVENTS);
|
|
172621
173338
|
state.recentEvents = recent.map((line) => {
|
|
@@ -172941,10 +173658,10 @@ function registerTelemetryCommand(program2) {
|
|
|
172941
173658
|
}
|
|
172942
173659
|
console.log(` ${chalk15.dim("Flush:")} every ${(config2.telemetry?.flushIntervalMs ?? 6e4) / 1e3}s`);
|
|
172943
173660
|
}
|
|
172944
|
-
const { join:
|
|
173661
|
+
const { join: join31 } = __require("node:path");
|
|
172945
173662
|
const { homedir: homedir13 } = __require("node:os");
|
|
172946
|
-
const telemetryFile =
|
|
172947
|
-
const idFile =
|
|
173663
|
+
const telemetryFile = join31(homedir13(), ".nestor", "telemetry.jsonl");
|
|
173664
|
+
const idFile = join31(homedir13(), ".nestor", "telemetry-id");
|
|
172948
173665
|
if (fs28.existsSync(idFile)) {
|
|
172949
173666
|
const installId = fs28.readFileSync(idFile, "utf-8").trim();
|
|
172950
173667
|
console.log(` ${chalk15.dim("Install ID:")} ${installId.slice(0, 8)}...`);
|
|
@@ -172985,7 +173702,7 @@ function setTelemetryEnabled(enabled) {
|
|
|
172985
173702
|
init_db();
|
|
172986
173703
|
init_table();
|
|
172987
173704
|
import chalk16 from "chalk";
|
|
172988
|
-
import { readFileSync as
|
|
173705
|
+
import { readFileSync as readFileSync25, writeFileSync as writeFileSync17 } from "node:fs";
|
|
172989
173706
|
function registerMemoryCommand(program2) {
|
|
172990
173707
|
const memory = program2.command("memory").description("Manage agent persistent memories");
|
|
172991
173708
|
memory.command("list").description("List memories for an agent").option("-a, --agent <id>", "Agent ID to filter by").option("-t, --type <type>", "Memory type filter (observation, fact, instruction, reflection)").option("-l, --limit <n>", "Maximum results", "20").action(async (options) => {
|
|
@@ -173189,13 +173906,13 @@ Memory Statistics for ${agentId}`));
|
|
|
173189
173906
|
}
|
|
173190
173907
|
}
|
|
173191
173908
|
const json = JSON.stringify(allMemories, null, 2);
|
|
173192
|
-
|
|
173909
|
+
writeFileSync17(outputFile, json, "utf-8");
|
|
173193
173910
|
console.log(chalk16.green(`Exported ${allMemories.length} memories to ${outputFile}`));
|
|
173194
173911
|
});
|
|
173195
173912
|
memory.command("import <file>").description("Import memories from JSON").action(async (file) => {
|
|
173196
173913
|
const store = await getStore();
|
|
173197
173914
|
try {
|
|
173198
|
-
const raw =
|
|
173915
|
+
const raw = readFileSync25(file, "utf-8");
|
|
173199
173916
|
const entries = JSON.parse(raw);
|
|
173200
173917
|
if (!Array.isArray(entries)) {
|
|
173201
173918
|
console.error(chalk16.red("Invalid format: expected a JSON array of memory entries."));
|
|
@@ -173715,8 +174432,8 @@ ${results.length} results for "${query}":
|
|
|
173715
174432
|
}
|
|
173716
174433
|
|
|
173717
174434
|
// src/commands/test.ts
|
|
173718
|
-
import { resolve as resolve17, relative as
|
|
173719
|
-
import { readdirSync as
|
|
174435
|
+
import { resolve as resolve17, relative as relative6 } from "node:path";
|
|
174436
|
+
import { readdirSync as readdirSync7, statSync as statSync7, existsSync as existsSync25 } from "node:fs";
|
|
173720
174437
|
import chalk20 from "chalk";
|
|
173721
174438
|
var TEST_FILE_PATTERNS = [
|
|
173722
174439
|
".nestor-test.yaml",
|
|
@@ -173729,7 +174446,7 @@ function registerTestCommand(program2) {
|
|
|
173729
174446
|
program2.command("test [path]").description("Run skill and agent test suites").option("-l, --list", "List discovered test files", false).option("-f, --file <file>", "Run a specific test file").option("-r, --record <file>", "Record LLM responses to a fixture file").option("-p, --prompt <prompt>", "Prompt for recording mode").option("-v, --verbose", "Show detailed test output", false).option("-j, --json", "Output results as JSON (for CI)", false).action(async (path30, opts) => {
|
|
173730
174447
|
if (opts.file) {
|
|
173731
174448
|
const filePath = resolve17(opts.file);
|
|
173732
|
-
if (!
|
|
174449
|
+
if (!existsSync25(filePath)) {
|
|
173733
174450
|
console.error(chalk20.red(`File not found: ${opts.file}`));
|
|
173734
174451
|
process.exit(1);
|
|
173735
174452
|
}
|
|
@@ -173760,7 +174477,7 @@ function registerTestCommand(program2) {
|
|
|
173760
174477
|
];
|
|
173761
174478
|
const allFiles = [];
|
|
173762
174479
|
for (const testDir of defaultTestDirs) {
|
|
173763
|
-
if (
|
|
174480
|
+
if (existsSync25(testDir)) {
|
|
173764
174481
|
allFiles.push(...discoverTestFiles(testDir));
|
|
173765
174482
|
}
|
|
173766
174483
|
}
|
|
@@ -173779,7 +174496,7 @@ function discoverTestFiles(dir) {
|
|
|
173779
174496
|
function walk(current) {
|
|
173780
174497
|
let entries;
|
|
173781
174498
|
try {
|
|
173782
|
-
entries =
|
|
174499
|
+
entries = readdirSync7(current);
|
|
173783
174500
|
} catch {
|
|
173784
174501
|
return;
|
|
173785
174502
|
}
|
|
@@ -173787,7 +174504,7 @@ function discoverTestFiles(dir) {
|
|
|
173787
174504
|
if (entry === "node_modules" || entry === ".git" || entry === "dist") continue;
|
|
173788
174505
|
const fullPath = resolve17(current, entry);
|
|
173789
174506
|
try {
|
|
173790
|
-
const stat =
|
|
174507
|
+
const stat = statSync7(fullPath);
|
|
173791
174508
|
if (stat.isDirectory()) {
|
|
173792
174509
|
walk(fullPath);
|
|
173793
174510
|
} else if (stat.isFile()) {
|
|
@@ -173803,7 +174520,7 @@ function discoverTestFiles(dir) {
|
|
|
173803
174520
|
}
|
|
173804
174521
|
}
|
|
173805
174522
|
}
|
|
173806
|
-
if (
|
|
174523
|
+
if (existsSync25(dir) && !statSync7(dir).isDirectory()) {
|
|
173807
174524
|
return [dir];
|
|
173808
174525
|
}
|
|
173809
174526
|
walk(dir);
|
|
@@ -173812,7 +174529,7 @@ function discoverTestFiles(dir) {
|
|
|
173812
174529
|
async function listTestFiles(dir) {
|
|
173813
174530
|
const files = discoverTestFiles(dir);
|
|
173814
174531
|
const nestorTestDir = resolve17(dir, ".nestor", "tests");
|
|
173815
|
-
if (
|
|
174532
|
+
if (existsSync25(nestorTestDir)) {
|
|
173816
174533
|
files.push(...discoverTestFiles(nestorTestDir));
|
|
173817
174534
|
}
|
|
173818
174535
|
const unique = [...new Set(files)];
|
|
@@ -173824,7 +174541,7 @@ async function listTestFiles(dir) {
|
|
|
173824
174541
|
Discovered ${unique.length} test file(s):
|
|
173825
174542
|
`));
|
|
173826
174543
|
for (const file of unique) {
|
|
173827
|
-
console.log(chalk20.dim(" ") + chalk20.cyan(
|
|
174544
|
+
console.log(chalk20.dim(" ") + chalk20.cyan(relative6(dir, file)));
|
|
173828
174545
|
}
|
|
173829
174546
|
console.log("");
|
|
173830
174547
|
}
|
|
@@ -173868,7 +174585,7 @@ async function runSkillTestsByName(skillName, verbose, json) {
|
|
|
173868
174585
|
];
|
|
173869
174586
|
const matchingFiles = [];
|
|
173870
174587
|
for (const dir of searchDirs) {
|
|
173871
|
-
if (!
|
|
174588
|
+
if (!existsSync25(dir)) continue;
|
|
173872
174589
|
const files = discoverTestFiles(dir);
|
|
173873
174590
|
for (const file of files) {
|
|
173874
174591
|
if (file.includes(skillName)) {
|
|
@@ -173894,7 +174611,7 @@ Running ${files.length} test suite(s) (legacy runner)...
|
|
|
173894
174611
|
let totalFailed = 0;
|
|
173895
174612
|
const startTime4 = Date.now();
|
|
173896
174613
|
for (const file of files) {
|
|
173897
|
-
const relPath =
|
|
174614
|
+
const relPath = relative6(process.cwd(), file);
|
|
173898
174615
|
let suite;
|
|
173899
174616
|
try {
|
|
173900
174617
|
suite = agentModule.AgentTestRunner.loadSuite(file);
|
|
@@ -174069,7 +174786,7 @@ init_db();
|
|
|
174069
174786
|
init_config2();
|
|
174070
174787
|
import chalk22 from "chalk";
|
|
174071
174788
|
import { randomUUID as randomUUID51 } from "node:crypto";
|
|
174072
|
-
import { readFileSync as
|
|
174789
|
+
import { readFileSync as readFileSync26, existsSync as existsSync26 } from "node:fs";
|
|
174073
174790
|
import { execSync as execSync3 } from "node:child_process";
|
|
174074
174791
|
function runShellCommand(cmd, cwd) {
|
|
174075
174792
|
try {
|
|
@@ -174140,11 +174857,11 @@ function registerLoopCommand(program2) {
|
|
|
174140
174857
|
program2.command("loop").description("Run an agent in a fresh-context loop until a specification is met (Ralph pattern)").option("--agent <name>", "Agent name to use", "default").option("--spec <text>", "Specification to achieve").option("--spec-file <path>", "File containing the specification").option("--verify <command>", "Shell command to verify spec (exit 0 = done)").option("--max-iterations <n>", "Max loop iterations", "10").option("--budget <usd>", "Max total budget in USD", "5").option("--cwd <path>", "Working directory", process.cwd()).action(async (opts) => {
|
|
174141
174858
|
let spec = opts.spec;
|
|
174142
174859
|
if (!spec && opts.specFile) {
|
|
174143
|
-
if (!
|
|
174860
|
+
if (!existsSync26(opts.specFile)) {
|
|
174144
174861
|
console.error(chalk22.red(`Spec file not found: ${opts.specFile}`));
|
|
174145
174862
|
process.exit(1);
|
|
174146
174863
|
}
|
|
174147
|
-
spec =
|
|
174864
|
+
spec = readFileSync26(opts.specFile, "utf-8").trim();
|
|
174148
174865
|
}
|
|
174149
174866
|
if (!spec) {
|
|
174150
174867
|
console.error(chalk22.red("Must provide --spec or --spec-file"));
|
|
@@ -174344,9 +175061,9 @@ function registerLoopCommand(program2) {
|
|
|
174344
175061
|
|
|
174345
175062
|
// src/index.ts
|
|
174346
175063
|
function checkBetaAccess() {
|
|
174347
|
-
const licenseFile =
|
|
174348
|
-
if (!
|
|
174349
|
-
const key =
|
|
175064
|
+
const licenseFile = join30(homedir12(), ".nestor", "license.key");
|
|
175065
|
+
if (!existsSync27(licenseFile)) return false;
|
|
175066
|
+
const key = readFileSync27(licenseFile, "utf-8").trim();
|
|
174350
175067
|
return /^NESTOR-BETA-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$/.test(key);
|
|
174351
175068
|
}
|
|
174352
175069
|
var command2 = process.argv[2];
|
|
@@ -174366,7 +175083,7 @@ if (command2 && !["--help", "-h", "--version", "-V", "install"].includes(command
|
|
|
174366
175083
|
}
|
|
174367
175084
|
}
|
|
174368
175085
|
var program = new Command();
|
|
174369
|
-
program.name("nestor-sh").description("Nestor AI Agent Platform \u2014 orchestrate, secure and monitor AI agents").version("
|
|
175086
|
+
program.name("nestor-sh").description("Nestor AI Agent Platform \u2014 orchestrate, secure and monitor AI agents").version("3.0.0");
|
|
174370
175087
|
registerStartCommand(program);
|
|
174371
175088
|
registerInstallCommand(program);
|
|
174372
175089
|
registerAgentCommand(program);
|