@probelabs/probe 0.6.0-rc295 → 0.6.0-rc297
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -0
- package/bin/binaries/{probe-v0.6.0-rc295-aarch64-apple-darwin.tar.gz → probe-v0.6.0-rc297-aarch64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc295-aarch64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc297-aarch64-unknown-linux-musl.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc295-x86_64-apple-darwin.tar.gz → probe-v0.6.0-rc297-x86_64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc295-x86_64-pc-windows-msvc.zip → probe-v0.6.0-rc297-x86_64-pc-windows-msvc.zip} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc295-x86_64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc297-x86_64-unknown-linux-musl.tar.gz} +0 -0
- package/build/agent/ProbeAgent.d.ts +40 -2
- package/build/agent/ProbeAgent.js +703 -11
- package/build/agent/mcp/client.js +115 -4
- package/build/agent/mcp/xmlBridge.js +13 -1
- package/build/agent/otelLogBridge.js +184 -0
- package/build/agent/simpleTelemetry.js +8 -0
- package/build/delegate.js +75 -6
- package/build/index.js +6 -2
- package/build/tools/common.js +84 -11
- package/build/tools/vercel.js +78 -18
- package/cjs/agent/ProbeAgent.cjs +1095 -185
- package/cjs/agent/simpleTelemetry.cjs +112 -0
- package/cjs/index.cjs +1207 -185
- package/index.d.ts +26 -0
- package/package.json +2 -2
- package/src/agent/ProbeAgent.d.ts +40 -2
- package/src/agent/ProbeAgent.js +703 -11
- package/src/agent/mcp/client.js +115 -4
- package/src/agent/mcp/xmlBridge.js +13 -1
- package/src/agent/otelLogBridge.js +184 -0
- package/src/agent/simpleTelemetry.js +8 -0
- package/src/delegate.js +75 -6
- package/src/index.js +6 -2
- package/src/tools/common.js +84 -11
- package/src/tools/vercel.js +78 -18
package/cjs/index.cjs
CHANGED
|
@@ -27051,14 +27051,64 @@ function detectStuckResponse(response) {
|
|
|
27051
27051
|
}
|
|
27052
27052
|
return false;
|
|
27053
27053
|
}
|
|
27054
|
+
function splitQuotedString(input) {
|
|
27055
|
+
const tokens = [];
|
|
27056
|
+
let current2 = "";
|
|
27057
|
+
let inQuote = null;
|
|
27058
|
+
let i = 0;
|
|
27059
|
+
while (i < input.length) {
|
|
27060
|
+
const ch = input[i];
|
|
27061
|
+
if (inQuote) {
|
|
27062
|
+
if (ch === "\\" && i + 1 < input.length) {
|
|
27063
|
+
current2 += input[i + 1];
|
|
27064
|
+
i += 2;
|
|
27065
|
+
continue;
|
|
27066
|
+
}
|
|
27067
|
+
if (ch === inQuote) {
|
|
27068
|
+
inQuote = null;
|
|
27069
|
+
i++;
|
|
27070
|
+
continue;
|
|
27071
|
+
}
|
|
27072
|
+
current2 += ch;
|
|
27073
|
+
i++;
|
|
27074
|
+
} else {
|
|
27075
|
+
if (ch === '"' || ch === "'") {
|
|
27076
|
+
inQuote = ch;
|
|
27077
|
+
i++;
|
|
27078
|
+
continue;
|
|
27079
|
+
}
|
|
27080
|
+
if (/[\s,]/.test(ch)) {
|
|
27081
|
+
if (current2.length > 0) {
|
|
27082
|
+
tokens.push(current2);
|
|
27083
|
+
current2 = "";
|
|
27084
|
+
}
|
|
27085
|
+
i++;
|
|
27086
|
+
continue;
|
|
27087
|
+
}
|
|
27088
|
+
current2 += ch;
|
|
27089
|
+
i++;
|
|
27090
|
+
}
|
|
27091
|
+
}
|
|
27092
|
+
if (current2.length > 0) {
|
|
27093
|
+
tokens.push(current2);
|
|
27094
|
+
}
|
|
27095
|
+
return tokens;
|
|
27096
|
+
}
|
|
27054
27097
|
function parseTargets(targets) {
|
|
27055
27098
|
if (!targets || typeof targets !== "string") {
|
|
27056
27099
|
return [];
|
|
27057
27100
|
}
|
|
27058
|
-
return targets
|
|
27101
|
+
return splitQuotedString(targets);
|
|
27059
27102
|
}
|
|
27060
27103
|
function parseAndResolvePaths(pathStr, cwd) {
|
|
27061
27104
|
if (!pathStr) return [];
|
|
27105
|
+
if (/["']/.test(pathStr)) {
|
|
27106
|
+
const paths2 = splitQuotedString(pathStr);
|
|
27107
|
+
return paths2.map((p) => {
|
|
27108
|
+
if ((0, import_path5.isAbsolute)(p)) return p;
|
|
27109
|
+
return cwd ? (0, import_path5.resolve)(cwd, p) : p;
|
|
27110
|
+
});
|
|
27111
|
+
}
|
|
27062
27112
|
let paths = pathStr.split(",").map((p) => p.trim()).filter((p) => p.length > 0);
|
|
27063
27113
|
paths = paths.flatMap((p) => {
|
|
27064
27114
|
if (!/\s/.test(p)) return [p];
|
|
@@ -27068,9 +27118,7 @@ function parseAndResolvePaths(pathStr, cwd) {
|
|
|
27068
27118
|
return allLookLikePaths ? parts : [p];
|
|
27069
27119
|
});
|
|
27070
27120
|
return paths.map((p) => {
|
|
27071
|
-
if ((0, import_path5.isAbsolute)(p))
|
|
27072
|
-
return p;
|
|
27073
|
-
}
|
|
27121
|
+
if ((0, import_path5.isAbsolute)(p)) return p;
|
|
27074
27122
|
return cwd ? (0, import_path5.resolve)(cwd, p) : p;
|
|
27075
27123
|
});
|
|
27076
27124
|
}
|
|
@@ -27103,7 +27151,7 @@ var init_common = __esm({
|
|
|
27103
27151
|
searchSchema = external_exports2.object({
|
|
27104
27152
|
query: external_exports2.string().describe("Search query \u2014 natural language questions or Elasticsearch-style keywords both work. For keywords: use quotes for exact phrases, AND/OR for boolean logic, - for negation. Probe handles stemming and camelCase/snake_case splitting automatically, so do NOT try case or style variations of the same keyword."),
|
|
27105
27153
|
path: external_exports2.string().optional().default(".").describe('Path to search in. For dependencies use "go:github.com/owner/repo", "js:package_name", or "rust:cargo_name" etc.'),
|
|
27106
|
-
exact: external_exports2.boolean().optional().default(false).describe(
|
|
27154
|
+
exact: external_exports2.boolean().optional().default(false).describe(`Default (false) enables stemming and keyword splitting for exploratory search - "getUserData" matches "get", "user", "data", etc. Set true for precise symbol lookup OR when searching for strings with punctuation/quotes/empty values (e.g. 'description: ""' \u2014 BM25 strips punctuation so exact=true is required for literal matching). Use true when you know the exact symbol name or need literal string matching.`),
|
|
27107
27155
|
maxTokens: external_exports2.number().nullable().optional().describe("Maximum tokens to return. Default is 20000. Set to null for unlimited results."),
|
|
27108
27156
|
session: external_exports2.string().optional().describe("Session ID for result caching and pagination. Pass the session ID from a previous search to get additional results (next page). Results already shown in a session are automatically excluded. Omit for a fresh search."),
|
|
27109
27157
|
nextPage: external_exports2.boolean().optional().default(false).describe("Set to true when requesting the next page of results. Requires passing the same session ID from the previous search output.")
|
|
@@ -48010,7 +48058,22 @@ function mapFlowchartParserError(err, text) {
|
|
|
48010
48058
|
const lineContent = allLines[Math.max(0, line - 1)] || "";
|
|
48011
48059
|
const beforeQuote = lineContent.slice(0, Math.max(0, column - 1));
|
|
48012
48060
|
const hasLinkBefore = beforeQuote.match(/--\s*$|==\s*$|-\.\s*$|-\.-\s*$|\[\s*$/);
|
|
48061
|
+
const caret0 = Math.max(0, column - 1);
|
|
48062
|
+
const firstBar = lineContent.lastIndexOf("|", caret0);
|
|
48063
|
+
const secondBar = firstBar >= 0 ? lineContent.indexOf("|", caret0 + 1) : -1;
|
|
48064
|
+
const inPipeLabel = firstBar >= 0 && secondBar > firstBar && firstBar < caret0 && secondBar > caret0;
|
|
48013
48065
|
if (inLinkRule || hasLinkBefore) {
|
|
48066
|
+
if (tokType === "QuotedString" && inPipeLabel) {
|
|
48067
|
+
return {
|
|
48068
|
+
line,
|
|
48069
|
+
column,
|
|
48070
|
+
severity: "error",
|
|
48071
|
+
code: "FL-EDGE-LABEL-QUOTE-IN-PIPES",
|
|
48072
|
+
message: "Quotes are not supported inside pipe-delimited edge labels.",
|
|
48073
|
+
hint: "Use " inside |...|, e.g., --|e.g. "navigate to example.com"|-->",
|
|
48074
|
+
length: len
|
|
48075
|
+
};
|
|
48076
|
+
}
|
|
48014
48077
|
if (tokType === "DiamondOpen" || tokType === "DiamondClose") {
|
|
48015
48078
|
return {
|
|
48016
48079
|
line,
|
|
@@ -48612,17 +48675,6 @@ ${br.example}`,
|
|
|
48612
48675
|
if (inRule("arrow") && err.name === "NoViableAltException") {
|
|
48613
48676
|
return { line, column, severity: "error", code: "SE-ARROW-INVALID", message: `Invalid sequence arrow near '${found}'.`, hint: "Use ->, -->, ->>, -->>, -x, --x, -), --), <<->>, or <<-->>", length: len };
|
|
48614
48677
|
}
|
|
48615
|
-
if ((err.name === "NoViableAltException" || err.name === "MismatchedTokenException") && tokType === "Minus") {
|
|
48616
|
-
return {
|
|
48617
|
-
line,
|
|
48618
|
-
column,
|
|
48619
|
-
severity: "error",
|
|
48620
|
-
code: "SE-BULLET-LINE-UNSUPPORTED",
|
|
48621
|
-
message: "Bullet list lines starting with '-' are not supported in sequence diagrams.",
|
|
48622
|
-
hint: "Wrap free\u2011form text in a note block instead, for example:\nNote over A : Item 1\nNote over A\n - Item 1\n - Item 2\nend note",
|
|
48623
|
-
length: len
|
|
48624
|
-
};
|
|
48625
|
-
}
|
|
48626
48678
|
if (inRule("noteStmt")) {
|
|
48627
48679
|
if (err.name === "MismatchedTokenException" && exp("Colon")) {
|
|
48628
48680
|
return { line, column, severity: "error", code: "SE-NOTE-MALFORMED", message: "Malformed note: missing colon before the note text.", hint: "Example: Note right of Alice: Hello", length: len };
|
|
@@ -48631,6 +48683,22 @@ ${br.example}`,
|
|
|
48631
48683
|
return { line, column, severity: "error", code: "SE-NOTE-MALFORMED", message: "Malformed note statement. Use left|right of X or over X[,Y]: text", hint: "Examples: Note over A,B: hi", length: len };
|
|
48632
48684
|
}
|
|
48633
48685
|
}
|
|
48686
|
+
if ((err.name === "NoViableAltException" || err.name === "MismatchedTokenException") && tokType === "Minus") {
|
|
48687
|
+
const nonWs = ltxt.search(/\S/);
|
|
48688
|
+
const minusAtLineStart = nonWs >= 0 && ltxt[nonWs] === "-" && column === nonWs + 1;
|
|
48689
|
+
if (!minusAtLineStart) {
|
|
48690
|
+
} else {
|
|
48691
|
+
return {
|
|
48692
|
+
line,
|
|
48693
|
+
column,
|
|
48694
|
+
severity: "error",
|
|
48695
|
+
code: "SE-BULLET-LINE-UNSUPPORTED",
|
|
48696
|
+
message: "Bullet list lines starting with '-' are not supported in sequence diagrams.",
|
|
48697
|
+
hint: "Wrap free\u2011form text in a note block instead, for example:\nNote over A : Item 1\nNote over A\n - Item 1\n - Item 2\nend note",
|
|
48698
|
+
length: len
|
|
48699
|
+
};
|
|
48700
|
+
}
|
|
48701
|
+
}
|
|
48634
48702
|
if (tokType === "ElseKeyword" && isInRule(err, "criticalBlock")) {
|
|
48635
48703
|
return {
|
|
48636
48704
|
line,
|
|
@@ -49430,7 +49498,7 @@ var Identifier2, NumberLiteral3, SequenceKeyword, ParticipantKeyword, ActorKeywo
|
|
|
49430
49498
|
var init_lexer4 = __esm({
|
|
49431
49499
|
"node_modules/@probelabs/maid/out/diagrams/sequence/lexer.js"() {
|
|
49432
49500
|
init_api6();
|
|
49433
|
-
Identifier2 = createToken({ name: "Identifier", pattern: /[A-Za-z_][A-Za-z0-9_]*/ });
|
|
49501
|
+
Identifier2 = createToken({ name: "Identifier", pattern: /[A-Za-z_][A-Za-z0-9_.]*(?:-(?![>x)\s])[A-Za-z0-9_.]+)*/ });
|
|
49434
49502
|
NumberLiteral3 = createToken({ name: "NumberLiteral", pattern: /[0-9]+/ });
|
|
49435
49503
|
SequenceKeyword = createToken({ name: "SequenceKeyword", pattern: /sequenceDiagram/, longer_alt: Identifier2 });
|
|
49436
49504
|
ParticipantKeyword = createToken({ name: "ParticipantKeyword", pattern: /participant/i, longer_alt: Identifier2 });
|
|
@@ -51250,6 +51318,135 @@ var init_validate5 = __esm({
|
|
|
51250
51318
|
}
|
|
51251
51319
|
});
|
|
51252
51320
|
|
|
51321
|
+
// node_modules/@probelabs/maid/out/core/frontmatter.js
|
|
51322
|
+
function parseFrontmatter(input) {
|
|
51323
|
+
const text = input.startsWith("\uFEFF") ? input.slice(1) : input;
|
|
51324
|
+
const lines = text.split(/\r?\n/);
|
|
51325
|
+
if (lines.length < 3 || lines[0].trim() !== "---")
|
|
51326
|
+
return null;
|
|
51327
|
+
let i = 1;
|
|
51328
|
+
const block = [];
|
|
51329
|
+
while (i < lines.length && lines[i].trim() !== "---") {
|
|
51330
|
+
block.push(lines[i]);
|
|
51331
|
+
i++;
|
|
51332
|
+
}
|
|
51333
|
+
if (i >= lines.length)
|
|
51334
|
+
return null;
|
|
51335
|
+
const body = lines.slice(i + 1).join("\n");
|
|
51336
|
+
const bodyStartLine = i + 2;
|
|
51337
|
+
const raw = block.join("\n");
|
|
51338
|
+
const config2 = {};
|
|
51339
|
+
const themeVars = {};
|
|
51340
|
+
let themeUnderConfig = false;
|
|
51341
|
+
let ctx = "root";
|
|
51342
|
+
for (const line of block) {
|
|
51343
|
+
if (!line.trim())
|
|
51344
|
+
continue;
|
|
51345
|
+
const indent = line.match(/^\s*/)?.[0].length ?? 0;
|
|
51346
|
+
const mKey = line.match(/^\s*([A-Za-z0-9_\-]+):\s*(.*)$/);
|
|
51347
|
+
if (!mKey)
|
|
51348
|
+
continue;
|
|
51349
|
+
const key = mKey[1];
|
|
51350
|
+
let value = mKey[2] || "";
|
|
51351
|
+
if (indent === 0) {
|
|
51352
|
+
if (key === "config") {
|
|
51353
|
+
ctx = "config";
|
|
51354
|
+
continue;
|
|
51355
|
+
}
|
|
51356
|
+
if (key === "themeVariables") {
|
|
51357
|
+
ctx = "theme";
|
|
51358
|
+
continue;
|
|
51359
|
+
}
|
|
51360
|
+
ctx = "root";
|
|
51361
|
+
continue;
|
|
51362
|
+
}
|
|
51363
|
+
if (ctx === "config") {
|
|
51364
|
+
if (indent <= 2 && key !== "pie" && key !== "themeVariables")
|
|
51365
|
+
continue;
|
|
51366
|
+
if (key === "pie") {
|
|
51367
|
+
ctx = "config.pie";
|
|
51368
|
+
ensure(config2, "pie", {});
|
|
51369
|
+
continue;
|
|
51370
|
+
}
|
|
51371
|
+
if (key === "themeVariables") {
|
|
51372
|
+
ctx = "theme";
|
|
51373
|
+
themeUnderConfig = true;
|
|
51374
|
+
continue;
|
|
51375
|
+
}
|
|
51376
|
+
continue;
|
|
51377
|
+
}
|
|
51378
|
+
if (ctx === "config.pie") {
|
|
51379
|
+
if (indent < 4) {
|
|
51380
|
+
if (key === "pie") {
|
|
51381
|
+
ctx = "config.pie";
|
|
51382
|
+
ensure(config2, "pie", {});
|
|
51383
|
+
continue;
|
|
51384
|
+
}
|
|
51385
|
+
if (key === "themeVariables") {
|
|
51386
|
+
ctx = "theme";
|
|
51387
|
+
themeUnderConfig = true;
|
|
51388
|
+
continue;
|
|
51389
|
+
}
|
|
51390
|
+
ctx = "config";
|
|
51391
|
+
continue;
|
|
51392
|
+
}
|
|
51393
|
+
setKV(config2.pie, key, value);
|
|
51394
|
+
continue;
|
|
51395
|
+
}
|
|
51396
|
+
if (ctx === "theme") {
|
|
51397
|
+
if (indent < 2) {
|
|
51398
|
+
ctx = "root";
|
|
51399
|
+
continue;
|
|
51400
|
+
}
|
|
51401
|
+
setKV(themeVars, key, value);
|
|
51402
|
+
continue;
|
|
51403
|
+
}
|
|
51404
|
+
}
|
|
51405
|
+
if (themeUnderConfig && Object.keys(themeVars).length) {
|
|
51406
|
+
ensure(config2, "themeVariables", {});
|
|
51407
|
+
Object.assign(config2.themeVariables, themeVars);
|
|
51408
|
+
}
|
|
51409
|
+
return {
|
|
51410
|
+
raw,
|
|
51411
|
+
body,
|
|
51412
|
+
bodyStartLine,
|
|
51413
|
+
config: Object.keys(config2).length ? config2 : void 0,
|
|
51414
|
+
themeVariables: Object.keys(themeVars).length ? themeVars : void 0
|
|
51415
|
+
};
|
|
51416
|
+
}
|
|
51417
|
+
function ensure(obj, key, def) {
|
|
51418
|
+
if (obj[key] == null)
|
|
51419
|
+
obj[key] = def;
|
|
51420
|
+
}
|
|
51421
|
+
function unquote(val) {
|
|
51422
|
+
const v = val.trim();
|
|
51423
|
+
if (v.startsWith('"') && v.endsWith('"') || v.startsWith("'") && v.endsWith("'")) {
|
|
51424
|
+
return v.slice(1, -1);
|
|
51425
|
+
}
|
|
51426
|
+
return v;
|
|
51427
|
+
}
|
|
51428
|
+
function setKV(target, key, rawValue) {
|
|
51429
|
+
const v = unquote(rawValue);
|
|
51430
|
+
if (v === "") {
|
|
51431
|
+
target[key] = "";
|
|
51432
|
+
return;
|
|
51433
|
+
}
|
|
51434
|
+
const num = Number(v);
|
|
51435
|
+
if (!Number.isNaN(num) && /^-?[0-9]+(\.[0-9]+)?$/.test(v)) {
|
|
51436
|
+
target[key] = num;
|
|
51437
|
+
return;
|
|
51438
|
+
}
|
|
51439
|
+
if (/^(true|false)$/i.test(v)) {
|
|
51440
|
+
target[key] = /^true$/i.test(v);
|
|
51441
|
+
return;
|
|
51442
|
+
}
|
|
51443
|
+
target[key] = v;
|
|
51444
|
+
}
|
|
51445
|
+
var init_frontmatter = __esm({
|
|
51446
|
+
"node_modules/@probelabs/maid/out/core/frontmatter.js"() {
|
|
51447
|
+
}
|
|
51448
|
+
});
|
|
51449
|
+
|
|
51253
51450
|
// node_modules/@probelabs/maid/out/core/router.js
|
|
51254
51451
|
function firstNonCommentLine(text) {
|
|
51255
51452
|
const lines = text.split(/\r?\n/);
|
|
@@ -51264,7 +51461,8 @@ function firstNonCommentLine(text) {
|
|
|
51264
51461
|
return void 0;
|
|
51265
51462
|
}
|
|
51266
51463
|
function detectDiagramType(text) {
|
|
51267
|
-
const
|
|
51464
|
+
const { content } = stripFrontmatter(text);
|
|
51465
|
+
const header = firstNonCommentLine(content);
|
|
51268
51466
|
if (!header)
|
|
51269
51467
|
return "unknown";
|
|
51270
51468
|
if (/^(flowchart|graph)\b/i.test(header))
|
|
@@ -51316,20 +51514,26 @@ function isOtherMermaidDiagram(headerLine) {
|
|
|
51316
51514
|
return OTHER.has(t);
|
|
51317
51515
|
}
|
|
51318
51516
|
function validate(text, options = {}) {
|
|
51319
|
-
const
|
|
51517
|
+
const { content, lineOffset } = stripFrontmatter(text);
|
|
51518
|
+
const type = detectDiagramType(content);
|
|
51519
|
+
const withOffset = (errors) => {
|
|
51520
|
+
if (lineOffset === 0)
|
|
51521
|
+
return errors;
|
|
51522
|
+
return errors.map((e) => ({ ...e, line: Math.max(1, (e.line || 1) + lineOffset) }));
|
|
51523
|
+
};
|
|
51320
51524
|
switch (type) {
|
|
51321
51525
|
case "flowchart":
|
|
51322
|
-
return { type, errors: validateFlowchart(
|
|
51526
|
+
return { type, errors: withOffset(validateFlowchart(content, options)) };
|
|
51323
51527
|
case "pie":
|
|
51324
|
-
return { type, errors: validatePie(
|
|
51528
|
+
return { type, errors: withOffset(validatePie(content, options)) };
|
|
51325
51529
|
case "sequence":
|
|
51326
|
-
return { type, errors: validateSequence(
|
|
51530
|
+
return { type, errors: withOffset(validateSequence(content, options)) };
|
|
51327
51531
|
case "class":
|
|
51328
|
-
return { type, errors: validateClass(
|
|
51532
|
+
return { type, errors: withOffset(validateClass(content, options)) };
|
|
51329
51533
|
case "state":
|
|
51330
|
-
return { type, errors: validateState(
|
|
51534
|
+
return { type, errors: withOffset(validateState(content, options)) };
|
|
51331
51535
|
default:
|
|
51332
|
-
const header = firstNonCommentLine(
|
|
51536
|
+
const header = firstNonCommentLine(content);
|
|
51333
51537
|
if (isOtherMermaidDiagram(header)) {
|
|
51334
51538
|
return { type, errors: [] };
|
|
51335
51539
|
}
|
|
@@ -51337,7 +51541,7 @@ function validate(text, options = {}) {
|
|
|
51337
51541
|
type,
|
|
51338
51542
|
errors: [
|
|
51339
51543
|
{
|
|
51340
|
-
line: 1,
|
|
51544
|
+
line: lineOffset + 1,
|
|
51341
51545
|
column: 1,
|
|
51342
51546
|
message: 'Diagram must start with "graph", "flowchart", "pie", "sequenceDiagram", "classDiagram" or "stateDiagram[-v2]"',
|
|
51343
51547
|
severity: "error",
|
|
@@ -51348,6 +51552,12 @@ function validate(text, options = {}) {
|
|
|
51348
51552
|
};
|
|
51349
51553
|
}
|
|
51350
51554
|
}
|
|
51555
|
+
function stripFrontmatter(text) {
|
|
51556
|
+
const fm = parseFrontmatter(text);
|
|
51557
|
+
if (!fm)
|
|
51558
|
+
return { content: text, lineOffset: 0 };
|
|
51559
|
+
return { content: fm.body, lineOffset: fm.bodyStartLine - 1 };
|
|
51560
|
+
}
|
|
51351
51561
|
var init_router = __esm({
|
|
51352
51562
|
"node_modules/@probelabs/maid/out/core/router.js"() {
|
|
51353
51563
|
init_validate();
|
|
@@ -51355,6 +51565,7 @@ var init_router = __esm({
|
|
|
51355
51565
|
init_validate3();
|
|
51356
51566
|
init_validate4();
|
|
51357
51567
|
init_validate5();
|
|
51568
|
+
init_frontmatter();
|
|
51358
51569
|
}
|
|
51359
51570
|
});
|
|
51360
51571
|
|
|
@@ -51566,16 +51777,18 @@ function computeFixes(text, errors, level = "safe") {
|
|
|
51566
51777
|
}
|
|
51567
51778
|
continue;
|
|
51568
51779
|
}
|
|
51569
|
-
if (is("FL-EDGE-LABEL-BRACKET", e) || is("FL-EDGE-LABEL-CURLY-IN-PIPES", e)) {
|
|
51780
|
+
if (is("FL-EDGE-LABEL-BRACKET", e) || is("FL-EDGE-LABEL-CURLY-IN-PIPES", e) || is("FL-EDGE-LABEL-QUOTE-IN-PIPES", e)) {
|
|
51570
51781
|
const lineText = lineTextAt(text, e.line);
|
|
51571
|
-
const
|
|
51572
|
-
const
|
|
51782
|
+
const col = Math.max(0, e.column - 1);
|
|
51783
|
+
const firstBar = lineText.lastIndexOf("|", col);
|
|
51784
|
+
const secondBar = firstBar >= 0 ? lineText.indexOf("|", col + 1) : -1;
|
|
51573
51785
|
if (firstBar >= 0 && secondBar > firstBar) {
|
|
51574
51786
|
const before = lineText.slice(0, firstBar + 1);
|
|
51575
51787
|
const label = lineText.slice(firstBar + 1, secondBar);
|
|
51576
51788
|
const after = lineText.slice(secondBar);
|
|
51577
51789
|
let fixedLabel = label.replace(/\[/g, "[").replace(/\]/g, "]");
|
|
51578
51790
|
fixedLabel = fixedLabel.replace(/\{/g, "{").replace(/\}/g, "}");
|
|
51791
|
+
fixedLabel = fixedLabel.replace(/\\"/g, """).replace(/"/g, """);
|
|
51579
51792
|
const fixedLine = before + fixedLabel + after;
|
|
51580
51793
|
const finalLine = fixedLine.replace(/\[([^\]]*)\]/g, (m, seg) => "[" + String(seg).replace(/`/g, "") + "]");
|
|
51581
51794
|
edits.push({ start: { line: e.line, column: 1 }, end: { line: e.line, column: lineText.length + 1 }, newText: finalLine });
|
|
@@ -62965,7 +63178,7 @@ ${overlay}</g>`;
|
|
|
62965
63178
|
});
|
|
62966
63179
|
|
|
62967
63180
|
// node_modules/@probelabs/maid/out/renderer/pie-builder.js
|
|
62968
|
-
function
|
|
63181
|
+
function unquote2(s) {
|
|
62969
63182
|
if (!s)
|
|
62970
63183
|
return s;
|
|
62971
63184
|
const first2 = s.charAt(0);
|
|
@@ -63015,7 +63228,7 @@ function buildPieModel(text) {
|
|
|
63015
63228
|
const collect = (k) => {
|
|
63016
63229
|
const arr = tnode.children?.[k] ?? [];
|
|
63017
63230
|
for (const tok of arr)
|
|
63018
|
-
parts.push(
|
|
63231
|
+
parts.push(unquote2(tok.image));
|
|
63019
63232
|
};
|
|
63020
63233
|
collect("QuotedString");
|
|
63021
63234
|
collect("Text");
|
|
@@ -63028,7 +63241,7 @@ function buildPieModel(text) {
|
|
|
63028
63241
|
const labelTok = snode.children?.sliceLabel?.[0]?.children?.QuotedString?.[0];
|
|
63029
63242
|
const numTok = snode.children?.NumberLiteral?.[0];
|
|
63030
63243
|
if (labelTok && numTok) {
|
|
63031
|
-
const label =
|
|
63244
|
+
const label = unquote2(labelTok.image).trim();
|
|
63032
63245
|
const value = Number(numTok.image);
|
|
63033
63246
|
if (!Number.isNaN(value)) {
|
|
63034
63247
|
model.slices.push({ label, value });
|
|
@@ -64184,128 +64397,6 @@ var init_state_renderer = __esm({
|
|
|
64184
64397
|
}
|
|
64185
64398
|
});
|
|
64186
64399
|
|
|
64187
|
-
// node_modules/@probelabs/maid/out/core/frontmatter.js
|
|
64188
|
-
function parseFrontmatter(input) {
|
|
64189
|
-
const text = input.startsWith("\uFEFF") ? input.slice(1) : input;
|
|
64190
|
-
const lines = text.split(/\r?\n/);
|
|
64191
|
-
if (lines.length < 3 || lines[0].trim() !== "---")
|
|
64192
|
-
return null;
|
|
64193
|
-
let i = 1;
|
|
64194
|
-
const block = [];
|
|
64195
|
-
while (i < lines.length && lines[i].trim() !== "---") {
|
|
64196
|
-
block.push(lines[i]);
|
|
64197
|
-
i++;
|
|
64198
|
-
}
|
|
64199
|
-
if (i >= lines.length)
|
|
64200
|
-
return null;
|
|
64201
|
-
const body = lines.slice(i + 1).join("\n");
|
|
64202
|
-
const raw = block.join("\n");
|
|
64203
|
-
const config2 = {};
|
|
64204
|
-
const themeVars = {};
|
|
64205
|
-
let themeUnderConfig = false;
|
|
64206
|
-
let ctx = "root";
|
|
64207
|
-
for (const line of block) {
|
|
64208
|
-
if (!line.trim())
|
|
64209
|
-
continue;
|
|
64210
|
-
const indent = line.match(/^\s*/)?.[0].length ?? 0;
|
|
64211
|
-
const mKey = line.match(/^\s*([A-Za-z0-9_\-]+):\s*(.*)$/);
|
|
64212
|
-
if (!mKey)
|
|
64213
|
-
continue;
|
|
64214
|
-
const key = mKey[1];
|
|
64215
|
-
let value = mKey[2] || "";
|
|
64216
|
-
if (indent === 0) {
|
|
64217
|
-
if (key === "config") {
|
|
64218
|
-
ctx = "config";
|
|
64219
|
-
continue;
|
|
64220
|
-
}
|
|
64221
|
-
if (key === "themeVariables") {
|
|
64222
|
-
ctx = "theme";
|
|
64223
|
-
continue;
|
|
64224
|
-
}
|
|
64225
|
-
ctx = "root";
|
|
64226
|
-
continue;
|
|
64227
|
-
}
|
|
64228
|
-
if (ctx === "config") {
|
|
64229
|
-
if (indent <= 2 && key !== "pie" && key !== "themeVariables")
|
|
64230
|
-
continue;
|
|
64231
|
-
if (key === "pie") {
|
|
64232
|
-
ctx = "config.pie";
|
|
64233
|
-
ensure(config2, "pie", {});
|
|
64234
|
-
continue;
|
|
64235
|
-
}
|
|
64236
|
-
if (key === "themeVariables") {
|
|
64237
|
-
ctx = "theme";
|
|
64238
|
-
themeUnderConfig = true;
|
|
64239
|
-
continue;
|
|
64240
|
-
}
|
|
64241
|
-
continue;
|
|
64242
|
-
}
|
|
64243
|
-
if (ctx === "config.pie") {
|
|
64244
|
-
if (indent < 4) {
|
|
64245
|
-
if (key === "pie") {
|
|
64246
|
-
ctx = "config.pie";
|
|
64247
|
-
ensure(config2, "pie", {});
|
|
64248
|
-
continue;
|
|
64249
|
-
}
|
|
64250
|
-
if (key === "themeVariables") {
|
|
64251
|
-
ctx = "theme";
|
|
64252
|
-
themeUnderConfig = true;
|
|
64253
|
-
continue;
|
|
64254
|
-
}
|
|
64255
|
-
ctx = "config";
|
|
64256
|
-
continue;
|
|
64257
|
-
}
|
|
64258
|
-
setKV(config2.pie, key, value);
|
|
64259
|
-
continue;
|
|
64260
|
-
}
|
|
64261
|
-
if (ctx === "theme") {
|
|
64262
|
-
if (indent < 2) {
|
|
64263
|
-
ctx = "root";
|
|
64264
|
-
continue;
|
|
64265
|
-
}
|
|
64266
|
-
setKV(themeVars, key, value);
|
|
64267
|
-
continue;
|
|
64268
|
-
}
|
|
64269
|
-
}
|
|
64270
|
-
if (themeUnderConfig && Object.keys(themeVars).length) {
|
|
64271
|
-
ensure(config2, "themeVariables", {});
|
|
64272
|
-
Object.assign(config2.themeVariables, themeVars);
|
|
64273
|
-
}
|
|
64274
|
-
return { raw, body, config: Object.keys(config2).length ? config2 : void 0, themeVariables: Object.keys(themeVars).length ? themeVars : void 0 };
|
|
64275
|
-
}
|
|
64276
|
-
function ensure(obj, key, def) {
|
|
64277
|
-
if (obj[key] == null)
|
|
64278
|
-
obj[key] = def;
|
|
64279
|
-
}
|
|
64280
|
-
function unquote2(val) {
|
|
64281
|
-
const v = val.trim();
|
|
64282
|
-
if (v.startsWith('"') && v.endsWith('"') || v.startsWith("'") && v.endsWith("'")) {
|
|
64283
|
-
return v.slice(1, -1);
|
|
64284
|
-
}
|
|
64285
|
-
return v;
|
|
64286
|
-
}
|
|
64287
|
-
function setKV(target, key, rawValue) {
|
|
64288
|
-
const v = unquote2(rawValue);
|
|
64289
|
-
if (v === "") {
|
|
64290
|
-
target[key] = "";
|
|
64291
|
-
return;
|
|
64292
|
-
}
|
|
64293
|
-
const num = Number(v);
|
|
64294
|
-
if (!Number.isNaN(num) && /^-?[0-9]+(\.[0-9]+)?$/.test(v)) {
|
|
64295
|
-
target[key] = num;
|
|
64296
|
-
return;
|
|
64297
|
-
}
|
|
64298
|
-
if (/^(true|false)$/i.test(v)) {
|
|
64299
|
-
target[key] = /^true$/i.test(v);
|
|
64300
|
-
return;
|
|
64301
|
-
}
|
|
64302
|
-
target[key] = v;
|
|
64303
|
-
}
|
|
64304
|
-
var init_frontmatter = __esm({
|
|
64305
|
-
"node_modules/@probelabs/maid/out/core/frontmatter.js"() {
|
|
64306
|
-
}
|
|
64307
|
-
});
|
|
64308
|
-
|
|
64309
64400
|
// node_modules/@probelabs/maid/out/renderer/class-builder.js
|
|
64310
64401
|
function textFromTokens3(tokens) {
|
|
64311
64402
|
if (!tokens || tokens.length === 0)
|
|
@@ -73542,6 +73633,9 @@ function isMethodAllowed(methodName, allowedMethods, blockedMethods) {
|
|
|
73542
73633
|
}
|
|
73543
73634
|
function createTransport(serverConfig) {
|
|
73544
73635
|
const { transport, command, args, url: url2, env } = serverConfig;
|
|
73636
|
+
if (serverConfig.transportInstance) {
|
|
73637
|
+
return serverConfig.transportInstance;
|
|
73638
|
+
}
|
|
73545
73639
|
switch (transport) {
|
|
73546
73640
|
case "stdio":
|
|
73547
73641
|
return new import_stdio.StdioClientTransport({
|
|
@@ -73625,6 +73719,7 @@ var init_client = __esm({
|
|
|
73625
73719
|
this.debug = options.debug || process.env.DEBUG_MCP === "1";
|
|
73626
73720
|
this.config = null;
|
|
73627
73721
|
this.tracer = options.tracer || null;
|
|
73722
|
+
this.agentEvents = options.agentEvents || null;
|
|
73628
73723
|
}
|
|
73629
73724
|
/**
|
|
73630
73725
|
* Record an MCP telemetry event if tracer is available
|
|
@@ -73852,11 +73947,21 @@ var init_client = __esm({
|
|
|
73852
73947
|
throw new Error(`Server ${tool6.serverName} not connected`);
|
|
73853
73948
|
}
|
|
73854
73949
|
const startTime = Date.now();
|
|
73950
|
+
const toolCallId = `mcp-${toolName}-${startTime}`;
|
|
73855
73951
|
this.recordMcpEvent("tool.call_started", {
|
|
73856
73952
|
toolName,
|
|
73857
73953
|
serverName: tool6.serverName,
|
|
73858
73954
|
originalToolName: tool6.originalName
|
|
73859
73955
|
});
|
|
73956
|
+
if (this.agentEvents) {
|
|
73957
|
+
this.agentEvents.emit("toolCall", {
|
|
73958
|
+
toolCallId,
|
|
73959
|
+
name: toolName,
|
|
73960
|
+
args,
|
|
73961
|
+
status: "started",
|
|
73962
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
73963
|
+
});
|
|
73964
|
+
}
|
|
73860
73965
|
try {
|
|
73861
73966
|
if (this.debug) {
|
|
73862
73967
|
console.error(`[MCP DEBUG] Calling ${toolName} with args:`, JSON.stringify(args, null, 2));
|
|
@@ -73886,6 +73991,14 @@ var init_client = __esm({
|
|
|
73886
73991
|
originalToolName: tool6.originalName,
|
|
73887
73992
|
durationMs
|
|
73888
73993
|
});
|
|
73994
|
+
if (this.agentEvents) {
|
|
73995
|
+
this.agentEvents.emit("toolCall", {
|
|
73996
|
+
toolCallId,
|
|
73997
|
+
name: toolName,
|
|
73998
|
+
status: "completed",
|
|
73999
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
74000
|
+
});
|
|
74001
|
+
}
|
|
73889
74002
|
return result;
|
|
73890
74003
|
} catch (error40) {
|
|
73891
74004
|
const durationMs = Date.now() - startTime;
|
|
@@ -73901,9 +74014,64 @@ var init_client = __esm({
|
|
|
73901
74014
|
durationMs,
|
|
73902
74015
|
isTimeout: error40.message.includes("timeout")
|
|
73903
74016
|
});
|
|
74017
|
+
if (this.agentEvents) {
|
|
74018
|
+
this.agentEvents.emit("toolCall", {
|
|
74019
|
+
toolCallId,
|
|
74020
|
+
name: toolName,
|
|
74021
|
+
status: "error",
|
|
74022
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
74023
|
+
});
|
|
74024
|
+
}
|
|
73904
74025
|
throw error40;
|
|
73905
74026
|
}
|
|
73906
74027
|
}
|
|
74028
|
+
/**
|
|
74029
|
+
* Call graceful_stop on all MCP servers that expose it.
|
|
74030
|
+
* This signals agent-type MCP servers to wrap up their work.
|
|
74031
|
+
* @returns {Promise<Array<{server: string, success: boolean, error?: string}>>}
|
|
74032
|
+
*/
|
|
74033
|
+
async callGracefulStopAll() {
|
|
74034
|
+
const results = [];
|
|
74035
|
+
for (const [serverName, clientInfo] of this.clients) {
|
|
74036
|
+
const qualifiedName = `${serverName}_graceful_stop`;
|
|
74037
|
+
if (this.tools.has(qualifiedName)) {
|
|
74038
|
+
if (this.debug) {
|
|
74039
|
+
console.log(`[DEBUG] MCP callGracefulStopAll: calling graceful_stop on server "${serverName}"`);
|
|
74040
|
+
}
|
|
74041
|
+
try {
|
|
74042
|
+
const timeoutMs = 5e3;
|
|
74043
|
+
const timeoutPromise = new Promise(
|
|
74044
|
+
(_, reject2) => setTimeout(() => reject2(new Error("graceful_stop timeout")), timeoutMs)
|
|
74045
|
+
);
|
|
74046
|
+
await Promise.race([
|
|
74047
|
+
clientInfo.client.callTool({ name: "graceful_stop", arguments: {} }, void 0, { timeout: timeoutMs }),
|
|
74048
|
+
timeoutPromise
|
|
74049
|
+
]);
|
|
74050
|
+
results.push({ server: serverName, success: true });
|
|
74051
|
+
if (this.debug) {
|
|
74052
|
+
console.log(`[DEBUG] MCP callGracefulStopAll: server "${serverName}" acknowledged graceful_stop`);
|
|
74053
|
+
}
|
|
74054
|
+
} catch (e) {
|
|
74055
|
+
results.push({ server: serverName, success: false, error: e.message });
|
|
74056
|
+
if (this.debug) {
|
|
74057
|
+
console.log(`[DEBUG] MCP callGracefulStopAll: server "${serverName}" graceful_stop failed: ${e.message}`);
|
|
74058
|
+
}
|
|
74059
|
+
}
|
|
74060
|
+
}
|
|
74061
|
+
}
|
|
74062
|
+
if (this.debug) {
|
|
74063
|
+
const withStop = results.length;
|
|
74064
|
+
const total = this.clients.size;
|
|
74065
|
+
console.log(`[DEBUG] MCP callGracefulStopAll: ${withStop}/${total} servers had graceful_stop tool`);
|
|
74066
|
+
}
|
|
74067
|
+
this.recordMcpEvent("graceful_stop.sweep_completed", {
|
|
74068
|
+
servers_total: this.clients.size,
|
|
74069
|
+
servers_with_graceful_stop: results.length,
|
|
74070
|
+
servers_acknowledged: results.filter((r) => r.success).length,
|
|
74071
|
+
servers_failed: results.filter((r) => !r.success).length
|
|
74072
|
+
});
|
|
74073
|
+
return results;
|
|
74074
|
+
}
|
|
73907
74075
|
/**
|
|
73908
74076
|
* Get all available tools with their schemas
|
|
73909
74077
|
* @returns {Object} Map of tool name to tool definition
|
|
@@ -73931,10 +74099,29 @@ var init_client = __esm({
|
|
|
73931
74099
|
inputSchema: tool6.inputSchema,
|
|
73932
74100
|
execute: async (args) => {
|
|
73933
74101
|
const result = await this.callTool(name15, args);
|
|
73934
|
-
if (result.content
|
|
73935
|
-
return result
|
|
74102
|
+
if (!result.content || !result.content[0]) {
|
|
74103
|
+
return JSON.stringify(result);
|
|
74104
|
+
}
|
|
74105
|
+
const hasImage = result.content.some((block) => block.type === "image");
|
|
74106
|
+
if (hasImage) {
|
|
74107
|
+
return { _mcpContent: result.content };
|
|
74108
|
+
}
|
|
74109
|
+
return result.content[0].text;
|
|
74110
|
+
},
|
|
74111
|
+
// Convert MCP content blocks (including images) to Vercel AI SDK format
|
|
74112
|
+
toModelOutput: ({ output }) => {
|
|
74113
|
+
if (output && typeof output === "object" && output._mcpContent) {
|
|
74114
|
+
const parts = [];
|
|
74115
|
+
for (const block of output._mcpContent) {
|
|
74116
|
+
if (block.type === "text") {
|
|
74117
|
+
parts.push({ type: "text", text: block.text });
|
|
74118
|
+
} else if (block.type === "image") {
|
|
74119
|
+
parts.push({ type: "image-data", data: block.data, mediaType: block.mimeType });
|
|
74120
|
+
}
|
|
74121
|
+
}
|
|
74122
|
+
return { type: "content", value: parts };
|
|
73936
74123
|
}
|
|
73937
|
-
return JSON.stringify(
|
|
74124
|
+
return { type: "text", value: typeof output === "string" ? output : JSON.stringify(output) };
|
|
73938
74125
|
}
|
|
73939
74126
|
};
|
|
73940
74127
|
}
|
|
@@ -74020,6 +74207,7 @@ var init_xmlBridge = __esm({
|
|
|
74020
74207
|
constructor(options = {}) {
|
|
74021
74208
|
this.debug = options.debug || false;
|
|
74022
74209
|
this.tracer = options.tracer || null;
|
|
74210
|
+
this.agentEvents = options.agentEvents || null;
|
|
74023
74211
|
this.mcpTools = {};
|
|
74024
74212
|
this.mcpManager = null;
|
|
74025
74213
|
this.toolDescriptions = {};
|
|
@@ -74062,7 +74250,7 @@ var init_xmlBridge = __esm({
|
|
|
74062
74250
|
if (this.debug) {
|
|
74063
74251
|
console.error("[MCP DEBUG] Initializing MCP client manager...");
|
|
74064
74252
|
}
|
|
74065
|
-
this.mcpManager = new MCPClientManager({ debug: this.debug, tracer: this.tracer });
|
|
74253
|
+
this.mcpManager = new MCPClientManager({ debug: this.debug, tracer: this.tracer, agentEvents: this.agentEvents });
|
|
74066
74254
|
const result = await this.mcpManager.initialize(mcpConfigs);
|
|
74067
74255
|
const vercelTools = this.mcpManager.getVercelTools();
|
|
74068
74256
|
this.mcpTools = vercelTools;
|
|
@@ -74114,6 +74302,16 @@ var init_xmlBridge = __esm({
|
|
|
74114
74302
|
isMcpTool(toolName) {
|
|
74115
74303
|
return toolName in this.mcpTools;
|
|
74116
74304
|
}
|
|
74305
|
+
/**
|
|
74306
|
+
* Call graceful_stop on all MCP servers that expose it.
|
|
74307
|
+
* @returns {Promise<Array>}
|
|
74308
|
+
*/
|
|
74309
|
+
async callGracefulStopAll() {
|
|
74310
|
+
if (this.mcpManager) {
|
|
74311
|
+
return this.mcpManager.callGracefulStopAll();
|
|
74312
|
+
}
|
|
74313
|
+
return [];
|
|
74314
|
+
}
|
|
74117
74315
|
/**
|
|
74118
74316
|
* Clean up MCP connections
|
|
74119
74317
|
*/
|
|
@@ -81499,7 +81697,7 @@ function deriveDescription(rawDescription, body) {
|
|
|
81499
81697
|
}
|
|
81500
81698
|
return truncateDescription(description);
|
|
81501
81699
|
}
|
|
81502
|
-
function
|
|
81700
|
+
function stripFrontmatter2(content) {
|
|
81503
81701
|
const { body } = extractFrontmatter(content);
|
|
81504
81702
|
return body.trim();
|
|
81505
81703
|
}
|
|
@@ -81640,7 +81838,7 @@ var init_registry = __esm({
|
|
|
81640
81838
|
const skill = this.skillsByName.get(name15);
|
|
81641
81839
|
if (!skill) return null;
|
|
81642
81840
|
const content = await (0, import_promises3.readFile)(skill.skillFilePath, "utf8");
|
|
81643
|
-
return
|
|
81841
|
+
return stripFrontmatter2(content);
|
|
81644
81842
|
}
|
|
81645
81843
|
async _resolveRealPath(target) {
|
|
81646
81844
|
try {
|
|
@@ -96673,6 +96871,7 @@ var init_ProbeAgent = __esm({
|
|
|
96673
96871
|
this.debug = options.debug || process.env.DEBUG === "1";
|
|
96674
96872
|
this.cancelled = false;
|
|
96675
96873
|
this._abortController = new AbortController();
|
|
96874
|
+
this._activeSubagents = /* @__PURE__ */ new Map();
|
|
96676
96875
|
this.tracer = options.tracer || null;
|
|
96677
96876
|
this.outline = !!options.outline;
|
|
96678
96877
|
this.searchDelegate = options.searchDelegate !== void 0 ? !!options.searchDelegate : true;
|
|
@@ -96784,14 +96983,31 @@ var init_ProbeAgent = __esm({
|
|
|
96784
96983
|
this.timeoutBehavior = options.timeoutBehavior ?? (() => {
|
|
96785
96984
|
const val = process.env.TIMEOUT_BEHAVIOR;
|
|
96786
96985
|
if (val === "hard") return "hard";
|
|
96986
|
+
if (val === "negotiated") return "negotiated";
|
|
96787
96987
|
return "graceful";
|
|
96788
96988
|
})();
|
|
96789
96989
|
this.gracefulTimeoutBonusSteps = options.gracefulTimeoutBonusSteps ?? (() => {
|
|
96790
96990
|
const parsed = parseInt(process.env.GRACEFUL_TIMEOUT_BONUS_STEPS, 10);
|
|
96791
96991
|
return isNaN(parsed) || parsed < 1 || parsed > 20 ? 4 : parsed;
|
|
96792
96992
|
})();
|
|
96993
|
+
this.negotiatedTimeoutBudget = options.negotiatedTimeoutBudget ?? (() => {
|
|
96994
|
+
const parsed = parseInt(process.env.NEGOTIATED_TIMEOUT_BUDGET, 10);
|
|
96995
|
+
return isNaN(parsed) || parsed < 6e4 || parsed > 72e5 ? 18e5 : parsed;
|
|
96996
|
+
})();
|
|
96997
|
+
this.negotiatedTimeoutMaxRequests = options.negotiatedTimeoutMaxRequests ?? (() => {
|
|
96998
|
+
const parsed = parseInt(process.env.NEGOTIATED_TIMEOUT_MAX_REQUESTS, 10);
|
|
96999
|
+
return isNaN(parsed) || parsed < 1 || parsed > 10 ? 3 : parsed;
|
|
97000
|
+
})();
|
|
97001
|
+
this.negotiatedTimeoutMaxPerRequest = options.negotiatedTimeoutMaxPerRequest ?? (() => {
|
|
97002
|
+
const parsed = parseInt(process.env.NEGOTIATED_TIMEOUT_MAX_PER_REQUEST, 10);
|
|
97003
|
+
return isNaN(parsed) || parsed < 6e4 || parsed > 36e5 ? 6e5 : parsed;
|
|
97004
|
+
})();
|
|
97005
|
+
this.gracefulStopDeadline = options.gracefulStopDeadline ?? (() => {
|
|
97006
|
+
const parsed = parseInt(process.env.GRACEFUL_STOP_DEADLINE, 10);
|
|
97007
|
+
return isNaN(parsed) || parsed < 5e3 || parsed > 3e5 ? 45e3 : parsed;
|
|
97008
|
+
})();
|
|
96793
97009
|
if (this.debug) {
|
|
96794
|
-
console.log(`[DEBUG] Timeout behavior: ${this.timeoutBehavior}, bonus steps: ${this.gracefulTimeoutBonusSteps}`);
|
|
97010
|
+
console.log(`[DEBUG] Timeout behavior: ${this.timeoutBehavior}, bonus steps: ${this.gracefulTimeoutBonusSteps}, graceful stop deadline: ${this.gracefulStopDeadline}ms`);
|
|
96795
97011
|
}
|
|
96796
97012
|
this.retryConfig = options.retry || {};
|
|
96797
97013
|
this.retryManager = null;
|
|
@@ -97143,6 +97359,18 @@ var init_ProbeAgent = __esm({
|
|
|
97143
97359
|
// Per-instance delegation limits
|
|
97144
97360
|
parentAbortSignal: this._abortController.signal,
|
|
97145
97361
|
// Propagate cancellation to delegations
|
|
97362
|
+
// Timeout settings for delegate subagents to inherit
|
|
97363
|
+
timeoutBehavior: this.timeoutBehavior,
|
|
97364
|
+
maxOperationTimeout: this.maxOperationTimeout,
|
|
97365
|
+
requestTimeout: this.requestTimeout,
|
|
97366
|
+
gracefulTimeoutBonusSteps: this.gracefulTimeoutBonusSteps,
|
|
97367
|
+
negotiatedTimeoutBudget: this.negotiatedTimeoutBudget,
|
|
97368
|
+
negotiatedTimeoutMaxRequests: this.negotiatedTimeoutMaxRequests,
|
|
97369
|
+
negotiatedTimeoutMaxPerRequest: this.negotiatedTimeoutMaxPerRequest,
|
|
97370
|
+
parentOperationStartTime: this._operationStartTime,
|
|
97371
|
+
// For remaining budget calculation
|
|
97372
|
+
onSubagentCreated: (sid, subagent) => this._registerSubagent(sid, subagent),
|
|
97373
|
+
onSubagentCompleted: (sid) => this._unregisterSubagent(sid),
|
|
97146
97374
|
outputBuffer: this._outputBuffer,
|
|
97147
97375
|
concurrencyLimiter: this.concurrencyLimiter,
|
|
97148
97376
|
// Global AI concurrency limiter
|
|
@@ -97727,7 +97955,7 @@ var init_ProbeAgent = __esm({
|
|
|
97727
97955
|
}
|
|
97728
97956
|
if (this.maxOperationTimeout && this.maxOperationTimeout > 0) {
|
|
97729
97957
|
const gts = this._gracefulTimeoutState;
|
|
97730
|
-
if (this.timeoutBehavior === "graceful" && gts) {
|
|
97958
|
+
if ((this.timeoutBehavior === "graceful" || this.timeoutBehavior === "negotiated") && gts) {
|
|
97731
97959
|
} else {
|
|
97732
97960
|
timeoutState.timeoutId = setTimeout(() => {
|
|
97733
97961
|
controller.abort();
|
|
@@ -98631,7 +98859,7 @@ var init_ProbeAgent = __esm({
|
|
|
98631
98859
|
}
|
|
98632
98860
|
mcpConfig = null;
|
|
98633
98861
|
}
|
|
98634
|
-
this.mcpBridge = new MCPXmlBridge({ debug: this.debug });
|
|
98862
|
+
this.mcpBridge = new MCPXmlBridge({ debug: this.debug, agentEvents: this.events });
|
|
98635
98863
|
await this.mcpBridge.initialize(mcpConfig);
|
|
98636
98864
|
const mcpToolNames = this.mcpBridge.getToolNames();
|
|
98637
98865
|
const mcpToolCount = mcpToolNames.length;
|
|
@@ -99114,6 +99342,7 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
99114
99342
|
} else {
|
|
99115
99343
|
options = schemaOrOptions || {};
|
|
99116
99344
|
}
|
|
99345
|
+
this._operationStartTime = Date.now();
|
|
99117
99346
|
try {
|
|
99118
99347
|
const oldHistoryLength = this.history.length;
|
|
99119
99348
|
if (this._outputBuffer && !options?._schemaFormatted && !options?._completionPromptProcessed) {
|
|
@@ -99194,7 +99423,10 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
99194
99423
|
}
|
|
99195
99424
|
}
|
|
99196
99425
|
let currentIteration = 0;
|
|
99197
|
-
let finalResult =
|
|
99426
|
+
let finalResult = null;
|
|
99427
|
+
const DEFAULT_MAX_ITER_MSG = "I was unable to complete your request due to reaching the maximum number of tool iterations.";
|
|
99428
|
+
const _toolCallLog = [];
|
|
99429
|
+
let abortSummaryTaken = false;
|
|
99198
99430
|
const baseMaxIterations = options._maxIterationsOverride || this.maxIterations || MAX_TOOL_ITERATIONS;
|
|
99199
99431
|
const maxIterations = options._maxIterationsOverride ? baseMaxIterations : options.schema ? baseMaxIterations + 4 : baseMaxIterations;
|
|
99200
99432
|
const isClaudeCode = this.clientApiProvider === "claude-code" || process.env.USE_CLAUDE_CODE === "true";
|
|
@@ -99334,6 +99566,233 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
99334
99566
|
bonusStepsMax: this.gracefulTimeoutBonusSteps
|
|
99335
99567
|
};
|
|
99336
99568
|
this._gracefulTimeoutState = gracefulTimeoutState;
|
|
99569
|
+
const negotiatedTimeoutState = {
|
|
99570
|
+
extensionsUsed: 0,
|
|
99571
|
+
totalExtraTimeMs: 0,
|
|
99572
|
+
softTimeoutId: null,
|
|
99573
|
+
hardAbortTimeoutId: null,
|
|
99574
|
+
maxRequests: this.negotiatedTimeoutMaxRequests,
|
|
99575
|
+
maxPerRequestMs: this.negotiatedTimeoutMaxPerRequest,
|
|
99576
|
+
budgetMs: this.negotiatedTimeoutBudget,
|
|
99577
|
+
observerRunning: false,
|
|
99578
|
+
// true while observer LLM call is in flight
|
|
99579
|
+
extensionMessage: null,
|
|
99580
|
+
// message to show in prepareStep after extension granted
|
|
99581
|
+
startTime: Date.now()
|
|
99582
|
+
};
|
|
99583
|
+
this._negotiatedTimeoutState = negotiatedTimeoutState;
|
|
99584
|
+
const activeTools = /* @__PURE__ */ new Map();
|
|
99585
|
+
this._activeTools = activeTools;
|
|
99586
|
+
const onToolCall = (event) => {
|
|
99587
|
+
const key = event.toolCallId || `${event.name}:${JSON.stringify(event.args || {}).slice(0, 100)}`;
|
|
99588
|
+
if (event.status === "started") {
|
|
99589
|
+
activeTools.set(key, {
|
|
99590
|
+
name: event.name,
|
|
99591
|
+
args: event.args,
|
|
99592
|
+
startedAt: event.timestamp || (/* @__PURE__ */ new Date()).toISOString()
|
|
99593
|
+
});
|
|
99594
|
+
} else if (event.status === "completed" || event.status === "error") {
|
|
99595
|
+
activeTools.delete(key);
|
|
99596
|
+
}
|
|
99597
|
+
};
|
|
99598
|
+
this.events.on("toolCall", onToolCall);
|
|
99599
|
+
const runTimeoutObserver = async () => {
|
|
99600
|
+
if (negotiatedTimeoutState.observerRunning) return;
|
|
99601
|
+
negotiatedTimeoutState.observerRunning = true;
|
|
99602
|
+
const remainingRequests = negotiatedTimeoutState.maxRequests - negotiatedTimeoutState.extensionsUsed;
|
|
99603
|
+
const remainingBudgetMs = negotiatedTimeoutState.budgetMs - negotiatedTimeoutState.totalExtraTimeMs;
|
|
99604
|
+
const maxPerReqMin = Math.round(negotiatedTimeoutState.maxPerRequestMs / 6e4);
|
|
99605
|
+
const elapsedMin = Math.round((Date.now() - negotiatedTimeoutState.startTime) / 6e4);
|
|
99606
|
+
if (remainingRequests <= 0 || remainingBudgetMs <= 0) {
|
|
99607
|
+
if (this.debug) {
|
|
99608
|
+
console.log(`[DEBUG] Timeout observer: no extensions/budget remaining \u2014 aborting in-flight tools and triggering graceful wind-down`);
|
|
99609
|
+
}
|
|
99610
|
+
if (this.tracer) {
|
|
99611
|
+
this.tracer.addEvent("negotiated_timeout.observer_exhausted", {
|
|
99612
|
+
extensions_used: negotiatedTimeoutState.extensionsUsed,
|
|
99613
|
+
max_requests: negotiatedTimeoutState.maxRequests,
|
|
99614
|
+
total_extra_time_ms: negotiatedTimeoutState.totalExtraTimeMs,
|
|
99615
|
+
budget_ms: negotiatedTimeoutState.budgetMs,
|
|
99616
|
+
elapsed_min: elapsedMin,
|
|
99617
|
+
active_tools: Array.from(activeTools.values()).map((t) => t.name)
|
|
99618
|
+
});
|
|
99619
|
+
}
|
|
99620
|
+
await this._initiateGracefulStop(gracefulTimeoutState, "budget/extensions exhausted");
|
|
99621
|
+
negotiatedTimeoutState.observerRunning = false;
|
|
99622
|
+
return;
|
|
99623
|
+
}
|
|
99624
|
+
const activeToolsList = Array.from(activeTools.values());
|
|
99625
|
+
const now = Date.now();
|
|
99626
|
+
const formatDuration = (ms) => {
|
|
99627
|
+
const totalSec = Math.round(ms / 1e3);
|
|
99628
|
+
if (totalSec < 60) return `${totalSec}s`;
|
|
99629
|
+
const min = Math.floor(totalSec / 60);
|
|
99630
|
+
const sec = totalSec % 60;
|
|
99631
|
+
if (min < 60) return `${min}m ${sec}s`;
|
|
99632
|
+
const hr = Math.floor(min / 60);
|
|
99633
|
+
const remainMin = min % 60;
|
|
99634
|
+
return `${hr}h ${remainMin}m`;
|
|
99635
|
+
};
|
|
99636
|
+
const activeToolsDesc = activeToolsList.length > 0 ? activeToolsList.map((t) => {
|
|
99637
|
+
const runningForMs = now - new Date(t.startedAt).getTime();
|
|
99638
|
+
return `- ${t.name}(${JSON.stringify(t.args || {}).slice(0, 200)}) \u2014 running for ${formatDuration(runningForMs)}`;
|
|
99639
|
+
}).join("\n") : "(none currently running)";
|
|
99640
|
+
const recentHistory = this.history.slice(-6).map((msg) => {
|
|
99641
|
+
const content = typeof msg.content === "string" ? msg.content.slice(0, 300) : JSON.stringify(msg.content).slice(0, 300);
|
|
99642
|
+
return `[${msg.role}]: ${content}`;
|
|
99643
|
+
}).join("\n");
|
|
99644
|
+
const observerPrompt = `You are a timeout observer for an AI coding agent. The agent has been working for ${elapsedMin} minute(s) and has reached its time limit.
|
|
99645
|
+
|
|
99646
|
+
## Recent Conversation
|
|
99647
|
+
${recentHistory || "(no history yet)"}
|
|
99648
|
+
|
|
99649
|
+
## Currently Running Tools
|
|
99650
|
+
${activeToolsDesc}
|
|
99651
|
+
|
|
99652
|
+
## Budget
|
|
99653
|
+
- Extensions used: ${negotiatedTimeoutState.extensionsUsed}/${negotiatedTimeoutState.maxRequests}
|
|
99654
|
+
- Time budget remaining: ${Math.round(remainingBudgetMs / 6e4)} minutes
|
|
99655
|
+
- Max per extension: ${maxPerReqMin} minutes
|
|
99656
|
+
|
|
99657
|
+
Decide whether the agent should get more time. EXTEND if:
|
|
99658
|
+
- Tools are actively running (especially delegates or complex analysis) \u2014 they need time to finish
|
|
99659
|
+
- The agent is making clear progress on a complex task
|
|
99660
|
+
- New information is being gathered that will improve the final answer
|
|
99661
|
+
|
|
99662
|
+
DO NOT EXTEND if:
|
|
99663
|
+
- The agent appears stuck in a loop (repeating the same tool calls or getting the same errors)
|
|
99664
|
+
- The conversation shows the agent retrying failed operations without changing approach
|
|
99665
|
+
- The agent has enough information to answer but keeps searching for more
|
|
99666
|
+
- Tool calls are returning empty or error results repeatedly
|
|
99667
|
+
- The agent is doing redundant work (searching for things it already found)
|
|
99668
|
+
|
|
99669
|
+
A stuck agent will not recover with more time \u2014 it will just burn the budget. Better to force it to answer with what it has.
|
|
99670
|
+
|
|
99671
|
+
Respond with ONLY valid JSON (no markdown, no explanation):
|
|
99672
|
+
{"extend": true, "minutes": <1-${maxPerReqMin}>, "reason": "your reason here"}
|
|
99673
|
+
or
|
|
99674
|
+
{"extend": false, "reason": "your reason here"}`;
|
|
99675
|
+
const observerFn = async () => {
|
|
99676
|
+
const modelInstance = this.provider ? this.provider(this.model) : this.model;
|
|
99677
|
+
if (this.debug) {
|
|
99678
|
+
console.log(`[DEBUG] Timeout observer: making LLM call (${activeToolsList.length} active tools, ${elapsedMin} min elapsed)`);
|
|
99679
|
+
}
|
|
99680
|
+
if (this.tracer) {
|
|
99681
|
+
this.tracer.addEvent("negotiated_timeout.observer_invoked", {
|
|
99682
|
+
elapsed_min: elapsedMin,
|
|
99683
|
+
active_tools: activeToolsList.map((t) => t.name),
|
|
99684
|
+
active_tools_detail: activeToolsList.map((t) => ({
|
|
99685
|
+
name: t.name,
|
|
99686
|
+
running_for_ms: now - new Date(t.startedAt).getTime(),
|
|
99687
|
+
args_preview: JSON.stringify(t.args || {}).slice(0, 100)
|
|
99688
|
+
})),
|
|
99689
|
+
active_tools_count: activeToolsList.length,
|
|
99690
|
+
extensions_used: negotiatedTimeoutState.extensionsUsed,
|
|
99691
|
+
remaining_requests: remainingRequests,
|
|
99692
|
+
remaining_budget_ms: remainingBudgetMs,
|
|
99693
|
+
history_length: this.history.length
|
|
99694
|
+
});
|
|
99695
|
+
}
|
|
99696
|
+
const observerResult = await (0, import_ai4.generateText)({
|
|
99697
|
+
model: modelInstance,
|
|
99698
|
+
messages: [{ role: "user", content: observerPrompt }],
|
|
99699
|
+
maxTokens: 500
|
|
99700
|
+
});
|
|
99701
|
+
const responseText = observerResult.text.trim();
|
|
99702
|
+
if (this.tracer) {
|
|
99703
|
+
this.tracer.addEvent("negotiated_timeout.observer_response", {
|
|
99704
|
+
response_text: responseText,
|
|
99705
|
+
usage_prompt_tokens: observerResult.usage?.promptTokens,
|
|
99706
|
+
usage_completion_tokens: observerResult.usage?.completionTokens
|
|
99707
|
+
});
|
|
99708
|
+
}
|
|
99709
|
+
const jsonStr = responseText.replace(/^```(?:json)?\s*/, "").replace(/\s*```$/, "");
|
|
99710
|
+
const decision = JSON.parse(jsonStr);
|
|
99711
|
+
if (decision.extend && decision.minutes > 0) {
|
|
99712
|
+
const requestedMs = Math.min(decision.minutes, maxPerReqMin) * 6e4;
|
|
99713
|
+
const grantedMs = Math.min(requestedMs, remainingBudgetMs, negotiatedTimeoutState.maxPerRequestMs);
|
|
99714
|
+
const grantedMin = Math.round(grantedMs / 6e4 * 10) / 10;
|
|
99715
|
+
negotiatedTimeoutState.extensionsUsed++;
|
|
99716
|
+
negotiatedTimeoutState.totalExtraTimeMs += grantedMs;
|
|
99717
|
+
negotiatedTimeoutState.extensionMessage = `\u23F0 Time limit was reached. The timeout observer granted ${grantedMin} more minute(s) (reason: ${decision.reason || "work in progress"}). Extensions remaining: ${negotiatedTimeoutState.maxRequests - negotiatedTimeoutState.extensionsUsed}. Continue your work efficiently.`;
|
|
99718
|
+
negotiatedTimeoutState.softTimeoutId = setTimeout(() => {
|
|
99719
|
+
runTimeoutObserver();
|
|
99720
|
+
}, grantedMs);
|
|
99721
|
+
if (this.debug) {
|
|
99722
|
+
console.log(`[DEBUG] Timeout observer: granted ${grantedMin} min (reason: ${decision.reason}). Extensions: ${negotiatedTimeoutState.extensionsUsed}/${negotiatedTimeoutState.maxRequests}`);
|
|
99723
|
+
}
|
|
99724
|
+
if (this.tracer) {
|
|
99725
|
+
this.tracer.addEvent("negotiated_timeout.observer_extended", {
|
|
99726
|
+
decision_reason: decision.reason,
|
|
99727
|
+
requested_minutes: decision.minutes,
|
|
99728
|
+
granted_ms: grantedMs,
|
|
99729
|
+
granted_min: grantedMin,
|
|
99730
|
+
extensions_used: negotiatedTimeoutState.extensionsUsed,
|
|
99731
|
+
max_requests: negotiatedTimeoutState.maxRequests,
|
|
99732
|
+
total_extra_time_ms: negotiatedTimeoutState.totalExtraTimeMs,
|
|
99733
|
+
budget_remaining_ms: remainingBudgetMs - grantedMs,
|
|
99734
|
+
active_tools: activeToolsList.map((t) => t.name),
|
|
99735
|
+
active_tools_count: activeToolsList.length
|
|
99736
|
+
});
|
|
99737
|
+
}
|
|
99738
|
+
this.events.emit("timeout.extended", {
|
|
99739
|
+
grantedMs,
|
|
99740
|
+
reason: decision.reason || "work in progress",
|
|
99741
|
+
extensionsUsed: negotiatedTimeoutState.extensionsUsed,
|
|
99742
|
+
extensionsRemaining: negotiatedTimeoutState.maxRequests - negotiatedTimeoutState.extensionsUsed,
|
|
99743
|
+
totalExtraTimeMs: negotiatedTimeoutState.totalExtraTimeMs,
|
|
99744
|
+
budgetRemainingMs: remainingBudgetMs - grantedMs
|
|
99745
|
+
});
|
|
99746
|
+
} else {
|
|
99747
|
+
if (this.debug) {
|
|
99748
|
+
console.log(`[DEBUG] Timeout observer: declined extension (reason: ${decision.reason}). Initiating graceful stop.`);
|
|
99749
|
+
}
|
|
99750
|
+
if (this.tracer) {
|
|
99751
|
+
this.tracer.addEvent("negotiated_timeout.observer_declined", {
|
|
99752
|
+
decision_reason: decision.reason,
|
|
99753
|
+
extensions_used: negotiatedTimeoutState.extensionsUsed,
|
|
99754
|
+
total_extra_time_ms: negotiatedTimeoutState.totalExtraTimeMs,
|
|
99755
|
+
elapsed_min: elapsedMin,
|
|
99756
|
+
active_tools: activeToolsList.map((t) => t.name)
|
|
99757
|
+
});
|
|
99758
|
+
}
|
|
99759
|
+
this.events.emit("timeout.windingDown", {
|
|
99760
|
+
reason: decision.reason || "observer declined",
|
|
99761
|
+
extensionsUsed: negotiatedTimeoutState.extensionsUsed,
|
|
99762
|
+
totalExtraTimeMs: negotiatedTimeoutState.totalExtraTimeMs
|
|
99763
|
+
});
|
|
99764
|
+
await this._initiateGracefulStop(gracefulTimeoutState, `observer declined: ${decision.reason}`);
|
|
99765
|
+
}
|
|
99766
|
+
};
|
|
99767
|
+
try {
|
|
99768
|
+
if (this.tracer) {
|
|
99769
|
+
await this.tracer.withSpan("negotiated_timeout.observer", observerFn, {
|
|
99770
|
+
"timeout.elapsed_min": elapsedMin,
|
|
99771
|
+
"timeout.extensions_used": negotiatedTimeoutState.extensionsUsed,
|
|
99772
|
+
"timeout.active_tools_count": activeToolsList.length,
|
|
99773
|
+
"timeout.remaining_budget_ms": remainingBudgetMs
|
|
99774
|
+
});
|
|
99775
|
+
} else {
|
|
99776
|
+
await observerFn();
|
|
99777
|
+
}
|
|
99778
|
+
} catch (err) {
|
|
99779
|
+
if (this.debug) {
|
|
99780
|
+
console.log(`[DEBUG] Timeout observer: LLM call failed (${err.message}). Initiating graceful stop.`);
|
|
99781
|
+
}
|
|
99782
|
+
if (this.tracer) {
|
|
99783
|
+
this.tracer.addEvent("negotiated_timeout.observer_error", {
|
|
99784
|
+
error_message: err.message,
|
|
99785
|
+
error_name: err.name,
|
|
99786
|
+
extensions_used: negotiatedTimeoutState.extensionsUsed,
|
|
99787
|
+
elapsed_min: elapsedMin
|
|
99788
|
+
});
|
|
99789
|
+
}
|
|
99790
|
+
await this._initiateGracefulStop(gracefulTimeoutState, `observer error: ${err.message}`);
|
|
99791
|
+
} finally {
|
|
99792
|
+
negotiatedTimeoutState.observerRunning = false;
|
|
99793
|
+
}
|
|
99794
|
+
};
|
|
99795
|
+
negotiatedTimeoutState.runObserver = runTimeoutObserver;
|
|
99337
99796
|
let compactionAttempted = false;
|
|
99338
99797
|
while (true) {
|
|
99339
99798
|
try {
|
|
@@ -99395,6 +99854,14 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
99395
99854
|
return false;
|
|
99396
99855
|
},
|
|
99397
99856
|
prepareStep: ({ steps, stepNumber }) => {
|
|
99857
|
+
if (negotiatedTimeoutState.extensionMessage && !gracefulTimeoutState.triggered) {
|
|
99858
|
+
const msg = negotiatedTimeoutState.extensionMessage;
|
|
99859
|
+
negotiatedTimeoutState.extensionMessage = null;
|
|
99860
|
+
if (this.debug) {
|
|
99861
|
+
console.log(`[DEBUG] prepareStep: delivering timeout observer extension message`);
|
|
99862
|
+
}
|
|
99863
|
+
return { userMessage: msg };
|
|
99864
|
+
}
|
|
99398
99865
|
if (gracefulTimeoutState.triggered) {
|
|
99399
99866
|
gracefulTimeoutState.bonusStepsUsed++;
|
|
99400
99867
|
const remaining = gracefulTimeoutState.bonusStepsMax - gracefulTimeoutState.bonusStepsUsed;
|
|
@@ -99420,8 +99887,12 @@ You are working with a workspace. Available paths: ${workspaceDesc}
|
|
|
99420
99887
|
return { toolChoice: "none" };
|
|
99421
99888
|
}
|
|
99422
99889
|
if (stepNumber === maxIterations - 1) {
|
|
99890
|
+
const searchesTried = _toolCallLog.filter((tc) => tc.name === "search").map((tc) => `"${tc.args.query || ""}"${tc.args.exact ? " (exact)" : ""}`).filter((v, i, a) => a.indexOf(v) === i);
|
|
99891
|
+
const searchSummary = searchesTried.length > 0 ? `
|
|
99892
|
+
Searches attempted: ${searchesTried.join(", ")}` : "";
|
|
99423
99893
|
return {
|
|
99424
|
-
toolChoice: "none"
|
|
99894
|
+
toolChoice: "none",
|
|
99895
|
+
userMessage: `\u26A0\uFE0F LAST ITERATION \u2014 you are out of tool calls. Provide your BEST answer NOW with the information gathered so far. If you could not find what was requested, explain exactly what you searched for and why it did not work, so the caller can try a different approach.${searchSummary}`
|
|
99425
99896
|
};
|
|
99426
99897
|
}
|
|
99427
99898
|
if (steps.length >= 2) {
|
|
@@ -99500,6 +99971,11 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
99500
99971
|
const { toolResults, toolCalls, text, reasoningText, finishReason, usage } = stepResult;
|
|
99501
99972
|
currentIteration++;
|
|
99502
99973
|
toolContext.currentIteration = currentIteration;
|
|
99974
|
+
if (toolCalls?.length > 0) {
|
|
99975
|
+
for (const tc of toolCalls) {
|
|
99976
|
+
_toolCallLog.push({ name: tc.toolName, args: tc.args || {} });
|
|
99977
|
+
}
|
|
99978
|
+
}
|
|
99503
99979
|
if (this.tracer) {
|
|
99504
99980
|
const stepEvent = {
|
|
99505
99981
|
"iteration": currentIteration,
|
|
@@ -99591,6 +100067,14 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
99591
100067
|
}, 6e4);
|
|
99592
100068
|
}, this.maxOperationTimeout);
|
|
99593
100069
|
}
|
|
100070
|
+
if (this.timeoutBehavior === "negotiated" && this.maxOperationTimeout > 0) {
|
|
100071
|
+
negotiatedTimeoutState.softTimeoutId = setTimeout(() => {
|
|
100072
|
+
if (this.debug) {
|
|
100073
|
+
console.log(`[DEBUG] Soft timeout after ${this.maxOperationTimeout}ms \u2014 invoking timeout observer`);
|
|
100074
|
+
}
|
|
100075
|
+
runTimeoutObserver();
|
|
100076
|
+
}, this.maxOperationTimeout);
|
|
100077
|
+
}
|
|
99594
100078
|
try {
|
|
99595
100079
|
const steps = await result.steps;
|
|
99596
100080
|
let finalText;
|
|
@@ -99611,6 +100095,12 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
99611
100095
|
} finally {
|
|
99612
100096
|
if (gracefulTimeoutId) clearTimeout(gracefulTimeoutId);
|
|
99613
100097
|
if (hardAbortTimeoutId) clearTimeout(hardAbortTimeoutId);
|
|
100098
|
+
if (negotiatedTimeoutState.softTimeoutId) clearTimeout(negotiatedTimeoutState.softTimeoutId);
|
|
100099
|
+
if (this._gracefulStopHardAbortId) {
|
|
100100
|
+
clearTimeout(this._gracefulStopHardAbortId);
|
|
100101
|
+
this._gracefulStopHardAbortId = null;
|
|
100102
|
+
}
|
|
100103
|
+
this.events.removeListener("toolCall", onToolCall);
|
|
99614
100104
|
}
|
|
99615
100105
|
};
|
|
99616
100106
|
let aiResult;
|
|
@@ -99650,7 +100140,7 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
99650
100140
|
}
|
|
99651
100141
|
if (gracefulTimeoutState.triggered) {
|
|
99652
100142
|
const timeoutNotice = "**Note: This response was generated under a time constraint. The research may be incomplete, and some planned searches or analysis steps were not completed.**\n\n";
|
|
99653
|
-
if (!finalResult || finalResult === "I was unable to complete your request
|
|
100143
|
+
if (!finalResult || finalResult === DEFAULT_MAX_ITER_MSG || finalResult.startsWith("I was unable to complete your request after")) {
|
|
99654
100144
|
try {
|
|
99655
100145
|
const allText = await aiResult.result.text;
|
|
99656
100146
|
if (allText && allText.trim()) {
|
|
@@ -99698,7 +100188,7 @@ ${toolSummaries.join("\n\n---\n\n")}`;
|
|
|
99698
100188
|
currentMessages.push(msg);
|
|
99699
100189
|
}
|
|
99700
100190
|
}
|
|
99701
|
-
if (this.completionPrompt && !options._completionPromptProcessed && !completionPromptInjected && finalResult) {
|
|
100191
|
+
if (this.completionPrompt && !options._completionPromptProcessed && !completionPromptInjected && !abortSummaryTaken && finalResult) {
|
|
99702
100192
|
completionPromptInjected = true;
|
|
99703
100193
|
preCompletionResult = finalResult;
|
|
99704
100194
|
if (this.debug) {
|
|
@@ -99770,6 +100260,118 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
99770
100260
|
}
|
|
99771
100261
|
break;
|
|
99772
100262
|
} catch (error40) {
|
|
100263
|
+
if (gracefulTimeoutState.triggered && error40?.name === "AbortError") {
|
|
100264
|
+
if (this.debug) {
|
|
100265
|
+
console.log(`[DEBUG] Negotiated timeout: abort caught \u2014 making summary LLM call with conversation context`);
|
|
100266
|
+
}
|
|
100267
|
+
if (this.tracer) {
|
|
100268
|
+
this.tracer.addEvent("negotiated_timeout.abort_summary_started", {
|
|
100269
|
+
conversation_messages: currentMessages.length,
|
|
100270
|
+
has_schema: !!options.schema,
|
|
100271
|
+
has_tasks: !!(this.enableTasks && this.taskManager)
|
|
100272
|
+
});
|
|
100273
|
+
}
|
|
100274
|
+
try {
|
|
100275
|
+
let taskContext = "";
|
|
100276
|
+
if (this.enableTasks && this.taskManager) {
|
|
100277
|
+
const taskSummary = this.taskManager.getTaskSummary?.();
|
|
100278
|
+
if (taskSummary) {
|
|
100279
|
+
taskContext = `
|
|
100280
|
+
|
|
100281
|
+
## Task Status
|
|
100282
|
+
${taskSummary}
|
|
100283
|
+
|
|
100284
|
+
Acknowledge which tasks were completed and which were not.`;
|
|
100285
|
+
}
|
|
100286
|
+
}
|
|
100287
|
+
let schemaContext = "";
|
|
100288
|
+
if (options.schema) {
|
|
100289
|
+
try {
|
|
100290
|
+
const parsedSchema = typeof options.schema === "string" ? JSON.parse(options.schema) : options.schema;
|
|
100291
|
+
schemaContext = `
|
|
100292
|
+
|
|
100293
|
+
IMPORTANT: Your response MUST be valid JSON matching this schema:
|
|
100294
|
+
${JSON.stringify(parsedSchema, null, 2)}
|
|
100295
|
+
|
|
100296
|
+
Respond with ONLY valid JSON \u2014 no markdown, no explanation, no text outside the JSON object. Include all findings and partial results within the JSON structure. If fields cannot be fully populated due to the interruption, use partial data or null values as appropriate.`;
|
|
100297
|
+
} catch {
|
|
100298
|
+
}
|
|
100299
|
+
}
|
|
100300
|
+
const summaryPrompt = `Your operation was interrupted by a timeout observer because the time limit was reached. Some of your tool calls were cancelled mid-execution.
|
|
100301
|
+
|
|
100302
|
+
Please provide a DETAILED summary of:
|
|
100303
|
+
1. What you were asked to do (the original task)
|
|
100304
|
+
2. What you accomplished \u2014 include ALL findings, code snippets, data, and conclusions you gathered
|
|
100305
|
+
3. What was still in progress or not yet started
|
|
100306
|
+
4. Any partial results or recommendations you can offer based on what you found so far${taskContext}${schemaContext}
|
|
100307
|
+
|
|
100308
|
+
Be thorough \u2014 this is the user's only response. Include all useful information you collected.`;
|
|
100309
|
+
const summaryMessages = [
|
|
100310
|
+
...currentMessages,
|
|
100311
|
+
{ role: "user", content: summaryPrompt }
|
|
100312
|
+
];
|
|
100313
|
+
const modelInstance = this.provider ? this.provider(this.model) : this.model;
|
|
100314
|
+
const summaryFn = async () => {
|
|
100315
|
+
const summaryResult = await (0, import_ai4.generateText)({
|
|
100316
|
+
model: modelInstance,
|
|
100317
|
+
messages: this.prepareMessagesWithImages(summaryMessages),
|
|
100318
|
+
maxTokens: 4e3
|
|
100319
|
+
});
|
|
100320
|
+
if (this.tracer) {
|
|
100321
|
+
this.tracer.addEvent("negotiated_timeout.abort_summary_completed", {
|
|
100322
|
+
summary_length: summaryResult.text?.length || 0,
|
|
100323
|
+
usage_prompt_tokens: summaryResult.usage?.promptTokens,
|
|
100324
|
+
usage_completion_tokens: summaryResult.usage?.completionTokens
|
|
100325
|
+
});
|
|
100326
|
+
}
|
|
100327
|
+
if (summaryResult.usage) {
|
|
100328
|
+
this.tokenCounter.recordUsage(summaryResult.usage);
|
|
100329
|
+
}
|
|
100330
|
+
return summaryResult.text;
|
|
100331
|
+
};
|
|
100332
|
+
let summaryText;
|
|
100333
|
+
if (this.tracer) {
|
|
100334
|
+
summaryText = await this.tracer.withSpan("negotiated_timeout.abort_summary", summaryFn, {
|
|
100335
|
+
"summary.conversation_messages": currentMessages.length
|
|
100336
|
+
});
|
|
100337
|
+
} else {
|
|
100338
|
+
summaryText = await summaryFn();
|
|
100339
|
+
}
|
|
100340
|
+
if (options.schema) {
|
|
100341
|
+
finalResult = summaryText || "{}";
|
|
100342
|
+
} else {
|
|
100343
|
+
const timeoutNotice = "**Note: This response was generated under a time constraint. The timeout observer interrupted the operation because the time budget was exhausted.**\n\n";
|
|
100344
|
+
finalResult = timeoutNotice + (summaryText || "The operation was interrupted before a response could be generated.");
|
|
100345
|
+
}
|
|
100346
|
+
if (options.onStream && finalResult) {
|
|
100347
|
+
options.onStream(finalResult);
|
|
100348
|
+
}
|
|
100349
|
+
if (this.debug) {
|
|
100350
|
+
console.log(`[DEBUG] Negotiated timeout: summary produced ${summaryText?.length || 0} chars`);
|
|
100351
|
+
}
|
|
100352
|
+
} catch (summaryErr) {
|
|
100353
|
+
if (this.debug) {
|
|
100354
|
+
console.log(`[DEBUG] Negotiated timeout: summary call failed (${summaryErr.message}), falling back to partial text`);
|
|
100355
|
+
}
|
|
100356
|
+
if (this.tracer) {
|
|
100357
|
+
this.tracer.addEvent("negotiated_timeout.abort_summary_error", {
|
|
100358
|
+
error_message: summaryErr.message
|
|
100359
|
+
});
|
|
100360
|
+
}
|
|
100361
|
+
const partialTexts = currentMessages.filter((m) => m.role === "assistant" && typeof m.content === "string" && m.content.trim()).map((m) => m.content);
|
|
100362
|
+
if (options.schema) {
|
|
100363
|
+
finalResult = partialTexts.length > 0 ? partialTexts[partialTexts.length - 1] : "{}";
|
|
100364
|
+
} else {
|
|
100365
|
+
const timeoutNotice = "**Note: This response was generated under a time constraint. The operation was interrupted and some work was not completed.**\n\n";
|
|
100366
|
+
finalResult = partialTexts.length > 0 ? timeoutNotice + partialTexts[partialTexts.length - 1] : timeoutNotice + "The operation was interrupted before enough information could be gathered. Please try again with a simpler query or increase the timeout.";
|
|
100367
|
+
}
|
|
100368
|
+
if (options.onStream && finalResult) {
|
|
100369
|
+
options.onStream(finalResult);
|
|
100370
|
+
}
|
|
100371
|
+
}
|
|
100372
|
+
abortSummaryTaken = true;
|
|
100373
|
+
break;
|
|
100374
|
+
}
|
|
99773
100375
|
if (!compactionAttempted && handleContextLimitError) {
|
|
99774
100376
|
const compactionResult = handleContextLimitError(error40, currentMessages, {
|
|
99775
100377
|
keepLastSegment: true,
|
|
@@ -99804,6 +100406,36 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
99804
100406
|
}
|
|
99805
100407
|
if (currentIteration >= maxIterations) {
|
|
99806
100408
|
console.warn(`[WARN] Max tool iterations (${maxIterations}) reached for session ${this.sessionId}.`);
|
|
100409
|
+
if (!finalResult || finalResult === DEFAULT_MAX_ITER_MSG) {
|
|
100410
|
+
try {
|
|
100411
|
+
const searchQueries = [];
|
|
100412
|
+
const toolCounts = {};
|
|
100413
|
+
for (const tc of _toolCallLog) {
|
|
100414
|
+
toolCounts[tc.name] = (toolCounts[tc.name] || 0) + 1;
|
|
100415
|
+
if (tc.name === "search") {
|
|
100416
|
+
const q = tc.args.query || "";
|
|
100417
|
+
const exact = tc.args.exact ? " (exact)" : "";
|
|
100418
|
+
searchQueries.push(`"${q}"${exact}`);
|
|
100419
|
+
}
|
|
100420
|
+
}
|
|
100421
|
+
const toolBreakdown = Object.entries(toolCounts).map(([name15, count]) => `${name15}: ${count}x`).join(", ");
|
|
100422
|
+
const uniqueSearches = [...new Set(searchQueries)];
|
|
100423
|
+
let summary = `I was unable to complete your request after ${currentIteration} tool iterations.
|
|
100424
|
+
|
|
100425
|
+
`;
|
|
100426
|
+
summary += `Tool calls made: ${toolBreakdown || "none"}
|
|
100427
|
+
`;
|
|
100428
|
+
if (uniqueSearches.length > 0) {
|
|
100429
|
+
summary += `Search queries tried: ${uniqueSearches.join(", ")}
|
|
100430
|
+
`;
|
|
100431
|
+
}
|
|
100432
|
+
summary += `
|
|
100433
|
+
The search approach may be fundamentally wrong for this query. Consider: using exact=true for literal string matching, using bash/grep for pattern-based file searches, or trying a completely different strategy instead of repeating similar searches.`;
|
|
100434
|
+
finalResult = summary;
|
|
100435
|
+
} catch {
|
|
100436
|
+
finalResult = DEFAULT_MAX_ITER_MSG;
|
|
100437
|
+
}
|
|
100438
|
+
}
|
|
99807
100439
|
}
|
|
99808
100440
|
this.history = currentMessages.map((msg) => ({ ...msg }));
|
|
99809
100441
|
if (this.history.length > MAX_HISTORY_MESSAGES) {
|
|
@@ -100338,6 +100970,134 @@ Double-check your response based on the criteria above. If everything looks good
|
|
|
100338
100970
|
console.log(`[DEBUG] Agent cancelled for session ${this.sessionId}`);
|
|
100339
100971
|
}
|
|
100340
100972
|
}
|
|
100973
|
+
/**
|
|
100974
|
+
* Trigger graceful wind-down from outside (e.g., parent agent).
|
|
100975
|
+
* Unlike cancel(), this does NOT abort — it sets the graceful timeout flag
|
|
100976
|
+
* so the agent finishes its current step and then winds down naturally.
|
|
100977
|
+
*/
|
|
100978
|
+
triggerGracefulWindDown() {
|
|
100979
|
+
if (this._gracefulTimeoutState && !this._gracefulTimeoutState.triggered) {
|
|
100980
|
+
this._gracefulTimeoutState.triggered = true;
|
|
100981
|
+
if (this.debug) {
|
|
100982
|
+
console.log(`[DEBUG] Graceful wind-down triggered externally for session ${this.sessionId}`);
|
|
100983
|
+
}
|
|
100984
|
+
if (this.tracer) {
|
|
100985
|
+
this.tracer.addEvent("graceful_stop.external_trigger", {
|
|
100986
|
+
"session.id": this.sessionId
|
|
100987
|
+
});
|
|
100988
|
+
}
|
|
100989
|
+
} else if (this.debug) {
|
|
100990
|
+
console.log(`[DEBUG] Graceful wind-down already active for session ${this.sessionId}, skipping`);
|
|
100991
|
+
}
|
|
100992
|
+
}
|
|
100993
|
+
/**
|
|
100994
|
+
* Initiate two-phase graceful stop: signal subagents and MCP servers to wind down,
|
|
100995
|
+
* then hard-abort after a deadline if they haven't finished.
|
|
100996
|
+
* @param {Object} gracefulTimeoutState - The graceful timeout state object from run()
|
|
100997
|
+
* @param {string} reason - Why the graceful stop was initiated
|
|
100998
|
+
*/
|
|
100999
|
+
async _initiateGracefulStop(gracefulTimeoutState, reason) {
|
|
101000
|
+
if (gracefulTimeoutState.triggered) return;
|
|
101001
|
+
if (this.debug) {
|
|
101002
|
+
console.log(`[DEBUG] Initiating graceful stop: ${reason} (subagents: ${this._activeSubagents.size}, hasMcpBridge: ${!!this.mcpBridge}, deadline: ${this.gracefulStopDeadline}ms)`);
|
|
101003
|
+
}
|
|
101004
|
+
gracefulTimeoutState.triggered = true;
|
|
101005
|
+
if (this.tracer) {
|
|
101006
|
+
this.tracer.addEvent("graceful_stop.initiated", {
|
|
101007
|
+
"session.id": this.sessionId,
|
|
101008
|
+
"graceful_stop.reason": reason,
|
|
101009
|
+
"graceful_stop.active_subagents": this._activeSubagents.size,
|
|
101010
|
+
"graceful_stop.has_mcp_bridge": !!this.mcpBridge,
|
|
101011
|
+
"graceful_stop.deadline_ms": this.gracefulStopDeadline
|
|
101012
|
+
});
|
|
101013
|
+
}
|
|
101014
|
+
let subagentsSignalled = 0;
|
|
101015
|
+
let subagentErrors = 0;
|
|
101016
|
+
for (const [sid, subagent] of this._activeSubagents) {
|
|
101017
|
+
try {
|
|
101018
|
+
subagent.triggerGracefulWindDown();
|
|
101019
|
+
subagentsSignalled++;
|
|
101020
|
+
if (this.debug) {
|
|
101021
|
+
console.log(`[DEBUG] Triggered graceful wind-down on subagent ${sid}`);
|
|
101022
|
+
}
|
|
101023
|
+
} catch (e) {
|
|
101024
|
+
subagentErrors++;
|
|
101025
|
+
if (this.debug) {
|
|
101026
|
+
console.log(`[DEBUG] Failed to trigger wind-down on subagent ${sid}: ${e.message}`);
|
|
101027
|
+
}
|
|
101028
|
+
}
|
|
101029
|
+
}
|
|
101030
|
+
let mcpResults = [];
|
|
101031
|
+
if (this.mcpBridge) {
|
|
101032
|
+
try {
|
|
101033
|
+
mcpResults = await this.mcpBridge.callGracefulStopAll();
|
|
101034
|
+
if (this.debug && mcpResults.length > 0) {
|
|
101035
|
+
console.log(`[DEBUG] MCP graceful_stop results: ${JSON.stringify(mcpResults)}`);
|
|
101036
|
+
}
|
|
101037
|
+
} catch (e) {
|
|
101038
|
+
if (this.debug) {
|
|
101039
|
+
console.log(`[DEBUG] MCP graceful_stop failed: ${e.message}`);
|
|
101040
|
+
}
|
|
101041
|
+
}
|
|
101042
|
+
}
|
|
101043
|
+
if (this.tracer) {
|
|
101044
|
+
this.tracer.addEvent("graceful_stop.signals_sent", {
|
|
101045
|
+
"session.id": this.sessionId,
|
|
101046
|
+
"graceful_stop.subagents_signalled": subagentsSignalled,
|
|
101047
|
+
"graceful_stop.subagent_errors": subagentErrors,
|
|
101048
|
+
"graceful_stop.mcp_servers_called": mcpResults.filter((r) => r.success).length,
|
|
101049
|
+
"graceful_stop.mcp_servers_failed": mcpResults.filter((r) => !r.success).length,
|
|
101050
|
+
"graceful_stop.mcp_servers_total": mcpResults.length
|
|
101051
|
+
});
|
|
101052
|
+
}
|
|
101053
|
+
this._gracefulStopHardAbortId = setTimeout(() => {
|
|
101054
|
+
if (this.debug) {
|
|
101055
|
+
console.log(`[DEBUG] Graceful stop deadline (${this.gracefulStopDeadline}ms) expired \u2014 hard aborting`);
|
|
101056
|
+
}
|
|
101057
|
+
if (this.tracer) {
|
|
101058
|
+
this.tracer.addEvent("graceful_stop.deadline_expired", {
|
|
101059
|
+
"session.id": this.sessionId,
|
|
101060
|
+
"graceful_stop.deadline_ms": this.gracefulStopDeadline
|
|
101061
|
+
});
|
|
101062
|
+
}
|
|
101063
|
+
if (this._abortController) this._abortController.abort();
|
|
101064
|
+
}, this.gracefulStopDeadline);
|
|
101065
|
+
}
|
|
101066
|
+
/**
|
|
101067
|
+
* Register an active subagent for graceful stop coordination.
|
|
101068
|
+
* @param {string} sessionId
|
|
101069
|
+
* @param {ProbeAgent} subagent
|
|
101070
|
+
*/
|
|
101071
|
+
_registerSubagent(sessionId, subagent) {
|
|
101072
|
+
this._activeSubagents.set(sessionId, subagent);
|
|
101073
|
+
if (this.debug) {
|
|
101074
|
+
console.log(`[DEBUG] Registered subagent ${sessionId} (active: ${this._activeSubagents.size})`);
|
|
101075
|
+
}
|
|
101076
|
+
if (this.tracer) {
|
|
101077
|
+
this.tracer.addEvent("subagent.registered", {
|
|
101078
|
+
"session.id": this.sessionId,
|
|
101079
|
+
"subagent.session_id": sessionId,
|
|
101080
|
+
"subagent.active_count": this._activeSubagents.size
|
|
101081
|
+
});
|
|
101082
|
+
}
|
|
101083
|
+
}
|
|
101084
|
+
/**
|
|
101085
|
+
* Unregister a completed subagent.
|
|
101086
|
+
* @param {string} sessionId
|
|
101087
|
+
*/
|
|
101088
|
+
_unregisterSubagent(sessionId) {
|
|
101089
|
+
this._activeSubagents.delete(sessionId);
|
|
101090
|
+
if (this.debug) {
|
|
101091
|
+
console.log(`[DEBUG] Unregistered subagent ${sessionId} (active: ${this._activeSubagents.size})`);
|
|
101092
|
+
}
|
|
101093
|
+
if (this.tracer) {
|
|
101094
|
+
this.tracer.addEvent("subagent.unregistered", {
|
|
101095
|
+
"session.id": this.sessionId,
|
|
101096
|
+
"subagent.session_id": sessionId,
|
|
101097
|
+
"subagent.active_count": this._activeSubagents.size
|
|
101098
|
+
});
|
|
101099
|
+
}
|
|
101100
|
+
}
|
|
100341
101101
|
/**
|
|
100342
101102
|
* Get the abort signal for this agent.
|
|
100343
101103
|
* Delegations and subagents should check this signal.
|
|
@@ -100380,8 +101140,15 @@ async function delegate({
|
|
|
100380
101140
|
// Optional per-instance manager, falls back to default singleton
|
|
100381
101141
|
concurrencyLimiter = null,
|
|
100382
101142
|
// Optional global AI concurrency limiter
|
|
100383
|
-
parentAbortSignal = null
|
|
101143
|
+
parentAbortSignal = null,
|
|
100384
101144
|
// Optional AbortSignal from parent to cancel this delegation
|
|
101145
|
+
// Timeout settings inherited from parent agent
|
|
101146
|
+
timeoutBehavior = void 0,
|
|
101147
|
+
requestTimeout = void 0,
|
|
101148
|
+
gracefulTimeoutBonusSteps = void 0,
|
|
101149
|
+
// Subagent lifecycle callbacks for graceful stop coordination
|
|
101150
|
+
onSubagentCreated = null,
|
|
101151
|
+
onSubagentCompleted = null
|
|
100385
101152
|
}) {
|
|
100386
101153
|
if (!task || typeof task !== "string") {
|
|
100387
101154
|
throw new Error("Task parameter is required and must be a string");
|
|
@@ -100464,12 +101231,38 @@ async function delegate({
|
|
|
100464
101231
|
// Inherit from parent
|
|
100465
101232
|
mcpConfigPath,
|
|
100466
101233
|
// Inherit from parent
|
|
100467
|
-
concurrencyLimiter
|
|
101234
|
+
concurrencyLimiter,
|
|
100468
101235
|
// Inherit global AI concurrency limiter
|
|
101236
|
+
// Inherit timeout behavior from parent — subagent gets its own graceful wind-down
|
|
101237
|
+
// so it can produce partial results instead of being hard-killed by the external timer.
|
|
101238
|
+
// The external delegate timeout (capped to parent's remaining budget) is the hard limit;
|
|
101239
|
+
// maxOperationTimeout on the subagent is set slightly shorter so its own wind-down
|
|
101240
|
+
// fires before the external kill.
|
|
101241
|
+
maxOperationTimeout: Math.max(1e4, timeout * 1e3 - 15e3),
|
|
101242
|
+
// 15s before external kill
|
|
101243
|
+
timeoutBehavior: timeoutBehavior || "graceful",
|
|
101244
|
+
requestTimeout,
|
|
101245
|
+
gracefulTimeoutBonusSteps: gracefulTimeoutBonusSteps ?? 2
|
|
101246
|
+
// fewer steps for subagents
|
|
100469
101247
|
});
|
|
101248
|
+
if (onSubagentCreated) {
|
|
101249
|
+
onSubagentCreated(sessionId, subagent);
|
|
101250
|
+
}
|
|
100470
101251
|
if (debug) {
|
|
100471
101252
|
console.error(`[DELEGATE] Created subagent with session ${sessionId}`);
|
|
100472
101253
|
console.error(`[DELEGATE] Subagent config: promptType=${promptType}, enableDelegate=false, maxIterations=${remainingIterations}`);
|
|
101254
|
+
console.error(`[DELEGATE] Timeout inheritance: externalTimeout=${timeout}s, maxOperationTimeout=${Math.max(1e4, timeout * 1e3 - 15e3)}ms, behavior=${timeoutBehavior || "graceful"}, bonusSteps=${gracefulTimeoutBonusSteps ?? 2}`);
|
|
101255
|
+
}
|
|
101256
|
+
if (tracer) {
|
|
101257
|
+
tracer.addEvent("delegation.subagent_created", {
|
|
101258
|
+
"delegation.session_id": sessionId,
|
|
101259
|
+
"delegation.parent_session_id": parentSessionId,
|
|
101260
|
+
"delegation.external_timeout_s": timeout,
|
|
101261
|
+
"delegation.internal_timeout_ms": Math.max(1e4, timeout * 1e3 - 15e3),
|
|
101262
|
+
"delegation.timeout_behavior": timeoutBehavior || "graceful",
|
|
101263
|
+
"delegation.bonus_steps": gracefulTimeoutBonusSteps ?? 2,
|
|
101264
|
+
"delegation.max_iterations": remainingIterations
|
|
101265
|
+
});
|
|
100473
101266
|
}
|
|
100474
101267
|
const timeoutPromise = new Promise((_, reject2) => {
|
|
100475
101268
|
timeoutId = setTimeout(() => {
|
|
@@ -100478,6 +101271,7 @@ async function delegate({
|
|
|
100478
101271
|
}, timeout * 1e3);
|
|
100479
101272
|
});
|
|
100480
101273
|
let parentAbortHandler;
|
|
101274
|
+
let parentAbortHardCancelId = null;
|
|
100481
101275
|
const parentAbortPromise = new Promise((_, reject2) => {
|
|
100482
101276
|
if (parentAbortSignal) {
|
|
100483
101277
|
if (parentAbortSignal.aborted) {
|
|
@@ -100486,8 +101280,31 @@ async function delegate({
|
|
|
100486
101280
|
return;
|
|
100487
101281
|
}
|
|
100488
101282
|
parentAbortHandler = () => {
|
|
100489
|
-
subagent.
|
|
100490
|
-
|
|
101283
|
+
subagent.triggerGracefulWindDown();
|
|
101284
|
+
if (debug) {
|
|
101285
|
+
console.error(`[DELEGATE] Parent abort signal received \u2014 triggered graceful wind-down on subagent ${sessionId}`);
|
|
101286
|
+
}
|
|
101287
|
+
if (tracer) {
|
|
101288
|
+
tracer.addEvent("delegation.parent_abort_phase1", {
|
|
101289
|
+
"delegation.session_id": sessionId,
|
|
101290
|
+
"delegation.parent_session_id": parentSessionId,
|
|
101291
|
+
"delegation.action": "graceful_wind_down"
|
|
101292
|
+
});
|
|
101293
|
+
}
|
|
101294
|
+
parentAbortHardCancelId = setTimeout(() => {
|
|
101295
|
+
if (debug) {
|
|
101296
|
+
console.error(`[DELEGATE] Graceful wind-down deadline expired \u2014 hard cancelling subagent ${sessionId}`);
|
|
101297
|
+
}
|
|
101298
|
+
if (tracer) {
|
|
101299
|
+
tracer.addEvent("delegation.parent_abort_phase2", {
|
|
101300
|
+
"delegation.session_id": sessionId,
|
|
101301
|
+
"delegation.parent_session_id": parentSessionId,
|
|
101302
|
+
"delegation.action": "hard_cancel"
|
|
101303
|
+
});
|
|
101304
|
+
}
|
|
101305
|
+
subagent.cancel();
|
|
101306
|
+
reject2(new Error("Delegation cancelled: parent operation was aborted (graceful wind-down deadline expired)"));
|
|
101307
|
+
}, 3e4);
|
|
100491
101308
|
};
|
|
100492
101309
|
parentAbortSignal.addEventListener("abort", parentAbortHandler, { once: true });
|
|
100493
101310
|
}
|
|
@@ -100503,6 +101320,13 @@ async function delegate({
|
|
|
100503
101320
|
if (parentAbortHandler && parentAbortSignal) {
|
|
100504
101321
|
parentAbortSignal.removeEventListener("abort", parentAbortHandler);
|
|
100505
101322
|
}
|
|
101323
|
+
if (parentAbortHardCancelId) {
|
|
101324
|
+
clearTimeout(parentAbortHardCancelId);
|
|
101325
|
+
parentAbortHardCancelId = null;
|
|
101326
|
+
}
|
|
101327
|
+
if (onSubagentCompleted) {
|
|
101328
|
+
onSubagentCompleted(sessionId);
|
|
101329
|
+
}
|
|
100506
101330
|
}
|
|
100507
101331
|
if (timeoutId !== null) {
|
|
100508
101332
|
clearTimeout(timeoutId);
|
|
@@ -101527,6 +102351,10 @@ function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, all
|
|
|
101527
102351
|
"- Use exact=true when searching for a KNOWN symbol name (function, type, variable, struct).",
|
|
101528
102352
|
"- exact=true matches the literal string only \u2014 no stemming, no splitting.",
|
|
101529
102353
|
'- This is ideal for precise lookups: exact=true "ForwardMessage", exact=true "SessionLimiter", exact=true "ThrottleRetryLimit".',
|
|
102354
|
+
"- IMPORTANT: Use exact=true when searching for strings containing punctuation, quotes, or empty values.",
|
|
102355
|
+
" Default BM25 search strips punctuation and treats quoted empty strings as noise.",
|
|
102356
|
+
` Example: searching for 'description: ""' with exact=false will NOT find empty description fields \u2014 it just matches "description".`,
|
|
102357
|
+
` Use exact=true for literal patterns like 'description: ""', 'value: \\'\\'', or any YAML/config field with specific punctuation.`,
|
|
101530
102358
|
"- Do NOT use exact=true for exploratory/conceptual queries \u2014 use the default for those.",
|
|
101531
102359
|
"",
|
|
101532
102360
|
"Combining searches with OR:",
|
|
@@ -101586,7 +102414,13 @@ function buildSearchDelegateTask({ searchQuery, searchPath, exact, language, all
|
|
|
101586
102414
|
"WHEN TO STOP:",
|
|
101587
102415
|
"- After you have explored the main concept AND related subsystems.",
|
|
101588
102416
|
"- Once you have 5-15 targets covering different aspects of the query.",
|
|
101589
|
-
'- If you get a "DUPLICATE SEARCH BLOCKED" message,
|
|
102417
|
+
'- If you get a "DUPLICATE SEARCH BLOCKED" message, do NOT rephrase the same query \u2014 try a FUNDAMENTALLY different approach:',
|
|
102418
|
+
" * Switch between exact=true and exact=false",
|
|
102419
|
+
" * Search for a broader term and filter results manually",
|
|
102420
|
+
" * Use listFiles to browse the directory structure directly",
|
|
102421
|
+
" * Look for related/surrounding patterns instead of the exact string",
|
|
102422
|
+
"- If 2-3 genuinely different search approaches fail, STOP and report what you tried and why it failed.",
|
|
102423
|
+
" Do NOT keep trying variations of the same failing concept.",
|
|
101590
102424
|
"",
|
|
101591
102425
|
"Strategy:",
|
|
101592
102426
|
"1. Analyze the query \u2014 identify key concepts, then brainstorm SYNONYMS and alternative terms for each.",
|
|
@@ -101658,8 +102492,8 @@ var init_vercel = __esm({
|
|
|
101658
102492
|
}
|
|
101659
102493
|
return result;
|
|
101660
102494
|
};
|
|
101661
|
-
const previousSearches = /* @__PURE__ */ new
|
|
101662
|
-
|
|
102495
|
+
const previousSearches = /* @__PURE__ */ new Map();
|
|
102496
|
+
const dupBlockCounts = /* @__PURE__ */ new Map();
|
|
101663
102497
|
const paginationCounts = /* @__PURE__ */ new Map();
|
|
101664
102498
|
const MAX_PAGES_PER_QUERY = 3;
|
|
101665
102499
|
return (0, import_ai5.tool)({
|
|
@@ -101710,20 +102544,25 @@ var init_vercel = __esm({
|
|
|
101710
102544
|
return await search(searchOptions);
|
|
101711
102545
|
};
|
|
101712
102546
|
if (!searchDelegate) {
|
|
101713
|
-
const searchKey = `${searchQuery}::${exact || false}`;
|
|
102547
|
+
const searchKey = `${searchPath}::${searchQuery}::${exact || false}`;
|
|
101714
102548
|
if (!nextPage) {
|
|
101715
102549
|
if (previousSearches.has(searchKey)) {
|
|
101716
|
-
|
|
102550
|
+
const blockCount = (dupBlockCounts.get(searchKey) || 0) + 1;
|
|
102551
|
+
dupBlockCounts.set(searchKey, blockCount);
|
|
101717
102552
|
if (debug) {
|
|
101718
|
-
console.error(`[DEDUP] Blocked duplicate search (${
|
|
102553
|
+
console.error(`[DEDUP] Blocked duplicate search (${blockCount}x): "${searchQuery}" (path: "${searchPath}")`);
|
|
102554
|
+
}
|
|
102555
|
+
if (blockCount >= 3) {
|
|
102556
|
+
return "STOP. You have been blocked " + blockCount + " times for repeating the same search. You MUST provide your final answer NOW with whatever information you have. Do NOT call any more tools.";
|
|
101719
102557
|
}
|
|
101720
|
-
|
|
101721
|
-
|
|
102558
|
+
const prev = previousSearches.get(searchKey);
|
|
102559
|
+
if (prev.hadResults) {
|
|
102560
|
+
return `DUPLICATE SEARCH BLOCKED (${blockCount}x). You already searched for "${searchQuery}" in this path and found results. Do NOT repeat. Use extract to examine the files you already found, try a COMPLETELY different keyword, or provide your final answer.`;
|
|
101722
102561
|
}
|
|
101723
|
-
|
|
102562
|
+
const exactHint = exact ? "You used exact=true. Try a broader search with exact=false, or use listFiles to browse the directory structure." : `Try exact=true if you need literal/punctuation matching (e.g. 'description: ""'), or use listFiles to explore directories, or search for a broader/related term and filter manually.`;
|
|
102563
|
+
return `DUPLICATE SEARCH BLOCKED (${blockCount}x). You already searched for "${searchQuery}" in this path and got NO results. This term does not appear in the codebase. Do NOT repeat or rephrase \u2014 try a FUNDAMENTALLY different approach: ${exactHint} If multiple approaches have failed, provide your final answer with what you know.`;
|
|
101724
102564
|
}
|
|
101725
|
-
previousSearches.
|
|
101726
|
-
consecutiveDupBlocks = 0;
|
|
102565
|
+
previousSearches.set(searchKey, { hadResults: false });
|
|
101727
102566
|
paginationCounts.set(searchKey, 0);
|
|
101728
102567
|
} else {
|
|
101729
102568
|
const pageCount = (paginationCounts.get(searchKey) || 0) + 1;
|
|
@@ -101737,6 +102576,14 @@ var init_vercel = __esm({
|
|
|
101737
102576
|
}
|
|
101738
102577
|
try {
|
|
101739
102578
|
const result = maybeAnnotate(await runRawSearch());
|
|
102579
|
+
if (typeof result === "string" && result.includes("No results found")) {
|
|
102580
|
+
if (/^[A-Z]+-\d+$/.test(searchQuery.trim()) || /^[A-Z]+-\d+$/.test(searchQuery.replace(/"/g, "").trim())) {
|
|
102581
|
+
return result + "\n\n\u26A0\uFE0F Your query looks like a ticket/issue ID (e.g., JIRA-1234). Ticket IDs are rarely present in source code. Search for the technical concepts described in the ticket instead (e.g., function names, error messages, variable names).";
|
|
102582
|
+
}
|
|
102583
|
+
} else if (typeof result === "string") {
|
|
102584
|
+
const entry = previousSearches.get(searchKey);
|
|
102585
|
+
if (entry) entry.hadResults = true;
|
|
102586
|
+
}
|
|
101740
102587
|
if (options.fileTracker && typeof result === "string") {
|
|
101741
102588
|
options.fileTracker.trackFilesFromOutput(result, effectiveSearchCwd).catch(() => {
|
|
101742
102589
|
});
|
|
@@ -102019,7 +102866,31 @@ var init_vercel = __esm({
|
|
|
102019
102866
|
});
|
|
102020
102867
|
};
|
|
102021
102868
|
delegateTool = (options = {}) => {
|
|
102022
|
-
const {
|
|
102869
|
+
const {
|
|
102870
|
+
debug = false,
|
|
102871
|
+
timeout = 300,
|
|
102872
|
+
cwd,
|
|
102873
|
+
allowedFolders,
|
|
102874
|
+
workspaceRoot,
|
|
102875
|
+
enableBash = false,
|
|
102876
|
+
bashConfig,
|
|
102877
|
+
architectureFileName,
|
|
102878
|
+
enableMcp = false,
|
|
102879
|
+
mcpConfig = null,
|
|
102880
|
+
mcpConfigPath = null,
|
|
102881
|
+
delegationManager = null,
|
|
102882
|
+
// Timeout settings inherited from parent agent
|
|
102883
|
+
timeoutBehavior,
|
|
102884
|
+
maxOperationTimeout,
|
|
102885
|
+
requestTimeout,
|
|
102886
|
+
gracefulTimeoutBonusSteps,
|
|
102887
|
+
negotiatedTimeoutBudget,
|
|
102888
|
+
negotiatedTimeoutMaxRequests,
|
|
102889
|
+
negotiatedTimeoutMaxPerRequest,
|
|
102890
|
+
parentOperationStartTime,
|
|
102891
|
+
onSubagentCreated,
|
|
102892
|
+
onSubagentCompleted
|
|
102893
|
+
} = options;
|
|
102023
102894
|
return (0, import_ai5.tool)({
|
|
102024
102895
|
name: "delegate",
|
|
102025
102896
|
description: delegateDescription,
|
|
@@ -102063,9 +102934,30 @@ var init_vercel = __esm({
|
|
|
102063
102934
|
console.error(`Using workspace root: ${effectivePath} (cwd was: ${cwd || "not set"})`);
|
|
102064
102935
|
}
|
|
102065
102936
|
}
|
|
102937
|
+
let effectiveTimeout = timeout;
|
|
102938
|
+
if (parentOperationStartTime && maxOperationTimeout) {
|
|
102939
|
+
const elapsed = Date.now() - parentOperationStartTime;
|
|
102940
|
+
const remaining = maxOperationTimeout - elapsed;
|
|
102941
|
+
const budgetCap = Math.max(30, Math.floor(remaining * 0.9 / 1e3));
|
|
102942
|
+
if (budgetCap < effectiveTimeout) {
|
|
102943
|
+
effectiveTimeout = budgetCap;
|
|
102944
|
+
if (debug) {
|
|
102945
|
+
console.error(`[DELEGATE] Capping timeout from ${timeout}s to ${effectiveTimeout}s (remaining parent budget: ${Math.floor(remaining / 1e3)}s)`);
|
|
102946
|
+
}
|
|
102947
|
+
if (tracer) {
|
|
102948
|
+
tracer.addEvent("delegation.budget_capped", {
|
|
102949
|
+
"delegation.original_timeout_s": timeout,
|
|
102950
|
+
"delegation.effective_timeout_s": effectiveTimeout,
|
|
102951
|
+
"delegation.parent_elapsed_ms": elapsed,
|
|
102952
|
+
"delegation.parent_remaining_ms": remaining,
|
|
102953
|
+
"delegation.parent_session_id": parentSessionId
|
|
102954
|
+
});
|
|
102955
|
+
}
|
|
102956
|
+
}
|
|
102957
|
+
}
|
|
102066
102958
|
const result = await delegate({
|
|
102067
102959
|
task,
|
|
102068
|
-
timeout,
|
|
102960
|
+
timeout: effectiveTimeout,
|
|
102069
102961
|
debug,
|
|
102070
102962
|
currentIteration: currentIteration || 0,
|
|
102071
102963
|
maxIterations: maxIterations || 30,
|
|
@@ -102084,7 +102976,14 @@ var init_vercel = __esm({
|
|
|
102084
102976
|
mcpConfigPath,
|
|
102085
102977
|
delegationManager,
|
|
102086
102978
|
// Per-instance delegation limits
|
|
102087
|
-
parentAbortSignal
|
|
102979
|
+
parentAbortSignal,
|
|
102980
|
+
// Inherit timeout settings for subagent
|
|
102981
|
+
timeoutBehavior,
|
|
102982
|
+
requestTimeout,
|
|
102983
|
+
gracefulTimeoutBonusSteps,
|
|
102984
|
+
// Subagent lifecycle callbacks for graceful stop coordination
|
|
102985
|
+
onSubagentCreated,
|
|
102986
|
+
onSubagentCompleted
|
|
102088
102987
|
});
|
|
102089
102988
|
return result;
|
|
102090
102989
|
}
|
|
@@ -103563,6 +104462,121 @@ var init_file_lister = __esm({
|
|
|
103563
104462
|
}
|
|
103564
104463
|
});
|
|
103565
104464
|
|
|
104465
|
+
// src/agent/otelLogBridge.js
|
|
104466
|
+
function getOtelApi() {
|
|
104467
|
+
if (otelApiAttempted) return otelApi;
|
|
104468
|
+
otelApiAttempted = true;
|
|
104469
|
+
try {
|
|
104470
|
+
otelApi = (function(name15) {
|
|
104471
|
+
return _require(name15);
|
|
104472
|
+
})("@opentelemetry/api");
|
|
104473
|
+
} catch {
|
|
104474
|
+
}
|
|
104475
|
+
return otelApi;
|
|
104476
|
+
}
|
|
104477
|
+
function getOtelLogger() {
|
|
104478
|
+
if (otelLoggerAttempted) return otelLogger;
|
|
104479
|
+
otelLoggerAttempted = true;
|
|
104480
|
+
try {
|
|
104481
|
+
const { logs } = (function(name15) {
|
|
104482
|
+
return _require(name15);
|
|
104483
|
+
})("@opentelemetry/api-logs");
|
|
104484
|
+
otelLogger = logs.getLogger("probe-agent");
|
|
104485
|
+
} catch {
|
|
104486
|
+
}
|
|
104487
|
+
return otelLogger;
|
|
104488
|
+
}
|
|
104489
|
+
function getTraceSuffix() {
|
|
104490
|
+
try {
|
|
104491
|
+
const api2 = getOtelApi();
|
|
104492
|
+
if (!api2) return "";
|
|
104493
|
+
const span = api2.trace.getSpan(api2.context.active());
|
|
104494
|
+
const ctx = span?.spanContext?.();
|
|
104495
|
+
if (!ctx?.traceId) return "";
|
|
104496
|
+
return ` [trace_id=${ctx.traceId} span_id=${ctx.spanId}]`;
|
|
104497
|
+
} catch {
|
|
104498
|
+
return "";
|
|
104499
|
+
}
|
|
104500
|
+
}
|
|
104501
|
+
function emitOtelLog(msg, level) {
|
|
104502
|
+
try {
|
|
104503
|
+
const logger = getOtelLogger();
|
|
104504
|
+
if (!logger) return;
|
|
104505
|
+
const api2 = getOtelApi();
|
|
104506
|
+
let traceId, spanId;
|
|
104507
|
+
if (api2) {
|
|
104508
|
+
const span = api2.trace.getSpan(api2.context.active());
|
|
104509
|
+
const ctx = span?.spanContext?.();
|
|
104510
|
+
if (ctx?.traceId) {
|
|
104511
|
+
traceId = ctx.traceId;
|
|
104512
|
+
spanId = ctx.spanId;
|
|
104513
|
+
}
|
|
104514
|
+
}
|
|
104515
|
+
logger.emit({
|
|
104516
|
+
severityNumber: OTEL_SEVERITY[level] || 9,
|
|
104517
|
+
severityText: level.toUpperCase(),
|
|
104518
|
+
body: msg,
|
|
104519
|
+
attributes: {
|
|
104520
|
+
"probe.logger": true,
|
|
104521
|
+
...traceId ? { trace_id: traceId, span_id: spanId } : {}
|
|
104522
|
+
}
|
|
104523
|
+
});
|
|
104524
|
+
} catch {
|
|
104525
|
+
}
|
|
104526
|
+
}
|
|
104527
|
+
function patchConsole() {
|
|
104528
|
+
if (patched) return;
|
|
104529
|
+
const methods = ["log", "info", "warn", "error"];
|
|
104530
|
+
const c = globalThis.console;
|
|
104531
|
+
for (const m of methods) {
|
|
104532
|
+
const orig = c[m].bind(c);
|
|
104533
|
+
originals[m] = orig;
|
|
104534
|
+
c[m] = (...args) => {
|
|
104535
|
+
const msgParts = args.map(
|
|
104536
|
+
(a) => typeof a === "string" ? a : a instanceof Error ? a.message : JSON.stringify(a)
|
|
104537
|
+
);
|
|
104538
|
+
const msg = msgParts.join(" ");
|
|
104539
|
+
emitOtelLog(msg, m === "log" ? "log" : m);
|
|
104540
|
+
const suffix = getTraceSuffix();
|
|
104541
|
+
if (suffix) {
|
|
104542
|
+
if (typeof args[0] === "string") {
|
|
104543
|
+
args[0] = args[0] + suffix;
|
|
104544
|
+
} else {
|
|
104545
|
+
args.push(suffix);
|
|
104546
|
+
}
|
|
104547
|
+
}
|
|
104548
|
+
return orig(...args);
|
|
104549
|
+
};
|
|
104550
|
+
}
|
|
104551
|
+
patched = true;
|
|
104552
|
+
}
|
|
104553
|
+
var import_module, _require, OTEL_SEVERITY, patched, originals, otelApi, otelApiAttempted, otelLogger, otelLoggerAttempted;
|
|
104554
|
+
var init_otelLogBridge = __esm({
|
|
104555
|
+
"src/agent/otelLogBridge.js"() {
|
|
104556
|
+
"use strict";
|
|
104557
|
+
import_module = require("module");
|
|
104558
|
+
_require = (0, import_module.createRequire)("file:///");
|
|
104559
|
+
OTEL_SEVERITY = {
|
|
104560
|
+
log: 9,
|
|
104561
|
+
// INFO
|
|
104562
|
+
info: 9,
|
|
104563
|
+
// INFO
|
|
104564
|
+
warn: 13,
|
|
104565
|
+
// WARN
|
|
104566
|
+
error: 17,
|
|
104567
|
+
// ERROR
|
|
104568
|
+
debug: 5
|
|
104569
|
+
// DEBUG
|
|
104570
|
+
};
|
|
104571
|
+
patched = false;
|
|
104572
|
+
originals = {};
|
|
104573
|
+
otelApi = null;
|
|
104574
|
+
otelApiAttempted = false;
|
|
104575
|
+
otelLogger = null;
|
|
104576
|
+
otelLoggerAttempted = false;
|
|
104577
|
+
}
|
|
104578
|
+
});
|
|
104579
|
+
|
|
103566
104580
|
// src/agent/simpleTelemetry.js
|
|
103567
104581
|
function initializeSimpleTelemetryFromOptions(options) {
|
|
103568
104582
|
const telemetry = new SimpleTelemetry({
|
|
@@ -103571,6 +104585,7 @@ function initializeSimpleTelemetryFromOptions(options) {
|
|
|
103571
104585
|
enableConsole: options.traceConsole,
|
|
103572
104586
|
filePath: options.traceFile || "./traces.jsonl"
|
|
103573
104587
|
});
|
|
104588
|
+
patchConsole();
|
|
103574
104589
|
return telemetry;
|
|
103575
104590
|
}
|
|
103576
104591
|
var import_fs15, import_path18, SimpleTelemetry, SimpleAppTracer;
|
|
@@ -103579,6 +104594,7 @@ var init_simpleTelemetry = __esm({
|
|
|
103579
104594
|
"use strict";
|
|
103580
104595
|
import_fs15 = require("fs");
|
|
103581
104596
|
import_path18 = require("path");
|
|
104597
|
+
init_otelLogBridge();
|
|
103582
104598
|
SimpleTelemetry = class {
|
|
103583
104599
|
constructor(options = {}) {
|
|
103584
104600
|
this.serviceName = options.serviceName || "probe-agent";
|
|
@@ -104029,6 +105045,9 @@ var init_hooks = __esm({
|
|
|
104029
105045
|
var index_exports = {};
|
|
104030
105046
|
__export(index_exports, {
|
|
104031
105047
|
DEFAULT_SYSTEM_MESSAGE: () => DEFAULT_SYSTEM_MESSAGE,
|
|
105048
|
+
ENGINE_ACTIVITY_TIMEOUT_DEFAULT: () => ENGINE_ACTIVITY_TIMEOUT_DEFAULT,
|
|
105049
|
+
ENGINE_ACTIVITY_TIMEOUT_MAX: () => ENGINE_ACTIVITY_TIMEOUT_MAX,
|
|
105050
|
+
ENGINE_ACTIVITY_TIMEOUT_MIN: () => ENGINE_ACTIVITY_TIMEOUT_MIN,
|
|
104032
105051
|
FileTracker: () => FileTracker,
|
|
104033
105052
|
HOOK_TYPES: () => HOOK_TYPES,
|
|
104034
105053
|
HookManager: () => HookManager,
|
|
@@ -104115,6 +105134,9 @@ init_index();
|
|
|
104115
105134
|
// Annotate the CommonJS export names for ESM import in node:
|
|
104116
105135
|
0 && (module.exports = {
|
|
104117
105136
|
DEFAULT_SYSTEM_MESSAGE,
|
|
105137
|
+
ENGINE_ACTIVITY_TIMEOUT_DEFAULT,
|
|
105138
|
+
ENGINE_ACTIVITY_TIMEOUT_MAX,
|
|
105139
|
+
ENGINE_ACTIVITY_TIMEOUT_MIN,
|
|
104118
105140
|
FileTracker,
|
|
104119
105141
|
HOOK_TYPES,
|
|
104120
105142
|
HookManager,
|