@pentoshi/clai 3.17.0 → 3.18.1

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 (48) hide show
  1. package/dist/agent/classic-renderer.js +4 -0
  2. package/dist/agent/classic-renderer.js.map +1 -1
  3. package/dist/agent/events.d.ts +3 -0
  4. package/dist/agent/finalize-gate.js +3 -18
  5. package/dist/agent/finalize-gate.js.map +1 -1
  6. package/dist/agent/must-continue.d.ts +1 -16
  7. package/dist/agent/must-continue.js +0 -31
  8. package/dist/agent/must-continue.js.map +1 -1
  9. package/dist/agent/plan-tool.d.ts +5 -0
  10. package/dist/agent/plan-tool.js +62 -3
  11. package/dist/agent/plan-tool.js.map +1 -1
  12. package/dist/agent/runner.js +37 -13
  13. package/dist/agent/runner.js.map +1 -1
  14. package/dist/agent/tool-call-parser.js +25 -6
  15. package/dist/agent/tool-call-parser.js.map +1 -1
  16. package/dist/app/adapters/agent-event-adapter.js +5 -0
  17. package/dist/app/adapters/agent-event-adapter.js.map +1 -1
  18. package/dist/app/controllers/plan-controller.js +10 -0
  19. package/dist/app/controllers/plan-controller.js.map +1 -1
  20. package/dist/app/events/app-event.d.ts +3 -0
  21. package/dist/app/events/app-event.js.map +1 -1
  22. package/dist/llm/http.js.map +1 -1
  23. package/dist/llm/router.js +14 -2
  24. package/dist/llm/router.js.map +1 -1
  25. package/dist/llm/tool-protocol.d.ts +1 -1
  26. package/dist/llm/tool-protocol.js +8 -0
  27. package/dist/llm/tool-protocol.js.map +1 -1
  28. package/dist/prompts/embedded.js +1 -1
  29. package/dist/prompts/embedded.js.map +1 -1
  30. package/dist/prompts/system.agent.md +3 -2
  31. package/dist/store/history-index.d.ts +9 -1
  32. package/dist/store/history-index.js +48 -28
  33. package/dist/store/history-index.js.map +1 -1
  34. package/dist/store/history.js +157 -18
  35. package/dist/store/history.js.map +1 -1
  36. package/dist/store/task-transitions.js +1 -1
  37. package/dist/store/task-transitions.js.map +1 -1
  38. package/dist/tools/definitions.js +3 -1
  39. package/dist/tools/definitions.js.map +1 -1
  40. package/dist/tui/state.js +8 -0
  41. package/dist/tui/state.js.map +1 -1
  42. package/dist/tui-v2/app/commands/config-commands.js +5 -1
  43. package/dist/tui-v2/app/commands/config-commands.js.map +1 -1
  44. package/dist/tui-v2/state/transcript-reducer.js +1 -0
  45. package/dist/tui-v2/state/transcript-reducer.js.map +1 -1
  46. package/dist/version.generated.d.ts +2 -2
  47. package/dist/version.generated.js +2 -2
  48. package/package.json +1 -1
