@kmugalkhod/lightcode 0.2.0 → 0.4.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/cli.js +261 -80
- package/package.json +1 -1
- package/server.js +276 -40
package/cli.js
CHANGED
|
@@ -124,7 +124,7 @@ var init_logger = __esm(() => {
|
|
|
124
124
|
});
|
|
125
125
|
|
|
126
126
|
// packages/shared/src/version.ts
|
|
127
|
-
var lightcodeVersion = "0.
|
|
127
|
+
var lightcodeVersion = "0.4.0";
|
|
128
128
|
|
|
129
129
|
// packages/shared/src/index.ts
|
|
130
130
|
var productName = "Lightcode";
|
|
@@ -998,7 +998,7 @@ var init_slash_page_menu = __esm(() => {
|
|
|
998
998
|
});
|
|
999
999
|
|
|
1000
1000
|
// packages/ai/src/constants.ts
|
|
1001
|
-
var MAX_TOOL_TEXT_OUTPUT_CHARS = 12000, MAX_TOOL_LIST_ENTRIES = 200, MAX_TOOL_SEARCH_RESULTS = 200, ANTHROPIC_TOOL_OPTIONAL_PARAMETER_BUDGET = 24;
|
|
1001
|
+
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;
|
|
1002
1002
|
|
|
1003
1003
|
// packages/ai/src/coding-agent-modes.ts
|
|
1004
1004
|
import { z } from "zod";
|
|
@@ -1594,13 +1594,13 @@ var init_base_schemas = __esm(() => {
|
|
|
1594
1594
|
|
|
1595
1595
|
// packages/ai/src/bash/schema.ts
|
|
1596
1596
|
import { z as z5 } from "zod";
|
|
1597
|
-
var bashDescription = "Run a shell command from workspace root with a timeout. Commands are classified before execution and may require approval.", bashInputSchema, bashProviderInputSchema, bashOutputSchema;
|
|
1597
|
+
var bashDescription = "Run a shell command from workspace root with a timeout. Bound noisy output at the source (head/tail/grep/wc, or write to a file then read a range) rather than dumping everything \u2014 output is truncated head+tail and wastes tokens. Commands are classified before execution and may require approval.", bashInputSchema, bashProviderInputSchema, bashOutputSchema;
|
|
1598
1598
|
var init_schema = __esm(() => {
|
|
1599
1599
|
init_base_schemas();
|
|
1600
1600
|
bashInputSchema = z5.object({
|
|
1601
1601
|
command: z5.string().min(1).max(4000),
|
|
1602
1602
|
timeoutMs: integerRangeSchema(1000, 120000, "timeoutMs").optional().default(30000),
|
|
1603
|
-
maxOutputChars: integerRangeSchema(200, MAX_TOOL_TEXT_OUTPUT_CHARS, "maxOutputChars").optional().default(
|
|
1603
|
+
maxOutputChars: integerRangeSchema(200, MAX_TOOL_TEXT_OUTPUT_CHARS, "maxOutputChars").optional().default(DEFAULT_TOOL_TEXT_OUTPUT_CHARS)
|
|
1604
1604
|
});
|
|
1605
1605
|
bashProviderInputSchema = z5.object({
|
|
1606
1606
|
command: z5.string().min(1).max(4000)
|
|
@@ -1710,7 +1710,7 @@ var init_schema5 = __esm(() => {
|
|
|
1710
1710
|
path: boundedPathSchema.optional(),
|
|
1711
1711
|
staged: z9.boolean().optional().default(false),
|
|
1712
1712
|
statOnly: z9.boolean().optional().default(false),
|
|
1713
|
-
maxChars: integerRangeSchema(200, MAX_TOOL_TEXT_OUTPUT_CHARS, "maxChars").optional().default(
|
|
1713
|
+
maxChars: integerRangeSchema(200, MAX_TOOL_TEXT_OUTPUT_CHARS, "maxChars").optional().default(DEFAULT_TOOL_TEXT_OUTPUT_CHARS)
|
|
1714
1714
|
});
|
|
1715
1715
|
gitDiffProviderInputSchema = z9.object({
|
|
1716
1716
|
path: boundedPathSchema.optional(),
|
|
@@ -1725,7 +1725,7 @@ var init_schema5 = __esm(() => {
|
|
|
1725
1725
|
gitShowInputSchema = z9.object({
|
|
1726
1726
|
revision: z9.string().min(1).max(240),
|
|
1727
1727
|
path: boundedPathSchema.optional(),
|
|
1728
|
-
maxChars: integerRangeSchema(200, MAX_TOOL_TEXT_OUTPUT_CHARS, "maxChars").optional().default(
|
|
1728
|
+
maxChars: integerRangeSchema(200, MAX_TOOL_TEXT_OUTPUT_CHARS, "maxChars").optional().default(DEFAULT_TOOL_TEXT_OUTPUT_CHARS)
|
|
1729
1729
|
});
|
|
1730
1730
|
gitShowProviderInputSchema = z9.object({
|
|
1731
1731
|
revision: z9.string().min(1).max(240),
|
|
@@ -1822,7 +1822,7 @@ var init_schema6 = __esm(() => {
|
|
|
1822
1822
|
|
|
1823
1823
|
// packages/ai/src/read-file/schema.ts
|
|
1824
1824
|
import { z as z11 } from "zod";
|
|
1825
|
-
var readFileDescription = "Read file content from the working directory
|
|
1825
|
+
var readFileDescription = "Read file content from the working directory. Prefer a startLine/endLine range to read only the region you need instead of the whole file \u2014 large files are truncated (head+tail) and waste tokens. Raise maxChars only when you truly need more.", readFileInputSchema, readFileProviderInputSchema, readFileOutputSchema;
|
|
1826
1826
|
var init_schema7 = __esm(() => {
|
|
1827
1827
|
init_base_schemas();
|
|
1828
1828
|
readFileInputSchema = z11.object({
|
|
@@ -2076,12 +2076,12 @@ var init_schema13 = __esm(() => {
|
|
|
2076
2076
|
|
|
2077
2077
|
// packages/ai/src/web-fetch/schema.ts
|
|
2078
2078
|
import { z as z19 } from "zod";
|
|
2079
|
-
var webFetchDescription = "Fetch a URL and return normalized, bounded text with source metadata. Requires network permission.", webFetchInputSchema, webFetchProviderInputSchema, webFetchErrorSchema, webFetchOutputSchema;
|
|
2079
|
+
var webFetchDescription = "Fetch a URL and return normalized, bounded text with source metadata. Keep maxChars modest and request more only if the answer wasn't in the returned text. Requires network permission.", webFetchInputSchema, webFetchProviderInputSchema, webFetchErrorSchema, webFetchOutputSchema;
|
|
2080
2080
|
var init_schema14 = __esm(() => {
|
|
2081
2081
|
init_base_schemas();
|
|
2082
2082
|
webFetchInputSchema = z19.object({
|
|
2083
2083
|
url: z19.string().url().max(4096),
|
|
2084
|
-
maxChars: integerRangeSchema(200, MAX_TOOL_TEXT_OUTPUT_CHARS, "maxChars").optional().default(
|
|
2084
|
+
maxChars: integerRangeSchema(200, MAX_TOOL_TEXT_OUTPUT_CHARS, "maxChars").optional().default(DEFAULT_TOOL_TEXT_OUTPUT_CHARS),
|
|
2085
2085
|
timeoutMs: integerRangeSchema(1000, 30000, "timeoutMs").optional().default(1e4)
|
|
2086
2086
|
});
|
|
2087
2087
|
webFetchProviderInputSchema = z19.object({
|
|
@@ -2857,11 +2857,11 @@ ${toolCallingDisciplineAddendum}` : "");
|
|
|
2857
2857
|
var cwdPromptPlaceholder = "{cwd}", defaultCodingAgentSystemPrompt, toolCallingDisciplineAddendum;
|
|
2858
2858
|
var init_coding_agent_prompt = __esm(() => {
|
|
2859
2859
|
init_coding_agent_modes();
|
|
2860
|
-
defaultCodingAgentSystemPrompt = "You are a
|
|
2860
|
+
defaultCodingAgentSystemPrompt = "You are a coding agent. Use tools for filesystem and codebase tasks instead of guessing, and only interact with files under this working directory: {cwd}. " + "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. " + `Use todo_write to keep multi-step work visible and current, inspect context before risky operations, and emit a brief, natural progress note before major tool actions and after important findings.
|
|
2861
2861
|
|
|
2862
|
-
` +
|
|
2862
|
+
` + `You are an agent \u2014 keep working until the request is fully resolved. Never stop with a partial answer; if you say you will do something, do it in the same turn by calling a tool. Do not finish while any todo is pending or in_progress \u2014 end your turn only when the task is complete or you are blocked on input that only the user can provide.
|
|
2863
2863
|
|
|
2864
|
-
` + "Long-running processes
|
|
2864
|
+
` + "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.";
|
|
2865
2865
|
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. " + "Call one tool at a time and wait for its result before deciding the next step.";
|
|
2866
2866
|
});
|
|
2867
2867
|
|
|
@@ -3646,6 +3646,10 @@ var init_config3 = __esm(() => {
|
|
|
3646
3646
|
preserveRecentMessages: z26.number().int().min(2).max(100).optional(),
|
|
3647
3647
|
contextWindowOverride: z26.number().int().min(8000).max(1e7).optional(),
|
|
3648
3648
|
summaryMaxChars: z26.number().int().min(200).max(50000).optional(),
|
|
3649
|
+
aggressivePruneWhenUncached: z26.boolean().optional(),
|
|
3650
|
+
uncachedPruneAtFraction: z26.number().min(0.2).max(0.9).optional(),
|
|
3651
|
+
uncachedPruneMinOutputChars: z26.number().int().min(200).max(12000).optional(),
|
|
3652
|
+
uncachedQuantizeUserTurns: z26.number().int().min(1).max(20).optional(),
|
|
3649
3653
|
maxInputTokens: z26.number().int().min(1).max(1e7).optional()
|
|
3650
3654
|
}).strict();
|
|
3651
3655
|
resolvedContextOptimizerConfigSchema = z26.object({
|
|
@@ -3654,15 +3658,23 @@ var init_config3 = __esm(() => {
|
|
|
3654
3658
|
pruneAtFraction: z26.number().min(0.2).max(0.9),
|
|
3655
3659
|
preserveRecentMessages: z26.number().int().min(2).max(100),
|
|
3656
3660
|
contextWindowOverride: z26.number().int().min(8000).max(1e7).nullable(),
|
|
3657
|
-
summaryMaxChars: z26.number().int().min(200).max(50000)
|
|
3661
|
+
summaryMaxChars: z26.number().int().min(200).max(50000),
|
|
3662
|
+
aggressivePruneWhenUncached: z26.boolean(),
|
|
3663
|
+
uncachedPruneAtFraction: z26.number().min(0.2).max(0.9),
|
|
3664
|
+
uncachedPruneMinOutputChars: z26.number().int().min(200).max(12000),
|
|
3665
|
+
uncachedQuantizeUserTurns: z26.number().int().min(1).max(20)
|
|
3658
3666
|
});
|
|
3659
3667
|
defaultContextOptimizerConfig = {
|
|
3660
3668
|
autoCompact: true,
|
|
3661
|
-
compactAtFraction: 0.
|
|
3669
|
+
compactAtFraction: 0.7,
|
|
3662
3670
|
pruneAtFraction: 0.6,
|
|
3663
3671
|
preserveRecentMessages: 6,
|
|
3664
3672
|
contextWindowOverride: null,
|
|
3665
|
-
summaryMaxChars: 4000
|
|
3673
|
+
summaryMaxChars: 4000,
|
|
3674
|
+
aggressivePruneWhenUncached: true,
|
|
3675
|
+
uncachedPruneAtFraction: 0.45,
|
|
3676
|
+
uncachedPruneMinOutputChars: 600,
|
|
3677
|
+
uncachedQuantizeUserTurns: 1
|
|
3666
3678
|
};
|
|
3667
3679
|
});
|
|
3668
3680
|
|
|
@@ -4128,9 +4140,13 @@ function buildProviderView(options) {
|
|
|
4128
4140
|
}
|
|
4129
4141
|
let estimate = estimateContextTokens(providerMessages);
|
|
4130
4142
|
let tier1 = null;
|
|
4131
|
-
|
|
4143
|
+
const uncachedActive = options.cacheActive === false && config.aggressivePruneWhenUncached;
|
|
4144
|
+
const pruneFraction = uncachedActive ? config.uncachedPruneAtFraction : config.pruneAtFraction;
|
|
4145
|
+
if (estimate.tokens > pruneFraction * contextWindow) {
|
|
4132
4146
|
tier1 = pruneToolOutputs(providerMessages, {
|
|
4133
|
-
preserveRecentMessages: config.preserveRecentMessages
|
|
4147
|
+
preserveRecentMessages: config.preserveRecentMessages,
|
|
4148
|
+
minOutputChars: uncachedActive ? config.uncachedPruneMinOutputChars : undefined,
|
|
4149
|
+
quantizeUserTurns: uncachedActive ? config.uncachedQuantizeUserTurns : undefined
|
|
4134
4150
|
});
|
|
4135
4151
|
if (tier1.savedChars > 0) {
|
|
4136
4152
|
providerMessages = tier1.messages;
|
|
@@ -4173,6 +4189,43 @@ var init_build_provider_view = __esm(() => {
|
|
|
4173
4189
|
init_tier1_prune();
|
|
4174
4190
|
});
|
|
4175
4191
|
|
|
4192
|
+
// packages/ai/src/context/normalize-provider-messages.ts
|
|
4193
|
+
import { isToolUIPart } from "ai";
|
|
4194
|
+
function hasDanglingToolParts(messages) {
|
|
4195
|
+
return messages.some((message) => message.parts.some((part) => isToolUIPart(part) && !terminalToolStates.has(part.state)));
|
|
4196
|
+
}
|
|
4197
|
+
function resolveDanglingToolParts(messages, errorText = interruptedToolErrorText) {
|
|
4198
|
+
return messages.map((message) => {
|
|
4199
|
+
if (message.role !== "assistant") {
|
|
4200
|
+
return message;
|
|
4201
|
+
}
|
|
4202
|
+
let changed = false;
|
|
4203
|
+
const parts = message.parts.map((part) => {
|
|
4204
|
+
if (!isToolUIPart(part) || terminalToolStates.has(part.state)) {
|
|
4205
|
+
return part;
|
|
4206
|
+
}
|
|
4207
|
+
changed = true;
|
|
4208
|
+
return {
|
|
4209
|
+
...part,
|
|
4210
|
+
state: "output-error",
|
|
4211
|
+
errorText
|
|
4212
|
+
};
|
|
4213
|
+
});
|
|
4214
|
+
return changed ? { ...message, parts } : message;
|
|
4215
|
+
});
|
|
4216
|
+
}
|
|
4217
|
+
function normalizeProviderMessages(messages) {
|
|
4218
|
+
return resolveDanglingToolParts(messages);
|
|
4219
|
+
}
|
|
4220
|
+
var terminalToolStates, interruptedToolErrorText = "Tool call was interrupted by a connection retry. Re-issue the tool call if it is still needed.";
|
|
4221
|
+
var init_normalize_provider_messages = __esm(() => {
|
|
4222
|
+
terminalToolStates = new Set([
|
|
4223
|
+
"output-available",
|
|
4224
|
+
"output-error",
|
|
4225
|
+
"output-denied"
|
|
4226
|
+
]);
|
|
4227
|
+
});
|
|
4228
|
+
|
|
4176
4229
|
// packages/ai/src/context/index.ts
|
|
4177
4230
|
var init_context = __esm(() => {
|
|
4178
4231
|
init_build_provider_view();
|
|
@@ -4181,6 +4234,7 @@ var init_context = __esm(() => {
|
|
|
4181
4234
|
init_estimate();
|
|
4182
4235
|
init_heuristic_summary();
|
|
4183
4236
|
init_message_parts();
|
|
4237
|
+
init_normalize_provider_messages();
|
|
4184
4238
|
init_tier1_prune();
|
|
4185
4239
|
});
|
|
4186
4240
|
|
|
@@ -4276,9 +4330,19 @@ function readEnvConfig(env) {
|
|
|
4276
4330
|
contextWindowOverride: parseNumberEnv(env.LIGHTCODE_CONTEXT_WINDOW, "LIGHTCODE_CONTEXT_WINDOW"),
|
|
4277
4331
|
maxInputTokens: parseNumberEnv(env.LIGHTCODE_CONTEXT_MAX_INPUT_TOKENS, "LIGHTCODE_CONTEXT_MAX_INPUT_TOKENS"),
|
|
4278
4332
|
preserveRecentMessages: parseNumberEnv(env.LIGHTCODE_CONTEXT_PRESERVE_RECENT_MESSAGES, "LIGHTCODE_CONTEXT_PRESERVE_RECENT_MESSAGES"),
|
|
4279
|
-
summaryMaxChars: parseNumberEnv(env.LIGHTCODE_CONTEXT_SUMMARY_MAX_CHARS, "LIGHTCODE_CONTEXT_SUMMARY_MAX_CHARS")
|
|
4333
|
+
summaryMaxChars: parseNumberEnv(env.LIGHTCODE_CONTEXT_SUMMARY_MAX_CHARS, "LIGHTCODE_CONTEXT_SUMMARY_MAX_CHARS"),
|
|
4334
|
+
aggressivePruneWhenUncached: parseBooleanEnv(env.LIGHTCODE_CONTEXT_AGGRESSIVE_PRUNE_UNCACHED, "LIGHTCODE_CONTEXT_AGGRESSIVE_PRUNE_UNCACHED"),
|
|
4335
|
+
uncachedPruneAtFraction: parseNumberEnv(env.LIGHTCODE_CONTEXT_UNCACHED_PRUNE_AT_FRACTION, "LIGHTCODE_CONTEXT_UNCACHED_PRUNE_AT_FRACTION"),
|
|
4336
|
+
uncachedPruneMinOutputChars: parseNumberEnv(env.LIGHTCODE_CONTEXT_UNCACHED_PRUNE_MIN_OUTPUT_CHARS, "LIGHTCODE_CONTEXT_UNCACHED_PRUNE_MIN_OUTPUT_CHARS"),
|
|
4337
|
+
uncachedQuantizeUserTurns: parseNumberEnv(env.LIGHTCODE_CONTEXT_UNCACHED_QUANTIZE_USER_TURNS, "LIGHTCODE_CONTEXT_UNCACHED_QUANTIZE_USER_TURNS")
|
|
4280
4338
|
};
|
|
4281
4339
|
const compactContextConfig = Object.fromEntries(Object.entries(contextConfig).filter(([, value]) => value !== undefined));
|
|
4340
|
+
const headroomConfig = {
|
|
4341
|
+
enabled: parseBooleanEnv(env.LIGHTCODE_HEADROOM_ENABLED, "LIGHTCODE_HEADROOM_ENABLED"),
|
|
4342
|
+
proxyUrl: env.LIGHTCODE_HEADROOM_PROXY_URL?.trim() || undefined,
|
|
4343
|
+
failOpen: parseBooleanEnv(env.LIGHTCODE_HEADROOM_FAIL_OPEN, "LIGHTCODE_HEADROOM_FAIL_OPEN")
|
|
4344
|
+
};
|
|
4345
|
+
const compactHeadroomConfig = Object.fromEntries(Object.entries(headroomConfig).filter(([, value]) => value !== undefined));
|
|
4282
4346
|
const rawConfig = {
|
|
4283
4347
|
provider: env.LIGHTCODE_PROVIDER,
|
|
4284
4348
|
model: env.LIGHTCODE_CHAT_MODEL,
|
|
@@ -4288,7 +4352,8 @@ function readEnvConfig(env) {
|
|
|
4288
4352
|
maxOutputTokens: parseNumberEnv(env.LIGHTCODE_MAX_OUTPUT_TOKENS, "LIGHTCODE_MAX_OUTPUT_TOKENS"),
|
|
4289
4353
|
maxSteps: parseNumberEnv(env.LIGHTCODE_MAX_STEPS, "LIGHTCODE_MAX_STEPS"),
|
|
4290
4354
|
maxRetries: parseNumberEnv(env.LIGHTCODE_MAX_RETRIES, "LIGHTCODE_MAX_RETRIES"),
|
|
4291
|
-
context: Object.keys(compactContextConfig).length > 0 ? compactContextConfig : undefined
|
|
4355
|
+
context: Object.keys(compactContextConfig).length > 0 ? compactContextConfig : undefined,
|
|
4356
|
+
headroom: Object.keys(compactHeadroomConfig).length > 0 ? compactHeadroomConfig : undefined
|
|
4292
4357
|
};
|
|
4293
4358
|
const compactConfig = Object.fromEntries(Object.entries(rawConfig).filter(([, value]) => value !== undefined));
|
|
4294
4359
|
const parsedConfig = lightcodeConfigSchema.safeParse(compactConfig);
|
|
@@ -4312,6 +4377,10 @@ function mergeConfig(...configs) {
|
|
|
4312
4377
|
...mergedConfig.autoContinue,
|
|
4313
4378
|
...config2.autoContinue
|
|
4314
4379
|
} : mergedConfig.autoContinue,
|
|
4380
|
+
headroom: config2.headroom ? {
|
|
4381
|
+
...mergedConfig.headroom,
|
|
4382
|
+
...config2.headroom
|
|
4383
|
+
} : mergedConfig.headroom,
|
|
4315
4384
|
allowedTools: config2.allowedTools ?? mergedConfig.allowedTools
|
|
4316
4385
|
}), {});
|
|
4317
4386
|
}
|
|
@@ -4352,6 +4421,10 @@ function loadLightcodeConfig({
|
|
|
4352
4421
|
autoContinue: {
|
|
4353
4422
|
...defaultAutoContinueConfig,
|
|
4354
4423
|
...mergedConfig.autoContinue
|
|
4424
|
+
},
|
|
4425
|
+
headroom: {
|
|
4426
|
+
...defaultHeadroomConfig,
|
|
4427
|
+
...mergedConfig.headroom
|
|
4355
4428
|
}
|
|
4356
4429
|
};
|
|
4357
4430
|
return lightcodeConfigLoadResultSchema.parse({
|
|
@@ -4359,7 +4432,7 @@ function loadLightcodeConfig({
|
|
|
4359
4432
|
loadedFiles: [userConfig.file, projectConfig.file]
|
|
4360
4433
|
});
|
|
4361
4434
|
}
|
|
4362
|
-
var lightcodeProviderSchema, autoContinueConfigSchema, resolvedAutoContinueConfigSchema, defaultAutoContinueConfig, lightcodeConfigSchema, lightcodeConfigDefaults, loadedConfigFileSchema, lightcodeResolvedConfigSchema, lightcodeConfigLoadResultSchema, lightcodeConfigStatusSchema, LightcodeConfigError;
|
|
4435
|
+
var lightcodeProviderSchema, autoContinueConfigSchema, resolvedAutoContinueConfigSchema, defaultAutoContinueConfig, headroomConfigSchema, resolvedHeadroomConfigSchema, defaultHeadroomConfig, lightcodeConfigSchema, lightcodeConfigDefaults, loadedConfigFileSchema, lightcodeResolvedConfigSchema, lightcodeConfigLoadResultSchema, lightcodeConfigStatusSchema, LightcodeConfigError;
|
|
4363
4436
|
var init_lightcode_config = __esm(() => {
|
|
4364
4437
|
init_coding_agent_modes();
|
|
4365
4438
|
init_coding_agent_modes();
|
|
@@ -4391,6 +4464,24 @@ var init_lightcode_config = __esm(() => {
|
|
|
4391
4464
|
maxErrorRetries: 5,
|
|
4392
4465
|
stallTimeoutSeconds: 180
|
|
4393
4466
|
};
|
|
4467
|
+
headroomConfigSchema = z28.object({
|
|
4468
|
+
enabled: z28.boolean().optional(),
|
|
4469
|
+
proxyUrl: z28.string().min(1).max(4096).optional(),
|
|
4470
|
+
providers: z28.array(lightcodeProviderSchema).optional(),
|
|
4471
|
+
failOpen: z28.boolean().optional()
|
|
4472
|
+
}).strict();
|
|
4473
|
+
resolvedHeadroomConfigSchema = z28.object({
|
|
4474
|
+
enabled: z28.boolean(),
|
|
4475
|
+
proxyUrl: z28.string().min(1).max(4096),
|
|
4476
|
+
providers: z28.array(lightcodeProviderSchema).nullable(),
|
|
4477
|
+
failOpen: z28.boolean()
|
|
4478
|
+
});
|
|
4479
|
+
defaultHeadroomConfig = {
|
|
4480
|
+
enabled: false,
|
|
4481
|
+
proxyUrl: "http://127.0.0.1:8787",
|
|
4482
|
+
providers: null,
|
|
4483
|
+
failOpen: true
|
|
4484
|
+
};
|
|
4394
4485
|
lightcodeConfigSchema = z28.object({
|
|
4395
4486
|
provider: lightcodeProviderSchema.optional(),
|
|
4396
4487
|
model: z28.string().min(1).max(240).optional(),
|
|
@@ -4402,10 +4493,11 @@ var init_lightcode_config = __esm(() => {
|
|
|
4402
4493
|
sandbox: sandboxConfigSchema.optional(),
|
|
4403
4494
|
mcp: mcpConfigSchema.optional(),
|
|
4404
4495
|
context: contextOptimizerConfigSchema.optional(),
|
|
4405
|
-
maxOutputTokens: z28.number().int().min(1).max(
|
|
4496
|
+
maxOutputTokens: z28.number().int().min(1).max(1e6).optional(),
|
|
4406
4497
|
maxSteps: z28.number().int().min(1).max(100).optional(),
|
|
4407
4498
|
maxRetries: z28.number().int().min(0).max(10).optional(),
|
|
4408
|
-
autoContinue: autoContinueConfigSchema.optional()
|
|
4499
|
+
autoContinue: autoContinueConfigSchema.optional(),
|
|
4500
|
+
headroom: headroomConfigSchema.optional()
|
|
4409
4501
|
}).strict();
|
|
4410
4502
|
lightcodeConfigDefaults = {
|
|
4411
4503
|
provider: "anthropic",
|
|
@@ -4414,7 +4506,8 @@ var init_lightcode_config = __esm(() => {
|
|
|
4414
4506
|
maxOutputTokens: 32768,
|
|
4415
4507
|
maxSteps: 30,
|
|
4416
4508
|
maxRetries: 5,
|
|
4417
|
-
autoContinue: defaultAutoContinueConfig
|
|
4509
|
+
autoContinue: defaultAutoContinueConfig,
|
|
4510
|
+
headroom: defaultHeadroomConfig
|
|
4418
4511
|
};
|
|
4419
4512
|
loadedConfigFileSchema = z28.object({
|
|
4420
4513
|
scope: z28.enum(["user", "project"]),
|
|
@@ -4426,10 +4519,11 @@ var init_lightcode_config = __esm(() => {
|
|
|
4426
4519
|
provider: lightcodeProviderSchema,
|
|
4427
4520
|
defaultMode: codingAgentModeSchema,
|
|
4428
4521
|
context: resolvedContextOptimizerConfigSchema,
|
|
4429
|
-
maxOutputTokens: z28.number().int().min(1).max(
|
|
4522
|
+
maxOutputTokens: z28.number().int().min(1).max(1e6),
|
|
4430
4523
|
maxSteps: z28.number().int().min(1).max(100),
|
|
4431
4524
|
maxRetries: z28.number().int().min(0).max(10),
|
|
4432
|
-
autoContinue: resolvedAutoContinueConfigSchema
|
|
4525
|
+
autoContinue: resolvedAutoContinueConfigSchema,
|
|
4526
|
+
headroom: resolvedHeadroomConfigSchema.optional()
|
|
4433
4527
|
});
|
|
4434
4528
|
lightcodeConfigLoadResultSchema = z28.object({
|
|
4435
4529
|
config: lightcodeResolvedConfigSchema,
|
|
@@ -4443,10 +4537,15 @@ var init_lightcode_config = __esm(() => {
|
|
|
4443
4537
|
baseUrl: z28.string().nullable(),
|
|
4444
4538
|
defaultMode: codingAgentModeSchema,
|
|
4445
4539
|
permissionMode: permissionModeSchema.nullable(),
|
|
4446
|
-
maxOutputTokens: z28.number().int().min(1).max(
|
|
4540
|
+
maxOutputTokens: z28.number().int().min(1).max(1e6),
|
|
4447
4541
|
maxSteps: z28.number().int().min(1).max(100),
|
|
4448
4542
|
autoContinue: resolvedAutoContinueConfigSchema,
|
|
4449
4543
|
contextWindow: z28.number().int().positive(),
|
|
4544
|
+
headroom: z28.object({
|
|
4545
|
+
enabled: z28.boolean(),
|
|
4546
|
+
proxyUrl: z28.string().nullable(),
|
|
4547
|
+
routed: z28.boolean()
|
|
4548
|
+
}),
|
|
4450
4549
|
missingCredentialHints: z28.array(z28.string())
|
|
4451
4550
|
});
|
|
4452
4551
|
LightcodeConfigError = class LightcodeConfigError extends Error {
|
|
@@ -4705,6 +4804,21 @@ var init_runtime = __esm(() => {
|
|
|
4705
4804
|
init_schema13();
|
|
4706
4805
|
});
|
|
4707
4806
|
|
|
4807
|
+
// packages/ai/src/providers/clamp-output-tokens.ts
|
|
4808
|
+
function clampMaxOutputTokens(configured, modelMaxCompletionTokens) {
|
|
4809
|
+
if (typeof modelMaxCompletionTokens === "number" && Number.isFinite(modelMaxCompletionTokens) && modelMaxCompletionTokens > 0) {
|
|
4810
|
+
return Math.min(configured, modelMaxCompletionTokens);
|
|
4811
|
+
}
|
|
4812
|
+
return configured;
|
|
4813
|
+
}
|
|
4814
|
+
function resolveMaxOutputTokens(configured, defaultValue, modelMaxCompletionTokens) {
|
|
4815
|
+
const hasModelCap = typeof modelMaxCompletionTokens === "number" && Number.isFinite(modelMaxCompletionTokens) && modelMaxCompletionTokens > 0;
|
|
4816
|
+
if (configured === defaultValue) {
|
|
4817
|
+
return hasModelCap ? modelMaxCompletionTokens : configured;
|
|
4818
|
+
}
|
|
4819
|
+
return clampMaxOutputTokens(configured, modelMaxCompletionTokens);
|
|
4820
|
+
}
|
|
4821
|
+
|
|
4708
4822
|
// packages/ai/src/providers/model-metadata.ts
|
|
4709
4823
|
function getModelContextWindow(provider, modelId) {
|
|
4710
4824
|
if (provider === "anthropic") {
|
|
@@ -5855,19 +5969,29 @@ var init_resolve_within_workspace = __esm(() => {
|
|
|
5855
5969
|
});
|
|
5856
5970
|
|
|
5857
5971
|
// packages/ai/src/common/output-utils.ts
|
|
5858
|
-
function
|
|
5972
|
+
function omissionMarker(omitted) {
|
|
5973
|
+
return `
|
|
5974
|
+
|
|
5975
|
+
... [${omitted} characters omitted; re-read a line range with read_file or raise maxChars] ...
|
|
5976
|
+
|
|
5977
|
+
`;
|
|
5978
|
+
}
|
|
5979
|
+
function truncateText(text, maxChars = DEFAULT_TOOL_TEXT_OUTPUT_CHARS) {
|
|
5859
5980
|
if (text.length <= maxChars) {
|
|
5860
5981
|
return {
|
|
5861
5982
|
text,
|
|
5862
5983
|
truncated: false
|
|
5863
5984
|
};
|
|
5864
5985
|
}
|
|
5865
|
-
const
|
|
5866
|
-
|
|
5867
|
-
|
|
5868
|
-
const
|
|
5986
|
+
const markerReserve = omissionMarker(text.length).length;
|
|
5987
|
+
const usable = Math.max(0, maxChars - markerReserve);
|
|
5988
|
+
const headChars = Math.floor(usable * 0.7);
|
|
5989
|
+
const tailChars = usable - headChars;
|
|
5990
|
+
const head = text.slice(0, headChars);
|
|
5991
|
+
const tail = tailChars > 0 ? text.slice(text.length - tailChars) : "";
|
|
5992
|
+
const omitted = text.length - head.length - tail.length;
|
|
5869
5993
|
return {
|
|
5870
|
-
text: `${
|
|
5994
|
+
text: `${head}${omissionMarker(omitted)}${tail}`,
|
|
5871
5995
|
truncated: true
|
|
5872
5996
|
};
|
|
5873
5997
|
}
|
|
@@ -6877,7 +7001,7 @@ async function executeReadFile(input, workspaceContext = getDefaultWorkspaceCont
|
|
|
6877
7001
|
const { start, end } = clampLineRange(lines.length, parsedInput.startLine, parsedInput.endLine);
|
|
6878
7002
|
const selectedContent = lines.slice(start - 1, end).join(`
|
|
6879
7003
|
`);
|
|
6880
|
-
const maxChars = parsedInput.maxChars ??
|
|
7004
|
+
const maxChars = parsedInput.maxChars ?? DEFAULT_TOOL_TEXT_OUTPUT_CHARS;
|
|
6881
7005
|
const truncated = truncateText(selectedContent, maxChars);
|
|
6882
7006
|
return readFileOutputSchema.parse({
|
|
6883
7007
|
path: relativePath,
|
|
@@ -7515,9 +7639,12 @@ __export(exports_runtime, {
|
|
|
7515
7639
|
sandboxConfigSchema: () => sandboxConfigSchema,
|
|
7516
7640
|
safeStringify: () => safeStringify,
|
|
7517
7641
|
runPluginHooks: () => runPluginHooks,
|
|
7642
|
+
resolvedHeadroomConfigSchema: () => resolvedHeadroomConfigSchema,
|
|
7518
7643
|
resolvedContextOptimizerConfigSchema: () => resolvedContextOptimizerConfigSchema,
|
|
7519
7644
|
resolvedAutoContinueConfigSchema: () => resolvedAutoContinueConfigSchema,
|
|
7520
7645
|
resolveWithinWorkspace: () => resolveWithinWorkspace,
|
|
7646
|
+
resolveMaxOutputTokens: () => resolveMaxOutputTokens,
|
|
7647
|
+
resolveDanglingToolParts: () => resolveDanglingToolParts,
|
|
7521
7648
|
resolveContextWindowTokens: () => resolveContextWindowTokens,
|
|
7522
7649
|
resolveCodingPermissionMode: () => resolveCodingPermissionMode,
|
|
7523
7650
|
requestUserInputToolProviderInputSchema: () => requestUserInputToolProviderInputSchema,
|
|
@@ -7547,6 +7674,7 @@ __export(exports_runtime, {
|
|
|
7547
7674
|
parseCodingToolInput: () => parseCodingToolInput,
|
|
7548
7675
|
parseChatStreamError: () => parseChatStreamError,
|
|
7549
7676
|
normalizeSandboxConfig: () => normalizeSandboxConfig,
|
|
7677
|
+
normalizeProviderMessages: () => normalizeProviderMessages,
|
|
7550
7678
|
normalizeContextOptimizerConfig: () => normalizeContextOptimizerConfig,
|
|
7551
7679
|
messageUsageMetadataSchema: () => messageUsageMetadataSchema,
|
|
7552
7680
|
mcpStdioServerConfigSchema: () => mcpStdioServerConfigSchema,
|
|
@@ -7577,7 +7705,10 @@ __export(exports_runtime, {
|
|
|
7577
7705
|
isRecord: () => isRecord3,
|
|
7578
7706
|
isPermissionDeniedError: () => isPermissionDeniedError,
|
|
7579
7707
|
isElidedToolOutput: () => isElidedToolOutput,
|
|
7708
|
+
interruptedToolErrorText: () => interruptedToolErrorText,
|
|
7709
|
+
headroomConfigSchema: () => headroomConfigSchema,
|
|
7580
7710
|
hasUnresolvedToolWork: () => hasUnresolvedToolWork,
|
|
7711
|
+
hasDanglingToolParts: () => hasDanglingToolParts,
|
|
7581
7712
|
getToolNameFromPart: () => getToolNameFromPart,
|
|
7582
7713
|
getTextPartContent: () => getTextPartContent,
|
|
7583
7714
|
getSandboxRuntimeStatus: () => getSandboxRuntimeStatus,
|
|
@@ -7628,6 +7759,7 @@ __export(exports_runtime, {
|
|
|
7628
7759
|
describeChatStreamError: () => describeChatStreamError,
|
|
7629
7760
|
defaultSubagentTaskMode: () => defaultSubagentTaskMode,
|
|
7630
7761
|
defaultPermissionModeForCodingMode: () => defaultPermissionModeForCodingMode,
|
|
7762
|
+
defaultHeadroomConfig: () => defaultHeadroomConfig,
|
|
7631
7763
|
defaultContextOptimizerConfig: () => defaultContextOptimizerConfig,
|
|
7632
7764
|
defaultCodingAgentSystemPrompt: () => defaultCodingAgentSystemPrompt,
|
|
7633
7765
|
defaultCodingAgentMode: () => defaultCodingAgentMode,
|
|
@@ -7663,6 +7795,7 @@ __export(exports_runtime, {
|
|
|
7663
7795
|
codingAgentModeSchema: () => codingAgentModeSchema,
|
|
7664
7796
|
codingAgentModeOrder: () => codingAgentModeOrder,
|
|
7665
7797
|
codingAgentCallOptionsSchema: () => codingAgentCallOptionsSchema,
|
|
7798
|
+
clampMaxOutputTokens: () => clampMaxOutputTokens,
|
|
7666
7799
|
chatInteractionUserPromptPayloadSchema: () => chatInteractionUserPromptPayloadSchema,
|
|
7667
7800
|
chatInteractionUpsertRequestSchema: () => chatInteractionUpsertRequestSchema,
|
|
7668
7801
|
chatInteractionToolCallIdSchema: () => chatInteractionToolCallIdSchema,
|
|
@@ -8026,7 +8159,7 @@ var init_auto_continue = __esm(() => {
|
|
|
8026
8159
|
import { useChat } from "@ai-sdk/react";
|
|
8027
8160
|
import {
|
|
8028
8161
|
DefaultChatTransport,
|
|
8029
|
-
isToolUIPart,
|
|
8162
|
+
isToolUIPart as isToolUIPart2,
|
|
8030
8163
|
lastAssistantMessageIsCompleteWithToolCalls,
|
|
8031
8164
|
safeValidateUIMessages
|
|
8032
8165
|
} from "ai";
|
|
@@ -8118,30 +8251,38 @@ function queueToolOutput(outputResult) {
|
|
|
8118
8251
|
console.warn("Failed to add tool output.", outputError);
|
|
8119
8252
|
});
|
|
8120
8253
|
}
|
|
8121
|
-
function
|
|
8122
|
-
if (
|
|
8123
|
-
return false;
|
|
8124
|
-
}
|
|
8125
|
-
if (message.parts.length === 0) {
|
|
8254
|
+
function isIncompletePart(part) {
|
|
8255
|
+
if ((part.type === "text" || part.type === "reasoning") && Reflect.get(part, "state") === "streaming") {
|
|
8126
8256
|
return true;
|
|
8127
8257
|
}
|
|
8128
|
-
return
|
|
8129
|
-
if ((part.type === "text" || part.type === "reasoning") && Reflect.get(part, "state") === "streaming") {
|
|
8130
|
-
return true;
|
|
8131
|
-
}
|
|
8132
|
-
return isToolUIPart(part) && part.state === "input-streaming";
|
|
8133
|
-
});
|
|
8258
|
+
return isToolUIPart2(part) && part.state === "input-streaming";
|
|
8134
8259
|
}
|
|
8135
|
-
function
|
|
8136
|
-
let
|
|
8137
|
-
while (
|
|
8138
|
-
|
|
8260
|
+
function pruneIncompleteTrailingAssistantParts(messages) {
|
|
8261
|
+
let result = messages;
|
|
8262
|
+
while (result.length > 0) {
|
|
8263
|
+
const lastIndex = result.length - 1;
|
|
8264
|
+
const last = result[lastIndex];
|
|
8265
|
+
if (last.role !== "assistant") {
|
|
8266
|
+
break;
|
|
8267
|
+
}
|
|
8268
|
+
const completeParts = last.parts.filter((part) => !isIncompletePart(part));
|
|
8269
|
+
if (completeParts.length === last.parts.length) {
|
|
8270
|
+
break;
|
|
8271
|
+
}
|
|
8272
|
+
if (completeParts.length === 0) {
|
|
8273
|
+
result = result.slice(0, lastIndex);
|
|
8274
|
+
continue;
|
|
8275
|
+
}
|
|
8276
|
+
const next = result.slice();
|
|
8277
|
+
next[lastIndex] = { ...last, parts: completeParts };
|
|
8278
|
+
result = next;
|
|
8279
|
+
break;
|
|
8139
8280
|
}
|
|
8140
|
-
return
|
|
8281
|
+
return result;
|
|
8141
8282
|
}
|
|
8142
8283
|
function hasUnresolvedToolParts(messages) {
|
|
8143
8284
|
return messages.some((message) => message.parts.some((part) => {
|
|
8144
|
-
if (!
|
|
8285
|
+
if (!isToolUIPart2(part)) {
|
|
8145
8286
|
return false;
|
|
8146
8287
|
}
|
|
8147
8288
|
return ![
|
|
@@ -8151,26 +8292,21 @@ function hasUnresolvedToolParts(messages) {
|
|
|
8151
8292
|
].includes(part.state);
|
|
8152
8293
|
}));
|
|
8153
8294
|
}
|
|
8154
|
-
function
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
|
|
8159
|
-
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
if (!isToolUIPart(part) || terminalToolPartStates.has(part.state)) {
|
|
8163
|
-
return part;
|
|
8295
|
+
function countCompletedWork(messages) {
|
|
8296
|
+
let total = 0;
|
|
8297
|
+
for (const message of messages) {
|
|
8298
|
+
for (const part of message.parts) {
|
|
8299
|
+
if ((part.type === "text" || part.type === "reasoning") && Reflect.get(part, "state") !== "streaming") {
|
|
8300
|
+
total += 1;
|
|
8301
|
+
} else if (isToolUIPart2(part) && terminalToolPartStates.has(part.state)) {
|
|
8302
|
+
total += 1;
|
|
8164
8303
|
}
|
|
8165
|
-
|
|
8166
|
-
|
|
8167
|
-
|
|
8168
|
-
|
|
8169
|
-
|
|
8170
|
-
|
|
8171
|
-
});
|
|
8172
|
-
return changed ? { ...message, parts } : message;
|
|
8173
|
-
});
|
|
8304
|
+
}
|
|
8305
|
+
}
|
|
8306
|
+
return total;
|
|
8307
|
+
}
|
|
8308
|
+
function sanitizeMessagesForRetry(messages) {
|
|
8309
|
+
return resolveDanglingToolParts(pruneIncompleteTrailingAssistantParts(messages));
|
|
8174
8310
|
}
|
|
8175
8311
|
function hasActiveClientToolWork({
|
|
8176
8312
|
messages,
|
|
@@ -8180,7 +8316,7 @@ function hasActiveClientToolWork({
|
|
|
8180
8316
|
const pendingApprovalIds = new Set(pendingApprovals.map((approval) => approval.toolCallId));
|
|
8181
8317
|
const pendingPromptIds = new Set(pendingUserPrompts.map((prompt) => prompt.toolCallId));
|
|
8182
8318
|
return messages.some((message) => message.parts.some((part) => {
|
|
8183
|
-
if (!
|
|
8319
|
+
if (!isToolUIPart2(part)) {
|
|
8184
8320
|
return false;
|
|
8185
8321
|
}
|
|
8186
8322
|
if (part.state === "input-streaming" || part.state === "approval-responded") {
|
|
@@ -8308,6 +8444,9 @@ function useCodingSessionChat({
|
|
|
8308
8444
|
autoContinueLimitsRef.current = autoContinueLimits;
|
|
8309
8445
|
const maxErrorRetriesRef = useRef(maxErrorRetries);
|
|
8310
8446
|
maxErrorRetriesRef.current = maxErrorRetries;
|
|
8447
|
+
const maxNoProgressRetries = maxErrorRetries + 3;
|
|
8448
|
+
const maxNoProgressRetriesRef = useRef(maxNoProgressRetries);
|
|
8449
|
+
maxNoProgressRetriesRef.current = maxNoProgressRetries;
|
|
8311
8450
|
const stallTimeoutMsRef = useRef(stallTimeoutMs);
|
|
8312
8451
|
stallTimeoutMsRef.current = stallTimeoutMs;
|
|
8313
8452
|
const lastStreamActivityRef = useRef(Date.now());
|
|
@@ -8316,11 +8455,18 @@ function useCodingSessionChat({
|
|
|
8316
8455
|
const errorRetriesRef = useRef(0);
|
|
8317
8456
|
const errorRetryTimerRef = useRef(null);
|
|
8318
8457
|
const lastDecidedAssistantIdRef = useRef(null);
|
|
8458
|
+
const lastProgressMarkerRef = useRef(0);
|
|
8459
|
+
const noProgressRetriesRef = useRef(0);
|
|
8460
|
+
const taskStuckRef = useRef(false);
|
|
8461
|
+
const messagesRef = useRef([]);
|
|
8319
8462
|
const advanceTurnKey = useCallback(() => {
|
|
8320
8463
|
turnCounterRef.current += 1;
|
|
8321
8464
|
turnKeyRef.current = `turn-${Date.now()}-${turnCounterRef.current}`;
|
|
8322
8465
|
autoContinuesRef.current = 0;
|
|
8323
8466
|
errorRetriesRef.current = 0;
|
|
8467
|
+
lastProgressMarkerRef.current = 0;
|
|
8468
|
+
noProgressRetriesRef.current = 0;
|
|
8469
|
+
taskStuckRef.current = false;
|
|
8324
8470
|
lastDecidedAssistantIdRef.current = null;
|
|
8325
8471
|
if (errorRetryTimerRef.current) {
|
|
8326
8472
|
clearTimeout(errorRetryTimerRef.current);
|
|
@@ -8328,6 +8474,20 @@ function useCodingSessionChat({
|
|
|
8328
8474
|
}
|
|
8329
8475
|
setAutoContinueState(null);
|
|
8330
8476
|
}, []);
|
|
8477
|
+
const registerRetryProgress = useCallback((currentMessages) => {
|
|
8478
|
+
const marker = countCompletedWork(currentMessages);
|
|
8479
|
+
if (marker > lastProgressMarkerRef.current) {
|
|
8480
|
+
lastProgressMarkerRef.current = marker;
|
|
8481
|
+
noProgressRetriesRef.current = 0;
|
|
8482
|
+
return true;
|
|
8483
|
+
}
|
|
8484
|
+
noProgressRetriesRef.current += 1;
|
|
8485
|
+
if (noProgressRetriesRef.current > maxNoProgressRetriesRef.current) {
|
|
8486
|
+
taskStuckRef.current = true;
|
|
8487
|
+
return false;
|
|
8488
|
+
}
|
|
8489
|
+
return true;
|
|
8490
|
+
}, []);
|
|
8331
8491
|
modeRef.current = mode;
|
|
8332
8492
|
cwdRef.current = cwd;
|
|
8333
8493
|
permissionModeRef.current = permissionMode;
|
|
@@ -8707,6 +8867,9 @@ function useCodingSessionChat({
|
|
|
8707
8867
|
lastStreamActivityRef.current = Date.now();
|
|
8708
8868
|
}
|
|
8709
8869
|
}, [messages, status]);
|
|
8870
|
+
useEffect(() => {
|
|
8871
|
+
messagesRef.current = messages;
|
|
8872
|
+
}, [messages]);
|
|
8710
8873
|
useEffect(() => {
|
|
8711
8874
|
if (status !== "streaming" && status !== "submitted") {
|
|
8712
8875
|
return;
|
|
@@ -8719,7 +8882,15 @@ function useCodingSessionChat({
|
|
|
8719
8882
|
})) {
|
|
8720
8883
|
return;
|
|
8721
8884
|
}
|
|
8722
|
-
if (stallRecoveryInFlightRef.current || errorRetriesRef.current >= maxErrorRetriesRef.current) {
|
|
8885
|
+
if (taskStuckRef.current || stallRecoveryInFlightRef.current || errorRetriesRef.current >= maxErrorRetriesRef.current) {
|
|
8886
|
+
return;
|
|
8887
|
+
}
|
|
8888
|
+
if (!registerRetryProgress(messagesRef.current)) {
|
|
8889
|
+
setAutoContinueState({
|
|
8890
|
+
attempt: errorRetriesRef.current,
|
|
8891
|
+
kind: "none",
|
|
8892
|
+
guardTripped: "no-progress"
|
|
8893
|
+
});
|
|
8723
8894
|
return;
|
|
8724
8895
|
}
|
|
8725
8896
|
stallRecoveryInFlightRef.current = true;
|
|
@@ -8741,12 +8912,12 @@ function useCodingSessionChat({
|
|
|
8741
8912
|
})();
|
|
8742
8913
|
}, 15000);
|
|
8743
8914
|
return () => clearInterval(intervalId);
|
|
8744
|
-
}, [clearError, sendMessage, setMessages, status, stop]);
|
|
8915
|
+
}, [clearError, registerRetryProgress, sendMessage, setMessages, status, stop]);
|
|
8745
8916
|
useEffect(() => {
|
|
8746
8917
|
if (status !== "ready" || error) {
|
|
8747
8918
|
return;
|
|
8748
8919
|
}
|
|
8749
|
-
if (isHistoryLoading || pendingApprovals.length > 0 || pendingUserPrompts.length > 0 || hasUnresolvedToolParts(messages)) {
|
|
8920
|
+
if (taskStuckRef.current || isHistoryLoading || pendingApprovals.length > 0 || pendingUserPrompts.length > 0 || hasUnresolvedToolParts(messages)) {
|
|
8750
8921
|
return;
|
|
8751
8922
|
}
|
|
8752
8923
|
const lastMessage = messages[messages.length - 1];
|
|
@@ -8798,7 +8969,7 @@ function useCodingSessionChat({
|
|
|
8798
8969
|
if (!error?.message || !isRecoverableChatErrorMessage(error.message)) {
|
|
8799
8970
|
return;
|
|
8800
8971
|
}
|
|
8801
|
-
if (pendingApprovals.length > 0 || pendingUserPrompts.length > 0 || errorRetryTimerRef.current || stallRecoveryInFlightRef.current) {
|
|
8972
|
+
if (taskStuckRef.current || pendingApprovals.length > 0 || pendingUserPrompts.length > 0 || errorRetryTimerRef.current || stallRecoveryInFlightRef.current) {
|
|
8802
8973
|
return;
|
|
8803
8974
|
}
|
|
8804
8975
|
if (errorRetriesRef.current >= maxErrorRetriesRef.current) {
|
|
@@ -8809,6 +8980,14 @@ function useCodingSessionChat({
|
|
|
8809
8980
|
const delay = Math.min(errorRetryBaseDelayMs * 2 ** (attempt - 1), errorRetryMaxDelayMs);
|
|
8810
8981
|
errorRetryTimerRef.current = setTimeout(() => {
|
|
8811
8982
|
errorRetryTimerRef.current = null;
|
|
8983
|
+
if (!registerRetryProgress(messagesRef.current)) {
|
|
8984
|
+
setAutoContinueState({
|
|
8985
|
+
attempt: errorRetriesRef.current,
|
|
8986
|
+
kind: "none",
|
|
8987
|
+
guardTripped: "no-progress"
|
|
8988
|
+
});
|
|
8989
|
+
return;
|
|
8990
|
+
}
|
|
8812
8991
|
errorRetriesRef.current = attempt;
|
|
8813
8992
|
setAutoContinueState({ attempt, kind: "retry-error" });
|
|
8814
8993
|
setMessages(retryMessages);
|
|
@@ -8828,6 +9007,7 @@ function useCodingSessionChat({
|
|
|
8828
9007
|
messages,
|
|
8829
9008
|
pendingApprovals.length,
|
|
8830
9009
|
pendingUserPrompts.length,
|
|
9010
|
+
registerRetryProgress,
|
|
8831
9011
|
sendMessage,
|
|
8832
9012
|
setMessages
|
|
8833
9013
|
]);
|
|
@@ -8906,7 +9086,7 @@ function useCodingSessionChat({
|
|
|
8906
9086
|
if (cancelled) {
|
|
8907
9087
|
return;
|
|
8908
9088
|
}
|
|
8909
|
-
const resumableMessages = restoredApprovals.length === 0 && restoredPrompts.length === 0 ?
|
|
9089
|
+
const resumableMessages = restoredApprovals.length === 0 && restoredPrompts.length === 0 ? pruneIncompleteTrailingAssistantParts(validatedMessages) : validatedMessages;
|
|
8910
9090
|
setMessagesRef.current(resumableMessages);
|
|
8911
9091
|
setPendingApprovals(restoredApprovals);
|
|
8912
9092
|
setPendingUserPrompts(restoredPrompts);
|
|
@@ -9027,7 +9207,7 @@ function useCodingSessionChat({
|
|
|
9027
9207
|
isSessionIdValid
|
|
9028
9208
|
};
|
|
9029
9209
|
}
|
|
9030
|
-
var recoverableDisconnectMessage = "Connection interrupted. Please retry or regenerate your last message.", buildModeAutoPromptResponse = "Proceed with implementation in Build mode. Continue without additional plan questions.", chatMessageUpdateThrottleMs = 50, retryCommandPattern, codingToolNameSet, errorRetryBaseDelayMs = 1000, errorRetryMaxDelayMs = 8000, disconnectErrorPattern, transientProviderErrorPattern,
|
|
9210
|
+
var recoverableDisconnectMessage = "Connection interrupted. Please retry or regenerate your last message.", buildModeAutoPromptResponse = "Proceed with implementation in Build mode. Continue without additional plan questions.", chatMessageUpdateThrottleMs = 50, retryCommandPattern, codingToolNameSet, errorRetryBaseDelayMs = 1000, errorRetryMaxDelayMs = 8000, disconnectErrorPattern, transientProviderErrorPattern, terminalToolPartStates;
|
|
9031
9211
|
var init_use_coding_session_chat = __esm(() => {
|
|
9032
9212
|
init_agent_tools();
|
|
9033
9213
|
init_chat_error();
|
|
@@ -9040,6 +9220,7 @@ var init_use_coding_session_chat = __esm(() => {
|
|
|
9040
9220
|
init_schema9();
|
|
9041
9221
|
init_runtime12();
|
|
9042
9222
|
init_auto_continue();
|
|
9223
|
+
init_normalize_provider_messages();
|
|
9043
9224
|
retryCommandPattern = /^\/?(retry|regenerate)$/i;
|
|
9044
9225
|
codingToolNameSet = new Set(Object.keys(codingToolInputSchemas));
|
|
9045
9226
|
disconnectErrorPattern = /(failed to fetch|networkerror|socket|connection|aborted|terminated|timed?\s?out|timeout|econnreset)/i;
|
|
@@ -10156,7 +10337,7 @@ var init_chat_message_tool_invocation_part = __esm(() => {
|
|
|
10156
10337
|
});
|
|
10157
10338
|
|
|
10158
10339
|
// apps/cli/src/components/chat/chat-message.tsx
|
|
10159
|
-
import { isToolUIPart as
|
|
10340
|
+
import { isToolUIPart as isToolUIPart3 } from "ai";
|
|
10160
10341
|
import { TextAttributes as TextAttributes9 } from "@opentui/core";
|
|
10161
10342
|
import { jsxDEV as jsxDEV13 } from "@opentui/react/jsx-dev-runtime";
|
|
10162
10343
|
function ChatMessage({ message, pendingApprovalIds }) {
|
|
@@ -10173,7 +10354,7 @@ function ChatMessage({ message, pendingApprovalIds }) {
|
|
|
10173
10354
|
part
|
|
10174
10355
|
}, key, false, undefined, this);
|
|
10175
10356
|
}
|
|
10176
|
-
if (
|
|
10357
|
+
if (isToolUIPart3(part)) {
|
|
10177
10358
|
return /* @__PURE__ */ jsxDEV13(ChatMessageToolInvocationPart, {
|
|
10178
10359
|
part,
|
|
10179
10360
|
pendingApprovalIds
|
|
@@ -11904,7 +12085,7 @@ function ChatScreen() {
|
|
|
11904
12085
|
paddingX: 1,
|
|
11905
12086
|
children: /* @__PURE__ */ jsxDEV21("text", {
|
|
11906
12087
|
fg: cliTheme.semantic.warning,
|
|
11907
|
-
children: autoContinueState.guardTripped === "doom-loop" ? "Agent appears stuck repeating itself \u2014 automatic continuation stopped. Send a message to resume." : `Reached the automatic continuation limit (${autoContinueState.attempt}). Send a message to resume.`
|
|
12088
|
+
children: autoContinueState.guardTripped === "doom-loop" ? "Agent appears stuck repeating itself \u2014 automatic continuation stopped. Send a message to resume." : autoContinueState.guardTripped === "no-progress" ? "The connection keeps dropping without making progress \u2014 automatic retry stopped. Send a message to resume." : `Reached the automatic continuation limit (${autoContinueState.attempt}). Send a message to resume.`
|
|
11908
12089
|
}, undefined, false, undefined, this)
|
|
11909
12090
|
}, undefined, false, undefined, this) : autoContinueState ? /* @__PURE__ */ jsxDEV21("box", {
|
|
11910
12091
|
paddingX: 1,
|