@kmugalkhod/lightcode 0.18.4 → 0.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/web/{index-kj8t3m63.js → index-1cpyqcg4.js} +56 -56
- package/assets/web/index.html +1 -1
- package/cli.js +94 -47
- package/package.json +1 -1
- package/server.js +408 -151
package/server.js
CHANGED
|
@@ -635,7 +635,7 @@ var init_web_auth = __esm(() => {
|
|
|
635
635
|
});
|
|
636
636
|
|
|
637
637
|
// packages/ai/src/constants.ts
|
|
638
|
-
var MAX_TOOL_TEXT_OUTPUT_CHARS = 12000, DEFAULT_TOOL_TEXT_OUTPUT_CHARS = 6000, MAX_TOOL_LIST_ENTRIES = 200, MAX_TOOL_SEARCH_RESULTS = 200, ANTHROPIC_TOOL_OPTIONAL_PARAMETER_BUDGET = 24, TODO_CONTENT_MAX_CHARS = 200, TODO_ACTIVE_FORM_MAX_CHARS = 80, PROGRESS_NOTE_PRUNE_MIN_CHARS = 200;
|
|
638
|
+
var MAX_TOOL_TEXT_OUTPUT_CHARS = 12000, DEFAULT_TOOL_TEXT_OUTPUT_CHARS = 6000, READ_FILE_OUTPUT_CHARS = 24000, MAX_TOOL_LIST_ENTRIES = 200, MAX_TOOL_SEARCH_RESULTS = 200, ANTHROPIC_TOOL_OPTIONAL_PARAMETER_BUDGET = 24, TODO_CONTENT_MAX_CHARS = 200, TODO_ACTIVE_FORM_MAX_CHARS = 80, PROGRESS_NOTE_PRUNE_MIN_CHARS = 200;
|
|
639
639
|
|
|
640
640
|
// packages/ai/src/coding-agent-modes.ts
|
|
641
641
|
import { z as z2 } from "zod";
|
|
@@ -2002,14 +2002,15 @@ var init_schema8 = __esm(() => {
|
|
|
2002
2002
|
|
|
2003
2003
|
// packages/ai/src/read-file/schema.ts
|
|
2004
2004
|
import { z as z19 } from "zod";
|
|
2005
|
-
var readFileDescription
|
|
2005
|
+
var readFileDescription, readFileInputSchema, readFileProviderInputSchema, readFileOutputSchema;
|
|
2006
2006
|
var init_schema9 = __esm(() => {
|
|
2007
2007
|
init_base_schemas();
|
|
2008
|
+
readFileDescription = "Read file content from the working directory. Returns whole lines, up to about 24,000 characters (roughly 600 lines) per call, so read a file in one call instead of in slices. " + "If the file is longer, the result stops at endLine and nextStartLine says where to continue. " + "To inspect one spot in a large file, grep for it first, then read a generous startLine/endLine range around it.";
|
|
2008
2009
|
readFileInputSchema = z19.object({
|
|
2009
2010
|
path: boundedPathSchema,
|
|
2010
2011
|
startLine: positiveLineSchema.optional(),
|
|
2011
2012
|
endLine: positiveLineSchema.optional(),
|
|
2012
|
-
maxChars: integerRangeSchema(1,
|
|
2013
|
+
maxChars: integerRangeSchema(1, READ_FILE_OUTPUT_CHARS, "maxChars").optional()
|
|
2013
2014
|
}).superRefine((value, ctx) => {
|
|
2014
2015
|
if (value.startLine !== undefined && value.endLine !== undefined && value.endLine < value.startLine) {
|
|
2015
2016
|
ctx.addIssue({
|
|
@@ -2030,7 +2031,8 @@ var init_schema9 = __esm(() => {
|
|
|
2030
2031
|
endLine: z19.number().int().min(1),
|
|
2031
2032
|
content: z19.string(),
|
|
2032
2033
|
totalLines: z19.number().int().nonnegative(),
|
|
2033
|
-
truncated: z19.boolean()
|
|
2034
|
+
truncated: z19.boolean(),
|
|
2035
|
+
nextStartLine: z19.number().int().min(1).optional()
|
|
2034
2036
|
});
|
|
2035
2037
|
});
|
|
2036
2038
|
|
|
@@ -2350,7 +2352,7 @@ var init_tool_registry = __esm(() => {
|
|
|
2350
2352
|
permissionMode: "read-only",
|
|
2351
2353
|
execution: "server",
|
|
2352
2354
|
availability: "git-workspace",
|
|
2353
|
-
activation: "
|
|
2355
|
+
activation: "core",
|
|
2354
2356
|
outputPolicy: "artifact-if-large"
|
|
2355
2357
|
},
|
|
2356
2358
|
git_diff: {
|
|
@@ -2363,7 +2365,7 @@ var init_tool_registry = __esm(() => {
|
|
|
2363
2365
|
permissionMode: "read-only",
|
|
2364
2366
|
execution: "server",
|
|
2365
2367
|
availability: "git-workspace",
|
|
2366
|
-
activation: "
|
|
2368
|
+
activation: "core",
|
|
2367
2369
|
outputPolicy: "artifact-if-large"
|
|
2368
2370
|
},
|
|
2369
2371
|
git_log: {
|
|
@@ -2376,7 +2378,7 @@ var init_tool_registry = __esm(() => {
|
|
|
2376
2378
|
permissionMode: "read-only",
|
|
2377
2379
|
execution: "server",
|
|
2378
2380
|
availability: "git-workspace",
|
|
2379
|
-
activation: "
|
|
2381
|
+
activation: "core",
|
|
2380
2382
|
outputPolicy: "artifact-if-large"
|
|
2381
2383
|
},
|
|
2382
2384
|
git_show: {
|
|
@@ -2389,7 +2391,7 @@ var init_tool_registry = __esm(() => {
|
|
|
2389
2391
|
permissionMode: "read-only",
|
|
2390
2392
|
execution: "server",
|
|
2391
2393
|
availability: "git-workspace",
|
|
2392
|
-
activation: "
|
|
2394
|
+
activation: "core",
|
|
2393
2395
|
outputPolicy: "artifact-if-large"
|
|
2394
2396
|
},
|
|
2395
2397
|
tool_search: {
|
|
@@ -2790,6 +2792,7 @@ var init_agent_tools = __esm(() => {
|
|
|
2790
2792
|
contextWindow: z27.number().int().positive().optional(),
|
|
2791
2793
|
preserveRecentTokens: z27.number().int().nonnegative().optional(),
|
|
2792
2794
|
originalInputTokens: z27.number().int().nonnegative().optional(),
|
|
2795
|
+
promptCacheActive: z27.boolean().optional(),
|
|
2793
2796
|
assemblyAbortSignal: z27.custom().optional(),
|
|
2794
2797
|
turnKey: z27.string().min(1).max(200).optional()
|
|
2795
2798
|
});
|
|
@@ -3068,10 +3071,10 @@ ${environmentContext.trim()}` : "");
|
|
|
3068
3071
|
var cwdPromptPlaceholder = "{cwd}", defaultCodingAgentSystemPrompt, toolCallingDisciplineAddendum;
|
|
3069
3072
|
var init_coding_agent_prompt = __esm(() => {
|
|
3070
3073
|
init_coding_agent_modes();
|
|
3071
|
-
defaultCodingAgentSystemPrompt = "You are a coding agent working inside the user's project at this working directory: {cwd}. " + 'You can already see the project \u2014 proactively read it. When the user asks you to review, explain, or work on "my code"/"this", inspect the working directory yourself with list_files, glob_search, grep, and read_file; NEVER ask the user to paste or share code that lives in this directory \u2014 open it. ' + "Use tools for filesystem and codebase tasks instead of guessing, and only interact with files under the working directory. " + "Prefer dedicated tools \u2014 glob_search for paths, grep for text search, structured git tools for repository inspection \u2014 and bash only when those are not enough. " + "Check the available skill descriptions for every task. When a skill is explicitly named or clearly matches the task, load it with the skill tool before acting and follow its instructions within the user's scope and tool permissions. Skill files may be installed outside the workspace; use the skill tool to read their relative supporting resources. Never claim to have used a skill you have not loaded. " + `Inspect context before risky operations. Progress notes: before a major tool action you may emit ONE short note (one sentence, ~15 words) saying what you are about to do. After a tool returns, mention a finding only if it changes your plan, and state it as fact grounded in what the tool actually returned \u2014 cite the file/line/symbol. NEVER claim you found, changed, or fixed something before a tool result confirms it. Skip notes for routine reads, and do not restate the todo list in prose.
|
|
3074
|
+
defaultCodingAgentSystemPrompt = "You are a coding agent working inside the user's project at this working directory: {cwd}. " + 'You can already see the project \u2014 proactively read it. When the user asks you to review, explain, or work on "my code"/"this", inspect the working directory yourself with list_files, glob_search, grep, and read_file; NEVER ask the user to paste or share code that lives in this directory \u2014 open it. ' + "Use tools for filesystem and codebase tasks instead of guessing, and only interact with files under the working directory. " + "Prefer dedicated tools \u2014 glob_search for paths, grep for text search, structured git tools for repository inspection \u2014 and bash only when those are not enough. " + "Gather context efficiently \u2014 every tool round trip costs the user seconds. The environment section maps the repository's files: use it to go straight to the right paths instead of listing directories. Locate before you read: use grep or glob_search to find the relevant files and line numbers, then read whole files (read_file returns up to about 600 lines per call) or, in larger files, a range of a few hundred lines around the spot \u2014 never many small slices, and never re-read content you already have. When several reads or searches do not depend on each other, request them together in one step. Skip generated output (dist/, build/, minified bundles, node_modules) unless the task is about it. Stop exploring once you have enough evidence to act or answer. " + "Check the available skill descriptions for every task. When a skill is explicitly named or clearly matches the task, load it with the skill tool before acting and follow its instructions within the user's scope and tool permissions. Skill files may be installed outside the workspace; use the skill tool to read their relative supporting resources. Never claim to have used a skill you have not loaded. " + `Inspect context before risky operations. Progress notes: before a major tool action you may emit ONE short note (one sentence, ~15 words) saying what you are about to do. After a tool returns, mention a finding only if it changes your plan, and state it as fact grounded in what the tool actually returned \u2014 cite the file/line/symbol. NEVER claim you found, changed, or fixed something before a tool result confirms it. Skip notes for routine reads, and do not restate the todo list in prose.
|
|
3072
3075
|
|
|
3073
3076
|
` + `Task list discipline \u2014 use the todo_write tool to keep a visible, evolving checklist:
|
|
3074
|
-
` + `- Create the list
|
|
3077
|
+
` + `- Create the list in your first step. For any task with roughly three or more distinct steps, or any multi-file or multi-stage work, call todo_write in your first response with every step listed and all of them set to pending \u2014 request it together with your first reads or searches, not as a separate step, and always before any edit.
|
|
3075
3078
|
` + `- Keep exactly ONE item in_progress at a time. Mark an item in_progress immediately before you start it; never have two items in_progress at once.
|
|
3076
3079
|
` + `- Mark an item completed only after a tool result confirms it is actually done (test passed, file written, build clean) \u2014 not on intent. Do this the MOMENT it is confirmed; do not batch completions or wait until the end of the turn.
|
|
3077
3080
|
` + `- Completions are monotonic: once a task is completed, do not silently move it back to pending or in_progress. Reopen it only if it genuinely regressed.
|
|
@@ -3083,7 +3086,7 @@ var init_coding_agent_prompt = __esm(() => {
|
|
|
3083
3086
|
` + `When the task is complete, end with a short summary (a few lines) grounded in the todos you actually completed and the real file diffs \u2014 name the files you edited, do not list steps you did not verify, and do not repeat the todo card verbatim. If anything is incomplete or you are blocked, say so plainly.
|
|
3084
3087
|
|
|
3085
3088
|
` + "Long-running processes (dev servers, watchers): never run them as plain foreground bash \u2014 the bash tool enforces a timeout and will kill them. Start them detached with output redirected to a log " + '(Windows: start /B cmd /c "npm run dev > dev.log 2>&1"; Unix: nohup npm run dev > dev.log 2>&1 &), then read the log to confirm startup and the actual port (do not assume the default). ' + "Never kill processes or free ports you did not open yourself.";
|
|
3086
|
-
toolCallingDisciplineAddendum = "Invoke tools only through the function-calling interface. " + "Never write tool calls as XML or plain text such as <tool_call>, <function_call>, <invoke>, or bare JSON in your message. " + "Tool arguments must be valid JSON matching the tool's schema. " + "
|
|
3089
|
+
toolCallingDisciplineAddendum = "Invoke tools only through the function-calling interface. " + "Never write tool calls as XML or plain text such as <tool_call>, <function_call>, <invoke>, or bare JSON in your message. " + "Tool arguments must be valid JSON matching the tool's schema. " + "You may request several independent tool calls in one response; wait for their results before making calls that depend on them.";
|
|
3087
3090
|
});
|
|
3088
3091
|
|
|
3089
3092
|
// packages/ai/src/common/coerce-tool-input.ts
|
|
@@ -3481,20 +3484,26 @@ function collectTextFromUnknown(value) {
|
|
|
3481
3484
|
}
|
|
3482
3485
|
return "";
|
|
3483
3486
|
}
|
|
3484
|
-
function
|
|
3487
|
+
function getUserTexts(messages, prompt) {
|
|
3488
|
+
const texts = [];
|
|
3485
3489
|
if (Array.isArray(messages)) {
|
|
3486
|
-
for (
|
|
3487
|
-
const message = messages[index];
|
|
3490
|
+
for (const message of messages) {
|
|
3488
3491
|
if (!isRecord4(message) || message.role !== "user") {
|
|
3489
3492
|
continue;
|
|
3490
3493
|
}
|
|
3491
3494
|
const text = collectTextFromUnknown(message).trim();
|
|
3492
3495
|
if (text) {
|
|
3493
|
-
|
|
3496
|
+
texts.push(text);
|
|
3494
3497
|
}
|
|
3495
3498
|
}
|
|
3496
3499
|
}
|
|
3497
|
-
|
|
3500
|
+
if (texts.length === 0) {
|
|
3501
|
+
const promptText = collectTextFromUnknown(prompt).trim();
|
|
3502
|
+
if (promptText) {
|
|
3503
|
+
texts.push(promptText);
|
|
3504
|
+
}
|
|
3505
|
+
}
|
|
3506
|
+
return texts;
|
|
3498
3507
|
}
|
|
3499
3508
|
function escapeRegExp(value) {
|
|
3500
3509
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -3520,23 +3529,20 @@ function selectCodingAgentIntentTools({
|
|
|
3520
3529
|
messages,
|
|
3521
3530
|
availableSkillNames = []
|
|
3522
3531
|
}) {
|
|
3523
|
-
const
|
|
3524
|
-
|
|
3525
|
-
if (!normalizedText || casualPromptPattern.test(normalizedText)) {
|
|
3532
|
+
const userTexts = getUserTexts(messages, prompt);
|
|
3533
|
+
if (userTexts.every((text) => casualPromptPattern.test(text))) {
|
|
3526
3534
|
return [];
|
|
3527
3535
|
}
|
|
3536
|
+
const latestText = userTexts.at(-1) ?? "";
|
|
3528
3537
|
const modeTools = getRegistryToolsForMode(mode);
|
|
3529
3538
|
const selected = new Set(modeTools.filter((toolName) => codingToolRegistry[toolName].activation === "core"));
|
|
3530
|
-
if (
|
|
3531
|
-
addTools(selected, gitToolNames);
|
|
3532
|
-
}
|
|
3533
|
-
if (webIntentPattern.test(userText)) {
|
|
3539
|
+
if (webIntentPattern.test(latestText)) {
|
|
3534
3540
|
addTools(selected, webToolNames);
|
|
3535
3541
|
}
|
|
3536
|
-
if (mcpIntentPattern.test(
|
|
3542
|
+
if (userTexts.some((text) => mcpIntentPattern.test(text))) {
|
|
3537
3543
|
addTools(selected, mcpToolNames);
|
|
3538
3544
|
}
|
|
3539
|
-
if (skillIntentPattern.test(
|
|
3545
|
+
if (userTexts.some((text) => skillIntentPattern.test(text) || requestsAvailableSkill(text, availableSkillNames))) {
|
|
3540
3546
|
selected.add("skill");
|
|
3541
3547
|
}
|
|
3542
3548
|
return modeTools.filter((toolName) => selected.has(toolName));
|
|
@@ -3616,21 +3622,14 @@ function limitProviderActiveTools(tools, maxTools = maxProviderActiveTools) {
|
|
|
3616
3622
|
const toolSet = new Set(tools);
|
|
3617
3623
|
return providerToolPriority.filter((toolName) => toolSet.has(toolName)).slice(0, maxTools);
|
|
3618
3624
|
}
|
|
3619
|
-
var casualPromptPattern,
|
|
3625
|
+
var casualPromptPattern, webIntentPattern, mcpIntentPattern, skillIntentPattern, webToolNames, mcpToolNames, maxProviderActiveTools = 24, providerToolPriority;
|
|
3620
3626
|
var init_intent_tool_selection = __esm(() => {
|
|
3621
3627
|
init_coding_agent_modes();
|
|
3622
3628
|
init_tool_registry();
|
|
3623
3629
|
casualPromptPattern = /^(hi|hello|hey|how are you|how r you|what'?s up|whats up|sup|thanks|thank you|ok|okay|yes|no|nice|cool|great)[\s?!.,]*$/i;
|
|
3624
|
-
gitIntentPattern = /(?:\bgit\b|\bcommits?\b|\bstaged?\b|\bunstaged\b|\buntracked\b|\bworking tree\b|\brepositor(?:y|ies)\s+(?:status|diff|history|changes))/i;
|
|
3625
3630
|
webIntentPattern = /(?:\bhttps?:\/\/|\bwww\.|\bweb(?:site|page)?\b|\binternet\b|\bonline\b|\burl\b|\bbrowser\b|\bsearch\s+(?:the\s+)?web\b|\bbrowse\s+(?:the\s+web|online|for)\b|\blook\s+up\b|\b(?:latest|current|recent|today'?s)\s+(?:news|price|weather|docs?|documentation|release|version)\b)/i;
|
|
3626
3631
|
mcpIntentPattern = /(?:\bmcp\b|\bmodel context protocol\b)/i;
|
|
3627
3632
|
skillIntentPattern = /\bskills?\b/i;
|
|
3628
|
-
gitToolNames = [
|
|
3629
|
-
"git_status",
|
|
3630
|
-
"git_diff",
|
|
3631
|
-
"git_log",
|
|
3632
|
-
"git_show"
|
|
3633
|
-
];
|
|
3634
3633
|
webToolNames = [
|
|
3635
3634
|
"web_fetch",
|
|
3636
3635
|
"web_search"
|
|
@@ -5160,19 +5159,44 @@ async function executeReadFile(input, workspaceContext = getDefaultWorkspaceCont
|
|
|
5160
5159
|
const fileContent = await fs4.readFile(resolvedPath, "utf8");
|
|
5161
5160
|
const lines = fileContent.split(/\r?\n/);
|
|
5162
5161
|
const { start, end } = clampLineRange(lines.length, parsedInput.startLine, parsedInput.endLine);
|
|
5163
|
-
const
|
|
5164
|
-
|
|
5165
|
-
const
|
|
5166
|
-
const truncated = truncateText(selectedContent, maxChars);
|
|
5162
|
+
const maxChars = parsedInput.maxChars ?? READ_FILE_OUTPUT_CHARS;
|
|
5163
|
+
const taken = takeWholeLines(lines.slice(start - 1, end), maxChars);
|
|
5164
|
+
const lastLine = start + taken.lineCount - 1;
|
|
5167
5165
|
return readFileOutputSchema.parse({
|
|
5168
5166
|
path: relativePath,
|
|
5169
5167
|
startLine: start,
|
|
5170
|
-
endLine:
|
|
5171
|
-
content:
|
|
5168
|
+
endLine: lastLine,
|
|
5169
|
+
content: taken.text,
|
|
5172
5170
|
totalLines: lines.length,
|
|
5173
|
-
truncated:
|
|
5171
|
+
truncated: taken.truncated,
|
|
5172
|
+
...lastLine < end ? { nextStartLine: lastLine + 1 } : {}
|
|
5174
5173
|
});
|
|
5175
5174
|
}
|
|
5175
|
+
function takeWholeLines(lines, maxChars) {
|
|
5176
|
+
let used = 0;
|
|
5177
|
+
let lineCount = 0;
|
|
5178
|
+
for (const line of lines) {
|
|
5179
|
+
const cost = line.length + (lineCount > 0 ? 1 : 0);
|
|
5180
|
+
if (used + cost > maxChars) {
|
|
5181
|
+
break;
|
|
5182
|
+
}
|
|
5183
|
+
used += cost;
|
|
5184
|
+
lineCount += 1;
|
|
5185
|
+
}
|
|
5186
|
+
if (lineCount === 0 && lines.length > 0) {
|
|
5187
|
+
return {
|
|
5188
|
+
text: truncateText(lines[0] ?? "", maxChars).text,
|
|
5189
|
+
lineCount: 1,
|
|
5190
|
+
truncated: true
|
|
5191
|
+
};
|
|
5192
|
+
}
|
|
5193
|
+
return {
|
|
5194
|
+
text: lines.slice(0, lineCount).join(`
|
|
5195
|
+
`),
|
|
5196
|
+
lineCount,
|
|
5197
|
+
truncated: lineCount < lines.length
|
|
5198
|
+
};
|
|
5199
|
+
}
|
|
5176
5200
|
var init_runtime8 = __esm(() => {
|
|
5177
5201
|
init_resolve_within_workspace();
|
|
5178
5202
|
init_output_utils();
|
|
@@ -6444,10 +6468,12 @@ function buildProviderView(options) {
|
|
|
6444
6468
|
}
|
|
6445
6469
|
const tokenBoundedCutoffIndex = computeTokenBoundedCompactionCutoffIndex(messages, preserveRecentTokens, afterAnchorIndex);
|
|
6446
6470
|
const userIndicesAfterAnchor = messages.map((message, index) => ({ message, index })).filter(({ message, index }) => index >= afterAnchorIndex && message.role === "user").map(({ index }) => index);
|
|
6447
|
-
const
|
|
6471
|
+
const rollingKeepUserTurns = Math.max(1, Math.ceil(config.uncachedRollingCompactionUserTurns / 2));
|
|
6472
|
+
const rollingTurnCutoffIndex = userIndicesAfterAnchor.length > rollingKeepUserTurns ? userIndicesAfterAnchor[userIndicesAfterAnchor.length - rollingKeepUserTurns] ?? afterAnchorIndex : afterAnchorIndex;
|
|
6448
6473
|
const overCompactThreshold = triggerTokens(estimate.tokens) > config.compactAtFraction * inputBudgetTokens;
|
|
6474
|
+
const rollingActive = (options.rollingCompaction ?? options.cacheActive === false) && config.aggressivePruneWhenUncached;
|
|
6449
6475
|
const userTurnsAfterAnchor = messages.slice(afterAnchorIndex).filter((message) => message.role === "user").length;
|
|
6450
|
-
const rollingThresholdReached =
|
|
6476
|
+
const rollingThresholdReached = rollingActive && userTurnsAfterAnchor > (options.continueRolling ? rollingKeepUserTurns : config.uncachedRollingCompactionUserTurns);
|
|
6451
6477
|
const compactionCutoffIndex = rollingThresholdReached ? Math.max(tokenBoundedCutoffIndex, rollingTurnCutoffIndex) : tokenBoundedCutoffIndex;
|
|
6452
6478
|
const coveredMessages = capCoverageToTokenBudget(messages.slice(afterAnchorIndex, compactionCutoffIndex), config.maxCoverageTokensPerCompaction);
|
|
6453
6479
|
let compactionBlockedReason = null;
|
|
@@ -6901,6 +6927,14 @@ import path12 from "path";
|
|
|
6901
6927
|
import {
|
|
6902
6928
|
toolModelMessageSchema
|
|
6903
6929
|
} from "ai";
|
|
6930
|
+
function resolveToolOutputArtifactThresholds({
|
|
6931
|
+
promptCacheActive
|
|
6932
|
+
}) {
|
|
6933
|
+
return {
|
|
6934
|
+
thresholdCharacters: promptCacheActive ? DEFAULT_CURRENT_TURN_TOOL_OUTPUT_THRESHOLD_CHARACTERS : DEFAULT_TOOL_OUTPUT_ARTIFACT_THRESHOLD_CHARACTERS,
|
|
6935
|
+
currentTurnThresholdCharacters: DEFAULT_CURRENT_TURN_TOOL_OUTPUT_THRESHOLD_CHARACTERS
|
|
6936
|
+
};
|
|
6937
|
+
}
|
|
6904
6938
|
function isRecord10(value) {
|
|
6905
6939
|
return typeof value === "object" && value !== null;
|
|
6906
6940
|
}
|
|
@@ -7080,12 +7114,19 @@ async function artifactizeLargeToolOutputs(messages, options = {}) {
|
|
|
7080
7114
|
if (previewCharacters < MIN_TOOL_OUTPUT_ARTIFACT_PREVIEW_CHARACTERS) {
|
|
7081
7115
|
throw new RangeError(`Tool-output artifact previews must allow at least ${MIN_TOOL_OUTPUT_ARTIFACT_PREVIEW_CHARACTERS} characters.`);
|
|
7082
7116
|
}
|
|
7117
|
+
const currentTurnThreshold = Math.max(0, Math.floor(options.currentTurnThresholdCharacters ?? thresholdCharacters));
|
|
7118
|
+
let currentTurnStart = 0;
|
|
7119
|
+
messages.forEach((message, index) => {
|
|
7120
|
+
if (message.role === "user")
|
|
7121
|
+
currentTurnStart = index + 1;
|
|
7122
|
+
});
|
|
7083
7123
|
const uniqueArtifacts = new Map;
|
|
7084
7124
|
let artifactizedOutputs = 0;
|
|
7085
7125
|
let savedCharacters = 0;
|
|
7086
7126
|
const providerMessages = [];
|
|
7087
|
-
for (const message of messages) {
|
|
7127
|
+
for (const [index, message] of messages.entries()) {
|
|
7088
7128
|
options.signal?.throwIfAborted();
|
|
7129
|
+
const limit = index >= currentTurnStart ? currentTurnThreshold : thresholdCharacters;
|
|
7089
7130
|
if (!Array.isArray(message.content)) {
|
|
7090
7131
|
providerMessages.push(message);
|
|
7091
7132
|
continue;
|
|
@@ -7099,7 +7140,7 @@ async function artifactizeLargeToolOutputs(messages, options = {}) {
|
|
|
7099
7140
|
}
|
|
7100
7141
|
const output = part.output;
|
|
7101
7142
|
const serialized = serializeToolResultOutput(output);
|
|
7102
|
-
if (serialized.length <=
|
|
7143
|
+
if (serialized.length <= limit) {
|
|
7103
7144
|
providerContent.push(part);
|
|
7104
7145
|
continue;
|
|
7105
7146
|
}
|
|
@@ -7131,7 +7172,7 @@ async function artifactizeLargeToolOutputs(messages, options = {}) {
|
|
|
7131
7172
|
savedCharacters
|
|
7132
7173
|
};
|
|
7133
7174
|
}
|
|
7134
|
-
var TOOL_OUTPUT_ARTIFACT_HANDLE_PREFIX = "lightcode-artifact://tool-output/sha256/", DEFAULT_TOOL_OUTPUT_ARTIFACT_THRESHOLD_CHARACTERS, DEFAULT_TOOL_OUTPUT_ARTIFACT_PREVIEW_CHARACTERS = 2400, MIN_TOOL_OUTPUT_ARTIFACT_PREVIEW_CHARACTERS = 512, SHA256_PATTERN, ARTIFACT_PREVIEW_MARKER = "[Lightcode tool-output artifact]";
|
|
7175
|
+
var TOOL_OUTPUT_ARTIFACT_HANDLE_PREFIX = "lightcode-artifact://tool-output/sha256/", DEFAULT_TOOL_OUTPUT_ARTIFACT_THRESHOLD_CHARACTERS, DEFAULT_CURRENT_TURN_TOOL_OUTPUT_THRESHOLD_CHARACTERS = 32000, DEFAULT_TOOL_OUTPUT_ARTIFACT_PREVIEW_CHARACTERS = 2400, MIN_TOOL_OUTPUT_ARTIFACT_PREVIEW_CHARACTERS = 512, SHA256_PATTERN, ARTIFACT_PREVIEW_MARKER = "[Lightcode tool-output artifact]";
|
|
7135
7176
|
var init_tool_output_artifacts = __esm(() => {
|
|
7136
7177
|
init_src();
|
|
7137
7178
|
DEFAULT_TOOL_OUTPUT_ARTIFACT_THRESHOLD_CHARACTERS = DEFAULT_TOOL_TEXT_OUTPUT_CHARS;
|
|
@@ -8617,7 +8658,10 @@ function createCodingAgent({
|
|
|
8617
8658
|
originalInputTokens: context.originalInputTokens
|
|
8618
8659
|
});
|
|
8619
8660
|
const artifactized = await artifactizeLargeToolOutputs(messages, {
|
|
8620
|
-
signal: context.assemblyAbortSignal
|
|
8661
|
+
signal: context.assemblyAbortSignal,
|
|
8662
|
+
...resolveToolOutputArtifactThresholds({
|
|
8663
|
+
promptCacheActive: context.promptCacheActive ?? false
|
|
8664
|
+
})
|
|
8621
8665
|
});
|
|
8622
8666
|
const assembled = assembler.assembleModelMessages(artifactized.messages, {
|
|
8623
8667
|
preserveRecentTokens: context.preserveRecentTokens
|
|
@@ -8683,6 +8727,7 @@ function createCodingAgent({
|
|
|
8683
8727
|
reservedOutputTokens: options.maxOutputTokens,
|
|
8684
8728
|
preserveRecentTokens: options.preserveRecentTokens,
|
|
8685
8729
|
originalInputTokens: options.originalInputTokens,
|
|
8730
|
+
promptCacheActive: options.promptCacheActive,
|
|
8686
8731
|
assemblyAbortSignal: options.assemblyAbortSignal
|
|
8687
8732
|
},
|
|
8688
8733
|
instructions
|
|
@@ -13342,7 +13387,8 @@ function summarizeRawModel(raw3) {
|
|
|
13342
13387
|
const pricingRaw = Reflect.get(raw3, "pricing");
|
|
13343
13388
|
const pricing = typeof pricingRaw === "object" && pricingRaw !== null ? {
|
|
13344
13389
|
prompt: typeof Reflect.get(pricingRaw, "prompt") === "string" ? Reflect.get(pricingRaw, "prompt") : null,
|
|
13345
|
-
completion: typeof Reflect.get(pricingRaw, "completion") === "string" ? Reflect.get(pricingRaw, "completion") : null
|
|
13390
|
+
completion: typeof Reflect.get(pricingRaw, "completion") === "string" ? Reflect.get(pricingRaw, "completion") : null,
|
|
13391
|
+
inputCacheRead: typeof Reflect.get(pricingRaw, "input_cache_read") === "string" ? Reflect.get(pricingRaw, "input_cache_read") : null
|
|
13346
13392
|
} : null;
|
|
13347
13393
|
return {
|
|
13348
13394
|
id,
|
|
@@ -13372,12 +13418,12 @@ async function listOpenRouterModels({
|
|
|
13372
13418
|
forceRefresh = false
|
|
13373
13419
|
} = {}) {
|
|
13374
13420
|
const cache = readCache();
|
|
13375
|
-
if (!forceRefresh && cache && Date.now() - cache.fetchedAt < cacheTtlMs) {
|
|
13421
|
+
if (!forceRefresh && cache && cache.version === modelsCacheVersion && Date.now() - cache.fetchedAt < cacheTtlMs) {
|
|
13376
13422
|
return { models: cache.models, fromCache: true };
|
|
13377
13423
|
}
|
|
13378
13424
|
try {
|
|
13379
13425
|
const models = await fetchModelsFromApi();
|
|
13380
|
-
writeCache({ fetchedAt: Date.now(), models });
|
|
13426
|
+
writeCache({ version: modelsCacheVersion, fetchedAt: Date.now(), models });
|
|
13381
13427
|
return { models, fromCache: false };
|
|
13382
13428
|
} catch (error) {
|
|
13383
13429
|
logger5.warn("openrouter_models_fetch_failed", {
|
|
@@ -13415,12 +13461,14 @@ function toCapabilityPricing(pricing) {
|
|
|
13415
13461
|
if (!Number.isFinite(promptPerToken) || !Number.isFinite(completionPerToken)) {
|
|
13416
13462
|
return null;
|
|
13417
13463
|
}
|
|
13464
|
+
const cacheReadPerToken = pricing.inputCacheRead ? Number.parseFloat(pricing.inputCacheRead) : Number.NaN;
|
|
13418
13465
|
return {
|
|
13419
13466
|
inputPerMTok: promptPerToken * 1e6,
|
|
13420
|
-
outputPerMTok: completionPerToken * 1e6
|
|
13467
|
+
outputPerMTok: completionPerToken * 1e6,
|
|
13468
|
+
cachedInputPerMTok: Number.isFinite(cacheReadPerToken) && cacheReadPerToken > 0 ? cacheReadPerToken * 1e6 : null
|
|
13421
13469
|
};
|
|
13422
13470
|
}
|
|
13423
|
-
var logger5, openRouterModelsUrl = "https://openrouter.ai/api/v1/models", cacheTtlMs, fetchTimeoutMs = 15000, openRouterModelSummarySchema, modelsCacheSchema;
|
|
13471
|
+
var logger5, openRouterModelsUrl = "https://openrouter.ai/api/v1/models", cacheTtlMs, fetchTimeoutMs = 15000, modelsCacheVersion = 2, openRouterModelSummarySchema, modelsCacheSchema;
|
|
13424
13472
|
var init_openrouter_models = __esm(() => {
|
|
13425
13473
|
init_src();
|
|
13426
13474
|
init_network_fetch();
|
|
@@ -13435,10 +13483,12 @@ var init_openrouter_models = __esm(() => {
|
|
|
13435
13483
|
supportsReasoning: z40.boolean(),
|
|
13436
13484
|
pricing: z40.object({
|
|
13437
13485
|
prompt: z40.string().nullable(),
|
|
13438
|
-
completion: z40.string().nullable()
|
|
13486
|
+
completion: z40.string().nullable(),
|
|
13487
|
+
inputCacheRead: z40.string().nullable().default(null)
|
|
13439
13488
|
}).nullable()
|
|
13440
13489
|
});
|
|
13441
13490
|
modelsCacheSchema = z40.object({
|
|
13491
|
+
version: z40.number().int().optional(),
|
|
13442
13492
|
fetchedAt: z40.number(),
|
|
13443
13493
|
models: z40.array(openRouterModelSummarySchema)
|
|
13444
13494
|
});
|
|
@@ -13722,6 +13772,7 @@ function resolveAnthropicModel({
|
|
|
13722
13772
|
contextWindow: getModelContextWindow("anthropic", modelId),
|
|
13723
13773
|
missingCredentialHints,
|
|
13724
13774
|
supportsPromptCaching: true,
|
|
13775
|
+
rollingCompaction: false,
|
|
13725
13776
|
pricing: getAnthropicModelPricing(modelId),
|
|
13726
13777
|
webSearchCapability,
|
|
13727
13778
|
providerTools: webSearchCapability.execution === "provider" ? {
|
|
@@ -13737,7 +13788,7 @@ function resolveCapabilityPricing(capabilities, cachedInputFactor) {
|
|
|
13737
13788
|
return {
|
|
13738
13789
|
inputPerMTok: pricing.inputPerMTok,
|
|
13739
13790
|
outputPerMTok: pricing.outputPerMTok,
|
|
13740
|
-
cachedInputPerMTok: cachedInputFactor === null ? null : pricing.inputPerMTok * cachedInputFactor
|
|
13791
|
+
cachedInputPerMTok: pricing.cachedInputPerMTok ?? (cachedInputFactor === null ? null : pricing.inputPerMTok * cachedInputFactor)
|
|
13741
13792
|
};
|
|
13742
13793
|
}
|
|
13743
13794
|
function resolveOpenAITransportModel({
|
|
@@ -13786,6 +13837,8 @@ function resolveOpenAITransportModel({
|
|
|
13786
13837
|
env,
|
|
13787
13838
|
storedCredentials
|
|
13788
13839
|
});
|
|
13840
|
+
const openRouterAnthropicFamily = isOpenRouter && isOpenRouterAnthropicFamilyModel(configuredModel);
|
|
13841
|
+
const openRouterCatalogCaching = isOpenRouter && (capabilities?.pricing?.cachedInputPerMTok ?? 0) > 0;
|
|
13789
13842
|
return {
|
|
13790
13843
|
provider: config6.provider,
|
|
13791
13844
|
configuredModel,
|
|
@@ -13799,8 +13852,9 @@ function resolveOpenAITransportModel({
|
|
|
13799
13852
|
contextWindow: capabilities?.contextLength ?? getModelContextWindow(config6.provider, configuredModel),
|
|
13800
13853
|
missingCredentialHints: apiKey ? [] : isOpenCodeZen ? ["Set OPENCODE_API_KEY to call OpenCode Zen models."] : isOpenRouter ? ["Set OPENROUTER_API_KEY to call OpenRouter models."] : [],
|
|
13801
13854
|
maxCompletionTokens: capabilities?.maxCompletionTokens ?? null,
|
|
13802
|
-
supportsPromptCaching:
|
|
13803
|
-
|
|
13855
|
+
supportsPromptCaching: openRouterAnthropicFamily || openRouterCatalogCaching,
|
|
13856
|
+
rollingCompaction: !openRouterAnthropicFamily,
|
|
13857
|
+
pricing: resolveCapabilityPricing(capabilities, openRouterAnthropicFamily ? 0.1 : null),
|
|
13804
13858
|
webSearchCapability,
|
|
13805
13859
|
providerTools: openRouterProvider && webSearchCapability.execution === "provider" ? {
|
|
13806
13860
|
web_search: createOpenRouterWebSearchTool(openRouterProvider, webSearchCapability)
|
|
@@ -14058,6 +14112,7 @@ var init_subagent_task_store = __esm(() => {
|
|
|
14058
14112
|
});
|
|
14059
14113
|
|
|
14060
14114
|
// apps/server/src/lib/workspace-context.ts
|
|
14115
|
+
import { execFile as execFile3 } from "child_process";
|
|
14061
14116
|
import { createHash as createHash5, randomUUID as randomUUID3 } from "crypto";
|
|
14062
14117
|
import {
|
|
14063
14118
|
chmod as chmod2,
|
|
@@ -14072,6 +14127,7 @@ import {
|
|
|
14072
14127
|
} from "fs/promises";
|
|
14073
14128
|
import { platform as platform3 } from "os";
|
|
14074
14129
|
import path21 from "path";
|
|
14130
|
+
import { promisify as promisify4 } from "util";
|
|
14075
14131
|
import { z as z41 } from "zod";
|
|
14076
14132
|
function isContainedPath(root, candidate) {
|
|
14077
14133
|
const relative = path21.relative(root, candidate);
|
|
@@ -14080,12 +14136,16 @@ function isContainedPath(root, candidate) {
|
|
|
14080
14136
|
function escapeAttribute(value) {
|
|
14081
14137
|
return value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
14082
14138
|
}
|
|
14083
|
-
function
|
|
14139
|
+
function sessionStatePath({
|
|
14140
|
+
directory,
|
|
14084
14141
|
sessionId,
|
|
14085
14142
|
dataDir
|
|
14086
14143
|
}) {
|
|
14087
14144
|
const sessionKey = createHash5("sha256").update(sessionId).digest("hex");
|
|
14088
|
-
return path21.join(dataDir ?? getLightcodeDataDir(),
|
|
14145
|
+
return path21.join(dataDir ?? getLightcodeDataDir(), directory, `${sessionKey}.json`);
|
|
14146
|
+
}
|
|
14147
|
+
function instructionEpochStatePath(options) {
|
|
14148
|
+
return sessionStatePath({ directory: "instruction-epochs", ...options });
|
|
14089
14149
|
}
|
|
14090
14150
|
async function loadInstructionEpochs(statePath) {
|
|
14091
14151
|
try {
|
|
@@ -14106,6 +14166,9 @@ async function loadInstructionEpochs(statePath) {
|
|
|
14106
14166
|
return [];
|
|
14107
14167
|
}
|
|
14108
14168
|
async function persistInstructionEpochs(statePath, epochs) {
|
|
14169
|
+
await writePrivateJsonFile(statePath, { epochs });
|
|
14170
|
+
}
|
|
14171
|
+
async function writePrivateJsonFile(statePath, value) {
|
|
14109
14172
|
const directory = path21.dirname(statePath);
|
|
14110
14173
|
await mkdir3(directory, { recursive: true, mode: 448 });
|
|
14111
14174
|
await chmod2(directory, 448).catch(() => {
|
|
@@ -14113,7 +14176,7 @@ async function persistInstructionEpochs(statePath, epochs) {
|
|
|
14113
14176
|
});
|
|
14114
14177
|
const temporaryPath = `${statePath}.${process.pid}.${randomUUID3()}.tmp`;
|
|
14115
14178
|
try {
|
|
14116
|
-
await writeFile2(temporaryPath, `${JSON.stringify(
|
|
14179
|
+
await writeFile2(temporaryPath, `${JSON.stringify(value, null, 2)}
|
|
14117
14180
|
`, { encoding: "utf8", flag: "wx", mode: 384 });
|
|
14118
14181
|
await rename2(temporaryPath, statePath);
|
|
14119
14182
|
await chmod2(statePath, 384).catch(() => {
|
|
@@ -14362,6 +14425,138 @@ async function buildDirectoryListing(cwd) {
|
|
|
14362
14425
|
return "(unable to list directory)";
|
|
14363
14426
|
}
|
|
14364
14427
|
}
|
|
14428
|
+
async function listRepositoryFiles(cwd) {
|
|
14429
|
+
try {
|
|
14430
|
+
const { stdout } = await execFileAsync3("git", ["ls-files", "--cached", "--others", "--exclude-standard", "-z"], {
|
|
14431
|
+
cwd,
|
|
14432
|
+
encoding: "utf8",
|
|
14433
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
14434
|
+
timeout: repositoryFileListTimeoutMs,
|
|
14435
|
+
windowsHide: true
|
|
14436
|
+
});
|
|
14437
|
+
return [...new Set(stdout.split("\x00").filter(Boolean))];
|
|
14438
|
+
} catch {
|
|
14439
|
+
return null;
|
|
14440
|
+
}
|
|
14441
|
+
}
|
|
14442
|
+
function createRepositoryTreeNode() {
|
|
14443
|
+
return { directories: new Map, files: [], fileCount: 0 };
|
|
14444
|
+
}
|
|
14445
|
+
function compareNames(left, right) {
|
|
14446
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
14447
|
+
}
|
|
14448
|
+
function visibleSubdirectories(node) {
|
|
14449
|
+
const all = [...node.directories.entries()].sort(([left], [right]) => compareNames(left, right)).map(([name, child]) => ({ name, node: child }));
|
|
14450
|
+
return {
|
|
14451
|
+
shown: all.slice(0, maxRepositoryMapChildren),
|
|
14452
|
+
hiddenCount: Math.max(0, all.length - maxRepositoryMapChildren)
|
|
14453
|
+
};
|
|
14454
|
+
}
|
|
14455
|
+
function subdirectoryLines(node, depth) {
|
|
14456
|
+
const indent = " ".repeat(depth);
|
|
14457
|
+
const { shown, hiddenCount } = visibleSubdirectories(node);
|
|
14458
|
+
const lines = shown.map(({ name, node: child }) => `${indent}${name}/ (${child.fileCount})`);
|
|
14459
|
+
if (hiddenCount > 0) {
|
|
14460
|
+
lines.push(`${indent}\u2026 ${hiddenCount} more folders`);
|
|
14461
|
+
}
|
|
14462
|
+
return lines;
|
|
14463
|
+
}
|
|
14464
|
+
function fileNameLines(node, depth) {
|
|
14465
|
+
const indent = " ".repeat(depth);
|
|
14466
|
+
const files = [...node.files].sort(compareNames);
|
|
14467
|
+
const lines = files.slice(0, maxRepositoryMapChildren).map((name) => `${indent}${name}`);
|
|
14468
|
+
if (files.length > lines.length) {
|
|
14469
|
+
lines.push(`${indent}\u2026 ${files.length - lines.length} more files`);
|
|
14470
|
+
}
|
|
14471
|
+
return lines;
|
|
14472
|
+
}
|
|
14473
|
+
function filePlaceholderLines(node, depth) {
|
|
14474
|
+
return node.files.length > 0 ? [`${" ".repeat(depth)}\u2026 ${node.files.length} files`] : [];
|
|
14475
|
+
}
|
|
14476
|
+
function linesCost(lines) {
|
|
14477
|
+
return lines.reduce((sum, line) => sum + line.length + 1, 0);
|
|
14478
|
+
}
|
|
14479
|
+
function formatRepositoryMap(paths, maxChars = maxRepositoryMapChars) {
|
|
14480
|
+
const root = createRepositoryTreeNode();
|
|
14481
|
+
for (const filePath of paths) {
|
|
14482
|
+
const segments = filePath.split("/").filter(Boolean);
|
|
14483
|
+
const fileName = segments.pop();
|
|
14484
|
+
if (!fileName) {
|
|
14485
|
+
continue;
|
|
14486
|
+
}
|
|
14487
|
+
let current = root;
|
|
14488
|
+
current.fileCount += 1;
|
|
14489
|
+
for (const segment of segments) {
|
|
14490
|
+
let child = current.directories.get(segment);
|
|
14491
|
+
if (!child) {
|
|
14492
|
+
child = createRepositoryTreeNode();
|
|
14493
|
+
current.directories.set(segment, child);
|
|
14494
|
+
}
|
|
14495
|
+
child.fileCount += 1;
|
|
14496
|
+
current = child;
|
|
14497
|
+
}
|
|
14498
|
+
current.files.push(fileName);
|
|
14499
|
+
}
|
|
14500
|
+
if (root.fileCount === 0) {
|
|
14501
|
+
return "(no files)";
|
|
14502
|
+
}
|
|
14503
|
+
const order = [
|
|
14504
|
+
{ node: root, depth: 0 }
|
|
14505
|
+
];
|
|
14506
|
+
const expanded = new Set;
|
|
14507
|
+
let used = 0;
|
|
14508
|
+
for (let index = 0;index < order.length; index += 1) {
|
|
14509
|
+
const { node, depth } = order[index];
|
|
14510
|
+
const cost = linesCost(subdirectoryLines(node, depth)) + linesCost(filePlaceholderLines(node, depth));
|
|
14511
|
+
if (node !== root && used + cost > maxChars) {
|
|
14512
|
+
continue;
|
|
14513
|
+
}
|
|
14514
|
+
used += cost;
|
|
14515
|
+
expanded.add(node);
|
|
14516
|
+
for (const { name, node: child } of visibleSubdirectories(node).shown) {
|
|
14517
|
+
if (!name.startsWith(".")) {
|
|
14518
|
+
order.push({ node: child, depth: depth + 1 });
|
|
14519
|
+
}
|
|
14520
|
+
}
|
|
14521
|
+
}
|
|
14522
|
+
const fileCandidates = order.filter(({ node }) => expanded.has(node) && node.files.length > 0).sort((left, right) => left.node === root ? -1 : right.node === root ? 1 : left.node.files.length - right.node.files.length);
|
|
14523
|
+
const filesShown = new Set;
|
|
14524
|
+
for (const { node, depth } of fileCandidates) {
|
|
14525
|
+
const delta = linesCost(fileNameLines(node, depth)) - linesCost(filePlaceholderLines(node, depth));
|
|
14526
|
+
if (used + delta > maxChars) {
|
|
14527
|
+
continue;
|
|
14528
|
+
}
|
|
14529
|
+
used += delta;
|
|
14530
|
+
filesShown.add(node);
|
|
14531
|
+
}
|
|
14532
|
+
const lines = [];
|
|
14533
|
+
const render = (node, depth) => {
|
|
14534
|
+
const { shown } = visibleSubdirectories(node);
|
|
14535
|
+
subdirectoryLines(node, depth).forEach((line, index) => {
|
|
14536
|
+
lines.push(line);
|
|
14537
|
+
const child = shown[index]?.node;
|
|
14538
|
+
if (child && expanded.has(child)) {
|
|
14539
|
+
render(child, depth + 1);
|
|
14540
|
+
}
|
|
14541
|
+
});
|
|
14542
|
+
lines.push(...filesShown.has(node) ? fileNameLines(node, depth) : filePlaceholderLines(node, depth));
|
|
14543
|
+
};
|
|
14544
|
+
render(root, 0);
|
|
14545
|
+
return lines.join(`
|
|
14546
|
+
`);
|
|
14547
|
+
}
|
|
14548
|
+
async function buildRepositoryOverview(cwd) {
|
|
14549
|
+
const files = await listRepositoryFiles(cwd);
|
|
14550
|
+
if (!files) {
|
|
14551
|
+
return ["Top-level entries:", await buildDirectoryListing(cwd)].join(`
|
|
14552
|
+
`);
|
|
14553
|
+
}
|
|
14554
|
+
return [
|
|
14555
|
+
`Repository files (${files.length}; dir/ (N) = N files inside, "\u2026" = more not shown; use glob_search or list_files for the rest):`,
|
|
14556
|
+
formatRepositoryMap(files)
|
|
14557
|
+
].join(`
|
|
14558
|
+
`);
|
|
14559
|
+
}
|
|
14365
14560
|
function buildGitSummary(cwd) {
|
|
14366
14561
|
const cached = gitSummaryCache.get(cwd);
|
|
14367
14562
|
if (cached && cached.expiresAt > Date.now()) {
|
|
@@ -14441,13 +14636,98 @@ async function buildWorkspaceInstructionBaseline({
|
|
|
14441
14636
|
`)
|
|
14442
14637
|
};
|
|
14443
14638
|
}
|
|
14639
|
+
function memoizeEnvironmentSnapshot(statePath, snapshot) {
|
|
14640
|
+
environmentSnapshotMemo.delete(statePath);
|
|
14641
|
+
environmentSnapshotMemo.set(statePath, snapshot);
|
|
14642
|
+
if (environmentSnapshotMemo.size > maxMemoizedEnvironmentSnapshots) {
|
|
14643
|
+
const oldest = environmentSnapshotMemo.keys().next().value;
|
|
14644
|
+
if (oldest !== undefined) {
|
|
14645
|
+
environmentSnapshotMemo.delete(oldest);
|
|
14646
|
+
}
|
|
14647
|
+
}
|
|
14648
|
+
return snapshot;
|
|
14649
|
+
}
|
|
14650
|
+
async function captureEnvironmentSnapshot(cwd) {
|
|
14651
|
+
const [overview, git] = await Promise.all([
|
|
14652
|
+
buildRepositoryOverview(cwd),
|
|
14653
|
+
buildGitSummary(cwd)
|
|
14654
|
+
]);
|
|
14655
|
+
const capturedAt = new Date().toISOString();
|
|
14656
|
+
return {
|
|
14657
|
+
cwd,
|
|
14658
|
+
capturedAt,
|
|
14659
|
+
body: [
|
|
14660
|
+
`Working directory: ${cwd}`,
|
|
14661
|
+
`Platform: ${describePlatform()}`,
|
|
14662
|
+
`Date: ${capturedAt.slice(0, 10)} (session start)`,
|
|
14663
|
+
"",
|
|
14664
|
+
"Git (snapshot from session start; call git_status for the current state):",
|
|
14665
|
+
git,
|
|
14666
|
+
"",
|
|
14667
|
+
overview
|
|
14668
|
+
].join(`
|
|
14669
|
+
`)
|
|
14670
|
+
};
|
|
14671
|
+
}
|
|
14672
|
+
async function loadEnvironmentSnapshot(statePath, cwd) {
|
|
14673
|
+
const memoized = environmentSnapshotMemo.get(statePath);
|
|
14674
|
+
if (memoized?.cwd === cwd) {
|
|
14675
|
+
return memoized;
|
|
14676
|
+
}
|
|
14677
|
+
try {
|
|
14678
|
+
const parsed = environmentSnapshotSchema.safeParse(JSON.parse(await readFile4(statePath, "utf8")));
|
|
14679
|
+
if (parsed.success && parsed.data.cwd === cwd) {
|
|
14680
|
+
return memoizeEnvironmentSnapshot(statePath, parsed.data);
|
|
14681
|
+
}
|
|
14682
|
+
if (!parsed.success) {
|
|
14683
|
+
logger7.warn("workspace_environment_snapshot_invalid", { statePath });
|
|
14684
|
+
}
|
|
14685
|
+
} catch (error) {
|
|
14686
|
+
const code = isRecord3(error) ? Reflect.get(error, "code") : undefined;
|
|
14687
|
+
if (code !== "ENOENT") {
|
|
14688
|
+
logger7.warn("workspace_environment_snapshot_load_failed", {
|
|
14689
|
+
statePath,
|
|
14690
|
+
error: getErrorMessage(error)
|
|
14691
|
+
});
|
|
14692
|
+
}
|
|
14693
|
+
}
|
|
14694
|
+
return null;
|
|
14695
|
+
}
|
|
14696
|
+
async function resolveEnvironmentSnapshot({
|
|
14697
|
+
cwd,
|
|
14698
|
+
sessionId,
|
|
14699
|
+
dataDir
|
|
14700
|
+
}) {
|
|
14701
|
+
if (!sessionId) {
|
|
14702
|
+
return captureEnvironmentSnapshot(cwd);
|
|
14703
|
+
}
|
|
14704
|
+
const statePath = sessionStatePath({
|
|
14705
|
+
directory: "session-environment",
|
|
14706
|
+
sessionId,
|
|
14707
|
+
dataDir
|
|
14708
|
+
});
|
|
14709
|
+
const existing = await loadEnvironmentSnapshot(statePath, cwd);
|
|
14710
|
+
if (existing) {
|
|
14711
|
+
return existing;
|
|
14712
|
+
}
|
|
14713
|
+
const snapshot = memoizeEnvironmentSnapshot(statePath, await captureEnvironmentSnapshot(cwd));
|
|
14714
|
+
try {
|
|
14715
|
+
await writePrivateJsonFile(statePath, snapshot);
|
|
14716
|
+
} catch (error) {
|
|
14717
|
+
logger7.warn("workspace_environment_snapshot_persist_failed", {
|
|
14718
|
+
statePath,
|
|
14719
|
+
error: getErrorMessage(error)
|
|
14720
|
+
});
|
|
14721
|
+
}
|
|
14722
|
+
return snapshot;
|
|
14723
|
+
}
|
|
14444
14724
|
async function buildWorkspaceContext({
|
|
14445
14725
|
cwd,
|
|
14446
14726
|
sessionId,
|
|
14447
14727
|
relatedPaths,
|
|
14448
14728
|
dataDir
|
|
14449
14729
|
}) {
|
|
14450
|
-
const [baseline, nestedInstructions,
|
|
14730
|
+
const [baseline, nestedInstructions, snapshot] = await Promise.all([
|
|
14451
14731
|
buildWorkspaceInstructionBaseline({ cwd }),
|
|
14452
14732
|
buildNestedWorkspaceInstructionBlock({
|
|
14453
14733
|
cwd,
|
|
@@ -14455,26 +14735,16 @@ async function buildWorkspaceContext({
|
|
|
14455
14735
|
relatedPaths,
|
|
14456
14736
|
dataDir
|
|
14457
14737
|
}),
|
|
14458
|
-
|
|
14459
|
-
buildGitSummary(cwd)
|
|
14738
|
+
resolveEnvironmentSnapshot({ cwd, sessionId, dataDir })
|
|
14460
14739
|
]);
|
|
14461
14740
|
const skills = buildAvailableSkills(cwd);
|
|
14462
|
-
const today = new Date().toISOString().slice(0, 10);
|
|
14463
14741
|
const parts = [
|
|
14464
14742
|
baseline.block,
|
|
14465
14743
|
nestedInstructions ? `
|
|
14466
14744
|
${nestedInstructions}` : "",
|
|
14467
14745
|
"",
|
|
14468
14746
|
"<environment>",
|
|
14469
|
-
|
|
14470
|
-
`Platform: ${describePlatform()}`,
|
|
14471
|
-
`Date: ${today}`,
|
|
14472
|
-
"",
|
|
14473
|
-
"Git:",
|
|
14474
|
-
git,
|
|
14475
|
-
"",
|
|
14476
|
-
"Top-level entries:",
|
|
14477
|
-
listing,
|
|
14747
|
+
snapshot.body,
|
|
14478
14748
|
skills ? `
|
|
14479
14749
|
${skills}` : "",
|
|
14480
14750
|
"</environment>"
|
|
@@ -14485,48 +14755,12 @@ ${skills}` : "",
|
|
|
14485
14755
|
\u2026 (environment truncated)
|
|
14486
14756
|
</environment>` : block;
|
|
14487
14757
|
}
|
|
14488
|
-
|
|
14489
|
-
cwd,
|
|
14490
|
-
sessionId,
|
|
14491
|
-
relatedPaths,
|
|
14492
|
-
dataDir
|
|
14493
|
-
}) {
|
|
14494
|
-
const [baseline, nestedInstructions, git] = await Promise.all([
|
|
14495
|
-
buildWorkspaceInstructionBaseline({ cwd }),
|
|
14496
|
-
buildNestedWorkspaceInstructionBlock({
|
|
14497
|
-
cwd,
|
|
14498
|
-
sessionId,
|
|
14499
|
-
relatedPaths,
|
|
14500
|
-
dataDir
|
|
14501
|
-
}),
|
|
14502
|
-
buildGitSummary(cwd)
|
|
14503
|
-
]);
|
|
14504
|
-
const skills = buildAvailableSkills(cwd);
|
|
14505
|
-
const today = new Date().toISOString().slice(0, 10);
|
|
14506
|
-
return [
|
|
14507
|
-
baseline.block,
|
|
14508
|
-
nestedInstructions ? `
|
|
14509
|
-
${nestedInstructions}` : "",
|
|
14510
|
-
"",
|
|
14511
|
-
"<environment>",
|
|
14512
|
-
`Working directory: ${cwd}`,
|
|
14513
|
-
`Platform: ${describePlatform()}`,
|
|
14514
|
-
`Date: ${today}`,
|
|
14515
|
-
"(Top-level listing is available through list_files; current git state follows.)",
|
|
14516
|
-
"",
|
|
14517
|
-
"Git:",
|
|
14518
|
-
git,
|
|
14519
|
-
skills ? `
|
|
14520
|
-
${skills}` : "",
|
|
14521
|
-
"</environment>"
|
|
14522
|
-
].join(`
|
|
14523
|
-
`);
|
|
14524
|
-
}
|
|
14525
|
-
var logger7, projectInstructionNames, maxListedEntries = 40, maxInstructionChars = 6000, maxNestedInstructionChars = 6000, maxNestedInstructionFileChars = 1600, maxBlockChars = 18000, instructionEpochSchema, instructionEpochStateSchema, gitSummaryCacheTtlMs = 5000, gitSummaryCache;
|
|
14758
|
+
var execFileAsync3, logger7, projectInstructionNames, maxListedEntries = 40, maxInstructionChars = 6000, maxNestedInstructionChars = 6000, maxNestedInstructionFileChars = 1600, maxRepositoryMapChars = 6000, maxRepositoryMapChildren = 32, maxBlockChars = 24000, repositoryFileListTimeoutMs = 5000, instructionEpochSchema, instructionEpochStateSchema, gitSummaryCacheTtlMs = 5000, gitSummaryCache, environmentSnapshotSchema, maxMemoizedEnvironmentSnapshots = 256, environmentSnapshotMemo;
|
|
14526
14759
|
var init_workspace_context = __esm(() => {
|
|
14527
14760
|
init_runtime17();
|
|
14528
14761
|
init_src2();
|
|
14529
14762
|
init_src();
|
|
14763
|
+
execFileAsync3 = promisify4(execFile3);
|
|
14530
14764
|
logger7 = createLogger("workspace-context");
|
|
14531
14765
|
projectInstructionNames = ["AGENTS.md", "CLAUDE.md"];
|
|
14532
14766
|
instructionEpochSchema = z41.object({
|
|
@@ -14540,6 +14774,12 @@ var init_workspace_context = __esm(() => {
|
|
|
14540
14774
|
epochs: z41.array(instructionEpochSchema)
|
|
14541
14775
|
});
|
|
14542
14776
|
gitSummaryCache = new Map;
|
|
14777
|
+
environmentSnapshotSchema = z41.object({
|
|
14778
|
+
cwd: z41.string().min(1),
|
|
14779
|
+
capturedAt: z41.string().min(1),
|
|
14780
|
+
body: z41.string()
|
|
14781
|
+
});
|
|
14782
|
+
environmentSnapshotMemo = new Map;
|
|
14543
14783
|
});
|
|
14544
14784
|
|
|
14545
14785
|
// apps/server/src/lib/subagent-runner.ts
|
|
@@ -14621,7 +14861,8 @@ async function runSubagentToolTask(input, context2, deps) {
|
|
|
14621
14861
|
abortSignal: context2.abortSignal,
|
|
14622
14862
|
prepareStep: async ({ messages }) => {
|
|
14623
14863
|
const artifactized = await artifactizeLargeToolOutputs(messages, {
|
|
14624
|
-
signal: context2.abortSignal
|
|
14864
|
+
signal: context2.abortSignal,
|
|
14865
|
+
currentTurnThresholdCharacters: DEFAULT_CURRENT_TURN_TOOL_OUTPUT_THRESHOLD_CHARACTERS
|
|
14625
14866
|
});
|
|
14626
14867
|
const turn = assembler.assembleModelMessages(artifactized.messages, {
|
|
14627
14868
|
preserveRecentTokens
|
|
@@ -15129,6 +15370,7 @@ async function streamSessionChat(c, sessionIdentifier, messagesPayload, cwd, mod
|
|
|
15129
15370
|
});
|
|
15130
15371
|
const contextConfig = lightcodeConfigResult.config.context;
|
|
15131
15372
|
const cacheActive = resolvedProviderModel.supportsPromptCaching;
|
|
15373
|
+
const rollingCompaction = resolvedProviderModel.rollingCompaction ?? !cacheActive;
|
|
15132
15374
|
const endpointLimitTokens = getLearnedContextLimit(chatModelId);
|
|
15133
15375
|
const effectiveContextWindow = resolveContextWindowTokens({
|
|
15134
15376
|
config: contextConfig,
|
|
@@ -15136,9 +15378,12 @@ async function streamSessionChat(c, sessionIdentifier, messagesPayload, cwd, mod
|
|
|
15136
15378
|
endpointLimitTokens
|
|
15137
15379
|
});
|
|
15138
15380
|
const reservedOutputTokens = Math.min(resolveMaxOutputTokens(lightcodeConfigResult.config.maxOutputTokens, lightcodeConfigDefaults.maxOutputTokens, resolvedProviderModel.maxCompletionTokens), Math.max(1024, Math.floor(effectiveContextWindow / 2)));
|
|
15139
|
-
const isFirstAssistantTurn = !validatedMessages.some((message) => message.role === "assistant");
|
|
15140
15381
|
const relatedPaths = collectRelatedWorkspacePaths(validatedMessages);
|
|
15141
|
-
const environmentContext =
|
|
15382
|
+
const environmentContext = await buildWorkspaceContext({
|
|
15383
|
+
cwd,
|
|
15384
|
+
sessionId,
|
|
15385
|
+
relatedPaths
|
|
15386
|
+
});
|
|
15142
15387
|
const availableSkillNames = listSkills({ cwd }).map((skill) => skill.name);
|
|
15143
15388
|
const useFastChatPath = shouldUseFastChatPath({
|
|
15144
15389
|
messages: providerInputMessages,
|
|
@@ -15208,6 +15453,7 @@ ${environmentContext}` : agentCallSettings.instructions;
|
|
|
15208
15453
|
endpointLimitTokens,
|
|
15209
15454
|
pendingInteractionCount,
|
|
15210
15455
|
cacheActive,
|
|
15456
|
+
rollingCompaction,
|
|
15211
15457
|
fixedInputTokens: turnAssembler.fixedInputTokens
|
|
15212
15458
|
});
|
|
15213
15459
|
if (contextConfig.autoCompact) {
|
|
@@ -15238,6 +15484,7 @@ ${environmentContext}` : agentCallSettings.instructions;
|
|
|
15238
15484
|
endpointLimitTokens,
|
|
15239
15485
|
pendingInteractionCount,
|
|
15240
15486
|
cacheActive,
|
|
15487
|
+
rollingCompaction,
|
|
15241
15488
|
fixedInputTokens: turnAssembler.fixedInputTokens
|
|
15242
15489
|
});
|
|
15243
15490
|
logger11.info("context_auto_compacted", {
|
|
@@ -15280,6 +15527,7 @@ ${environmentContext}` : agentCallSettings.instructions;
|
|
|
15280
15527
|
endpointLimitTokens,
|
|
15281
15528
|
pendingInteractionCount: 0,
|
|
15282
15529
|
cacheActive,
|
|
15530
|
+
rollingCompaction,
|
|
15283
15531
|
fixedInputTokens: turnAssembler.fixedInputTokens
|
|
15284
15532
|
});
|
|
15285
15533
|
if (overflowView.coveredMessages.length > 0) {
|
|
@@ -15306,6 +15554,7 @@ ${environmentContext}` : agentCallSettings.instructions;
|
|
|
15306
15554
|
endpointLimitTokens,
|
|
15307
15555
|
pendingInteractionCount: 0,
|
|
15308
15556
|
cacheActive,
|
|
15557
|
+
rollingCompaction,
|
|
15309
15558
|
fixedInputTokens: turnAssembler.fixedInputTokens
|
|
15310
15559
|
});
|
|
15311
15560
|
logger11.info("context_overflow_recovery", {
|
|
@@ -15359,7 +15608,7 @@ ${environmentContext}` : agentCallSettings.instructions;
|
|
|
15359
15608
|
noteContextOverflow(sessionId);
|
|
15360
15609
|
};
|
|
15361
15610
|
const maybeRunRollingCompaction = async (finishedMessages) => {
|
|
15362
|
-
if (
|
|
15611
|
+
if (!rollingCompaction || !contextConfig.autoCompact) {
|
|
15363
15612
|
return;
|
|
15364
15613
|
}
|
|
15365
15614
|
if (rollingCompactionInFlight.has(sessionId)) {
|
|
@@ -15367,38 +15616,45 @@ ${environmentContext}` : agentCallSettings.instructions;
|
|
|
15367
15616
|
}
|
|
15368
15617
|
rollingCompactionInFlight.add(sessionId);
|
|
15369
15618
|
try {
|
|
15370
|
-
|
|
15371
|
-
const
|
|
15372
|
-
|
|
15373
|
-
|
|
15374
|
-
|
|
15375
|
-
|
|
15376
|
-
|
|
15377
|
-
|
|
15378
|
-
|
|
15379
|
-
|
|
15380
|
-
|
|
15381
|
-
|
|
15382
|
-
|
|
15383
|
-
|
|
15619
|
+
let latestState = await loadSessionContextStateSafe(sessionId);
|
|
15620
|
+
const pendingInteractionCount2 = await countPendingChatInteractions(sessionId);
|
|
15621
|
+
for (let round = 1;round <= MAX_ROLLING_COMPACTION_ROUNDS; round += 1) {
|
|
15622
|
+
const rollingView = buildProviderView({
|
|
15623
|
+
messages: finishedMessages,
|
|
15624
|
+
contextState: latestState,
|
|
15625
|
+
config: contextConfig,
|
|
15626
|
+
modelContextWindow: resolvedProviderModel.contextWindow,
|
|
15627
|
+
reservedOutputTokens: budgetReservedOutputTokens,
|
|
15628
|
+
endpointLimitTokens,
|
|
15629
|
+
pendingInteractionCount: pendingInteractionCount2,
|
|
15630
|
+
cacheActive,
|
|
15631
|
+
rollingCompaction,
|
|
15632
|
+
continueRolling: round > 1,
|
|
15633
|
+
fixedInputTokens: turnAssembler.fixedInputTokens
|
|
15634
|
+
});
|
|
15635
|
+
if (!rollingView.needsRollingCompaction) {
|
|
15636
|
+
return;
|
|
15637
|
+
}
|
|
15638
|
+
const compaction = await compactSessionContext({
|
|
15639
|
+
sessionId,
|
|
15640
|
+
coveredMessages: rollingView.coveredMessages,
|
|
15641
|
+
previousState: latestState,
|
|
15642
|
+
model: resolvedProviderModel.model,
|
|
15643
|
+
modelId: chatModelId,
|
|
15644
|
+
cwd,
|
|
15645
|
+
config: contextConfig,
|
|
15646
|
+
estimatedTokens: rollingView.estimate.tokens,
|
|
15647
|
+
contextWindow: rollingView.contextWindow
|
|
15648
|
+
});
|
|
15649
|
+
latestState = compaction.state;
|
|
15650
|
+
logger11.info("context_rolling_compaction", {
|
|
15651
|
+
sessionId,
|
|
15652
|
+
round,
|
|
15653
|
+
tier: compaction.state.tier,
|
|
15654
|
+
usedFallback: compaction.usedFallback,
|
|
15655
|
+
coveredMessageCount: compaction.state.coveredMessageCount
|
|
15656
|
+
});
|
|
15384
15657
|
}
|
|
15385
|
-
const compaction = await compactSessionContext({
|
|
15386
|
-
sessionId,
|
|
15387
|
-
coveredMessages: rollingView.coveredMessages,
|
|
15388
|
-
previousState: latestState,
|
|
15389
|
-
model: resolvedProviderModel.model,
|
|
15390
|
-
modelId: chatModelId,
|
|
15391
|
-
cwd,
|
|
15392
|
-
config: contextConfig,
|
|
15393
|
-
estimatedTokens: rollingView.estimate.tokens,
|
|
15394
|
-
contextWindow: rollingView.contextWindow
|
|
15395
|
-
});
|
|
15396
|
-
logger11.info("context_rolling_compaction", {
|
|
15397
|
-
sessionId,
|
|
15398
|
-
tier: compaction.state.tier,
|
|
15399
|
-
usedFallback: compaction.usedFallback,
|
|
15400
|
-
coveredMessageCount: compaction.state.coveredMessageCount
|
|
15401
|
-
});
|
|
15402
15658
|
} catch (error) {
|
|
15403
15659
|
logger11.error("context_rolling_compaction_failed", {
|
|
15404
15660
|
sessionId,
|
|
@@ -15615,6 +15871,7 @@ ${environmentContext}` : agentCallSettings.instructions;
|
|
|
15615
15871
|
contextWindow: view.contextWindow,
|
|
15616
15872
|
preserveRecentTokens: view.preserveRecentTokens,
|
|
15617
15873
|
originalInputTokens: estimateStructuralTokens(providerInputMessages) + turnAssembler.fixedInputTokens,
|
|
15874
|
+
promptCacheActive: cacheActive,
|
|
15618
15875
|
assemblyAbortSignal: requestAbortSignal,
|
|
15619
15876
|
turnKey: [...validatedMessages].reverse().find((message) => message.role === "user")?.id
|
|
15620
15877
|
},
|
|
@@ -15680,7 +15937,7 @@ ${environmentContext}` : agentCallSettings.instructions;
|
|
|
15680
15937
|
}, 500);
|
|
15681
15938
|
}
|
|
15682
15939
|
}
|
|
15683
|
-
var logger11, recoverableDisconnectMessage = "Connection interrupted. Please retry or regenerate your last message.", providerBillingOrQuotaMessage, fastChatSystemPrompt, fastChatMaxOutputTokens = 512, MAX_COMPACTION_ROUNDS = 1, rollingCompactionInFlight;
|
|
15940
|
+
var logger11, recoverableDisconnectMessage = "Connection interrupted. Please retry or regenerate your last message.", providerBillingOrQuotaMessage, fastChatSystemPrompt, fastChatMaxOutputTokens = 512, MAX_COMPACTION_ROUNDS = 1, MAX_ROLLING_COMPACTION_ROUNDS = 4, rollingCompactionInFlight;
|
|
15684
15941
|
var init_chat_stream = __esm(() => {
|
|
15685
15942
|
init_src2();
|
|
15686
15943
|
init_src();
|
|
@@ -15742,11 +15999,7 @@ async function assembleStoredSessionProviderTurn({
|
|
|
15742
15999
|
messages,
|
|
15743
16000
|
cwd: session.cwd
|
|
15744
16001
|
});
|
|
15745
|
-
const environmentContext =
|
|
15746
|
-
cwd: session.cwd,
|
|
15747
|
-
sessionId: session.id,
|
|
15748
|
-
relatedPaths: collectRelatedWorkspacePaths(messages)
|
|
15749
|
-
}) : await buildWorkspaceContext({
|
|
16002
|
+
const environmentContext = await buildWorkspaceContext({
|
|
15750
16003
|
cwd: session.cwd,
|
|
15751
16004
|
sessionId: session.id,
|
|
15752
16005
|
relatedPaths: collectRelatedWorkspacePaths(messages)
|
|
@@ -15799,6 +16052,7 @@ async function assembleStoredSessionProviderTurn({
|
|
|
15799
16052
|
endpointLimitTokens,
|
|
15800
16053
|
reservedOutputTokens,
|
|
15801
16054
|
cacheActive: resolvedProviderModel.supportsPromptCaching,
|
|
16055
|
+
rollingCompaction: resolvedProviderModel.rollingCompaction ?? !resolvedProviderModel.supportsPromptCaching,
|
|
15802
16056
|
fixedInputTokens: baseAssembler.fixedInputTokens
|
|
15803
16057
|
});
|
|
15804
16058
|
const assembler = new ProviderTurnAssembler({
|
|
@@ -15811,7 +16065,10 @@ async function assembleStoredSessionProviderTurn({
|
|
|
15811
16065
|
});
|
|
15812
16066
|
const modelMessages = await convertToModelMessages(normalizeProviderMessages(view.providerMessages), { tools });
|
|
15813
16067
|
const artifactized = await artifactizeLargeToolOutputs(modelMessages, {
|
|
15814
|
-
signal: abortSignal
|
|
16068
|
+
signal: abortSignal,
|
|
16069
|
+
...resolveToolOutputArtifactThresholds({
|
|
16070
|
+
promptCacheActive: resolvedProviderModel.supportsPromptCaching
|
|
16071
|
+
})
|
|
15815
16072
|
});
|
|
15816
16073
|
const assembled = assembler.assembleModelMessages(artifactized.messages, { preserveRecentTokens: view.preserveRecentTokens });
|
|
15817
16074
|
return { view, assembled };
|