@multiplayer-app/agent 0.1.10 → 0.1.12
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/agent/model-failure.d.ts +10 -0
- package/dist/agent/model-failure.d.ts.map +1 -0
- package/dist/agent/model-failure.js +50 -0
- package/dist/agent/model-failure.js.map +1 -0
- package/dist/agent/profiles/research.d.ts.map +1 -1
- package/dist/agent/profiles/research.js +21 -11
- package/dist/agent/profiles/research.js.map +1 -1
- package/dist/agent/progress-reminder.test.d.ts +2 -0
- package/dist/agent/progress-reminder.test.d.ts.map +1 -0
- package/dist/agent/progress-reminder.test.js +20 -0
- package/dist/agent/progress-reminder.test.js.map +1 -0
- package/dist/agent/turn-runner.d.ts +18 -1
- package/dist/agent/turn-runner.d.ts.map +1 -1
- package/dist/agent/turn-runner.js +60 -7
- package/dist/agent/turn-runner.js.map +1 -1
- package/dist/context-pruning.d.ts +13 -0
- package/dist/context-pruning.d.ts.map +1 -0
- package/dist/context-pruning.js +61 -0
- package/dist/context-pruning.js.map +1 -0
- package/dist/context-pruning.test.d.ts +2 -0
- package/dist/context-pruning.test.d.ts.map +1 -0
- package/dist/context-pruning.test.js +48 -0
- package/dist/context-pruning.test.js.map +1 -0
- package/dist/models/resolve-model.d.ts.map +1 -1
- package/dist/models/resolve-model.js +3 -1
- package/dist/models/resolve-model.js.map +1 -1
- package/dist/models/usage.d.ts +4 -0
- package/dist/models/usage.d.ts.map +1 -1
- package/dist/models/usage.js +8 -2
- package/dist/models/usage.js.map +1 -1
- package/dist/research/extract-texts.d.ts +41 -0
- package/dist/research/extract-texts.d.ts.map +1 -0
- package/dist/research/extract-texts.js +239 -0
- package/dist/research/extract-texts.js.map +1 -0
- package/dist/research/extract-texts.test.d.ts +2 -0
- package/dist/research/extract-texts.test.d.ts.map +1 -0
- package/dist/research/extract-texts.test.js +120 -0
- package/dist/research/extract-texts.test.js.map +1 -0
- package/dist/research/extraction-tool.d.ts +1 -1
- package/dist/research/extraction-tool.d.ts.map +1 -1
- package/dist/research/extraction-tool.js +24 -50
- package/dist/research/extraction-tool.js.map +1 -1
- package/dist/research/extraction-tool.test.js +2 -0
- package/dist/research/extraction-tool.test.js.map +1 -1
- package/dist/research/filingramp/attachment-tools.d.ts.map +1 -1
- package/dist/research/filingramp/attachment-tools.js +122 -23
- package/dist/research/filingramp/attachment-tools.js.map +1 -1
- package/dist/research/filingramp/document-search-tool.d.ts.map +1 -1
- package/dist/research/filingramp/document-search-tool.js +88 -30
- package/dist/research/filingramp/document-search-tool.js.map +1 -1
- package/dist/research/filingramp/filing-detail-tool.d.ts +4 -0
- package/dist/research/filingramp/filing-detail-tool.d.ts.map +1 -1
- package/dist/research/filingramp/filing-detail-tool.js +57 -10
- package/dist/research/filingramp/filing-detail-tool.js.map +1 -1
- package/dist/research/filingramp/shared.d.ts +16 -0
- package/dist/research/filingramp/shared.d.ts.map +1 -1
- package/dist/research/filingramp/shared.js +74 -2
- package/dist/research/filingramp/shared.js.map +1 -1
- package/dist/research/filingramp-contract.d.ts.map +1 -1
- package/dist/research/filingramp-contract.js +8 -2
- package/dist/research/filingramp-contract.js.map +1 -1
- package/dist/research/filingramp-tools.d.ts +1 -0
- package/dist/research/filingramp-tools.d.ts.map +1 -1
- package/dist/research/filingramp-tools.js +5 -0
- package/dist/research/filingramp-tools.js.map +1 -1
- package/dist/research/filingramp-tools.test.js +93 -0
- package/dist/research/filingramp-tools.test.js.map +1 -1
- package/dist/research/prompt.d.ts.map +1 -1
- package/dist/research/prompt.js +16 -7
- package/dist/research/prompt.js.map +1 -1
- package/dist/runtime/config.d.ts.map +1 -1
- package/dist/runtime/config.js +6 -5
- package/dist/runtime/config.js.map +1 -1
- package/dist/runtime/lambda-microvm.js +73 -25
- package/dist/runtime/lambda-microvm.js.map +1 -1
- package/dist/runtime/microvm-bootstrap.d.ts +18 -0
- package/dist/runtime/microvm-bootstrap.d.ts.map +1 -0
- package/dist/runtime/microvm-bootstrap.js +77 -0
- package/dist/runtime/microvm-bootstrap.js.map +1 -0
- package/dist/runtime/microvm-bootstrap.test.d.ts +2 -0
- package/dist/runtime/microvm-bootstrap.test.d.ts.map +1 -0
- package/dist/runtime/microvm-bootstrap.test.js +50 -0
- package/dist/runtime/microvm-bootstrap.test.js.map +1 -0
- package/dist/session/runtime.d.ts +8 -0
- package/dist/session/runtime.d.ts.map +1 -1
- package/dist/session/runtime.js +49 -8
- package/dist/session/runtime.js.map +1 -1
- package/dist/tool-call-repair.d.ts +11 -0
- package/dist/tool-call-repair.d.ts.map +1 -0
- package/dist/tool-call-repair.js +91 -0
- package/dist/tool-call-repair.js.map +1 -0
- package/dist/tool-call-repair.test.d.ts +2 -0
- package/dist/tool-call-repair.test.d.ts.map +1 -0
- package/dist/tool-call-repair.test.js +50 -0
- package/dist/tool-call-repair.test.js.map +1 -0
- package/dist/tools/exec-tools.d.ts +1 -0
- package/dist/tools/exec-tools.d.ts.map +1 -1
- package/dist/tools/exec-tools.js +23 -3
- package/dist/tools/exec-tools.js.map +1 -1
- package/dist/transport/protocol.d.ts +9 -4
- package/dist/transport/protocol.d.ts.map +1 -1
- package/dist/transport/protocol.js +6 -6
- package/dist/transport/protocol.js.map +1 -1
- package/dist/transport/protocol.test.js +1 -1
- package/dist/transport/protocol.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** The failure as the provider reported it, for the log: the message plus the response body it hides. */
|
|
2
|
+
export declare function describeModelFailure(error: unknown): string;
|
|
3
|
+
/**
|
|
4
|
+
* What the user reads when a model call fails for good: the cause in one sentence and what to
|
|
5
|
+
* do about it. The provider's own text goes to the log instead, since it carries API key ids,
|
|
6
|
+
* spend figures and request internals that an end user cannot act on and should not see.
|
|
7
|
+
* Undefined for failures that are not the provider's (storage, workspace), whose message stands.
|
|
8
|
+
*/
|
|
9
|
+
export declare function userFacingModelFailure(error: unknown): string | undefined;
|
|
10
|
+
//# sourceMappingURL=model-failure.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-failure.d.ts","sourceRoot":"","sources":["../../src/agent/model-failure.ts"],"names":[],"mappings":"AAEA,yGAAyG;AACzG,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAM3D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAwBzE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.describeModelFailure = describeModelFailure;
|
|
4
|
+
exports.userFacingModelFailure = userFacingModelFailure;
|
|
5
|
+
const ai_1 = require("ai");
|
|
6
|
+
/** The failure as the provider reported it, for the log: the message plus the response body it hides. */
|
|
7
|
+
function describeModelFailure(error) {
|
|
8
|
+
const cause = unwrap(error);
|
|
9
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
10
|
+
const body = cause === null || cause === void 0 ? void 0 : cause.responseBody;
|
|
11
|
+
if (typeof body !== 'string' || !body.trim() || message.includes(body.trim()))
|
|
12
|
+
return message;
|
|
13
|
+
return `${message} body=${body.trim().slice(0, 600)}`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* What the user reads when a model call fails for good: the cause in one sentence and what to
|
|
17
|
+
* do about it. The provider's own text goes to the log instead, since it carries API key ids,
|
|
18
|
+
* spend figures and request internals that an end user cannot act on and should not see.
|
|
19
|
+
* Undefined for failures that are not the provider's (storage, workspace), whose message stands.
|
|
20
|
+
*/
|
|
21
|
+
function userFacingModelFailure(error) {
|
|
22
|
+
const cause = unwrap(error);
|
|
23
|
+
const statusCode = cause === null || cause === void 0 ? void 0 : cause.statusCode;
|
|
24
|
+
const status = typeof statusCode === 'number' ? statusCode : undefined;
|
|
25
|
+
const text = describeModelFailure(cause).toLowerCase();
|
|
26
|
+
if (status === 402 || /key limit|spending limit|insufficient credits|insufficient_quota|quota|billing/.test(text)) {
|
|
27
|
+
return 'The AI provider has reached the spending limit for this workspace. Ask an administrator to raise it, then send the request again.';
|
|
28
|
+
}
|
|
29
|
+
if (status === 401 || status === 403 || /invalid api key|unauthorized|forbidden|authentication/.test(text)) {
|
|
30
|
+
return "The AI provider rejected this workspace's API key. Ask an administrator to check the provider settings.";
|
|
31
|
+
}
|
|
32
|
+
if (/context length|context window|too many tokens|maximum context|prompt is too long|input is too long/.test(text)) {
|
|
33
|
+
return 'The conversation is too long for the selected model. Start a new session or choose a model with a larger context window.';
|
|
34
|
+
}
|
|
35
|
+
if (status === 404 || /model .*not found|no endpoints found|not a valid model/.test(text)) {
|
|
36
|
+
return 'The selected model is not available from the AI provider. Choose another model and try again.';
|
|
37
|
+
}
|
|
38
|
+
if (status === 429 || /rate.?limit|too many requests|overloaded/.test(text)) {
|
|
39
|
+
return 'The AI provider is busy right now. Try again in a moment.';
|
|
40
|
+
}
|
|
41
|
+
if ((status !== undefined && status >= 500) || /econnreset|etimedout|fetch failed|socket hang up|timed out/.test(text)) {
|
|
42
|
+
return 'The AI provider did not respond. Try again in a moment.';
|
|
43
|
+
}
|
|
44
|
+
return ai_1.APICallError.isInstance(cause) || status !== undefined ? 'The AI provider returned an error. Try again in a moment.' : undefined;
|
|
45
|
+
}
|
|
46
|
+
/** The ai SDK wraps the last provider error in a RetryError once its own retries run out. */
|
|
47
|
+
function unwrap(error) {
|
|
48
|
+
return ai_1.RetryError.isInstance(error) ? error.lastError : error;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=model-failure.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-failure.js","sourceRoot":"","sources":["../../src/agent/model-failure.ts"],"names":[],"mappings":";;AAGA,oDAMC;AAQD,wDAwBC;AAzCD,2BAA6C;AAE7C,yGAAyG;AACzG,SAAgB,oBAAoB,CAAC,KAAc;IACjD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAC3B,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IACtE,MAAM,IAAI,GAAI,KAA2C,aAA3C,KAAK,uBAAL,KAAK,CAAwC,YAAY,CAAA;IACvE,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAAE,OAAO,OAAO,CAAA;IAC7F,OAAO,GAAG,OAAO,SAAS,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAA;AACvD,CAAC;AAED;;;;;GAKG;AACH,SAAgB,sBAAsB,CAAC,KAAc;IACnD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAC3B,MAAM,UAAU,GAAI,KAAyC,aAAzC,KAAK,uBAAL,KAAK,CAAsC,UAAU,CAAA;IACzE,MAAM,MAAM,GAAG,OAAO,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAA;IACtE,MAAM,IAAI,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAA;IACtD,IAAI,MAAM,KAAK,GAAG,IAAI,gFAAgF,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAClH,OAAO,mIAAmI,CAAA;IAC5I,CAAC;IACD,IAAI,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,GAAG,IAAI,uDAAuD,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3G,OAAO,yGAAyG,CAAA;IAClH,CAAC;IACD,IAAI,oGAAoG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpH,OAAO,0HAA0H,CAAA;IACnI,CAAC;IACD,IAAI,MAAM,KAAK,GAAG,IAAI,wDAAwD,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1F,OAAO,+FAA+F,CAAA;IACxG,CAAC;IACD,IAAI,MAAM,KAAK,GAAG,IAAI,0CAA0C,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5E,OAAO,2DAA2D,CAAA;IACpE,CAAC;IACD,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,MAAM,IAAI,GAAG,CAAC,IAAI,4DAA4D,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACvH,OAAO,yDAAyD,CAAA;IAClE,CAAC;IACD,OAAO,iBAAY,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,2DAA2D,CAAC,CAAC,CAAC,SAAS,CAAA;AACzI,CAAC;AAED,6FAA6F;AAC7F,SAAS,MAAM,CAAC,KAAc;IAC5B,OAAO,eAAU,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAA;AAC/D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"research.d.ts","sourceRoot":"","sources":["../../../src/agent/profiles/research.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"research.d.ts","sourceRoot":"","sources":["../../../src/agent/profiles/research.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAEpD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAQ9D,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,GAAG,eAAe,CAyCrG"}
|
|
@@ -8,9 +8,16 @@ const filingramp_tools_1 = require("../../research/filingramp-tools");
|
|
|
8
8
|
const prompt_1 = require("../../research/prompt");
|
|
9
9
|
const tools_1 = require("../../session/tools");
|
|
10
10
|
function createResearchAgent(config, workspaceDir) {
|
|
11
|
-
// Keep authentication and resolved scope labels across turns. These tools do not own turn state
|
|
11
|
+
// Keep authentication and resolved scope labels across turns. These tools do not own turn state:
|
|
12
|
+
// bulk progress goes to whichever turn is running, through the slot createTools fills each turn.
|
|
13
|
+
let reportProgress;
|
|
12
14
|
const filingTools = config.filingRamp
|
|
13
|
-
? (0, filingramp_tools_1.createFilingRampTools)({
|
|
15
|
+
? (0, filingramp_tools_1.createFilingRampTools)({
|
|
16
|
+
client: new filingramp_client_1.FilingRampClient(config.filingRamp),
|
|
17
|
+
workspaceDir,
|
|
18
|
+
scope: config.researchScope,
|
|
19
|
+
onProgress: (toolCallId, done, total, label) => reportProgress === null || reportProgress === void 0 ? void 0 : reportProgress([{ key: 'bulk', label, status: done < total ? 'active' : 'done', detail: `${done}/${total}` }], toolCallId),
|
|
20
|
+
})
|
|
14
21
|
: {};
|
|
15
22
|
if (!config.filingRamp) {
|
|
16
23
|
console.warn('[session] research profile without FilingRamp credentials — filing tools disabled');
|
|
@@ -29,15 +36,18 @@ function createResearchAgent(config, workspaceDir) {
|
|
|
29
36
|
restored,
|
|
30
37
|
});
|
|
31
38
|
},
|
|
32
|
-
createTools: (context) =>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
createTools: (context) => {
|
|
40
|
+
reportProgress = (steps, toolCallId) => context.reportProgress(steps, toolCallId);
|
|
41
|
+
return {
|
|
42
|
+
...(0, tools_1.createSessionTools)(context, config.mcpConnections),
|
|
43
|
+
...filingTools,
|
|
44
|
+
extract_from_texts: (0, extraction_tool_1.createExtractionTool)(context, {
|
|
45
|
+
id: config.extractionModel,
|
|
46
|
+
provider: config.provider,
|
|
47
|
+
attribution: attribution_1.OPENROUTER_APPS.DEEP_RESEARCH,
|
|
48
|
+
}),
|
|
49
|
+
};
|
|
50
|
+
},
|
|
41
51
|
};
|
|
42
52
|
}
|
|
43
53
|
//# sourceMappingURL=research.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"research.js","sourceRoot":"","sources":["../../../src/agent/profiles/research.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"research.js","sourceRoot":"","sources":["../../../src/agent/profiles/research.ts"],"names":[],"mappings":";;AAUA,kDAyCC;AAlDD,0DAA0D;AAE1D,oEAAqE;AACrE,wEAAmE;AACnE,sEAAuE;AACvE,kDAA0F;AAC1F,+CAAwD;AAGxD,SAAgB,mBAAmB,CAAC,MAA0B,EAAE,YAAoB;IAClF,iGAAiG;IACjG,iGAAiG;IACjG,IAAI,cAAgE,CAAA;IACpE,MAAM,WAAW,GAAG,MAAM,CAAC,UAAU;QACnC,CAAC,CAAC,IAAA,wCAAqB,EAAC;YACpB,MAAM,EAAE,IAAI,oCAAgB,CAAC,MAAM,CAAC,UAAU,CAAC;YAC/C,YAAY;YACZ,KAAK,EAAE,MAAM,CAAC,aAAa;YAC3B,UAAU,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,CAC7C,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAG,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,IAAI,KAAK,EAAE,EAAE,CAAC,EAAE,UAAU,CAAC;SAC/H,CAAC;QACJ,CAAC,CAAC,EAAE,CAAA;IACN,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,mFAAmF,CAAC,CAAA;IACnG,CAAC;IAED,OAAO;QACL,OAAO,EAAE,UAAU;QACnB,KAAK,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,WAAW,EAAE,6BAAe,CAAC,aAAa,EAAE;QAClG,QAAQ,EAAE,EAAE;QACZ,oBAAoB,EAAE,gCAAuB;QAC7C,YAAY,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,EAAE;;YAAC,OAAA,IAAA,kCAAyB,EAAC;gBACrE,KAAK,EAAE,MAAM,CAAC,aAAa;gBAC3B,YAAY,EAAE,OAAO,CAAC,MAAA,MAAM,CAAC,UAAU,0CAAE,YAAY,CAAC;gBACtD,WAAW;gBACX,QAAQ;aACT,CAAC,CAAA;SAAA;QACF,WAAW,EAAE,CAAC,OAAO,EAAE,EAAE;YACvB,cAAc,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,EAAE,UAAU,CAAC,CAAA;YACjF,OAAO;gBACL,GAAG,IAAA,0BAAkB,EAAC,OAAO,EAAE,MAAM,CAAC,cAAc,CAAC;gBACrD,GAAG,WAAW;gBACd,kBAAkB,EAAE,IAAA,sCAAoB,EAAC,OAAO,EAAE;oBAChD,EAAE,EAAE,MAAM,CAAC,eAAe;oBAC1B,QAAQ,EAAE,MAAM,CAAC,QAAQ;oBACzB,WAAW,EAAE,6BAAe,CAAC,aAAa;iBAC3C,CAAC;aACH,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress-reminder.test.d.ts","sourceRoot":"","sources":["../../src/agent/progress-reminder.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
7
|
+
const node_test_1 = require("node:test");
|
|
8
|
+
const turn_runner_1 = require("./turn-runner");
|
|
9
|
+
const step = (...names) => ({ toolCalls: names.map((toolName) => ({ toolName })) });
|
|
10
|
+
(0, node_test_1.describe)('stepsSinceProgress', () => {
|
|
11
|
+
(0, node_test_1.it)('counts steps after the last report_progress call', () => {
|
|
12
|
+
strict_1.default.equal((0, turn_runner_1.stepsSinceProgress)([step('report_progress'), step('get_filing'), step('run_command')]), 2);
|
|
13
|
+
strict_1.default.equal((0, turn_runner_1.stepsSinceProgress)([step('get_filing'), step('report_progress', 'run_command')]), 0);
|
|
14
|
+
});
|
|
15
|
+
(0, node_test_1.it)('counts every step when the agent never reported', () => {
|
|
16
|
+
strict_1.default.equal((0, turn_runner_1.stepsSinceProgress)([step('get_filing'), step('run_command')]), 2);
|
|
17
|
+
strict_1.default.equal((0, turn_runner_1.stepsSinceProgress)([]), 0);
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
//# sourceMappingURL=progress-reminder.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress-reminder.test.js","sourceRoot":"","sources":["../../src/agent/progress-reminder.test.ts"],"names":[],"mappings":";;;;;AAAA,gEAAuC;AACvC,yCAAwC;AACxC,+CAAkD;AAElD,MAAM,IAAI,GAAG,CAAC,GAAG,KAAe,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAA;AAE7F,IAAA,oBAAQ,EAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,IAAA,cAAE,EAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,gBAAM,CAAC,KAAK,CAAC,IAAA,gCAAkB,EAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QACvG,gBAAM,CAAC,KAAK,CAAC,IAAA,gCAAkB,EAAC,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IACnG,CAAC,CAAC,CAAA;IAEF,IAAA,cAAE,EAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,gBAAM,CAAC,KAAK,CAAC,IAAA,gCAAkB,EAAC,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;QAC9E,gBAAM,CAAC,KAAK,CAAC,IAAA,gCAAkB,EAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
|
|
@@ -2,6 +2,12 @@ import { type ModelMessage } from 'ai';
|
|
|
2
2
|
import type { AgentDefinition } from './definition';
|
|
3
3
|
import type { OutboundEvent } from '../transport/link';
|
|
4
4
|
import { type TokenUsage } from '../models/usage';
|
|
5
|
+
/** Steps since the agent last called report_progress in this turn (all of them when it never did). */
|
|
6
|
+
export declare function stepsSinceProgress(steps: Array<{
|
|
7
|
+
toolCalls: Array<{
|
|
8
|
+
toolName: string;
|
|
9
|
+
}>;
|
|
10
|
+
}>): number;
|
|
5
11
|
export interface TurnInput {
|
|
6
12
|
messageId: string;
|
|
7
13
|
messages: ModelMessage[];
|
|
@@ -9,6 +15,10 @@ export interface TurnInput {
|
|
|
9
15
|
workspaceDir: string;
|
|
10
16
|
abortSignal: AbortSignal;
|
|
11
17
|
budgetExceeded(): boolean;
|
|
18
|
+
/** Past the share of the budget where a research turn stops and saves what it has. */
|
|
19
|
+
nearBudget?(): boolean;
|
|
20
|
+
/** The user chose "wrap up" at the budget pause: this turn only saves what there is. */
|
|
21
|
+
wrapUpOnly?: boolean;
|
|
12
22
|
recordUsage(usage: TokenUsage): void;
|
|
13
23
|
emit(event: OutboundEvent): void;
|
|
14
24
|
}
|
|
@@ -17,15 +27,22 @@ interface TurnOutput {
|
|
|
17
27
|
messages: ModelMessage[];
|
|
18
28
|
partialText: string;
|
|
19
29
|
askedUser: boolean;
|
|
30
|
+
/** The turn ran the budget wrap-up. */
|
|
31
|
+
wrappedUp?: boolean;
|
|
32
|
+
/** The wrap-up wrote or published files, so the pause notice may say the work is saved. */
|
|
33
|
+
saved?: boolean;
|
|
20
34
|
}
|
|
21
35
|
export type TurnResult = TurnOutput & ({
|
|
22
36
|
status: 'completed';
|
|
23
37
|
text: string;
|
|
24
38
|
} | {
|
|
25
39
|
status: 'aborted';
|
|
26
|
-
}
|
|
40
|
+
}
|
|
41
|
+
/** `error` is the failure as the provider reported it (for the log); `userMessage` is what the user reads. */
|
|
42
|
+
| {
|
|
27
43
|
status: 'failed';
|
|
28
44
|
error: string;
|
|
45
|
+
userMessage: string;
|
|
29
46
|
});
|
|
30
47
|
/** Executes one turn. It neither mutates conversation history nor checkpoints or schedules work. */
|
|
31
48
|
export declare class TurnRunner {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turn-runner.d.ts","sourceRoot":"","sources":["../../src/agent/turn-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,YAAY,
|
|
1
|
+
{"version":3,"file":"turn-runner.d.ts","sourceRoot":"","sources":["../../src/agent/turn-runner.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,YAAY,EAAiC,MAAM,IAAI,CAAA;AAC9F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAGtD,OAAO,EAAW,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAkB1D,sGAAsG;AACtG,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC;IAAE,SAAS,EAAE,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,GAAG,MAAM,CAKnG;AAED,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,WAAW,CAAA;IACxB,cAAc,IAAI,OAAO,CAAA;IACzB,sFAAsF;IACtF,UAAU,CAAC,IAAI,OAAO,CAAA;IACtB,wFAAwF;IACxF,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAA;IACpC,IAAI,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAA;CACjC;AAED,UAAU,UAAU;IAClB,kGAAkG;IAClG,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,OAAO,CAAA;IAClB,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,2FAA2F;IAC3F,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,CAClC;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE;AACvB,8GAA8G;GAC5G;IAAE,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAC3D,CAAA;AAED,oGAAoG;AACpG,qBAAa,UAAU;IACT,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,eAAe;IAElD,GAAG,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC;CA6GjD"}
|
|
@@ -1,19 +1,43 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TurnRunner = void 0;
|
|
4
|
+
exports.stepsSinceProgress = stepsSinceProgress;
|
|
4
5
|
const ai_1 = require("ai");
|
|
5
6
|
const resolve_model_1 = require("../models/resolve-model");
|
|
6
7
|
const usage_1 = require("../models/usage");
|
|
8
|
+
const context_pruning_1 = require("../context-pruning");
|
|
9
|
+
const tool_call_repair_1 = require("../tool-call-repair");
|
|
10
|
+
const model_failure_1 = require("./model-failure");
|
|
11
|
+
/** Steps the budget wrap-up may take (write notes and findings, publish, summarize) before the turn stops. */
|
|
12
|
+
const WRAP_UP_STEPS = 4;
|
|
13
|
+
const WRAP_UP_TOOLS = ['write_files', 'read_file', 'run_command', 'publish_results'];
|
|
14
|
+
const WRAP_UP_INSTRUCTIONS = `(Automatic note, not from the user.) The token budget for this session is nearly used up. Stop researching now: no new searches, downloads or extraction. In the next few steps only:
|
|
15
|
+
1. Update research/notes.md: what is done, what is not, and the exact next step.
|
|
16
|
+
2. Write research/findings.md as a draft marked PARTIAL at the top, with what you found so far and its coverage (documents read vs not yet read).
|
|
17
|
+
3. Call publish_results with those files, then end with a short summary saying the findings are partial and the user can reply "continue".`;
|
|
18
|
+
/** Steps without a report_progress call after which the agent is reminded to update the checklist. */
|
|
19
|
+
const PROGRESS_REMINDER_STEPS = 6;
|
|
20
|
+
const PROGRESS_REMINDER = '(Automatic check, not from the user: the pinned "Research progress" checklist still shows the phases as you last reported them. If a phase has started or finished since, call report_progress with the full updated list now, alongside your next action. If nothing changed, ignore this note.)';
|
|
21
|
+
/** Steps since the agent last called report_progress in this turn (all of them when it never did). */
|
|
22
|
+
function stepsSinceProgress(steps) {
|
|
23
|
+
for (let index = steps.length - 1; index >= 0; index -= 1) {
|
|
24
|
+
if (steps[index].toolCalls.some((call) => call.toolName === 'report_progress'))
|
|
25
|
+
return steps.length - 1 - index;
|
|
26
|
+
}
|
|
27
|
+
return steps.length;
|
|
28
|
+
}
|
|
7
29
|
/** Executes one turn. It neither mutates conversation history nor checkpoints or schedules work. */
|
|
8
30
|
class TurnRunner {
|
|
9
31
|
constructor(definition) {
|
|
10
32
|
this.definition = definition;
|
|
11
33
|
}
|
|
12
34
|
async run(input) {
|
|
13
|
-
var _a, _b;
|
|
35
|
+
var _a, _b, _c;
|
|
14
36
|
const { messageId, abortSignal, emit } = input;
|
|
15
37
|
let partialText = '';
|
|
16
38
|
let askedUser = false;
|
|
39
|
+
let wrapUpFrom;
|
|
40
|
+
let saved = false;
|
|
17
41
|
let responseMessages;
|
|
18
42
|
const recordUsage = (usage, model) => {
|
|
19
43
|
input.recordUsage(usage);
|
|
@@ -32,14 +56,41 @@ class TurnRunner {
|
|
|
32
56
|
};
|
|
33
57
|
try {
|
|
34
58
|
abortSignal.throwIfAborted();
|
|
35
|
-
const { model, maxSteps } = this.definition;
|
|
59
|
+
const { model, maxSteps, profile } = this.definition;
|
|
60
|
+
const tools = this.definition.createTools(context);
|
|
61
|
+
// The wrap-up needs a research workspace to save into; the coding profile just stops at the budget.
|
|
62
|
+
const research = profile === 'research';
|
|
63
|
+
const wrapUpDone = ({ steps }) => wrapUpFrom !== undefined ? steps.length - wrapUpFrom >= WRAP_UP_STEPS : !research && input.budgetExceeded();
|
|
36
64
|
const result = (0, ai_1.streamText)({
|
|
37
65
|
model: (0, resolve_model_1.resolveLanguageModel)(model.provider, model.id, model.attribution),
|
|
38
66
|
system: input.instructions,
|
|
39
67
|
messages: input.messages,
|
|
40
|
-
tools
|
|
68
|
+
tools,
|
|
41
69
|
abortSignal,
|
|
42
|
-
stopWhen: [(0, ai_1.stepCountIs)(maxSteps), () => askedUser
|
|
70
|
+
stopWhen: [(0, ai_1.stepCountIs)(maxSteps), () => askedUser, wrapUpDone],
|
|
71
|
+
experimental_repairToolCall: tool_call_repair_1.repairStringifiedToolInput,
|
|
72
|
+
prepareStep: ({ stepNumber, steps, messages }) => {
|
|
73
|
+
var _a;
|
|
74
|
+
const pruned = (0, context_pruning_1.pruneToolResults)(messages);
|
|
75
|
+
if (wrapUpFrom === undefined && research && (input.wrapUpOnly || ((_a = input.nearBudget) === null || _a === void 0 ? void 0 : _a.call(input))))
|
|
76
|
+
wrapUpFrom = stepNumber;
|
|
77
|
+
if (wrapUpFrom === undefined) {
|
|
78
|
+
// The chat pins the checklist; a stale one tells the user nothing is moving. The note is
|
|
79
|
+
// appended for this step only, after the cached prefix, and is never saved. Once every
|
|
80
|
+
// PROGRESS_REMINDER_STEPS quiet steps, so an agent whose phase has not changed is not nagged.
|
|
81
|
+
const since = stepsSinceProgress(steps);
|
|
82
|
+
const stale = research && 'report_progress' in tools && since > 0 && since % PROGRESS_REMINDER_STEPS === 0;
|
|
83
|
+
return { messages: stale ? [...pruned, { role: 'user', content: PROGRESS_REMINDER }] : pruned };
|
|
84
|
+
}
|
|
85
|
+
// The instructions go last, as a note, rather than into the system prompt: the model acts on
|
|
86
|
+
// the newest message (in one run it ignored a system-only switch and ended on leftover
|
|
87
|
+
// text), and the cached prefix stays intact. A forced tool call (toolChoice "required") is
|
|
88
|
+
// not an option: Anthropic rejects it while extended thinking is on.
|
|
89
|
+
return {
|
|
90
|
+
messages: saved ? pruned : [...pruned, { role: 'user', content: WRAP_UP_INSTRUCTIONS }],
|
|
91
|
+
activeTools: WRAP_UP_TOOLS.filter((name) => name in tools),
|
|
92
|
+
};
|
|
93
|
+
},
|
|
43
94
|
});
|
|
44
95
|
for await (const part of result.fullStream) {
|
|
45
96
|
switch (part.type) {
|
|
@@ -51,6 +102,8 @@ class TurnRunner {
|
|
|
51
102
|
emit({ type: 'reasoning_delta', messageId, text: part.text });
|
|
52
103
|
break;
|
|
53
104
|
case 'tool-call':
|
|
105
|
+
if (wrapUpFrom !== undefined && (part.toolName === 'publish_results' || part.toolName === 'write_files'))
|
|
106
|
+
saved = true;
|
|
54
107
|
emit({ type: 'tool_call_start', messageId, toolCallId: part.toolCallId, toolName: part.toolName, input: part.input });
|
|
55
108
|
break;
|
|
56
109
|
case 'tool-result':
|
|
@@ -75,7 +128,7 @@ class TurnRunner {
|
|
|
75
128
|
abortSignal.throwIfAborted();
|
|
76
129
|
responseMessages = (await result.response).messages;
|
|
77
130
|
const text = await result.text;
|
|
78
|
-
return { status: 'completed', messages: responseMessages, text, partialText, askedUser };
|
|
131
|
+
return { status: 'completed', messages: responseMessages, text, partialText, askedUser, wrappedUp: wrapUpFrom !== undefined, saved };
|
|
79
132
|
}
|
|
80
133
|
catch (error) {
|
|
81
134
|
const aborted = abortSignal.aborted;
|
|
@@ -83,10 +136,10 @@ class TurnRunner {
|
|
|
83
136
|
const messages = responseMessages !== null && responseMessages !== void 0 ? responseMessages : [{
|
|
84
137
|
role: 'assistant', content: partialText || (aborted ? '(stopped by the user)' : '(turn failed)'),
|
|
85
138
|
}];
|
|
86
|
-
const output = { messages, partialText, askedUser };
|
|
139
|
+
const output = { messages, partialText, askedUser, wrappedUp: wrapUpFrom !== undefined, saved };
|
|
87
140
|
return aborted
|
|
88
141
|
? { ...output, status: 'aborted' }
|
|
89
|
-
: { ...output, status: 'failed', error: error
|
|
142
|
+
: { ...output, status: 'failed', error: (0, model_failure_1.describeModelFailure)(error), userMessage: (_c = (0, model_failure_1.userFacingModelFailure)(error)) !== null && _c !== void 0 ? _c : (0, model_failure_1.describeModelFailure)(error) };
|
|
90
143
|
}
|
|
91
144
|
}
|
|
92
145
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turn-runner.js","sourceRoot":"","sources":["../../src/agent/turn-runner.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"turn-runner.js","sourceRoot":"","sources":["../../src/agent/turn-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ModelMessage } from 'ai';
|
|
2
|
+
export interface PruneOptions {
|
|
3
|
+
/** Messages at the end of the conversation that are never pruned (the steps the agent is working on). */
|
|
4
|
+
keepRecent: number;
|
|
5
|
+
/** Results smaller than this are kept: they cost little and often carry the answer. */
|
|
6
|
+
minChars: number;
|
|
7
|
+
/** Prune only once the prunable results together exceed this many characters. */
|
|
8
|
+
triggerChars: number;
|
|
9
|
+
}
|
|
10
|
+
export declare const DEFAULT_PRUNE_OPTIONS: PruneOptions;
|
|
11
|
+
/** Returns `messages` unchanged until old bulky tool results pass `triggerChars`, then a copy with them stubbed. */
|
|
12
|
+
export declare function pruneToolResults(messages: ModelMessage[], options?: PruneOptions): ModelMessage[];
|
|
13
|
+
//# sourceMappingURL=context-pruning.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-pruning.d.ts","sourceRoot":"","sources":["../src/context-pruning.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AAEtC,MAAM,WAAW,YAAY;IAC3B,yGAAyG;IACzG,UAAU,EAAE,MAAM,CAAA;IAClB,uFAAuF;IACvF,QAAQ,EAAE,MAAM,CAAA;IAChB,iFAAiF;IACjF,YAAY,EAAE,MAAM,CAAA;CACrB;AAED,eAAO,MAAM,qBAAqB,EAAE,YAAwE,CAAA;AA6B5G,oHAAoH;AACpH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,EAAE,OAAO,GAAE,YAAoC,GAAG,YAAY,EAAE,CAuBxH"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_PRUNE_OPTIONS = void 0;
|
|
4
|
+
exports.pruneToolResults = pruneToolResults;
|
|
5
|
+
exports.DEFAULT_PRUNE_OPTIONS = { keepRecent: 6, minChars: 2000, triggerChars: 120000 };
|
|
6
|
+
const PATH_KEYS = ['path', 'textPath', 'saved', 'manifest', 'outputManifest', 'outputPath', 'saveHits'];
|
|
7
|
+
function isToolResult(part) {
|
|
8
|
+
return !!part && typeof part === 'object' && part.type === 'tool-result';
|
|
9
|
+
}
|
|
10
|
+
/** Workspace paths a tool result mentions at its top level (or one level down, e.g. `saved.path`). */
|
|
11
|
+
function mentionedPaths(output) {
|
|
12
|
+
const value = output && typeof output === 'object' && 'value' in output ? output.value : output;
|
|
13
|
+
if (!value || typeof value !== 'object')
|
|
14
|
+
return [];
|
|
15
|
+
const found = [];
|
|
16
|
+
for (const key of PATH_KEYS) {
|
|
17
|
+
const entry = value[key];
|
|
18
|
+
if (typeof entry === 'string')
|
|
19
|
+
found.push(entry);
|
|
20
|
+
else if (entry && typeof entry === 'object' && typeof entry.path === 'string')
|
|
21
|
+
found.push(entry.path);
|
|
22
|
+
}
|
|
23
|
+
return [...new Set(found)];
|
|
24
|
+
}
|
|
25
|
+
function stub(part, chars) {
|
|
26
|
+
const paths = mentionedPaths(part.output);
|
|
27
|
+
const where = paths.length ? ` Its data is on disk: ${paths.join(', ')}.` : ' Re-run the tool or read the workspace files if you need it again.';
|
|
28
|
+
return { ...part, output: { type: 'text', value: `[${part.toolName} result removed from the conversation to save tokens (${chars.toLocaleString()} chars).${where}]` } };
|
|
29
|
+
}
|
|
30
|
+
/** Returns `messages` unchanged until old bulky tool results pass `triggerChars`, then a copy with them stubbed. */
|
|
31
|
+
function pruneToolResults(messages, options = exports.DEFAULT_PRUNE_OPTIONS) {
|
|
32
|
+
const cutoff = Math.max(0, messages.length - options.keepRecent);
|
|
33
|
+
let prunable = 0;
|
|
34
|
+
for (const message of messages.slice(0, cutoff)) {
|
|
35
|
+
if (message.role !== 'tool')
|
|
36
|
+
continue;
|
|
37
|
+
for (const part of message.content) {
|
|
38
|
+
if (!isToolResult(part))
|
|
39
|
+
continue;
|
|
40
|
+
const chars = JSON.stringify(part.output).length;
|
|
41
|
+
if (chars >= options.minChars)
|
|
42
|
+
prunable += chars;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (prunable < options.triggerChars)
|
|
46
|
+
return messages;
|
|
47
|
+
return messages.map((message, index) => {
|
|
48
|
+
if (index >= cutoff || message.role !== 'tool')
|
|
49
|
+
return message;
|
|
50
|
+
return {
|
|
51
|
+
...message,
|
|
52
|
+
content: message.content.map((part) => {
|
|
53
|
+
if (!isToolResult(part))
|
|
54
|
+
return part;
|
|
55
|
+
const chars = JSON.stringify(part.output).length;
|
|
56
|
+
return chars >= options.minChars ? stub(part, chars) : part;
|
|
57
|
+
}),
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=context-pruning.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-pruning.js","sourceRoot":"","sources":["../src/context-pruning.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-pruning.test.d.ts","sourceRoot":"","sources":["../src/context-pruning.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
7
|
+
const node_test_1 = require("node:test");
|
|
8
|
+
const context_pruning_1 = require("./context-pruning");
|
|
9
|
+
function call(id) {
|
|
10
|
+
return { role: 'assistant', content: [{ type: 'tool-call', toolCallId: id, toolName: 'get_filing', input: {} }] };
|
|
11
|
+
}
|
|
12
|
+
function result(id, value) {
|
|
13
|
+
return { role: 'tool', content: [{ type: 'tool-result', toolCallId: id, toolName: 'get_filing', output: { type: 'json', value: value } }] };
|
|
14
|
+
}
|
|
15
|
+
const options = { keepRecent: 2, minChars: 100, triggerChars: 1000 };
|
|
16
|
+
(0, node_test_1.describe)('pruneToolResults', () => {
|
|
17
|
+
(0, node_test_1.it)('keeps everything while old bulky results stay under the trigger', () => {
|
|
18
|
+
const messages = [{ role: 'user', content: 'q' }, call('1'), result('1', { data: 'x'.repeat(500) }), call('2'), result('2', { ok: true })];
|
|
19
|
+
strict_1.default.equal((0, context_pruning_1.pruneToolResults)(messages, options), messages);
|
|
20
|
+
});
|
|
21
|
+
(0, node_test_1.it)('stubs old bulky results with the paths they pointed to, and keeps recent and small ones', () => {
|
|
22
|
+
const messages = [
|
|
23
|
+
{ role: 'user', content: 'q' },
|
|
24
|
+
call('1'),
|
|
25
|
+
result('1', { data: 'x'.repeat(1200), saved: { path: 'data/filings/T1.json', bytes: 9 }, manifest: { path: 'data/manifests/T1-attachments.jsonl' } }),
|
|
26
|
+
call('2'),
|
|
27
|
+
result('2', { ok: true }),
|
|
28
|
+
call('3'),
|
|
29
|
+
result('3', { data: 'y'.repeat(1200) }),
|
|
30
|
+
];
|
|
31
|
+
const pruned = (0, context_pruning_1.pruneToolResults)(messages, options);
|
|
32
|
+
const output = (index) => pruned[index].content[0].output;
|
|
33
|
+
strict_1.default.equal(output(2).type, 'text');
|
|
34
|
+
strict_1.default.match(String(output(2).value), /get_filing result removed.*data\/filings\/T1\.json, data\/manifests\/T1-attachments\.jsonl/);
|
|
35
|
+
strict_1.default.deepEqual(output(4), { type: 'json', value: { ok: true } });
|
|
36
|
+
strict_1.default.equal(output(6).type, 'json');
|
|
37
|
+
strict_1.default.equal(messages[2], messages[2], 'input is not mutated');
|
|
38
|
+
strict_1.default.equal(messages[2].content[0].output.type, 'json');
|
|
39
|
+
});
|
|
40
|
+
(0, node_test_1.it)('is monotonic: a result pruned at one step stays pruned when more steps follow', () => {
|
|
41
|
+
const base = [{ role: 'user', content: 'q' }, call('1'), result('1', { data: 'x'.repeat(1200) }), call('2'), result('2', { data: 'y'.repeat(150) })];
|
|
42
|
+
const later = [...base, call('3'), result('3', { data: 'z'.repeat(150) })];
|
|
43
|
+
const first = (0, context_pruning_1.pruneToolResults)(base, options);
|
|
44
|
+
const second = (0, context_pruning_1.pruneToolResults)(later, options);
|
|
45
|
+
strict_1.default.deepEqual(second.slice(0, 3), first.slice(0, 3));
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=context-pruning.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-pruning.test.js","sourceRoot":"","sources":["../src/context-pruning.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-model.d.ts","sourceRoot":"","sources":["../../src/models/resolve-model.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AACvC,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AACxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAE5D,oGAAoG;AACpG,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,aAAa,
|
|
1
|
+
{"version":3,"file":"resolve-model.d.ts","sourceRoot":"","sources":["../../src/models/resolve-model.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAA;AACvC,OAAO,EAAwB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AACxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAE5D,oGAAoG;AACpG,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,aAAa,CAatH"}
|
|
@@ -10,7 +10,9 @@ const attribution_1 = require("./attribution");
|
|
|
10
10
|
function resolveLanguageModel(provider, modelId, app) {
|
|
11
11
|
if (provider.openrouterApiKey) {
|
|
12
12
|
const openrouter = (0, ai_sdk_provider_1.createOpenRouter)({ apiKey: provider.openrouterApiKey, headers: (0, attribution_1.openRouterAppHeaders)(app) });
|
|
13
|
-
|
|
13
|
+
// Anthropic prompt caching: every step of a turn re-sends the whole conversation, and the
|
|
14
|
+
// cached prefix is what keeps a long research turn affordable.
|
|
15
|
+
return openrouter.chat(modelId, modelId.startsWith('anthropic/') ? { cache_control: { type: 'ephemeral' } } : {});
|
|
14
16
|
}
|
|
15
17
|
if (provider.anthropicApiKey || process.env.ANTHROPIC_API_KEY) {
|
|
16
18
|
const anthropic = (0, anthropic_1.createAnthropic)({ apiKey: provider.anthropicApiKey });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolve-model.js","sourceRoot":"","sources":["../../src/models/resolve-model.ts"],"names":[],"mappings":";;AASA,
|
|
1
|
+
{"version":3,"file":"resolve-model.js","sourceRoot":"","sources":["../../src/models/resolve-model.ts"],"names":[],"mappings":";;AASA,oDAaC;AAtBD,8FAA8F;AAC9F,8FAA8F;AAC9F,iDAAmD;AACnD,iEAA8D;AAE9D,+CAAwE;AAGxE,oGAAoG;AACpG,SAAgB,oBAAoB,CAAC,QAA6B,EAAE,OAAe,EAAE,GAAkB;IACrG,IAAI,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,IAAA,kCAAgB,EAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,gBAAgB,EAAE,OAAO,EAAE,IAAA,kCAAoB,EAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QAC9G,0FAA0F;QAC1F,+DAA+D;QAC/D,OAAO,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IACnH,CAAC;IACD,IAAI,QAAQ,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;QAC9D,MAAM,SAAS,GAAG,IAAA,2BAAe,EAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,eAAe,EAAE,CAAC,CAAA;QACvE,8EAA8E;QAC9E,OAAO,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,CAAA;IACvD,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAA;AAC9F,CAAC"}
|
package/dist/models/usage.d.ts
CHANGED
|
@@ -2,6 +2,10 @@ export interface TokenUsage {
|
|
|
2
2
|
inputTokens: number;
|
|
3
3
|
outputTokens: number;
|
|
4
4
|
totalTokens: number;
|
|
5
|
+
/** Part of inputTokens served from the provider's prompt cache. */
|
|
6
|
+
cacheReadTokens?: number;
|
|
7
|
+
/** Part of inputTokens written to the prompt cache. */
|
|
8
|
+
cacheWriteTokens?: number;
|
|
5
9
|
}
|
|
6
10
|
export declare function usageOf(part: unknown): TokenUsage | undefined;
|
|
7
11
|
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/models/usage.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/models/usage.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,CAc7D"}
|
package/dist/models/usage.js
CHANGED
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.usageOf = usageOf;
|
|
4
4
|
function usageOf(part) {
|
|
5
|
-
var _a, _b, _c;
|
|
5
|
+
var _a, _b, _c, _d, _e;
|
|
6
6
|
const usage = part.usage;
|
|
7
7
|
if (!usage)
|
|
8
8
|
return undefined;
|
|
9
9
|
const inputTokens = (_a = usage.inputTokens) !== null && _a !== void 0 ? _a : 0;
|
|
10
10
|
const outputTokens = (_b = usage.outputTokens) !== null && _b !== void 0 ? _b : 0;
|
|
11
|
-
return {
|
|
11
|
+
return {
|
|
12
|
+
inputTokens,
|
|
13
|
+
outputTokens,
|
|
14
|
+
totalTokens: (_c = usage.totalTokens) !== null && _c !== void 0 ? _c : inputTokens + outputTokens,
|
|
15
|
+
cacheReadTokens: (_d = usage.inputTokenDetails) === null || _d === void 0 ? void 0 : _d.cacheReadTokens,
|
|
16
|
+
cacheWriteTokens: (_e = usage.inputTokenDetails) === null || _e === void 0 ? void 0 : _e.cacheWriteTokens,
|
|
17
|
+
};
|
|
12
18
|
}
|
|
13
19
|
//# sourceMappingURL=usage.js.map
|
package/dist/models/usage.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/models/usage.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/models/usage.ts"],"names":[],"mappings":";;AAUA,0BAcC;AAdD,SAAgB,OAAO,CAAC,IAAa;;IACnC,MAAM,KAAK,GAAI,IAEb,CAAC,KAAK,CAAA;IACR,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAA;IAC5B,MAAM,WAAW,GAAG,MAAA,KAAK,CAAC,WAAW,mCAAI,CAAC,CAAA;IAC1C,MAAM,YAAY,GAAG,MAAA,KAAK,CAAC,YAAY,mCAAI,CAAC,CAAA;IAC5C,OAAO;QACL,WAAW;QACX,YAAY;QACZ,WAAW,EAAE,MAAA,KAAK,CAAC,WAAW,mCAAI,WAAW,GAAG,YAAY;QAC5D,eAAe,EAAE,MAAA,KAAK,CAAC,iBAAiB,0CAAE,eAAe;QACzD,gBAAgB,EAAE,MAAA,KAAK,CAAC,iBAAiB,0CAAE,gBAAgB;KAC5D,CAAA;AACH,CAAC"}
|