@pentoshi/clai 3.11.10 → 3.11.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/dist/agent/compaction-summary.d.ts +10 -2
  2. package/dist/agent/compaction-summary.js +15 -3
  3. package/dist/agent/compaction-summary.js.map +1 -1
  4. package/dist/agent/context-manager.js +49 -15
  5. package/dist/agent/context-manager.js.map +1 -1
  6. package/dist/agent/events.d.ts +6 -0
  7. package/dist/agent/finalize-gate.d.ts +1 -0
  8. package/dist/agent/finalize-gate.js +2 -1
  9. package/dist/agent/finalize-gate.js.map +1 -1
  10. package/dist/agent/loop-guard.d.ts +13 -0
  11. package/dist/agent/loop-guard.js +54 -8
  12. package/dist/agent/loop-guard.js.map +1 -1
  13. package/dist/agent/runner.js +35 -12
  14. package/dist/agent/runner.js.map +1 -1
  15. package/dist/agent/tool-history.js +1 -1
  16. package/dist/agent/tool-history.js.map +1 -1
  17. package/dist/agent/turn-outcome.js +3 -0
  18. package/dist/agent/turn-outcome.js.map +1 -1
  19. package/dist/app/adapters/agent-event-adapter.js +6 -0
  20. package/dist/app/adapters/agent-event-adapter.js.map +1 -1
  21. package/dist/app/controllers/session-compact-helper.d.ts +1 -0
  22. package/dist/app/controllers/session-compact-helper.js +15 -23
  23. package/dist/app/controllers/session-compact-helper.js.map +1 -1
  24. package/dist/app/controllers/session-context-limits.d.ts +4 -2
  25. package/dist/app/controllers/session-context-limits.js +26 -7
  26. package/dist/app/controllers/session-context-limits.js.map +1 -1
  27. package/dist/app/controllers/session-context-usage.d.ts +1 -0
  28. package/dist/app/controllers/session-context-usage.js +14 -0
  29. package/dist/app/controllers/session-context-usage.js.map +1 -1
  30. package/dist/app/controllers/session-controller.d.ts +1 -0
  31. package/dist/app/controllers/session-controller.js +11 -3
  32. package/dist/app/controllers/session-controller.js.map +1 -1
  33. package/dist/app/events/app-event.d.ts +4 -0
  34. package/dist/app/events/app-event.js.map +1 -1
  35. package/dist/llm/adapters/openai-tools.d.ts +1 -0
  36. package/dist/llm/adapters/openai-tools.js +10 -0
  37. package/dist/llm/adapters/openai-tools.js.map +1 -1
  38. package/dist/llm/bynara.js +8 -2
  39. package/dist/llm/bynara.js.map +1 -1
  40. package/dist/llm/http.d.ts +1 -1
  41. package/dist/llm/http.js +6 -0
  42. package/dist/llm/http.js.map +1 -1
  43. package/dist/llm/key-rotation.d.ts +1 -1
  44. package/dist/llm/key-rotation.js +4 -0
  45. package/dist/llm/key-rotation.js.map +1 -1
  46. package/dist/llm/router.d.ts +2 -0
  47. package/dist/llm/router.js +35 -3
  48. package/dist/llm/router.js.map +1 -1
  49. package/dist/prompts/index.d.ts +4 -1
  50. package/dist/prompts/index.js +12 -3
  51. package/dist/prompts/index.js.map +1 -1
  52. package/dist/store/config.d.ts +5 -0
  53. package/dist/store/config.js +37 -3
  54. package/dist/store/config.js.map +1 -1
  55. package/dist/store/keys.js +2 -2
  56. package/dist/store/keys.js.map +1 -1
  57. package/dist/tools/file-diff.js +59 -27
  58. package/dist/tools/file-diff.js.map +1 -1
  59. package/dist/tui-v2/bootstrap/composition-root.js +3 -0
  60. package/dist/tui-v2/bootstrap/composition-root.js.map +1 -1
  61. package/dist/tui-v2/components/transcript/transcript-view.js +8 -7
  62. package/dist/tui-v2/components/transcript/transcript-view.js.map +1 -1
  63. package/dist/tui-v2/components/transcript/use-transcript-selection.js +57 -22
  64. package/dist/tui-v2/components/transcript/use-transcript-selection.js.map +1 -1
  65. package/dist/tui-v2/composer/composer-editor.js +5 -1
  66. package/dist/tui-v2/composer/composer-editor.js.map +1 -1
  67. package/dist/tui-v2/controllers/selection-controller.js +7 -1
  68. package/dist/tui-v2/controllers/selection-controller.js.map +1 -1
  69. package/dist/tui-v2/state/semantic-document.js +13 -1
  70. package/dist/tui-v2/state/semantic-document.js.map +1 -1
  71. package/dist/tui-v2/state/transcript-reducer.js +12 -4
  72. package/dist/tui-v2/state/transcript-reducer.js.map +1 -1
  73. package/dist/version.generated.d.ts +2 -2
  74. package/dist/version.generated.js +2 -2
  75. package/package.json +1 -1