@@ -70,14 +70,14 @@ import { stripSentinelTokens, parseToolCall, recognizeBareToolJson, looksLikeTru
70
70
  import { createSessionPolicy, isPreApprovalAllowedTool, isPlanModeAllowedShellCommand, isPlanModeAllowedTool, isPlanApprovedByStatus, planHasOpenWork, isAbortError, shouldEnableImageOcr, } from "./session-policy.js";
71
71
  import { saveToolOutput, summarizeOutput, formatToolContext, } from "./tool-output-formatting.js";
72
72
  import { codingSessionFromContext, isProtocolPlaceholderOutput, progressPauseMode, } from "./progress-pause-policy.js";
73
- import { renderPlanForTerminal, planContextMessage, upsertPlanContextMessage, handlePlanTool, resolvePlanTaskId, } from "./plan-tool.js";
73
+ import { renderPlanForTerminal, planContextMessage, removePlanContextMessage, upsertPlanContextMessage, handlePlanTool, resolvePlanTaskId, } from "./plan-tool.js";
74
74
  import { readDeclaredParentTaskId, resolveResponderParent, isExplicitResponderDelegation, delegationTaskTitle, } from "./responder-parent.js";
75
75
  import { readTaskUpdateArgs, distinctAdvancingTaskIds, isSimultaneousTaskAdvance, batchUpdateSignature, buildMultiUpdateReminder, buildMultiOpenRejection, multiUpdateToast, multiOpenToast, openingTaskIds, } from "./task-sync.js";
76
76
  import { absorbLooseWorkIntoLedger, applyDestinationCwd, canMarkTaskDone, hasLocalRuntimeProof, hasRemoteWorkProof, isDevServerCall, isEvidenceWorkTool, isFeatureImplementationCall, isPackageInstallCommand, isPlanPreflightTool, isPortListeningOutput, isReadOnlyReconTool, isRemoteActiveTestCall, isRemoteReconToolCall, isScaffoldCreateCommand, isServerReadyOutput, ledgerFromTaskEvidence, pickPendingTaskForToolCall, recordTaskWorkSuccess, resolveUserDestinationHint, taskEvidenceFromLedger, TOOL_ABORT_GRACE_MS, toolHardBudgetMs, toolStallBudgetMs, userAskedForFeatureApp, } from "./task-evidence.js";
77
77
  import { buildSessionStateBlock, inferNextHint, upsertSessionStateMessage, } from "./session-state.js";
78
78
  import { buildContinueOrientation, looksLikeContinueOrResumePrompt, } from "./continue-orient.js";
79
79
  import { detectPackageManager } from "./workspace-orient.js";
80
- import { budgetRemaining, consumeBudget, createRecoveryBudgets, } from "./must-continue.js";
80
+ import { consumeBudget, createRecoveryBudgets, } from "./must-continue.js";
81
81
  import { chooseFinalizeRecovery } from "./finalize-gate.js";
82
82
  import { outOfScopeToolMessage, scopeContextMessage } from "./scope-context.js";
83
83
  import { EngagementPolicyEngine, actionFromUrl, engagementActionsForToolCall, evaluateEngagementAction, } from "../safety/engagement-policy.js";
@@ -1040,11 +1040,13 @@ export async function runAgentTurn(prompt, options = {}) {
1040
1040
  if (idleOrSocialPrompt || informationalQuery)
1041
1041
  return;
1042
1042
  const runningJobs = jobManager.getRunningJobs(session.sessionId);
1043
- const p = plan ?? activePlan;
1043
+ const p = plan === null ? undefined : plan ?? activePlan;
1044
1044
  if (!buildLikeTurn &&
1045
1045
  !pentestLikeTurn &&
1046
1046
  !p &&
1047
1047
  runningJobs.length === 0) {
1048
+ if (plan === null)
1049
+ removePlanContextMessage(messages);
1048
1050
  return;
1049
1051
  }
1050
1052
  const root = getActiveProjectRoot() ?? p?.meta?.projectRoot;
@@ -1090,6 +1092,9 @@ export async function runAgentTurn(prompt, options = {}) {
1090
1092
  if (p) {
1091
1093
  upsertPlanContextMessage(messages, planContextMessage(p, session.planApproved.value));
1092
1094
  }
1095
+ else {
1096
+ removePlanContextMessage(messages);
1097
+ }
1093
1098
  upsertSessionStateMessage(messages, buildSessionStateBlock(snap));
1094
1099
  };
1095
1100
  refreshSessionState(activePlan);
@@ -1373,12 +1378,7 @@ export async function runAgentTurn(prompt, options = {}) {
1373
1378
  loopGuard.recordAttempt(step, call.name, call.args, true, 0, output);
1374
1379
  return { ok: true, call, result, contextOutput: output };
1375
1380
  }
1376
- if (call.name === "plan.create" ||
1377
- call.name === "task.add" ||
1378
- call.name === "task.move" ||
1379
- call.name === "job.read" ||
1380
- call.name === "task.read" ||
1381
- call.name === "task.update") {
1381
+ if (RUNNER_META_TOOL_NAMES.has(call.name)) {
1382
1382
  if (call.name === "job.read" || call.name === "task.read") {
1383
1383
  const requestedNotificationId = typeof call.args.notificationId === "string"
1384
1384
  ? call.args.notificationId.trim()
@@ -1589,6 +1589,13 @@ export async function runAgentTurn(prompt, options = {}) {
1589
1589
  if (root)
1590
1590
  setActiveProjectRootIfValid(root);
1591
1591
  }
1592
+ if (planResult.ok && planResult.cleared) {
1593
+ pendingSessionStatePlan = null;
1594
+ removePlanContextMessage(messages);
1595
+ emit({ type: "plan-cleared", sessionId: session.sessionId });
1596
+ if (writesDirectly)
1597
+ process.stdout.write(planResult.display);
1598
+ }
1592
1599
  const result = { ok: planResult.ok, output: planResult.modelNote };
1593
1600
  emitToolResult(toolEventId, result, planResult.modelNote);
1594
1601
  const statusIcon = result.ok ? chalk.green(" ✓") : chalk.red(" ✗");
@@ -4107,8 +4114,7 @@ export async function runAgentTurn(prompt, options = {}) {
4107
4114
  "If analysis is incomplete, call only the bounded evidence tool needed now. If each result has been analyzed and is satisfactory, you MUST call job.read with its jobId or exact notificationId before giving a final response. job.read does not require an active plan; do not create or update a plan merely to acknowledge a result."));
4108
4115
  continue;
4109
4116
  }
4110
- const deferResponderReport = session.planApproved.value &&
4111
- budgetRemaining(recovery, "prematureComplete")
4117
+ const deferResponderReport = session.planApproved.value
4112
4118
  ? shouldYieldForDeclaredResponderDependency(livePlanAtCompletion, jobManager.getRunningJobs(session.sessionId), jobManager.getPendingNotifications(session.sessionId), responderWakeNotificationId)
4113
4119
  : false;
4114
4120
  const finalizeRecovery = chooseFinalizeRecovery({
@@ -4414,13 +4420,32 @@ export async function runAgentTurn(prompt, options = {}) {
4414
4420
  if (allCalls.length > 1) {
4415
4421
  writeNotice("info", `${allCalls.length} tool calls in this message — read-only in parallel, writes in order (failures do not cancel siblings)`, chalk.dim(` ℹ ${allCalls.length} tool calls — parallel reads, ordered writes; failures continue\n`));
4416
4422
  }
4417
- for (const deferred of activeDeferredToolCalls.slice(0, allCalls.length)) {
4423
+ // Cards streamed from partial text can predate their arguments. The
4424
+ // executed call is authoritative, so refresh a stale card in place
4425
+ // (same event id → the reducer updates the queued row, no new card).
4426
+ const flushableDeferred = activeDeferredToolCalls.slice(0, allCalls.length);
4427
+ for (let i = 0; i < flushableDeferred.length; i += 1) {
4428
+ const deferred = flushableDeferred[i];
4418
4429
  if (!deferred.call.name || deferred.call.name === "…")
4419
4430
  continue;
4431
+ const finalCall = allCalls[i];
4432
+ const stale = finalCall !== undefined &&
4433
+ (finalCall.name !== deferred.call.name ||
4434
+ formatToolArgs(finalCall) !== formatToolArgs(deferred.call));
4435
+ if (stale) {
4436
+ deferred.call = finalCall;
4437
+ const refreshedLine = chalk.cyan(` ▶ ${finalCall.name}`) +
4438
+ chalk.gray(` ${formatToolArgs(finalCall)}`);
4439
+ deferred.rendered =
4440
+ styleToolChatter(finalCall, refreshedLine) + "\n";
4441
+ }
4420
4442
  if (!deferred.shown) {
4421
4443
  writeToolCall(deferred.eventId, deferred.call, deferred.rendered);
4422
4444
  deferred.shown = true;
4423
4445
  }
4446
+ else if (stale) {
4447
+ writeToolCall(deferred.eventId, deferred.call, "");
4448
+ }
4424
4449
  }
4425
4450
  if (historyNativeCalls.length) {
4426
4451
  appendAssistantWithTools(messages, beforeTool ?? "", historyNativeCalls, completion.reasoningBlock ??
@@ -4579,7 +4604,6 @@ export async function runAgentTurn(prompt, options = {}) {
4579
4604
  sawSuccessfulMutation = false;
4580
4605
  }
4581
4606
  if (res.ok && isEvidenceWorkTool(res.call.name)) {
4582
- recovery.prematureComplete = 0;
4583
4607
  recovery.actionIntent = 0;
4584
4608
  recovery.errorFix = 0;
4585
4609
  }