@illuma-ai/agents 1.3.0 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/graphs/Graph.cjs +5 -12
- package/dist/cjs/graphs/Graph.cjs.map +1 -1
- package/dist/cjs/main.cjs +4 -0
- package/dist/cjs/main.cjs.map +1 -1
- package/dist/cjs/utils/errors.cjs +113 -0
- package/dist/cjs/utils/errors.cjs.map +1 -0
- package/dist/esm/graphs/Graph.mjs +5 -12
- package/dist/esm/graphs/Graph.mjs.map +1 -1
- package/dist/esm/main.mjs +1 -0
- package/dist/esm/main.mjs.map +1 -1
- package/dist/esm/utils/errors.mjs +109 -0
- package/dist/esm/utils/errors.mjs.map +1 -0
- package/dist/types/utils/errors.d.ts +37 -0
- package/dist/types/utils/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/graphs/Graph.ts +5 -14
- package/src/utils/__tests__/errors.test.ts +136 -0
- package/src/utils/errors.ts +115 -0
- package/src/utils/index.ts +1 -0
package/dist/cjs/main.cjs
CHANGED
|
@@ -62,6 +62,7 @@ var contextPressure = require('./utils/contextPressure.cjs');
|
|
|
62
62
|
var toolDiscoveryCache = require('./utils/toolDiscoveryCache.cjs');
|
|
63
63
|
var pruneCalibration = require('./utils/pruneCalibration.cjs');
|
|
64
64
|
var fileManifest = require('./utils/fileManifest.cjs');
|
|
65
|
+
var errors = require('./utils/errors.cjs');
|
|
65
66
|
var index$1 = require('./llm/openai/index.cjs');
|
|
66
67
|
var index = require('./llm/openrouter/index.cjs');
|
|
67
68
|
var providers = require('./llm/providers.cjs');
|
|
@@ -425,6 +426,9 @@ exports.createPruneCalibration = pruneCalibration.createPruneCalibration;
|
|
|
425
426
|
exports.updatePruneCalibration = pruneCalibration.updatePruneCalibration;
|
|
426
427
|
exports.FILE_MANIFEST_PREFIX = fileManifest.FILE_MANIFEST_PREFIX;
|
|
427
428
|
exports.buildFileManifestBlock = fileManifest.buildFileManifestBlock;
|
|
429
|
+
exports.extractErrorMessage = errors.extractErrorMessage;
|
|
430
|
+
exports.isContextOverflowError = errors.isContextOverflowError;
|
|
431
|
+
exports.isLikelyContextOverflowError = errors.isLikelyContextOverflowError;
|
|
428
432
|
exports.CustomOpenAIClient = index$1.CustomOpenAIClient;
|
|
429
433
|
exports.ChatOpenRouter = index.ChatOpenRouter;
|
|
430
434
|
exports.getChatModelClass = providers.getChatModelClass;
|
package/dist/cjs/main.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"main.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Context-overflow error detection helpers.
|
|
5
|
+
*
|
|
6
|
+
* Provider error messages vary — Anthropic returns "prompt is too long",
|
|
7
|
+
* OpenAI returns "context_length_exceeded", Bedrock returns "Input is too
|
|
8
|
+
* long", Google returns a size-limit phrase. This module centralises the
|
|
9
|
+
* phrase list so the agent graph's emergency-prune retry can classify
|
|
10
|
+
* errors consistently instead of duplicating inline substring matches at
|
|
11
|
+
* each call site.
|
|
12
|
+
*
|
|
13
|
+
* The strict check (`isContextOverflowError`) matches only known phrases.
|
|
14
|
+
* The loose check (`isLikelyContextOverflowError`) also matches a heuristic
|
|
15
|
+
* regex for providers we haven't explicitly catalogued. Both filter out
|
|
16
|
+
* false positives (rate-limit, auth, quota, billing) that might otherwise
|
|
17
|
+
* trigger an unnecessary prune retry.
|
|
18
|
+
*/
|
|
19
|
+
const CONTEXT_OVERFLOW_PHRASES = [
|
|
20
|
+
'request_too_large',
|
|
21
|
+
'context length exceeded',
|
|
22
|
+
'maximum context length',
|
|
23
|
+
'prompt is too long',
|
|
24
|
+
'exceeds model context window',
|
|
25
|
+
'exceeds the model',
|
|
26
|
+
'too large for model',
|
|
27
|
+
'context_length_exceeded',
|
|
28
|
+
'max_tokens',
|
|
29
|
+
'token limit',
|
|
30
|
+
'input too long',
|
|
31
|
+
'input is too long',
|
|
32
|
+
'payload too large',
|
|
33
|
+
'content_too_large',
|
|
34
|
+
];
|
|
35
|
+
const CONTEXT_OVERFLOW_HINT_RE = /413|too large|too long|context.*exceed|exceed.*context|token.*limit|limit.*token|prompt.*size|size.*limit|maximum.*length|length.*maximum/i;
|
|
36
|
+
const FALSE_POSITIVE_RE = /rate.?limit|too many requests|quota|billing|auth|permission|forbidden/i;
|
|
37
|
+
/**
|
|
38
|
+
* Extracts a human-readable error message from an unknown error value.
|
|
39
|
+
* Walks common shapes: strings, Error instances, `{ message }`,
|
|
40
|
+
* `{ error: string }`, `{ error: { message } }`. Falls back to
|
|
41
|
+
* JSON.stringify or String() so callers never have to null-check.
|
|
42
|
+
*/
|
|
43
|
+
function extractErrorMessage(error) {
|
|
44
|
+
if (error == null) {
|
|
45
|
+
return '';
|
|
46
|
+
}
|
|
47
|
+
if (typeof error === 'string') {
|
|
48
|
+
return error;
|
|
49
|
+
}
|
|
50
|
+
if (error instanceof Error) {
|
|
51
|
+
return error.message;
|
|
52
|
+
}
|
|
53
|
+
if (typeof error === 'object') {
|
|
54
|
+
const record = error;
|
|
55
|
+
if (typeof record.message === 'string') {
|
|
56
|
+
return record.message;
|
|
57
|
+
}
|
|
58
|
+
if (typeof record.error === 'string') {
|
|
59
|
+
return record.error;
|
|
60
|
+
}
|
|
61
|
+
if (typeof record.error === 'object' &&
|
|
62
|
+
record.error != null &&
|
|
63
|
+
typeof record.error.message === 'string') {
|
|
64
|
+
return record.error.message;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
return JSON.stringify(error);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return String(error);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Strict check: returns true only for known, unambiguous context-overflow
|
|
76
|
+
* phrases. Use when the recovery action is expensive (full prune + retry)
|
|
77
|
+
* and false positives are undesirable.
|
|
78
|
+
*/
|
|
79
|
+
function isContextOverflowError(errorMessage) {
|
|
80
|
+
if (!errorMessage) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
const lower = errorMessage.toLowerCase();
|
|
84
|
+
if (FALSE_POSITIVE_RE.test(lower)) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
return CONTEXT_OVERFLOW_PHRASES.some((phrase) => lower.includes(phrase));
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Loose check: returns true for known phrases OR heuristic regex matches.
|
|
91
|
+
* Preferred by the graph's emergency-prune retry because the cost of a
|
|
92
|
+
* false positive is one extra retry with a smaller context, while the
|
|
93
|
+
* cost of a false negative is an opaque provider failure surfaced to
|
|
94
|
+
* the user.
|
|
95
|
+
*/
|
|
96
|
+
function isLikelyContextOverflowError(errorMessage) {
|
|
97
|
+
if (!errorMessage) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
if (isContextOverflowError(errorMessage)) {
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
const lower = errorMessage.toLowerCase();
|
|
104
|
+
if (FALSE_POSITIVE_RE.test(lower)) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
return CONTEXT_OVERFLOW_HINT_RE.test(lower);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
exports.extractErrorMessage = extractErrorMessage;
|
|
111
|
+
exports.isContextOverflowError = isContextOverflowError;
|
|
112
|
+
exports.isLikelyContextOverflowError = isLikelyContextOverflowError;
|
|
113
|
+
//# sourceMappingURL=errors.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.cjs","sources":["../../../src/utils/errors.ts"],"sourcesContent":["/**\n * Context-overflow error detection helpers.\n *\n * Provider error messages vary — Anthropic returns \"prompt is too long\",\n * OpenAI returns \"context_length_exceeded\", Bedrock returns \"Input is too\n * long\", Google returns a size-limit phrase. This module centralises the\n * phrase list so the agent graph's emergency-prune retry can classify\n * errors consistently instead of duplicating inline substring matches at\n * each call site.\n *\n * The strict check (`isContextOverflowError`) matches only known phrases.\n * The loose check (`isLikelyContextOverflowError`) also matches a heuristic\n * regex for providers we haven't explicitly catalogued. Both filter out\n * false positives (rate-limit, auth, quota, billing) that might otherwise\n * trigger an unnecessary prune retry.\n */\n\nconst CONTEXT_OVERFLOW_PHRASES = [\n 'request_too_large',\n 'context length exceeded',\n 'maximum context length',\n 'prompt is too long',\n 'exceeds model context window',\n 'exceeds the model',\n 'too large for model',\n 'context_length_exceeded',\n 'max_tokens',\n 'token limit',\n 'input too long',\n 'input is too long',\n 'payload too large',\n 'content_too_large',\n] as const;\n\nconst CONTEXT_OVERFLOW_HINT_RE =\n /413|too large|too long|context.*exceed|exceed.*context|token.*limit|limit.*token|prompt.*size|size.*limit|maximum.*length|length.*maximum/i;\n\nconst FALSE_POSITIVE_RE =\n /rate.?limit|too many requests|quota|billing|auth|permission|forbidden/i;\n\n/**\n * Extracts a human-readable error message from an unknown error value.\n * Walks common shapes: strings, Error instances, `{ message }`,\n * `{ error: string }`, `{ error: { message } }`. Falls back to\n * JSON.stringify or String() so callers never have to null-check.\n */\nexport function extractErrorMessage(error: unknown): string {\n if (error == null) {\n return '';\n }\n if (typeof error === 'string') {\n return error;\n }\n if (error instanceof Error) {\n return error.message;\n }\n if (typeof error === 'object') {\n const record = error as Record<string, unknown>;\n if (typeof record.message === 'string') {\n return record.message;\n }\n if (typeof record.error === 'string') {\n return record.error;\n }\n if (\n typeof record.error === 'object' &&\n record.error != null &&\n typeof (record.error as Record<string, unknown>).message === 'string'\n ) {\n return (record.error as Record<string, unknown>).message as string;\n }\n }\n try {\n return JSON.stringify(error);\n } catch {\n return String(error);\n }\n}\n\n/**\n * Strict check: returns true only for known, unambiguous context-overflow\n * phrases. Use when the recovery action is expensive (full prune + retry)\n * and false positives are undesirable.\n */\nexport function isContextOverflowError(errorMessage?: string): boolean {\n if (!errorMessage) {\n return false;\n }\n const lower = errorMessage.toLowerCase();\n if (FALSE_POSITIVE_RE.test(lower)) {\n return false;\n }\n return CONTEXT_OVERFLOW_PHRASES.some((phrase) => lower.includes(phrase));\n}\n\n/**\n * Loose check: returns true for known phrases OR heuristic regex matches.\n * Preferred by the graph's emergency-prune retry because the cost of a\n * false positive is one extra retry with a smaller context, while the\n * cost of a false negative is an opaque provider failure surfaced to\n * the user.\n */\nexport function isLikelyContextOverflowError(errorMessage?: string): boolean {\n if (!errorMessage) {\n return false;\n }\n if (isContextOverflowError(errorMessage)) {\n return true;\n }\n const lower = errorMessage.toLowerCase();\n if (FALSE_POSITIVE_RE.test(lower)) {\n return false;\n }\n return CONTEXT_OVERFLOW_HINT_RE.test(lower);\n}\n"],"names":[],"mappings":";;AAAA;;;;;;;;;;;;;;;AAeG;AAEH,MAAM,wBAAwB,GAAG;IAC/B,mBAAmB;IACnB,yBAAyB;IACzB,wBAAwB;IACxB,oBAAoB;IACpB,8BAA8B;IAC9B,mBAAmB;IACnB,qBAAqB;IACrB,yBAAyB;IACzB,YAAY;IACZ,aAAa;IACb,gBAAgB;IAChB,mBAAmB;IACnB,mBAAmB;IACnB,mBAAmB;CACX;AAEV,MAAM,wBAAwB,GAC5B,4IAA4I;AAE9I,MAAM,iBAAiB,GACrB,wEAAwE;AAE1E;;;;;AAKG;AACG,SAAU,mBAAmB,CAAC,KAAc,EAAA;AAChD,IAAA,IAAI,KAAK,IAAI,IAAI,EAAE;AACjB,QAAA,OAAO,EAAE;IACX;AACA,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;AAC7B,QAAA,OAAO,KAAK;IACd;AACA,IAAA,IAAI,KAAK,YAAY,KAAK,EAAE;QAC1B,OAAO,KAAK,CAAC,OAAO;IACtB;AACA,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;QAC7B,MAAM,MAAM,GAAG,KAAgC;AAC/C,QAAA,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE;YACtC,OAAO,MAAM,CAAC,OAAO;QACvB;AACA,QAAA,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE;YACpC,OAAO,MAAM,CAAC,KAAK;QACrB;AACA,QAAA,IACE,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ;YAChC,MAAM,CAAC,KAAK,IAAI,IAAI;YACpB,OAAQ,MAAM,CAAC,KAAiC,CAAC,OAAO,KAAK,QAAQ,EACrE;AACA,YAAA,OAAQ,MAAM,CAAC,KAAiC,CAAC,OAAiB;QACpE;IACF;AACA,IAAA,IAAI;AACF,QAAA,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC;IAC9B;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB;AACF;AAEA;;;;AAIG;AACG,SAAU,sBAAsB,CAAC,YAAqB,EAAA;IAC1D,IAAI,CAAC,YAAY,EAAE;AACjB,QAAA,OAAO,KAAK;IACd;AACA,IAAA,MAAM,KAAK,GAAG,YAAY,CAAC,WAAW,EAAE;AACxC,IAAA,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACjC,QAAA,OAAO,KAAK;IACd;AACA,IAAA,OAAO,wBAAwB,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC1E;AAEA;;;;;;AAMG;AACG,SAAU,4BAA4B,CAAC,YAAqB,EAAA;IAChE,IAAI,CAAC,YAAY,EAAE;AACjB,QAAA,OAAO,KAAK;IACd;AACA,IAAA,IAAI,sBAAsB,CAAC,YAAY,CAAC,EAAE;AACxC,QAAA,OAAO,IAAI;IACb;AACA,IAAA,MAAM,KAAK,GAAG,YAAY,CAAC,WAAW,EAAE;AACxC,IAAA,IAAI,iBAAiB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACjC,QAAA,OAAO,KAAK;IACd;AACA,IAAA,OAAO,wBAAwB,CAAC,IAAI,CAAC,KAAK,CAAC;AAC7C;;;;;;"}
|
|
@@ -27,6 +27,7 @@ import { hasTaskTool, buildPostPruneNote, detectDocuments, shouldInjectMultiDocH
|
|
|
27
27
|
import { ToolDiscoveryCache } from '../utils/toolDiscoveryCache.mjs';
|
|
28
28
|
import { createPruneCalibration, applyCalibration, updatePruneCalibration } from '../utils/pruneCalibration.mjs';
|
|
29
29
|
import { buildFileManifestBlock } from '../utils/fileManifest.mjs';
|
|
30
|
+
import { isLikelyContextOverflowError } from '../utils/errors.mjs';
|
|
30
31
|
import { getChatModelClass, manualToolStreamProviders } from '../llm/providers.mjs';
|
|
31
32
|
import { ToolNode, toolsCondition } from '../tools/ToolNode.mjs';
|
|
32
33
|
import { ChatOpenAI, AzureChatOpenAI } from '../llm/openai/index.mjs';
|
|
@@ -1548,14 +1549,8 @@ class StandardGraph extends Graph {
|
|
|
1548
1549
|
}, config);
|
|
1549
1550
|
}
|
|
1550
1551
|
catch (primaryError) {
|
|
1551
|
-
|
|
1552
|
-
const
|
|
1553
|
-
const isInputTooLongError = errorMessage.includes('too long') ||
|
|
1554
|
-
errorMessage.includes('input is too long') ||
|
|
1555
|
-
errorMessage.includes('context length') ||
|
|
1556
|
-
errorMessage.includes('maximum context') ||
|
|
1557
|
-
errorMessage.includes('validationexception') ||
|
|
1558
|
-
errorMessage.includes('prompt is too long');
|
|
1552
|
+
const errorMessage = primaryError.message;
|
|
1553
|
+
const isInputTooLongError = isLikelyContextOverflowError(errorMessage);
|
|
1559
1554
|
// Log when we detect the error
|
|
1560
1555
|
if (isInputTooLongError) {
|
|
1561
1556
|
mwarn('[Graph] Detected input too long error:', errorMessage.substring(0, 200));
|
|
@@ -1659,10 +1654,8 @@ If I seem to be missing something we discussed earlier, just give me a quick rem
|
|
|
1659
1654
|
console.info(`[Graph] ✅ Retry successful at ${reductionFactor * 100}% with ${reducedMessages.length} messages (reduced from ${finalMessages.length})`);
|
|
1660
1655
|
}
|
|
1661
1656
|
catch (retryError) {
|
|
1662
|
-
const retryErrorMsg = retryError.message
|
|
1663
|
-
const stillTooLong = retryErrorMsg
|
|
1664
|
-
retryErrorMsg.includes('context length') ||
|
|
1665
|
-
retryErrorMsg.includes('validationexception');
|
|
1657
|
+
const retryErrorMsg = retryError.message;
|
|
1658
|
+
const stillTooLong = isLikelyContextOverflowError(retryErrorMsg);
|
|
1666
1659
|
if (stillTooLong && reductionFactor > 0.1) {
|
|
1667
1660
|
mwarn(`[Graph] Still too long at ${reductionFactor * 100}%, trying more aggressive pruning...`);
|
|
1668
1661
|
}
|