@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.
Files changed (3) hide show
  1. package/cli.js +261 -80
  2. package/package.json +1 -1
  3. 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.2.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(MAX_TOOL_TEXT_OUTPUT_CHARS)
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(MAX_TOOL_TEXT_OUTPUT_CHARS)
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(MAX_TOOL_TEXT_OUTPUT_CHARS)
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 with optional line range limits.", readFileInputSchema, readFileProviderInputSchema, readFileOutputSchema;
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(MAX_TOOL_TEXT_OUTPUT_CHARS),
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 basic coding agent. Use tools for filesystem and codebase tasks instead of guessing. " + "Respect the user's intent, explain changes clearly, and prefer incremental, auditable actions. " + "You can only interact with files under this working directory: {cwd}. " + "Use glob_search for path discovery, grep for text search, structured git tools for repository inspection, and bash only when dedicated tools are not enough. " + "Use todo_write to keep multi-step implementation work visible and current. " + "For risky or uncertain operations, inspect context first and be explicit about assumptions. " + "While working, emit brief progress notes in natural language before major tool actions and after important findings. " + `Keep them short, human, and concrete. Vary wording naturally and avoid repetitive templates or rigid labels.
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
- ` + "You are an agent \u2014 keep working until the user's request is fully resolved before ending your turn. " + "Never stop with a partial answer. If you say you will do something, do it in the same turn by calling a tool. " + "Use todo_write to track multi-step work and do not finish while any todo is pending or in_progress. " + `Only end your turn when the task is complete or you are blocked on input that only the user can provide.
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: never run dev servers, watchers, or other non-exiting commands as plain foreground bash \u2014 " + "the bash tool enforces a timeout and the command will be killed. Start them detached with output redirected to a " + 'log file (e.g. on Windows: start /B cmd /c "npm run dev > dev.log 2>&1"; on Unix: nohup npm run dev > dev.log 2>&1 &), ' + "wait briefly, then verify by reading the log file or with a bounded probe like curl --max-time 5. " + "Dev servers do not always get their default port \u2014 read the actual port from the startup log instead of assuming it. " + "Never kill processes or free ports you did not open yourself; other tools (including this agent's own backend) may be using them.";
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.8,
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
- if (estimate.tokens > config.pruneAtFraction * contextWindow) {
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(200000).optional(),
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(200000),
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(200000),
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 truncateText(text, maxChars = MAX_TOOL_TEXT_OUTPUT_CHARS) {
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 suffix = `
5866
-
5867
- ... output truncated to ${maxChars} characters ...`;
5868
- const allowedLength = Math.max(0, maxChars - suffix.length);
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: `${text.slice(0, allowedLength)}${suffix}`,
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 ?? MAX_TOOL_TEXT_OUTPUT_CHARS;
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 isIncompleteAssistantMessage(message) {
8122
- if (message.role !== "assistant") {
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 message.parts.some((part) => {
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 trimIncompleteTrailingAssistantMessages(messages) {
8136
- let endIndex = messages.length;
8137
- while (endIndex > 0 && isIncompleteAssistantMessage(messages[endIndex - 1])) {
8138
- endIndex -= 1;
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 endIndex === messages.length ? messages : messages.slice(0, endIndex);
8281
+ return result;
8141
8282
  }
8142
8283
  function hasUnresolvedToolParts(messages) {
8143
8284
  return messages.some((message) => message.parts.some((part) => {
8144
- if (!isToolUIPart(part)) {
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 sanitizeMessagesForRetry(messages) {
8155
- const trimmed = trimIncompleteTrailingAssistantMessages(messages);
8156
- return trimmed.map((message) => {
8157
- if (message.role !== "assistant") {
8158
- return message;
8159
- }
8160
- let changed = false;
8161
- const parts = message.parts.map((part) => {
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
- changed = true;
8166
- return {
8167
- ...part,
8168
- state: "output-error",
8169
- errorText: interruptedToolRetryErrorText
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 (!isToolUIPart(part)) {
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 ? trimIncompleteTrailingAssistantMessages(validatedMessages) : validatedMessages;
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, interruptedToolRetryErrorText = "Tool call was interrupted by a connection retry. Re-issue the tool call if it is still needed.", terminalToolPartStates;
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 isToolUIPart2 } from "ai";
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 (isToolUIPart2(part)) {
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,