omnius 1.0.462 → 1.0.464

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/dist/index.js CHANGED
@@ -567631,7 +567631,15 @@ function ago(ms) {
567631
567631
  const h = Math.floor(m2 / 60);
567632
567632
  return `${h}h ago`;
567633
567633
  }
567634
- function computeNextActionHint(reconciled) {
567634
+ function computeNextActionHint(reconciled, recentFailures, focusDirective) {
567635
+ if (focusDirective?.requiredNextAction) {
567636
+ const reason = focusDirective.reason ? ` Reason: ${focusDirective.reason.slice(0, 180)}.` : "";
567637
+ return `Active recovery directive requires ${focusDirective.requiredNextAction}.${reason} Follow that before completion or unrelated work.`;
567638
+ }
567639
+ if (recentFailures.length > 0) {
567640
+ const first2 = recentFailures[0];
567641
+ return `Resolve or explicitly account for unresolved failure "${first2.stem}" (${first2.attempts} attempt${first2.attempts === 1 ? "" : "s"}). Do not infer completion from plan state while failures remain.`;
567642
+ }
567635
567643
  const inProgress = reconciled.find((t2) => t2.reconciled === "in_progress");
567636
567644
  if (inProgress)
567637
567645
  return `Continue your in-progress item: "${inProgress.content.slice(0, 100)}".`;
@@ -567661,7 +567669,10 @@ function computeNextActionHint(reconciled) {
567661
567669
  const first2 = completedUnverified[0];
567662
567670
  return `A completed todo has a verifyCommand that hasn't run during this snapshot: ${first2.rationale}`;
567663
567671
  }
567664
- return `All declared plan items appear satisfied. If the goal is met, declare with task_complete; otherwise add new todos for remaining work.`;
567672
+ if (reconciled.length === 0) {
567673
+ return `No declared plan items are available. Continue from the active goal and evidence; report completion only with direct verification.`;
567674
+ }
567675
+ return `Declared plan items have no visible gaps. Continue from the active goal and evidence; report completion only with direct verification.`;
567665
567676
  }
567666
567677
  function regenerate(opts) {
567667
567678
  const startMs = Date.now();
@@ -567756,7 +567767,18 @@ function regenerate(opts) {
567756
567767
  }
567757
567768
  }
567758
567769
  lines.push(``);
567759
- const nextActionHint = computeNextActionHint(reconciled);
567770
+ if (opts.focusDirective?.requiredNextAction) {
567771
+ lines.push(`ACTIVE RECOVERY DIRECTIVE:`);
567772
+ lines.push(` required_next_action=${opts.focusDirective.requiredNextAction}`);
567773
+ if (opts.focusDirective.state) {
567774
+ lines.push(` state=${opts.focusDirective.state}`);
567775
+ }
567776
+ if (opts.focusDirective.reason) {
567777
+ lines.push(` reason=${opts.focusDirective.reason.slice(0, 240)}`);
567778
+ }
567779
+ lines.push(``);
567780
+ }
567781
+ const nextActionHint = computeNextActionHint(reconciled, opts.recentFailures, opts.focusDirective);
567760
567782
  lines.push(`SUGGESTED NEXT STEP (derived from gap analysis, not authoritative):`);
567761
567783
  lines.push(` ${nextActionHint}`);
567762
567784
  lines.push(``);
@@ -575157,21 +575179,13 @@ function violatesDirective(directive, input) {
575157
575179
  }
575158
575180
  if (input.toolName === "ask_user")
575159
575181
  return false;
575182
+ const family = actionFamily(input.toolName, input.args);
575183
+ if (directive.requiredNextAction !== "update_todos" && directiveExplicitlyForbidsCall(directive, input, family)) {
575184
+ return true;
575185
+ }
575160
575186
  if (directive.requiredNextAction === "read_authoritative_target" && input.usesAuthoritativeTargetEvidence && isEditTool(input.toolName)) {
575161
575187
  return false;
575162
575188
  }
575163
- const family = actionFamily(input.toolName, input.args);
575164
- if (directive.requiredNextAction !== "update_todos") {
575165
- if (directive.forbiddenActionFamilies.includes(family))
575166
- return true;
575167
- if (directive.forbiddenActionFamilies.includes(input.toolName)) {
575168
- if (input.toolName === "shell" && input.isReadLike)
575169
- return false;
575170
- if (input.toolName === "shell" && input.shellLikelyMutatesFilesystem)
575171
- return false;
575172
- return true;
575173
- }
575174
- }
575175
575189
  switch (directive.requiredNextAction) {
575176
575190
  case "update_todos":
575177
575191
  if (input.toolName === "shell")
@@ -575204,6 +575218,17 @@ function violatesDirective(directive, input) {
575204
575218
  return false;
575205
575219
  }
575206
575220
  }
575221
+ function directiveExplicitlyForbidsCall(directive, input, family) {
575222
+ if (directive.forbiddenActionFamilies.includes(family))
575223
+ return true;
575224
+ if (!directive.forbiddenActionFamilies.includes(input.toolName))
575225
+ return false;
575226
+ if (input.toolName === "shell" && input.isReadLike)
575227
+ return false;
575228
+ if (input.toolName === "shell" && input.shellLikelyMutatesFilesystem)
575229
+ return false;
575230
+ return true;
575231
+ }
575207
575232
  function forbiddenCachedEvidenceFamilies(input, family) {
575208
575233
  return [family];
575209
575234
  }
@@ -578503,7 +578528,7 @@ function classifyThinkOutcome(raw) {
578503
578528
  }
578504
578529
  return null;
578505
578530
  }