@@ -55,7 +55,7 @@ import { analyzeTask, formatTaskAnalysisHint, isNarrowExplicitNmapOperation, } f
55
55
  import { computeMaxIterations, computeStepBudget } from "./step-budget.js";
56
56
  import { isScratchOnlyWrite } from "./scratch-write.js";
57
57
  import { buildDurableEnvelope, WorkLedger, } from "./durable-envelope.js";
58
- import { COMPACTION_SYSTEM_PROMPT, } from "./compaction-summary.js";
58
+ import { COMPACTION_SYSTEM_PROMPT, COMPACTION_MAX_COMPLETION_TOKENS, COMPACTION_MAP_MAX_COMPLETION_TOKENS, } from "./compaction-summary.js";
59
59
  import { maybeAppendPlanModeReminder, PLAN_REMINDER_TOAST, } from "./plan-mode-reminders.js";
60
60
  import { LoopGuard } from "./loop-guard.js";
61
61
  import { appendInterruptedReasoning, interruptedReasoningBrief, isMeaningfulResumptionYield, } from "./interrupted-reasoning.js";
@@ -557,10 +557,11 @@ export async function runAgentTurn(prompt, options = {}) {
557
557
  imageView: visionAvailable,
558
558
  // E6: slim native constitution when API tool schemas are attached.
559
559
  ...(native ? { slimNative: reliability.slimNativePrompt } : {}),
560
- ...(pentestPromptTurn ? { pentest: true } : {}),
561
560
  });
562
561
  };
563
- const systemSections = [renderRequestEnvironmentContext()];
562
+ const systemSections = [
563
+ renderRequestEnvironmentContext({ plan: activePlan }),
564
+ ];
564
565
  if (projectContext) {
565
566
  systemSections.push(`Project context from .clai/context.md:\n${projectContext}`);
566
567
  }
@@ -2828,10 +2829,13 @@ export async function runAgentTurn(prompt, options = {}) {
2828
2829
  { role: "user", content: summaryPrompt },
2829
2830
  ],
2830
2831
  temperature: 0.1,
2831
- maxTokens: 2_048,
2832
+ maxTokens: stage?.phase === "map"
2833
+ ? COMPACTION_MAP_MAX_COMPLETION_TOKENS
2834
+ : COMPACTION_MAX_COMPLETION_TOKENS,
2835
+ thinking: { enabled: false, effort: "none" },
2832
2836
  signal: options.signal,
2833
2837
  };
2834
- const response = await streamWithProvider(request, (token) => deltaParser?.push(token), { onStatus: () => undefined });
2838
+ const response = await streamWithProvider(request, (token) => deltaParser?.push(token), { onStatus: () => undefined, maxRetries: 0 });
2835
2839
  deltaParser?.finish();
2836
2840
  const parsed = stripThinking(response.text);
2837
2841
  if (parsed.visible.trim() || !parsed.hasThinking)
@@ -2846,9 +2850,11 @@ export async function runAgentTurn(prompt, options = {}) {
2846
2850
  { role: "user", content: summaryPrompt },
2847
2851
  ],
2848
2852
  temperature: 0,
2849
- maxTokens: 8_192,
2853
+ maxTokens: stage?.phase === "map"
2854
+ ? COMPACTION_MAP_MAX_COMPLETION_TOKENS
2855
+ : COMPACTION_MAX_COMPLETION_TOKENS,
2850
2856
  thinking: { enabled: false, effort: "none" },
2851
- });
2857
+ }, { maxRetries: 0 });
2852
2858
  const retryVisible = stripThinking(retry.text).visible.trim();