578506
- var TOOL_SUBSETS, TOOL_AUTO_DEMOTE_TURNS, TOOL_ACTION_REASON_KEYS, TOOL_ACTION_REASON_SCOPES, TOOL_ACTION_REASON_SCHEMA, SYSTEM_PROMPT, SYSTEM_PROMPT_MEDIUM, SYSTEM_PROMPT_SMALL, VISUAL_TOOLS, AUDIO_TOOLS, SOCIAL_TOOLS, SPATIAL_TOOLS, CODE_TOOLS, AgenticRunner, OllamaAgenticBackend;
578531
+ var TOOL_SUBSETS, TOOL_AUTO_DEMOTE_TURNS, TOOL_ACTION_REASON_KEYS, TOOL_ACTION_REASON_SCOPES, READ_ONLY_ACTION_REASON_OPTIONAL_TOOLS, TOOL_ACTION_REASON_SCHEMA, SYSTEM_PROMPT, SYSTEM_PROMPT_MEDIUM, SYSTEM_PROMPT_SMALL, VISUAL_TOOLS, AUDIO_TOOLS, SOCIAL_TOOLS, SPATIAL_TOOLS, CODE_TOOLS, AgenticRunner, OllamaAgenticBackend;
578507
578532
  var init_agenticRunner = __esm({
578508
578533
  "packages/orchestrator/dist/agenticRunner.js"() {
578509
578534
  "use strict";
@@ -578608,6 +578633,25 @@ var init_agenticRunner = __esm({
578608
578633
  "completion",
578609
578634
  "other"
578610
578635
  ]);
578636
+ READ_ONLY_ACTION_REASON_OPTIONAL_TOOLS = /* @__PURE__ */ new Set([
578637
+ "file_read",
578638
+ "file_explore",
578639
+ "list_directory",
578640
+ "grep_search",
578641
+ "grep",
578642
+ "glob_find",
578643
+ "find_files",
578644
+ "todo_read",
578645
+ "memory_read",
578646
+ "memory_search",
578647
+ "semantic_map",
578648
+ "code_graph",
578649
+ "graph_query",
578650
+ "graph_traverse",
578651
+ "web_search",
578652
+ "web_fetch",
578653
+ "tool_search"
578654
+ ]);
578611
578655
  TOOL_ACTION_REASON_SCHEMA = {
578612
578656
  type: "object",
578613
578657
  description: "Compact public action contract for this exact tool call. Do not include hidden chain-of-thought; use concise task-state facts.",
@@ -579548,7 +579592,7 @@ ${parts.join("\n")}
579548
579592
  if (ts.failedApproaches.length > 0) {
579549
579593
  lines.push(`recent_failed_approaches=${ts.failedApproaches.slice(-3).join(" | ").replace(/\s+/g, " ").slice(0, 420)}`);
579550
579594
  }
579551
- lines.push("tool_call_contract=Each tool call must include action_reason {task_anchor,intent,evidence,expected_result,scope}; compact public facts only, no hidden chain-of-thought.");
579595
+ lines.push("tool_call_contract=Mutating/side-effectful tool calls require action_reason {task_anchor,intent,evidence,expected_result,scope}; read-only evidence tools may include it but must never be blocked only for missing metadata. Compact public facts only, no hidden chain-of-thought.");
579552
579596
  lines.push(`scope_contract=${Array.from(TOOL_ACTION_REASON_SCOPES).join("|")}; use targeted_patch for constrained code edits and full_file_rewrite only for deliberate whole-file replacement.`);
579553
579597
  const focus = this._focusSupervisor?.snapshot().directive ?? null;
579554
579598
  if (focus) {
@@ -584760,7 +584804,7 @@ ${blob}
584760
584804
  * size. The hash is computed over the full canonical value.
584761
584805
  */
584762
584806
  _buildExactArgsKey(args) {
584763
- return Object.entries(args ?? {}).sort(([a2], [b]) => a2.localeCompare(b)).map(([k, v]) => `${k}=${this._formatExactArgValue(v)}`).join(",");
584807
+ return Object.entries(args ?? {}).filter(([key]) => !TOOL_ACTION_REASON_KEYS.has(key)).sort(([a2], [b]) => a2.localeCompare(b)).map(([k, v]) => `${k}=${this._formatExactArgValue(v)}`).join(",");
584764
584808
  }
584765
584809
  _buildToolFingerprint(name10, args) {
584766
584810
  const canonical = this.lookupRegisteredTool(name10)?.name ?? name10;
@@ -585235,7 +585279,8 @@ Rewrite it now for ${ctx3.model}.`;
585235
585279
  const unknownKeys = providedKeys.filter((key) => !props.has(key));
585236
585280
  const aliases = this.suggestArgumentAliases(missingRequired, providedKeys, args, props);
585237
585281
  const corrected = this.buildCorrectedArgsPreview(args, props, aliases);
585238
- const siblingMatches = this.findSiblingToolSchemaMatches(toolName, providedKeys);
585282
+ const actionReasonOnlyFailure = validationError.includes("[TOOL ACTION REASON CONTRACT]");
585283
+ const siblingMatches = actionReasonOnlyFailure ? [] : this.findSiblingToolSchemaMatches(toolName, providedKeys);
585239
585284
  const lines = [
585240
585285
  `[RUNTIME TOOL ARGUMENT REPAIR]`,
585241
585286
  `Tool call failed before execution: ${toolName}`,
@@ -585300,7 +585345,10 @@ Rewrite it now for ${ctx3.model}.`;
585300
585345
  path: ["file", "image", "media", "filepath", "file_path", "filename"],
585301
585346
  image: ["path", "file", "media", "filepath", "file_path", "filename"],
585302
585347
  command: ["cmd", "shell_command"],
585303
- query: ["prompt", "task", "message", "input", "text"]
585348
+ query: ["prompt", "task", "message", "input", "text"],
585349
+ start_line: ["line", "lineNumber", "line_number", "startLine"],
585350
+ end_line: ["endLine", "end_line", "lineEnd", "line_end", "end"],
585351
+ new_content: ["content", "newContent", "new_content"]
585304
585352
  };
585305
585353
  for (const required of missingRequired) {
585306
585354
  for (const alias of aliasMap[required] ?? []) {
@@ -586794,6 +586842,7 @@ TASK: ${scrubbedTask}` : scrubbedTask;
586794
586842
  preview: (entry.wentWrong || "").slice(0, 200),
586795
586843
  distinctErrors: entry.errorSignatures?.size
586796
586844
  })).sort((a2, b) => b.attempts - a2.attempts).slice(0, 5);
586845
+ const _wsFocusDirective = this._focusSupervisor?.snapshot().directive ?? null;
586797
586846
  const _ws = regenerate({
586798
586847
  workingDir: _wsWorkingDir,
586799
586848
  goal: this._taskState.originalGoal || this._taskState.goal || "",
@@ -586801,6 +586850,11 @@ TASK: ${scrubbedTask}` : scrubbedTask;
586801
586850
  triggerReason: _wsTrigger,
586802
586851
  todos: _wsTodos,
586803
586852
  recentFailures: _wsFailures,
586853
+ focusDirective: _wsFocusDirective ? {
586854
+ requiredNextAction: _wsFocusDirective.requiredNextAction,
586855
+ reason: _wsFocusDirective.reason,
586856
+ state: _wsFocusDirective.state
586857
+ } : null,
586804
586858
  maxFiles: WORLD_STATE_MAX_FILES,
586805
586859
  lastBuildSuccess: this._lastBuildSuccessTurn >= 0 ? {
586806
586860
  command: this._lastBuildSuccessCommand,
@@ -587181,6 +587235,25 @@ If this matches your current shape, try it before continuing.`
587181
587235
  if (_m)
587182
587236
  _staleSamples.push(` - ${c9.name}: ${_m[0]}`);
587183
587237
  }
587238
+ const _reg44FocusDirective = this._focusDirectiveSuppressesEditPressure();
587239
+ const _reg44ChoiceLines = _reg44FocusDirective ? [
587240
+ `A focus recovery directive is active and overrides the generic stuck escape options.`,
587241
+ `Required next action: ${_reg44FocusDirective.requiredNextAction}.`,
587242
+ `Reason: ${_reg44FocusDirective.reason}.`,
587243
+ `Do not choose a generic produce/complete/debate escape until this recovery directive is satisfied or reported impossible with evidence.`
587244
+ ] : [
587245
+ `Pick ONE of these for your next response:`,
587246
+ ``,
587247
+ ` (a) PRODUCE: emit a file_write / file_edit / file_patch that creates or changes project content. Even a partial draft of the next planned file is progress. Use shell only for commands/tests/system operations, not as a workaround for failed edit-tool encoding.`,
587248
+ ``,
587249
+ ` (b) ERROR-INFORMED LOCAL TRIAGE: anchor on the freshest local failure, identify the implicated file/path/symbol/command, then make one targeted local move instead of broad exploration.`,
587250
+ ``,
587251
+ this._renderLocalFailureNudge(turn),
587252
+ ``,
587253
+ ` (c) DEBATE: if you've tried 3+ approaches and they all hit the same wall, invoke \`debate\` with the failed task as the prompt — get a second opinion.`,
587254
+ ``,
587255
+ ` (d) DECLARE BLOCKED: if you genuinely cannot make progress (missing dependency, ambiguous spec, external service down), call \`task_complete\` with a summary that NAMES THE BLOCKER explicitly. Don't keep looping.`
587256
+ ];
587184
587257
  messages2.push({
587185
587258
  role: "system",
587186
587259
  content: [
@@ -587194,17 +587267,7 @@ If this matches your current shape, try it before continuing.`
587194
587267
  ``,
587195
587268
  `You are consuming turns without producing new state. Every shape of "agent stuck" — read-heavy without writes, repeated cache hits, blocked-shell loops, no-op todo updates — looks like this signal. The exact tool names don't matter; the ratio does.`,
587196
587269
  ``,
587197
- `Pick ONE of these for your next response:`,
587198
- ``,
587199
- ` (a) PRODUCE: emit a file_write / file_edit / file_patch that creates or changes project content. Even a partial draft of the next planned file is progress. Use shell only for commands/tests/system operations, not as a workaround for failed edit-tool encoding.`,
587200
- ``,
587201
- ` (b) ERROR-INFORMED LOCAL TRIAGE: anchor on the freshest local failure, identify the implicated file/path/symbol/command, then make one targeted local move instead of broad exploration.`,
587202
- ``,
587203
- this._renderLocalFailureNudge(turn),
587204
- ``,
587205
- ` (c) DEBATE: if you've tried 3+ approaches and they all hit the same wall, invoke \`debate\` with the failed task as the prompt — get a second opinion.`,
587206
- ``,
587207
- ` (d) DECLARE BLOCKED: if you genuinely cannot make progress (missing dependency, ambiguous spec, external service down), call \`task_complete\` with a summary that NAMES THE BLOCKER explicitly. Don't keep looping.`,
587270
+ ..._reg44ChoiceLines,
587208
587271
  ``,
587209
587272
  `Recent failures (real or synthetic):`,
587210
587273
  _failureBlocks,
@@ -587359,6 +587422,27 @@ ${_staleSamples.join("\n")}` : ``,
587359
587422
  });
587360
587423
  if (_wtWorstCount >= _wtThreshold && !_wtHadSuccessfulVerify) {
587361
587424
  this._writeThrashCooldownUntilTurn = turn + 8;
587425
+ const _reg50FocusDirective = this._focusDirectiveSuppressesEditPressure();
587426
+ const _reg50ChoiceLines = _reg50FocusDirective ? [
587427
+ `A focus recovery directive is active and overrides the generic write-thrash choices.`,
587428
+ `Required next action: ${_reg50FocusDirective.requiredNextAction}.`,
587429
+ `Reason: ${_reg50FocusDirective.reason}.`,
587430
+ `Do not write ${_wtWorstPath} again until the focus directive is satisfied or reported impossible with evidence.`
587431
+ ] : [
587432
+ `Pick ONE of these for your next response:`,
587433
+ ``,
587434
+ ` (a) RUN-AND-READ: Run the EXACT command that fails (test/typecheck/build) and READ THE FULL ERROR MESSAGE LITERALLY. Do not summarize it from memory; paste it back into context. The current write hasn't been validated against any error.`,
587435
+ ``,
587436
+ ` (b) DELETE-AND-RESTART: If the file has been rewritten ${_wtWorstCount} times, the current approach is wrong. Either delete the file and try a fundamentally different design, OR revert to a known-good earlier version (use git, working_notes, or memory_search to find one).`,
587437
+ ``,
587438
+ ` (c) ERROR-INFORMED LOCAL TRIAGE: use the exact failing local command and error line to identify one implicated path/symbol/config key, then inspect or change only that target. Do not search online for a codebase-local failure.`,
587439
+ ``,
587440
+ this._renderLocalFailureNudge(turn),
587441
+ ``,
587442
+ ` (d) DECLARE BLOCKED: If the file's correct shape genuinely isn't knowable from the spec + this codebase, call task_complete with a summary that names this specific file as the blocker. Don't burn more turns on it.`,
587443
+ ``,
587444
+ `Do NOT in your next response: write to ${_wtWorstPath} again without first running and reading the failing command's output.`
587445
+ ];
587362
587446
  messages2.push({
587363
587447
  role: "system",
587364
587448
  content: [
@@ -587369,19 +587453,7 @@ ${_staleSamples.join("\n")}` : ``,
587369
587453
  ``,
587370
587454
  `No successful test/build/typecheck command ran between writes — you are iterating the file blind, hoping the next variation works. This is a write-thrash anti-pattern. Repeated edits without verification confirm nothing.`,
587371
587455
  ``,
587372
- `Pick ONE of these for your next response:`,
587373
- ``,
587374
- ` (a) RUN-AND-READ: Run the EXACT command that fails (test/typecheck/build) and READ THE FULL ERROR MESSAGE LITERALLY. Do not summarize it from memory; paste it back into context. The current write hasn't been validated against any error.`,
587375
- ``,
587376
- ` (b) DELETE-AND-RESTART: If the file has been rewritten ${_wtWorstCount} times, the current approach is wrong. Either delete the file and try a fundamentally different design, OR revert to a known-good earlier version (use git, working_notes, or memory_search to find one).`,
587377
- ``,
587378
- ` (c) ERROR-INFORMED LOCAL TRIAGE: use the exact failing local command and error line to identify one implicated path/symbol/config key, then inspect or change only that target. Do not search online for a codebase-local failure.`,
587379
- ``,
587380
- this._renderLocalFailureNudge(turn),
587381
- ``,
587382
- ` (d) DECLARE BLOCKED: If the file's correct shape genuinely isn't knowable from the spec + this codebase, call task_complete with a summary that names this specific file as the blocker. Don't burn more turns on it.`,
587383
- ``,
587384
- `Do NOT in your next response: write to ${_wtWorstPath} again without first running and reading the failing command's output.`
587456
+ ..._reg50ChoiceLines
587385
587457
  ].join("\n")
587386
587458
  });
587387
587459
  this.emit({
@@ -587497,6 +587569,25 @@ ${_staleSamples.join("\n")}` : ``,
587497
587569
  }
587498
587570
  if (_efWorstCount >= _efThreshold) {
587499
587571
  this._editFailThrashCooldownUntilTurn = turn + 8;
587572
+ const _reg53FocusDirective = this._focusDirectiveSuppressesEditPressure();
587573
+ const _reg53ChoiceLines = _reg53FocusDirective ? [
587574
+ `A focus recovery directive is active and overrides generic stale-edit recovery choices.`,
587575
+ `Required next action: ${_reg53FocusDirective.requiredNextAction}.`,
587576
+ `Reason: ${_reg53FocusDirective.reason}.`,
587577
+ `Do not call file_edit or batch_edit on ${_efWorstPath} again until that directive is satisfied or reported impossible with evidence.`
587578
+ ] : [
587579
+ `STOP guessing variants of old_string. Pick ONE of these for your next response:`,
587580
+ ``,
587581
+ ` (a) FILE_READ + COPY-EXACT: Call file_read on ${_efWorstPath}, then copy the EXACT bytes (whitespace, indentation, punctuation) for old_string from that read. Do not paraphrase or reformat.`,
587582
+ ``,
587583
+ ` (b) USE THE INLINE SNIPPET: Recent edit failures already include a "closest match" snippet showing the actual current content near where you tried to edit. Read that snippet in your last error message and use its content verbatim as old_string.`,
587584
+ ``,
587585
+ ` (c) REPLACE_ALL: If you want a global rename, set replace_all=true and the uniqueness check is bypassed.`,
587586
+ ``,
587587
+ ` (d) CONSTRAINED PATCH: If the exact replacement is too brittle, use file_patch with expected_old_content or batch_edit/file_edit against fresh current text. Use file_write only for new files, dry-run proposals, or deliberate hash-guarded full_file_rewrite actions.`,
587588
+ ``,
587589
+ `Do NOT in your next response: call file_edit or batch_edit on ${_efWorstPath} again with another guess at old_string.`
587590
+ ];
587500
587591
  messages2.push({
587501
587592
  role: "system",
587502
587593
  content: [
@@ -587507,17 +587598,7 @@ ${_staleSamples.join("\n")}` : ``,
587507
587598
  ``,
587508
587599
  `Each failure means your old_string did not match the file content. Your remembered version of this file has diverged from what's on disk — likely because an earlier edit succeeded and shifted things, or because you guessed at the file's content.`,
587509
587600
  ``,
587510
- `STOP guessing variants of old_string. Pick ONE of these for your next response:`,
587511
- ``,
587512
- ` (a) FILE_READ + COPY-EXACT: Call file_read on ${_efWorstPath}, then copy the EXACT bytes (whitespace, indentation, punctuation) for old_string from that read. Do not paraphrase or reformat.`,
587513
- ``,
587514
- ` (b) USE THE INLINE SNIPPET: Recent edit failures already include a "closest match" snippet showing the actual current content near where you tried to edit. Read that snippet in your last error message and use its content verbatim as old_string.`,
587515
- ``,
587516
- ` (c) REPLACE_ALL: If you want a global rename, set replace_all=true and the uniqueness check is bypassed.`,
587517
- ``,
587518
- ` (d) CONSTRAINED PATCH: If the exact replacement is too brittle, use file_patch with expected_old_content or batch_edit/file_edit against fresh current text. Use file_write only for new files, dry-run proposals, or deliberate hash-guarded full_file_rewrite actions.`,
587519
- ``,
587520
- `Do NOT in your next response: call file_edit or batch_edit on ${_efWorstPath} again with another guess at old_string.`
587601
+ ..._reg53ChoiceLines
587521
587602
  ].join("\n")
587522
587603
  });
587523
587604
  this.emit({
@@ -588619,7 +588700,7 @@ ${memoryLines.join("\n")}`
588619
588700
  const executeSingle = async (tc) => {
588620
588701
  if (this.aborted)
588621
588702
  return null;
588622
- const actionReasonForAdvisory = this._extractToolActionReason(tc.arguments ?? {});
588703
+ const actionReasonForAdvisory = this._toolActionReasonForCall(tc.name, tc.arguments ?? {});
588623
588704
  const cohortKey = this.buildArgCohortKey(tc.name, tc.arguments);
588624
588705
  const cohort = this._argCohorts.get(cohortKey);
588625
588706
  if (cohort && cohort.failure >= 3 && cohort.success === 0) {
@@ -589483,6 +589564,7 @@ ${cachedResult}`,
589483
589564
  let validationError = this._validateToolActionReason(resolvedTool?.name ?? tc.name, tc.arguments ?? {});
589484
589565
  if (!validationError) {
589485
589566
  tc.arguments = this._stripToolActionReasonArgs(tc.arguments ?? {});
589567
+ tc.arguments = this._normalizeToolArgsForExecution(resolvedTool?.name ?? tc.name, tc.arguments ?? {});
589486
589568
  validationError = this._validateFileWriteOverwriteContract(resolvedTool?.name ?? tc.name, tc.arguments ?? {}, toolActionReason);
589487
589569
  }
589488
589570
  if (!validationError) {
@@ -593769,21 +593851,40 @@ ${marker}` : marker);
593769
593851
  }
593770
593852
  return matchesFresh(args);
593771
593853
  }
593772
- _requiresToolActionReason(toolName) {
593854
+ _toolActionReasonPolicy(toolName, args) {
593773
593855
  if (process.env["OMNIUS_DISABLE_TOOL_ACTION_REASON"] === "1") {
593774
- return false;
593856
+ return "disabled";
593775
593857
  }
593776
593858
  if ((process.env["VITEST"] || process.env["NODE_ENV"] === "test") && process.env["OMNIUS_REQUIRE_TOOL_ACTION_REASON"] !== "1") {
593777
- return false;
593859
+ return "disabled";
593778
593860
  }
593779
593861
  if (this.options.artifactMode === "internal")
593780
- return false;
593862
+ return "disabled";
593781
593863
  if (toolName.startsWith("__"))
593782
- return false;
593783
- return true;
593864
+ return "disabled";
593865
+ return this._toolActionReasonIsOptional(toolName, args) ? "optional" : "required";
593866
+ }
593867
+ _requiresToolActionReason(toolName, args) {
593868
+ return this._toolActionReasonPolicy(toolName, args) === "required";
593869
+ }
593870
+ _toolActionReasonIsOptional(toolName, args) {
593871
+ const resolved = this.lookupRegisteredTool(toolName);
593872
+ const canonical = resolved?.name ?? toolName;
593873
+ if (READ_ONLY_ACTION_REASON_OPTIONAL_TOOLS.has(canonical))
593874
+ return true;
593875
+ const tool = resolved?.tool;
593876
+ if (typeof tool?.isReadOnly === "function") {
593877
+ try {
593878
+ if (tool.isReadOnly(args ?? {}))
593879
+ return true;
593880
+ } catch {
593881
+ }
593882
+ }
593883
+ return false;
593784
593884
  }
593785
593885
  _withToolActionReasonSchema(toolName, parameters) {
593786
- if (!this._requiresToolActionReason(toolName)) {
593886
+ const policy = this._toolActionReasonPolicy(toolName);
593887
+ if (policy === "disabled") {
593787
593888
  return parameters ?? { type: "object", properties: {} };
593788
593889
  }
593789
593890
  const base3 = parameters && typeof parameters === "object" && !Array.isArray(parameters) ? { ...parameters } : { type: "object" };
@@ -593794,11 +593895,21 @@ ${marker}` : marker);
593794
593895
  ...base3,
593795
593896
  type: "object",
593796
593897
  properties,
593797
- required: [.../* @__PURE__ */ new Set([...required, "action_reason"])]
593898
+ required: policy === "required" ? [.../* @__PURE__ */ new Set([...required, "action_reason"])] : required
593798
593899
  };
593799
593900
  }
593800
593901
  _extractToolActionReason(args) {
593801
- const raw = args["action_reason"] ?? args["actionReason"] ?? args["justification"];
593902
+ let raw = args["action_reason"] ?? args["actionReason"] ?? args["justification"];
593903
+ if (typeof raw === "string") {
593904
+ const trimmed = raw.trim();
593905
+ if (!trimmed)
593906
+ return null;
593907
+ try {
593908
+ raw = JSON.parse(trimmed);
593909
+ } catch {
593910
+ return null;
593911
+ }
593912
+ }
593802
593913
  if (!raw || typeof raw !== "object" || Array.isArray(raw))
593803
593914
  return null;
593804
593915
  const rec = raw;
@@ -593811,20 +593922,46 @@ ${marker}` : marker);
593811
593922
  };
593812
593923
  return reason;
593813
593924
  }
593925
+ _toolActionReasonForCall(toolName, args) {
593926
+ const explicit = this._extractToolActionReason(args);
593927
+ if (explicit)
593928
+ return explicit;
593929
+ if (this._toolActionReasonPolicy(toolName, args) !== "optional")
593930
+ return null;
593931
+ return this._synthesizeReadOnlyToolActionReason(toolName, args);
593932
+ }
593933
+ _synthesizeReadOnlyToolActionReason(toolName, args) {
593934
+ const canonical = this.lookupRegisteredTool(toolName)?.name ?? toolName;
593935
+ const goal = this._taskState.currentStep || this._taskState.nextAction || this._taskState.goal || this._taskState.originalGoal || "current task";
593936
+ const targets = this._extractToolTargetPaths(canonical, args).slice(0, 3);
593937
+ const targetText = targets.length > 0 ? ` for ${targets.join(", ")}` : "";
593938
+ return {
593939
+ task_anchor: String(goal).replace(/\s+/g, " ").trim().slice(0, 160),
593940
+ intent: `Run read-only ${canonical}${targetText} to gather current evidence.`,
593941
+ evidence: "Read-only metadata fallback; no project mutation is authorized by this action.",
593942
+ expected_result: `Current ${canonical} evidence for the next decision.`,
593943
+ scope: "discovery"
593944
+ };
593945
+ }
593814
593946
  _validateToolActionReason(toolName, args) {
593815
- if (!this._requiresToolActionReason(toolName))
593947
+ const policy = this._toolActionReasonPolicy(toolName, args);
593948
+ if (policy === "disabled")
593816
593949
  return null;
593817
593950
  const raw = args["action_reason"] ?? args["actionReason"] ?? args["justification"];
593818
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
593951
+ if (!raw || typeof raw === "string" && !raw.trim()) {
593952
+ if (policy === "optional")
593953
+ return null;
593819
593954
  return [
593820
593955
  "[TOOL ACTION REASON CONTRACT]",
593821
- `Every tool call must include action_reason: { task_anchor, intent, evidence, expected_result, scope }.`,
593956
+ `This side-effectful tool call must include action_reason: { task_anchor, intent, evidence, expected_result, scope }.`,
593822
593957
  `Use compact public facts only; do not include hidden chain-of-thought.`,
593823
593958
  `scope must be one of: ${Array.from(TOOL_ACTION_REASON_SCOPES).join(", ")}.`
593824
593959
  ].join("\n");
593825
593960
  }
593826
593961
  const reason = this._extractToolActionReason(args);
593827
593962
  if (!reason) {
593963
+ if (policy === "optional")
593964
+ return null;
593828
593965
  return "[TOOL ACTION REASON CONTRACT] action_reason must be an object with compact public task-state fields.";
593829
593966
  }
593830
593967
  const missing = [
@@ -593835,9 +593972,13 @@ ${marker}` : marker);
593835
593972
  "scope"
593836
593973
  ].filter((key) => reason[key].length < 3);
593837
593974
  if (missing.length > 0) {
593975
+ if (policy === "optional")
593976
+ return null;
593838
593977
  return `[TOOL ACTION REASON CONTRACT] action_reason missing non-empty field(s): ${missing.join(", ")}.`;
593839
593978
  }
593840
593979
  if (!TOOL_ACTION_REASON_SCOPES.has(reason.scope)) {
593980
+ if (policy === "optional")
593981
+ return null;
593841
593982
  return `[TOOL ACTION REASON CONTRACT] action_reason.scope="${reason.scope}" is invalid. Use one of: ${Array.from(TOOL_ACTION_REASON_SCOPES).join(", ")}.`;
593842
593983
  }
593843
593984
  return null;
@@ -593854,6 +593995,39 @@ ${marker}` : marker);
593854
593995
  }
593855
593996
  return changed ? next : args;
593856
593997
  }
593998
+ _normalizeToolArgsForExecution(toolName, args) {
593999
+ if (toolName !== "file_patch")
594000
+ return args;
594001
+ let next = args;
594002
+ const copy = () => {
594003
+ if (next === args)
594004
+ next = { ...args };
594005
+ return next;
594006
+ };
594007
+ const coerceLineNumber = (value2) => {
594008
+ if (typeof value2 === "number")
594009
+ return value2;
594010
+ if (typeof value2 === "string" && /^\d+$/.test(value2.trim())) {
594011
+ return Number(value2.trim());
594012
+ }
594013
+ return value2;
594014
+ };
594015
+ if (next["start_line"] === void 0 && args["line"] !== void 0) {
594016
+ copy()["start_line"] = coerceLineNumber(args["line"]);
594017
+ }
594018
+ if (next["end_line"] === void 0 && args["line_end"] !== void 0) {
594019
+ copy()["end_line"] = coerceLineNumber(args["line_end"]);
594020
+ }
594021
+ if (next["end_line"] === void 0 && args["endLine"] !== void 0) {
594022
+ copy()["end_line"] = coerceLineNumber(args["endLine"]);
594023
+ }
594024
+ for (const key of ["start_line", "end_line"]) {
594025
+ if (typeof next[key] === "string") {
594026
+ copy()[key] = coerceLineNumber(next[key]);
594027
+ }
594028
+ }
594029
+ return next;
594030
+ }
593857
594031
  _validateFileWriteOverwriteContract(toolName, args, actionReason) {
593858
594032
  if (toolName !== "file_write")
593859
594033
  return null;
@@ -595862,7 +596036,7 @@ ${trimmedNew}`;
595862
596036
  args = JSON.parse(tc.function.arguments);
595863
596037
  } catch {
595864
596038
  }
595865
- const actionReason = this._extractToolActionReason(args);
596039
+ const actionReason = this._toolActionReasonForCall(name10, args);
595866
596040
  const argsKey = this._buildExactArgsKey(args);
595867
596041
  const fingerprint = this._buildToolFingerprint(name10, args);
595868
596042
  const prior = this._adversaryToolOutcomes.find((o2) => o2.succeeded && o2.tool === name10 && o2.fingerprint === fingerprint && o2.stateVersion === this._adversaryStateVersion && o2.turn < turn);
@@ -627821,6 +627995,7 @@ var omnius_directory_exports = {};
627821
627995
  __export(omnius_directory_exports, {
627822
627996
  OMNIUS_DIR: () => OMNIUS_DIR,
627823
627997
  buildContextRestorePrompt: () => buildContextRestorePrompt,
627998
+ buildContextRestoreSnapshot: () => buildContextRestoreSnapshot,
627824
627999
  buildHandoffPrompt: () => buildHandoffPrompt,
627825
628000
  cleanPromptForDiary: () => cleanPromptForDiary,
627826
628001
  clearTaskHandoff: () => clearTaskHandoff,
@@ -628764,9 +628939,7 @@ function selectActiveTaskAnchor(repoRoot) {
628764
628939
  return null;
628765
628940
  }
628766
628941
  }
628767
- function buildActiveTaskAnchor(repoRoot) {
628768
- const selected = selectActiveTaskAnchor(repoRoot);
628769
- if (!selected) return null;
628942
+ function formatActiveTaskAnchor(selected) {
628770
628943
  const ledger = selected.ledger;
628771
628944
  const evidence = ledger.evidence ?? [];
628772
628945
  const selectedEvidence = [...evidence.slice(0, 2), ...evidence.slice(-4)];
@@ -628800,6 +628973,131 @@ ${boardCards.join("\n")}
628800
628973
  ` : "") + `Continuation rule: when the user asks to continue, resume this active task unless the new prompt names a different target.
628801
628974
  </active-task-anchor>`;
628802
628975
  }
628976
+ function uniqueSessionIds(ids) {
628977
+ const seen = /* @__PURE__ */ new Set();
628978
+ const out = [];
628979
+ for (const raw of ids) {
628980
+ const id2 = String(raw || "").trim();
628981
+ if (!id2 || seen.has(id2)) continue;
628982
+ seen.add(id2);
628983
+ out.push(id2);
628984
+ }
628985
+ return out;
628986
+ }
628987
+ function collectRestoreSessionIds(ctx3, activeTask, historySessionId) {
628988
+ const entries = ctx3?.entries ?? [];
628989
+ const usefulEntries = entries.filter((entry) => !isManualSessionEntry(entry));
628990
+ const chronological = usefulEntries.length > 0 ? usefulEntries : entries;
628991
+ return uniqueSessionIds([
628992
+ activeTask?.ledger.runId,
628993
+ ...[...chronological].reverse().map((entry) => entry.sessionId),
628994
+ ...[...entries].reverse().map((entry) => entry.sessionId),
628995
+ historySessionId
628996
+ ]);
628997
+ }
628998
+ function childMapForTodos(todos) {
628999
+ const byId = new Set(todos.map((todo) => todo.id));
629000
+ const byParent = /* @__PURE__ */ new Map();
629001
+ for (const todo of todos) {
629002
+ if (!todo.parentId || !byId.has(todo.parentId)) continue;
629003
+ const bucket = byParent.get(todo.parentId) ?? [];
629004
+ bucket.push(todo);
629005
+ byParent.set(todo.parentId, bucket);
629006
+ }
629007
+ for (const bucket of byParent.values()) {
629008
+ bucket.sort((a2, b) => a2.createdAt - b.createdAt || a2.id.localeCompare(b.id));
629009
+ }
629010
+ return byParent;
629011
+ }
629012
+ function statusRank2(status) {
629013
+ switch (status) {
629014
+ case "in_progress":
629015
+ return 0;
629016
+ case "blocked":
629017
+ return 1;
629018
+ case "pending":
629019
+ return 2;
629020
+ case "completed":
629021
+ return 3;
629022
+ default:
629023
+ return 4;
629024
+ }
629025
+ }
629026
+ function orderedTodoTree(todos) {
629027
+ const byId = new Set(todos.map((todo) => todo.id));
629028
+ const byParent = childMapForTodos(todos);
629029
+ const roots = todos.filter((todo) => !todo.parentId || !byId.has(todo.parentId)).sort((a2, b) => statusRank2(a2.status) - statusRank2(b.status) || a2.createdAt - b.createdAt || a2.id.localeCompare(b.id));
629030
+ const out = [];
629031
+ const seen = /* @__PURE__ */ new Set();
629032
+ const visit = (todo, depth) => {
629033
+ if (seen.has(todo.id)) return;
629034
+ seen.add(todo.id);
629035
+ out.push({ todo, depth });
629036
+ for (const child of byParent.get(todo.id) ?? []) visit(child, depth + 1);
629037
+ };
629038
+ for (const root of roots) visit(root, 0);
629039
+ for (const todo of todos) visit(todo, 0);
629040
+ return out;
629041
+ }
629042
+ function formatTodoLine(todo, depth) {
629043
+ const indent2 = " ".repeat(Math.min(depth, 6));
629044
+ const blocker = todo.blocker ? ` blocker="${normalizeSessionText(todo.blocker, 120)}"` : "";
629045
+ const verify2 = todo.verifyCommand ? ` verify="${normalizeSessionText(todo.verifyCommand, 120)}"` : "";
629046
+ const artifacts = todo.declaredArtifacts && todo.declaredArtifacts.length > 0 ? ` artifacts=${todo.declaredArtifacts.slice(0, 4).map((item) => normalizeSessionText(item, 80)).join(",")}` : "";
629047
+ return `${indent2}- [${todo.status}] ${normalizeSessionText(todo.content, 180)} (id=${todo.id}${todo.parentId ? ` parent=${todo.parentId}` : ""}${blocker}${verify2}${artifacts})`;
629048
+ }
629049
+ function buildRestoredTodoBlock(sessionId, todos) {
629050
+ const byParent = childMapForTodos(todos);
629051
+ const leafTodos = todos.filter((todo) => (byParent.get(todo.id)?.length ?? 0) === 0);
629052
+ const completedLeaves = leafTodos.filter((todo) => todo.status === "completed").length;
629053
+ const activeTodos = todos.filter((todo) => todo.status === "in_progress" || todo.status === "blocked").sort((a2, b) => statusRank2(a2.status) - statusRank2(b.status) || b.updatedAt - a2.updatedAt).slice(0, 8);
629054
+ const ordered = orderedTodoTree(todos);
629055
+ const visible = ordered.slice(0, 48);
629056
+ const omitted = Math.max(0, ordered.length - visible.length);
629057
+ const activeLines = activeTodos.map((todo) => `- [${todo.status}] ${normalizeSessionText(todo.content, 180)} (id=${todo.id})`);
629058
+ const treeLines = visible.map(({ todo, depth }) => formatTodoLine(todo, depth));
629059
+ return `<restored-todo-state>
629060
+ todo_session_id=${sessionId}
629061
+ total=${todos.length}; leaf_progress=${completedLeaves}/${leafTodos.length || todos.length}
629062
+ ` + (activeLines.length > 0 ? `Active/blocked items:
629063
+ ${activeLines.join("\n")}
629064
+ ` : "") + `Todo tree:
629065
+ ${treeLines.join("\n")}${omitted > 0 ? `
629066
+ - ... ${omitted} more todo(s) in restored session` : ""}
629067
+ Continuation contract: this is the live checklist from the restored run. Continue it and update it with todo_write; do not recreate a parallel plan unless the new user request explicitly changes direction.
629068
+ </restored-todo-state>`;
629069
+ }
629070
+ function findRestoredTodoState(sessionIds) {
629071
+ for (const sessionId of sessionIds) {
629072
+ const todos = readTodos(sessionId).filter((todo) => todo && todo.id && todo.content);
629073
+ if (todos.length === 0) continue;
629074
+ return {
629075
+ sessionId,
629076
+ todos,
629077
+ block: buildRestoredTodoBlock(sessionId, todos)
629078
+ };
629079
+ }
629080
+ return null;
629081
+ }
629082
+ function buildRestoreHistoryAnchor(repoRoot) {
629083
+ const [latest] = listSessions(repoRoot);
629084
+ if (!latest?.id) return null;
629085
+ const lines = loadSessionHistory(repoRoot, latest.id) ?? [];
629086
+ const meaningfulTail = lines.map((line) => cleanSessionHistoryDisplayLine(line)).filter((line) => line && !isNoisySessionHistoryLine(line)).slice(-18).map((line) => `- ${normalizeSessionText(line, 220)}`);
629087
+ const path12 = join136(OMNIUS_DIR, SESSIONS_DIR, `${latest.id}.jsonl`);
629088
+ const block = `<restored-interface-history>
629089
+ latest_visual_session_id=${latest.id}
629090
+ full_transcript_path=${path12}
629091
+ recorded_lines=${lines.length}
629092
+ ` + (meaningfulTail.length > 0 ? `Recent visible transcript tail:
629093
+ ${meaningfulTail.join("\n")}
629094
+ ` : "") + `Recall contract: the full transcript artifact above is restored into the TUI scrollback and is the authoritative previous interface state. Read it only when exact prior UI/tool output is needed; otherwise use this restored state to avoid rediscovery.
629095
+ </restored-interface-history>`;
629096
+ return { sessionId: latest.id, path: path12, lineCount: lines.length, block };
629097
+ }
629098
+ function appendRestoreBlocks(base3, blocks) {
629099
+ return [base3, ...blocks].filter((part) => part && part.trim()).join("\n\n");
629100
+ }
628803
629101
  function formatSessionHistoryDisplay(ctx3) {
628804
629102
  return buildSessionHistoryBoxLines(
628805
629103
  sessionContextToHistoryBoxData(ctx3),
@@ -628825,10 +629123,15 @@ function sessionContextToHistoryBoxData(ctx3, title = "Session History") {
628825
629123
  updatedAt: ctx3?.updatedAt ?? null
628826
629124
  };
628827
629125
  }
628828
- function buildContextRestorePrompt(repoRoot) {
629126
+ function buildContextRestoreSnapshot(repoRoot) {
628829
629127
  const ctx3 = loadSessionContext(repoRoot);
628830
629128
  const handoffPrompt = buildHandoffPrompt(repoRoot);
628831
- const activeTaskAnchor = buildActiveTaskAnchor(repoRoot);
629129
+ const activeTask = selectActiveTaskAnchor(repoRoot);
629130
+ const activeTaskAnchor = activeTask ? formatActiveTaskAnchor(activeTask) : null;
629131
+ const historyAnchor = buildRestoreHistoryAnchor(repoRoot);
629132
+ const restoreSessionIds = collectRestoreSessionIds(ctx3, activeTask, historyAnchor?.sessionId);
629133
+ const restoredTodos = findRestoredTodoState(restoreSessionIds);
629134
+ const sourceSessionId = restoredTodos?.sessionId ?? restoreSessionIds[0];
628832
629135
  if (handoffPrompt) {
628833
629136
  const usefulEntries2 = (ctx3?.entries ?? []).filter((entry) => !isManualSessionEntry(entry));
628834
629137
  const baseCtx = ctx3 && ctx3.entries.length > 0 ? `
@@ -628838,13 +629141,37 @@ Recent tasks: ${(usefulEntries2.length > 0 ? usefulEntries2 : ctx3.entries).slic
628838
629141
  (e2) => `[${e2.completed ? "done" : "partial"}] ${normalizeSessionText(e2.summary || e2.task, 80)}`
628839
629142
  ).join(", ")}
628840
629143
  </session-recap>` : "";
628841
- return handoffPrompt + (activeTaskAnchor ? `
629144
+ const prompt2 = appendRestoreBlocks(
629145
+ handoffPrompt + (activeTaskAnchor ? `
628842
629146
 
628843
- ${activeTaskAnchor}` : "") + baseCtx;
629147
+ ${activeTaskAnchor}` : "") + baseCtx,
629148
+ [restoredTodos?.block, historyAnchor?.block]
629149
+ );
629150
+ return {
629151
+ prompt: prompt2,
629152
+ sourceSessionId,
629153
+ todoSessionId: restoredTodos?.sessionId,
629154
+ todoCount: restoredTodos?.todos.length ?? 0,
629155
+ historySessionId: historyAnchor?.sessionId,
629156
+ historyPath: historyAnchor?.path,
629157
+ historyLineCount: historyAnchor?.lineCount
629158
+ };
629159
+ }
629160
+ if (!ctx3 || ctx3.entries.length === 0) {
629161
+ const prompt2 = appendRestoreBlocks(activeTaskAnchor ?? "", [restoredTodos?.block, historyAnchor?.block]);
629162
+ if (!prompt2.trim()) return null;
629163
+ return {
629164
+ prompt: prompt2,
629165
+ sourceSessionId,
629166
+ todoSessionId: restoredTodos?.sessionId,
629167
+ todoCount: restoredTodos?.todos.length ?? 0,
629168
+ historySessionId: historyAnchor?.sessionId,
629169
+ historyPath: historyAnchor?.path,
629170
+ historyLineCount: historyAnchor?.lineCount
629171
+ };
628844
629172
  }
628845
- if (!ctx3 || ctx3.entries.length === 0) return activeTaskAnchor;
628846
629173
  const usefulEntries = ctx3.entries.filter((entry) => !isManualSessionEntry(entry));
628847
- const recent = (usefulEntries.length > 0 ? usefulEntries : ctx3.entries).slice(-5);
629174
+ const recent = (usefulEntries.length > 0 ? usefulEntries : ctx3.entries).slice(-20);
628848
629175
  const chronology = recent.map((e2) => {
628849
629176
  const status = e2.completed ? "done" : "partial";
628850
629177
  const summary = normalizeSessionText(e2.assistantResponse || e2.summary || e2.task, 140);
@@ -628855,7 +629182,7 @@ ${activeTaskAnchor}` : "") + baseCtx;
628855
629182
  const last2 = recent[recent.length - 1] ?? ctx3.entries[ctx3.entries.length - 1];
628856
629183
  const lastCompleted = [...usefulEntries].reverse().find((entry) => entry.completed);
628857
629184
  const latestCompleted = lastCompleted ? `Latest completed task: ${normalizeSessionText(lastCompleted.assistantResponse || lastCompleted.summary || lastCompleted.task, 180)}` : "";
628858
- const recentDialogue = recent.slice(-3).map((entry) => {
629185
+ const recentDialogue = recent.slice(-8).map((entry) => {
628859
629186
  const assistant = normalizeSessionText(entry.assistantResponse || entry.summary, 320) || "(no assistant reply captured)";
628860
629187
  const user = cleanPromptForDiary(entry.task).slice(0, 220);
628861
629188
  return `User: ${user}
@@ -628865,10 +629192,12 @@ Assistant: ${assistant}`;
628865
629192
  Provenance: ${last2.provenance} (file_read to expand)` : "";
628866
629193
  const kg = `
628867
629194
  KG summary: .omnius/context/kg-summary/latest.md (file_read to expand; legacy pointer: .omnius/context/kg-summary-latest.md)`;
628868
- return `<session-recap>
629195
+ const prompt = appendRestoreBlocks(
629196
+ `<session-recap>
628869
629197
  ` + (activeTaskAnchor ? `${activeTaskAnchor}
628870
629198
 
628871
629199
  ` : "") + `Project chronology (older to newer):
629200
+ Scope: full retained rolling window (${recent.length} entr${recent.length === 1 ? "y" : "ies"}).
628872
629201
  ${chronology.join("\n")}
628873
629202
  ` + (latestCompleted ? `
628874
629203
  ${latestCompleted}
@@ -628877,7 +629206,21 @@ Most recent exchanges (older to newer):
628877
629206
  ${recentDialogue}
628878
629207
  ` + (activeTaskAnchor ? `For continuation prompts, resume the active task anchor above; use chronology only to avoid repeating completed work.${prov}${kg}
628879
629208
  ` : `Continue from the latest exchange and do not repeat completed work.${prov}${kg}
628880
- `) + `</session-recap>`;
629209
+ `) + `</session-recap>`,
629210
+ [restoredTodos?.block, historyAnchor?.block]
629211
+ );
629212
+ return {
629213
+ prompt,
629214
+ sourceSessionId,
629215
+ todoSessionId: restoredTodos?.sessionId,
629216
+ todoCount: restoredTodos?.todos.length ?? 0,
629217
+ historySessionId: historyAnchor?.sessionId,
629218
+ historyPath: historyAnchor?.path,
629219
+ historyLineCount: historyAnchor?.lineCount
629220
+ };
629221
+ }
629222
+ function buildContextRestorePrompt(repoRoot) {
629223
+ return buildContextRestoreSnapshot(repoRoot)?.prompt ?? null;
628881
629224
  }
628882
629225
  function getLastTaskSummary(repoRoot) {
628883
629226
  const ctx3 = loadSessionContext(repoRoot);
@@ -629204,6 +629547,7 @@ var OMNIUS_DIR, LEGACY_DIRS, SUBDIRS, gitignoreWatchers, gitignoreRetryTimers, C
629204
629547
  var init_omnius_directory = __esm({
629205
629548
  "packages/cli/src/tui/omnius-directory.ts"() {
629206
629549
  "use strict";
629550
+ init_dist5();
629207
629551
  init_task_complete_box();
629208
629552
  OMNIUS_DIR = ".omnius";
629209
629553
  LEGACY_DIRS = [".oa", ".open-agents"];
@@ -632134,6 +632478,12 @@ var init_status_bar = __esm({
632134
632478
  }
632135
632479
  return out;
632136
632480
  }
632481
+ /** Capture the main session scrollback for persistence, independent of active tab. */
632482
+ capturePersistedSessionLines(width = 100) {
632483
+ const mainView = this._agentViews.get("main");
632484
+ const lines = mainView?.contentLines ?? this._contentLines;
632485
+ return this.expandDynamicBlockSentinels(lines, width);
632486
+ }
632137
632487
  /**
632138
632488
  * Append a previously-registered dynamic block's sentinel to scrollback
632139
632489
  * and trigger a repaint. The block's renderer fires immediately at the
@@ -633500,6 +633850,40 @@ var init_status_bar = __esm({
633500
633850
  this.fillContentArea();
633501
633851
  this.renderFooterAndPositionInput();
633502
633852
  }
633853
+ /**
633854
+ * Restore persisted scrollback into the main TUI view after process restart.
633855
+ *
633856
+ * Session transcripts are persisted with dynamic blocks already expanded, so
633857
+ * this intentionally restores plain rendered lines rather than stale sentinel
633858
+ * callbacks from a prior process.
633859
+ */
633860
+ restoreMainContentLines(lines) {
633861
+ const mainView = this._agentViews.get("main");
633862
+ const restored = lines.filter((line) => typeof line === "string").slice(-this._contentMaxLines);
633863
+ if (mainView) {
633864
+ mainView.contentLines.splice(0, mainView.contentLines.length, ...restored);
633865
+ mainView.scrollOffset = 0;
633866
+ this._activeViewId = "main";
633867
+ this._contentLines = mainView.contentLines;
633868
+ } else {
633869
+ this._contentLines.splice(0, this._contentLines.length, ...restored);
633870
+ }
633871
+ this._contentScrollOffset = 0;
633872
+ this._pendingTrailingBlanks = 0;
633873
+ this._inProgressLine = "";
633874
+ this.clearStreamingRepaintTimer();
633875
+ this._lastBufferedFingerprint = "";
633876
+ this._lastBufferedAt = 0;
633877
+ this._autoScroll = true;
633878
+ this.markContentMutated();
633879
+ this.clampContentScrollOffset();
633880
+ if (this.active) {
633881
+ this.fillContentArea();
633882
+ this.repaintContent();
633883
+ this.renderFooterAndPositionInput();
633884
+ this.refreshHeaderContent();
633885
+ }
633886
+ }
633503
633887
  /** Set callback for header focus changes (wired by interactive.ts to banner) */
633504
633888
  setHeaderFocusHandler(handler) {
633505
633889
  this._headerFocusHandler = handler;
@@ -659283,11 +659667,12 @@ sleep 1
659283
659667
  const prompt = ctx3.contextRestore?.();
659284
659668
  if (prompt) {
659285
659669
  const info = ctx3.contextShow?.();
659670
+ const snapshot = typeof prompt === "string" ? null : prompt;
659671
+ ctx3.setRestoredContext?.(prompt);
659286
659672
  renderInfo(
659287
- `Context restored from ${info?.entries ?? 0} saved session(s). Will be injected into your next task.`
659673
+ `Context restored from ${info?.entries ?? 0} saved session(s)${snapshot?.historyLineCount ? `; replayed ${snapshot.historyLineCount} transcript line(s)` : ""}${snapshot?.todoCount ? `; restored ${snapshot.todoCount} todo(s)` : ""}. Will be injected into your next task.`
659288
659674
  );
659289
- renderContextHistory(ctx3, "Session History");
659290
- ctx3.setRestoredContext?.(prompt);
659675
+ if (!snapshot?.historyLineCount) renderContextHistory(ctx3, "Session History");
659291
659676
  } else {
659292
659677
  renderWarning(
659293
659678
  "No saved session context found. Complete a task first, or use /context save."
@@ -738589,7 +738974,7 @@ async function runSelfImprovementCycle(repoRoot) {
738589
738974
  } catch {
738590
738975
  }
738591
738976
  }
738592
- function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType, contextWindowSize, modelCaps, personality, deepContext, onCompaction, emotionEngine, flowEnabled, slashCommandHandler, thinkingEnabled, askUserCallback, selfModifyEnabled, sessionMetrics, realtimeEnabled) {
738977
+ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce, statusBar, sudoCallback, costTracker, onComplete, taskType, contextWindowSize, modelCaps, personality, deepContext, onCompaction, emotionEngine, flowEnabled, slashCommandHandler, thinkingEnabled, askUserCallback, selfModifyEnabled, sessionMetrics, realtimeEnabled, restoredRunSessionId) {
738593
738978
  const voiceStyleMap = {
738594
738979
  concise: 1,
738595
738980
  balanced: 3,
@@ -738610,7 +738995,7 @@ function startTask(task, config, repoRoot, voice, stream, taskStores, bruteForce
738610
738995
  if (emotionEngine) emotionEngine.autistMode = true;
738611
738996
  }
738612
738997
  const modelTier2 = getModelTier(config.model);
738613
- const sessionId = `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
738998
+ const sessionId = typeof restoredRunSessionId === "string" && restoredRunSessionId.trim() ? restoredRunSessionId.trim() : `${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
738614
738999
  const taskMetricDescription = cleanForStorage(task).replace(/\s+/g, " ").slice(0, 160) || "task";
738615
739000
  costTracker?.startTask(taskMetricDescription);
738616
739001
  sessionMetrics?.startTask(taskMetricDescription);
@@ -740614,7 +740999,8 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
740614
740999
  toolCalls: result.toolCalls,
740615
741000
  completed: result.completed,
740616
741001
  model: config.model,
740617
- source: "task_complete"
741002
+ source: "task_complete",
741003
+ sessionId
740618
741004
  });
740619
741005
  } catch {
740620
741006
  }
@@ -740651,7 +741037,8 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
740651
741037
  toolCalls: result.toolCalls,
740652
741038
  completed: result.completed,
740653
741039
  model: config.model,
740654
- source: "task_complete"
741040
+ source: "task_complete",
741041
+ sessionId
740655
741042
  },
740656
741043
  accomplishments: extractedAccomplishments.length > 0 ? extractedAccomplishments : [
740657
741044
  `Completed task in ${result.turns} turns with ${result.toolCalls} tool calls`
@@ -740675,11 +741062,7 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
740675
741062
  }
740676
741063
  try {
740677
741064
  const historySessionId = process.env["OMNIUS_SESSION_ID"] || `session-${Date.now().toString(36)}`;
740678
- const rawContentLines = statusBar?._contentLines ?? [];
740679
- const contentLines = typeof statusBar?.expandDynamicBlockSentinels === "function" ? statusBar.expandDynamicBlockSentinels(
740680
- rawContentLines,
740681
- 100
740682
- ) : rawContentLines;
741065
+ const contentLines = typeof statusBar?.capturePersistedSessionLines === "function" ? statusBar.capturePersistedSessionLines(100) : statusBar?._contentLines ?? [];
740683
741066
  if (contentLines.length > 0) {
740684
741067
  const description = cleanPromptForDiary(task).slice(0, 240);
740685
741068
  const historyTitle = description.slice(0, 80) || void 0;
@@ -740920,6 +741303,8 @@ async function startInteractive(config, repoPath2) {
740920
741303
  }
740921
741304
  await bootstrapMcpAndPlugins(repoRoot);
740922
741305
  let restoredSessionContext = null;
741306
+ let restoredTaskSessionId = null;
741307
+ let saveVisualSessionSnapshotRef = null;
740923
741308
  let terminalRestoredForExit = false;
740924
741309
  let interactiveExiting = false;
740925
741310
  let idleMemoryMaintenance = null;
@@ -740948,6 +741333,10 @@ async function startInteractive(config, repoPath2) {
740948
741333
  );
740949
741334
  const cleanupAndExit = (code8) => {
740950
741335
  interactiveExiting = true;
741336
+ try {
741337
+ saveVisualSessionSnapshotRef?.("process exit");
741338
+ } catch {
741339
+ }
740951
741340
  if (_shellToolRef) _shellToolRef.killAll();
740952
741341
  idleMemoryMaintenance?.stop();
740953
741342
  killAllFullSubAgents();
@@ -741464,14 +741853,14 @@ ${result.summary}`
741464
741853
  const { getLastTaskSummary: getLastTaskSummary2 } = (init_omnius_directory(), __toCommonJS(omnius_directory_exports));
741465
741854
  const taskSummary = hasTaskToResume ? getLastTaskSummary2(repoRoot) : null;
741466
741855
  const resumeMsg = taskSummary ? `v${version5} — picking up: ${taskSummary}` : `Updated to v${version5}.`;
741856
+ const restoreSnapshot = buildContextRestoreSnapshot(repoRoot);
741857
+ const replayedVisual = restoreSnapshot ? applyRestoreSnapshot(restoreSnapshot, { replayVisual: true }) : false;
741467
741858
  writeContent(() => {
741468
741859
  renderInfo(resumeMsg);
741469
- const resumePrompt = buildContextRestorePrompt(repoRoot);
741470
- if (resumePrompt) {
741471
- restoredSessionContext = resumePrompt;
741860
+ if (restoreSnapshot) {
741472
741861
  const info = loadSessionContext(repoRoot);
741473
741862
  renderInfo(
741474
- `Context restored from ${info?.entries.length ?? 0} session(s).`
741863
+ `Context restored from ${info?.entries.length ?? 0} session(s)${replayedVisual ? `; replayed ${restoreSnapshot.historyLineCount ?? 0} transcript line(s).` : "."}`
741475
741864
  );
741476
741865
  }
741477
741866
  });
@@ -742455,6 +742844,69 @@ This is an independent background session started from /background.`
742455
742844
  }
742456
742845
  }
742457
742846
  setDreamWriteContent(writeContent);
742847
+ function saveVisualSessionSnapshot(reason) {
742848
+ try {
742849
+ const historySessionId = process.env["OMNIUS_SESSION_ID"] || process.env["OMNIUS_TUI_SESSION_ID"] || `session-${Date.now().toString(36)}`;
742850
+ const contentLines = statusBar.capturePersistedSessionLines(100);
742851
+ if (contentLines.length === 0) return;
742852
+ const description = cleanPromptForDiary(lastSubmittedPrompt || lastCompletedSummary || reason).slice(0, 240) || reason;
742853
+ const historyTitle = description.slice(0, 80) || void 0;
742854
+ saveSessionHistory(repoRoot, historySessionId, contentLines, {
742855
+ name: historyTitle,
742856
+ description,
742857
+ taskCount: 1,
742858
+ model: currentConfig.model
742859
+ });
742860
+ importTranscriptSession({
742861
+ id: `tui:${historySessionId}`,
742862
+ projectRoot: repoRoot,
742863
+ model: currentConfig.model,
742864
+ title: historyTitle,
742865
+ description,
742866
+ transcriptLines: contentLines,
742867
+ updatedAt: Date.now()
742868
+ });
742869
+ } catch {
742870
+ }
742871
+ }
742872
+ saveVisualSessionSnapshotRef = saveVisualSessionSnapshot;
742873
+ function replayRestoredVisualSession(snapshot) {
742874
+ if (!snapshot.historySessionId) return false;
742875
+ const lines = loadSessionHistory(repoRoot, snapshot.historySessionId);
742876
+ if (!lines || lines.length === 0) return false;
742877
+ try {
742878
+ statusBar.restoreMainContentLines(lines);
742879
+ return true;
742880
+ } catch {
742881
+ return false;
742882
+ }
742883
+ }
742884
+ function applyRestoreSnapshot(snapshot, options2 = {}) {
742885
+ if (options2.injectNextTask !== false) {
742886
+ restoredSessionContext = snapshot.prompt;
742887
+ }
742888
+ const restoredId = snapshot.todoSessionId || snapshot.sourceSessionId || null;
742889
+ restoredTaskSessionId = restoredId;
742890
+ if (restoredId) {
742891
+ try {
742892
+ process.env["OMNIUS_SESSION_ID"] = restoredId;
742893
+ } catch {
742894
+ }
742895
+ try {
742896
+ setTodoSessionId(restoredId);
742897
+ } catch {
742898
+ }
742899
+ try {
742900
+ setTuiTasksSession(restoredId);
742901
+ } catch {
742902
+ }
742903
+ try {
742904
+ refreshTuiTasks();
742905
+ } catch {
742906
+ }
742907
+ }
742908
+ return options2.replayVisual ? replayRestoredVisualSession(snapshot) : false;
742909
+ }
742458
742910
  async function writeContentAsync(fn) {
742459
742911
  if (!statusBar.isActive) return fn();
742460
742912
  if (isNeovimActive()) {
@@ -743230,6 +743682,7 @@ Log: ${nexusLogPath}`
743230
743682
  clearInterval(reminderDispatchTimer);
743231
743683
  reminderDispatchTimer = null;
743232
743684
  }
743685
+ saveVisualSessionSnapshot("command exit");
743233
743686
  statusBar.deactivate();
743234
743687
  if (carousel.isRunning) carousel.stop();
743235
743688
  banner.stop();
@@ -745446,7 +745899,8 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
745446
745899
  toolCalls: sessionToolCallCount,
745447
745900
  source: "manual",
745448
745901
  completed: false,
745449
- model: currentConfig.model
745902
+ model: currentConfig.model,
745903
+ sessionId: getTodoSessionId() || process.env["OMNIUS_SESSION_ID"]
745450
745904
  };
745451
745905
  saveSessionContext(repoRoot, entry);
745452
745906
  return true;
@@ -745455,10 +745909,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
745455
745909
  }
745456
745910
  },
745457
745911
  contextRestore() {
745458
- return buildContextRestorePrompt(repoRoot);
745912
+ return buildContextRestoreSnapshot(repoRoot);
745459
745913
  },
745460
745914
  setRestoredContext(ctx3) {
745461
- restoredSessionContext = ctx3;
745915
+ if (typeof ctx3 === "string") {
745916
+ restoredSessionContext = ctx3;
745917
+ } else {
745918
+ applyRestoreSnapshot(ctx3, { replayVisual: true });
745919
+ }
745462
745920
  },
745463
745921
  contextShow() {
745464
745922
  const ctx3 = loadSessionContext(repoRoot);
@@ -745601,28 +746059,30 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
745601
746059
  const auto = countdown <= 0;
745602
746060
  const doRestore = selectResult.confirmed && selectResult.key === "restore";
745603
746061
  if (doRestore) {
745604
- const prompt = buildContextRestorePrompt(repoRoot);
745605
- if (prompt) {
745606
- restoredSessionContext = prompt;
746062
+ const snapshot = buildContextRestoreSnapshot(repoRoot);
746063
+ if (snapshot) {
746064
+ const replayedVisual = applyRestoreSnapshot(snapshot, { replayVisual: true });
745607
746065
  const info = loadSessionContext(repoRoot);
745608
746066
  writeContent(() => {
745609
746067
  renderInfo(
745610
- auto ? `Context auto-restored from ${info?.entries.length ?? 0} session(s).` : `Context restored from ${info?.entries.length ?? 0} session(s).`
746068
+ auto ? `Context auto-restored from ${info?.entries.length ?? 0} session(s)${replayedVisual ? `; replayed ${snapshot.historyLineCount ?? 0} transcript line(s)` : ""}${snapshot.todoCount ? `; restored ${snapshot.todoCount} todo(s)` : ""}.` : `Context restored from ${info?.entries.length ?? 0} session(s)${replayedVisual ? `; replayed ${snapshot.historyLineCount ?? 0} transcript line(s)` : ""}${snapshot.todoCount ? `; restored ${snapshot.todoCount} todo(s)` : ""}.`
745611
746069
  );
745612
- if (statusBar.isActive && !isNeovimActive() && !isOverlayActive()) {
745613
- renderSessionHistoryBox(
745614
- {
745615
- registerDynamicBlock: (id2, render2) => statusBar.registerDynamicBlock(id2, render2),
745616
- appendDynamicBlock: (id2) => statusBar.appendDynamicBlock(id2)
745617
- },
745618
- sessionContextToHistoryBoxData(info, "Session History")
745619
- );
745620
- } else {
745621
- const historyDisplay = formatSessionHistoryDisplay(info);
745622
- process.stdout.write(
745623
- historyDisplay.endsWith("\n") ? historyDisplay : `${historyDisplay}
746070
+ if (!replayedVisual) {
746071
+ if (statusBar.isActive && !isNeovimActive() && !isOverlayActive()) {
746072
+ renderSessionHistoryBox(
746073
+ {
746074
+ registerDynamicBlock: (id2, render2) => statusBar.registerDynamicBlock(id2, render2),
746075
+ appendDynamicBlock: (id2) => statusBar.appendDynamicBlock(id2)
746076
+ },
746077
+ sessionContextToHistoryBoxData(info, "Session History")
746078
+ );
746079
+ } else {
746080
+ const historyDisplay = formatSessionHistoryDisplay(info);
746081
+ process.stdout.write(
746082
+ historyDisplay.endsWith("\n") ? historyDisplay : `${historyDisplay}
745624
746083
  `
745625
- );
746084
+ );
746085
+ }
745626
746086
  }
745627
746087
  });
745628
746088
  } else {
@@ -745682,7 +746142,14 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
745682
746142
  const pendingTask = loadPendingTask(repoRoot);
745683
746143
  if (pendingTask) {
745684
746144
  setTimeout(() => {
745685
- const sessionCtx = buildContextRestorePrompt(repoRoot);
746145
+ const restoreSnapshot = buildContextRestoreSnapshot(repoRoot);
746146
+ if (restoreSnapshot) {
746147
+ applyRestoreSnapshot(restoreSnapshot, {
746148
+ replayVisual: true,
746149
+ injectNextTask: false
746150
+ });
746151
+ }
746152
+ const sessionCtx = restoreSnapshot?.prompt ?? buildContextRestorePrompt(repoRoot);
745686
746153
  const resumeContext = [
745687
746154
  sessionCtx || "",
745688
746155
  `Continuing task after update: ${pendingTask.prompt}`,
@@ -745853,6 +746320,7 @@ ${result.content.slice(0, 2e3)}${result.content.length > 2e3 ? "\n[truncated]" :
745853
746320
  const quitMatch = input.trim().replace(/^\//, "").toLowerCase();
745854
746321
  if (quitMatch === "quit" || quitMatch === "exit" || quitMatch === "q") {
745855
746322
  interactiveExiting = true;
746323
+ saveVisualSessionSnapshot("quit");
745856
746324
  if (activeTask) activeTask.runner.abort();
745857
746325
  idleMemoryMaintenance?.stop();
745858
746326
  taskManager.stopAll();
@@ -745870,6 +746338,7 @@ ${result.content.slice(0, 2e3)}${result.content.length > 2e3 ? "\n[truncated]" :
745870
746338
  );
745871
746339
  if (cmdResult === "exit") {
745872
746340
  interactiveExiting = true;
746341
+ saveVisualSessionSnapshot("command exit");
745873
746342
  if (activeTask) activeTask.runner.abort();
745874
746343
  idleMemoryMaintenance?.stop();
745875
746344
  taskManager.stopAll();
@@ -746434,6 +746903,7 @@ ${formatTaskCompletionMeta(previousMetaForIntake)}`
746434
746903
  } catch {
746435
746904
  }
746436
746905
  let taskInput = fullInput;
746906
+ let taskSessionId = restoredTaskSessionId;
746437
746907
  if (restoredSessionContext) {
746438
746908
  taskInput = `${restoredSessionContext}
746439
746909
 
@@ -746442,6 +746912,7 @@ ${formatTaskCompletionMeta(previousMetaForIntake)}`
746442
746912
  NEW TASK: ${fullInput}`;
746443
746913
  restoredSessionContext = null;
746444
746914
  }
746915
+ restoredTaskSessionId = null;
746445
746916
  if (taskIntakePacket) {
746446
746917
  taskInput = `${taskIntakePacket}
746447
746918
 
@@ -746490,7 +746961,8 @@ ${taskInput}`;
746490
746961
  handleAskUser,
746491
746962
  selfModifyEnabled,
746492
746963
  sessionMetrics,
746493
- realtimeEnabled
746964
+ realtimeEnabled,
746965
+ taskSessionId
746494
746966
  );
746495
746967
  activeTask = task;
746496
746968
  _recallText = null;
@@ -746729,6 +747201,7 @@ Rationale: ${proposal.rationale}${provenanceNote}${dmnDevDiscipline(proposal.cat
746729
747201
  rl.on("close", () => {
746730
747202
  if (interactiveExiting) return;
746731
747203
  interactiveExiting = true;
747204
+ saveVisualSessionSnapshot("readline close");
746732
747205
  if (peerMesh) {
746733
747206
  peerMesh.stop().catch(() => {
746734
747207
  });
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.462",
3
+ "version": "1.0.464",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.462",
9
+ "version": "1.0.464",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
@@ -430,9 +430,9 @@
430
430
  }
431
431
  },
432
432
  "node_modules/@helia/utils/node_modules/cborg": {
433
- "version": "5.1.6",
434
- "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.6.tgz",
435
- "integrity": "sha512-apu/mOSODJ98JXBz3cbiv/gAFX4oaCZQQ53+8b4IPjc1wylYxd8eJis87QP7ic4AOE4O02j02jjfUgVZUJIIvA==",
433
+ "version": "5.1.7",
434
+ "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.7.tgz",
435
+ "integrity": "sha512-rGg2MG9zZEUKtKqjkBppIWUecTXf9N1vs1Qru43vJWoDaODhCrtmzdehCaA/aq/c1cPI5A0kPrJ5Tf+jIfhV4w==",
436
436
  "license": "Apache-2.0",
437
437
  "bin": {
438
438
  "cborg": "lib/bin.js"
@@ -461,9 +461,9 @@
461
461
  }
462
462
  },
463
463
  "node_modules/@ipld/dag-cbor/node_modules/cborg": {
464
- "version": "5.1.6",
465
- "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.6.tgz",
466
- "integrity": "sha512-apu/mOSODJ98JXBz3cbiv/gAFX4oaCZQQ53+8b4IPjc1wylYxd8eJis87QP7ic4AOE4O02j02jjfUgVZUJIIvA==",
464
+ "version": "5.1.7",
465
+ "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.7.tgz",
466
+ "integrity": "sha512-rGg2MG9zZEUKtKqjkBppIWUecTXf9N1vs1Qru43vJWoDaODhCrtmzdehCaA/aq/c1cPI5A0kPrJ5Tf+jIfhV4w==",
467
467
  "license": "Apache-2.0",
468
468
  "bin": {
469
469
  "cborg": "lib/bin.js"
@@ -480,9 +480,9 @@
480
480
  }
481
481
  },
482
482
  "node_modules/@ipld/dag-json/node_modules/cborg": {
483
- "version": "5.1.6",
484
- "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.6.tgz",
485
- "integrity": "sha512-apu/mOSODJ98JXBz3cbiv/gAFX4oaCZQQ53+8b4IPjc1wylYxd8eJis87QP7ic4AOE4O02j02jjfUgVZUJIIvA==",
483
+ "version": "5.1.7",
484
+ "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.7.tgz",
485
+ "integrity": "sha512-rGg2MG9zZEUKtKqjkBppIWUecTXf9N1vs1Qru43vJWoDaODhCrtmzdehCaA/aq/c1cPI5A0kPrJ5Tf+jIfhV4w==",
486
486
  "license": "Apache-2.0",
487
487
  "bin": {
488
488
  "cborg": "lib/bin.js"
@@ -4342,9 +4342,9 @@
4342
4342
  }
4343
4343
  },
4344
4344
  "node_modules/ipns/node_modules/cborg": {
4345
- "version": "5.1.6",
4346
- "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.6.tgz",
4347
- "integrity": "sha512-apu/mOSODJ98JXBz3cbiv/gAFX4oaCZQQ53+8b4IPjc1wylYxd8eJis87QP7ic4AOE4O02j02jjfUgVZUJIIvA==",
4345
+ "version": "5.1.7",
4346
+ "resolved": "https://registry.npmjs.org/cborg/-/cborg-5.1.7.tgz",
4347
+ "integrity": "sha512-rGg2MG9zZEUKtKqjkBppIWUecTXf9N1vs1Qru43vJWoDaODhCrtmzdehCaA/aq/c1cPI5A0kPrJ5Tf+jIfhV4w==",
4348
4348
  "license": "Apache-2.0",
4349
4349
  "bin": {
4350
4350
  "cborg": "lib/bin.js"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.462",
3
+ "version": "1.0.464",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",