2853
2859
  if (retryVisible && compactionId) {
2854
2860
  writeCompactionDelta(compactionId, retryVisible);
@@ -3123,7 +3129,7 @@ export async function runAgentTurn(prompt, options = {}) {
3123
3129
  ? `${seconds}s`
3124
3130
  : `${Math.floor(seconds / 60)}m${String(seconds % 60).padStart(2, "0")}s`;
3125
3131
  if (generatedTokens > 0 && !inThinking) {
3126
- return `generating response · ${generatedTokens} tokens · ${elapsed}`;
3132
+ return `generating response · ${elapsed}`;
3127
3133
  }
3128
3134
  if (sawReasoning)
3129
3135
  return `thinking · ${elapsed}`;
@@ -3168,6 +3174,11 @@ export async function runAgentTurn(prompt, options = {}) {
3168
3174
  const turnTools = selectToolDefs(nativeToolsActive, useCompactSystemPrompt);
3169
3175
  toolsAttached = Boolean(turnTools?.length);
3170
3176
  const contextBreakdown = buildContextBreakdown(messages, toolsAttached ? turnTools : undefined);
3177
+ emit({
3178
+ type: "context-estimate",
3179
+ estimatedTokens: contextBreakdown.estimatedTotalTokens,
3180
+ model,
3181
+ });
3171
3182
  // E4: advisory only — never blocks free-tier users.
3172
3183
  if (!freeTierLargeContextWarned) {
3173
3184
  const notices = freeTierGuardNotices({
@@ -3723,7 +3734,10 @@ export async function runAgentTurn(prompt, options = {}) {
3723
3734
  const salvageHistoryCalls = ensureUniqueToolCallIds(nativeToolCalls, toolCallIdsInHistory(messages));
3724
3735
  const salvagedCallIndex = nativeToolCalls.indexOf(writeTc);
3725
3736
  const salvagedCallId = salvageHistoryCalls[salvagedCallIndex]?.id ?? writeTc.id;
3726
- appendAssistantWithTools(messages, assistantText.visible, salvageHistoryCalls, completion.reasoningBlock);
3737
+ appendAssistantWithTools(messages, assistantText.visible, salvageHistoryCalls, completion.reasoningBlock ??
3738
+ (assistantText.hasThinking && assistantText.thinkContent
3739
+ ? { text: assistantText.thinkContent }
3740
+ : undefined));
3727
3741
  for (const tc of salvageHistoryCalls) {
3728
3742
  appendToolResult(messages, tc.id, tc.id === salvagedCallId
3729
3743
  ? `Tool ${tc.name} result (exit=0, ok=true):\nSalvaged partial write: ${lineCount} lines to ${salvaged.path}`
@@ -4073,6 +4087,7 @@ export async function runAgentTurn(prompt, options = {}) {
4073
4087
  sawServerTail,
4074
4088
  sawLocalHttpProbe,
4075
4089
  sawFailedLocalHttpProbe,
4090
+ serverCriterionRequired: outcomeState.outcome.criteria.some((criterion) => criterion.domain === "server" && criterion.required),
4076
4091
  sawActivePentestTest,
4077
4092
  sawSuccessfulMutation,
4078
4093
  featureAppAsk,
@@ -4256,7 +4271,9 @@ export async function runAgentTurn(prompt, options = {}) {
4256
4271
  if (sequenceDecision.suppress) {
4257
4272
  const reason = sequenceDecision.terminal
4258
4273
  ? "The model repeated the same action sequence after it was already suppressed. No commands were run again."
4259
- : "The same action sequence already ran in the previous model round. No commands were run again; reuse the existing results and choose a materially different next action or finish.";
4274
+ : sequenceDecision.oscillation
4275
+ ? "This exact action sequence already completed earlier this turn (the agent is oscillating back to finished work). No commands were run again; every one of these results is already in context — synthesize them and either advance to a genuinely new action or finish."
4276
+ : "The same action sequence already ran in the previous model round. No commands were run again; reuse the existing results and choose a materially different next action or finish.";
4260
4277
  writeNotice("warn", reason, chalk.yellow(` ⚠ ${reason}\n`));
4261
4278
  const suppressedResults = bound.map((b) => {
4262
4279
  const duplicate = runIds.has(b.id);
@@ -4286,7 +4303,10 @@ export async function runAgentTurn(prompt, options = {}) {
4286
4303
  emitToolResult(eventId, result, resultReason);
4287
4304
  }
4288
4305
  if (historyNativeCalls.length) {
4289
- appendAssistantWithTools(messages, beforeTool ?? "", historyNativeCalls, completion.reasoningBlock);
4306
+ appendAssistantWithTools(messages, beforeTool ?? "", historyNativeCalls, completion.reasoningBlock ??
4307
+ (assistantText.hasThinking && assistantText.thinkContent
4308
+ ? { text: assistantText.thinkContent }
4309
+ : undefined));
4290
4310
  for (const { b, resultReason, result } of suppressedResults) {
4291
4311
  appendToolResult(messages, b.id, `Tool ${b.call.name} result (exit=${result.exitCode}, ok=false):\n${resultReason}`, b.call.name, false);
4292
4312
  }
@@ -4327,7 +4347,10 @@ export async function runAgentTurn(prompt, options = {}) {
4327
4347
  }
4328
4348
  }
4329
4349
  if (historyNativeCalls.length) {
4330
- appendAssistantWithTools(messages, beforeTool ?? "", historyNativeCalls, completion.reasoningBlock);
4350
+ appendAssistantWithTools(messages, beforeTool ?? "", historyNativeCalls, completion.reasoningBlock ??
4351
+ (assistantText.hasThinking && assistantText.thinkContent
4352
+ ? { text: assistantText.thinkContent }
4353
+ : undefined));
4331
4354
  }
4332
4355
  else {
4333
4356
  const standardizedContent = (beforeTool ? beforeTool.trim() + "\n\n" : "") +