omnius 1.0.387 → 1.0.388

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
@@ -25024,7 +25024,7 @@ var init_list_directory = __esm({
25024
25024
  ListDirectoryTool = class {
25025
25025
  name = "list_directory";
25026
25026
  aliases = ["ls", "dir"];
25027
- description = "List files and directories at a given path. Shows file sizes and types. Output includes full relative paths you can use directly in subsequent tool calls.";
25027
+ description = "List files and directories at a given path. Shows file sizes and types. Output includes full relative paths.";
25028
25028
  parameters = {
25029
25029
  type: "object",
25030
25030
  properties: {
@@ -25075,20 +25075,12 @@ var init_list_directory = __esm({
25075
25075
  }
25076
25076
  if (dirs.length > 0 || files.length > 0) {
25077
25077
  lines.push("");
25078
- lines.push("Next steps use these exact paths:");
25078
+ lines.push("Discovered child paths (data only):");
25079
25079
  if (dirs.length > 0) {
25080
- for (const d2 of dirs.slice(0, 8)) {
25081
- lines.push(` list_directory("${d2}")`);
25082
- }
25083
- if (dirs.length > 8)
25084
- lines.push(` ... and ${dirs.length - 8} more directories`);
25080
+ lines.push(` directories: ${dirs.slice(0, 8).join(", ")}${dirs.length > 8 ? ` (+${dirs.length - 8} more)` : ""}`);
25085
25081
  }
25086
25082
  if (files.length > 0) {
25087
- for (const f2 of files.slice(0, 5)) {
25088
- lines.push(` file_read("${f2}")`);
25089
- }
25090
- if (files.length > 5)
25091
- lines.push(` ... and ${files.length - 5} more files`);
25083
+ lines.push(` files: ${files.slice(0, 8).join(", ")}${files.length > 8 ? ` (+${files.length - 8} more)` : ""}`);
25092
25084
  }
25093
25085
  }
25094
25086
  return {
@@ -25126,7 +25118,7 @@ var init_list_directory = __esm({
25126
25118
  const remaining = entries.filter((entry) => !kgSummaries.includes(entry));
25127
25119
  const syntheticLines = [
25128
25120
  `g ${dirPath}/kg-summary-*.md ${kgSummaries.length} generated summaries collapsed, ${totalBytes} bytes`,
25129
- ` latest generated summary: file_read("${latestPath}")`
25121
+ ` latest generated summary path: ${latestPath}`
25130
25122
  ];
25131
25123
  return { entries: remaining, syntheticLines };
25132
25124
  }
@@ -573194,7 +573186,7 @@ var init_agenticRunner = __esm({
573194
573186
  if (this.options.subAgent || this.options.recursionDepth > 0)
573195
573187
  return [];
573196
573188
  const normalizedGoal = goal.replace(/\s+/g, " ").trim();
573197
- if (normalizedGoal.length < 120)
573189
+ if (normalizedGoal.length < 120 && !this._isContinuationResumeGoal(normalizedGoal))
573198
573190
  return [];
573199
573191
  return [
573200
573192
  {
@@ -573258,6 +573250,44 @@ var init_agenticRunner = __esm({
573258
573250
  }
573259
573251
  ];
573260
573252
  }
573253
+ _isContinuationResumeGoal(goal) {
573254
+ const tokens = goal.toLowerCase().replace(/[^a-z0-9]+/g, " ").split(/\s+/).filter(Boolean);
573255
+ if (tokens.length === 0 || tokens.length > 14)
573256
+ return false;
573257
+ const continuationTerms = /* @__PURE__ */ new Set([
573258
+ "again",
573259
+ "and",
573260
+ "back",
573261
+ "carry",
573262
+ "complete",
573263
+ "continue",
573264
+ "finish",
573265
+ "from",
573266
+ "last",
573267
+ "latest",
573268
+ "left",
573269
+ "my",
573270
+ "off",
573271
+ "please",
573272
+ "previous",
573273
+ "prior",
573274
+ "proceed",
573275
+ "request",
573276
+ "resume",
573277
+ "task",
573278
+ "that",
573279
+ "the",
573280
+ "this",
573281
+ "to",
573282
+ "try",
573283
+ "work"
573284
+ ]);
573285
+ const hasResumeVerb = tokens.some((token) => token === "continue" || token === "resume" || token === "proceed" || token === "complete" || token === "finish");
573286
+ if (!hasResumeVerb)
573287
+ return false;
573288
+ const continuationTokenCount = tokens.filter((token) => continuationTerms.has(token)).length;
573289
+ return continuationTokenCount / tokens.length >= 0.7;
573290
+ }
573261
573291
  /**
573262
573292
  * Build a compact workboard context string for injection into the
573263
573293
  * system prompt. Returns null when no active board exists or when
@@ -614782,6 +614812,129 @@ function loadSessionContext(repoRoot) {
614782
614812
  return null;
614783
614813
  }
614784
614814
  }
614815
+ function readJsonOrNull(filePath) {
614816
+ try {
614817
+ if (!existsSync113(filePath)) return null;
614818
+ return JSON.parse(readFileSync90(filePath, "utf-8"));
614819
+ } catch {
614820
+ return null;
614821
+ }
614822
+ }
614823
+ function isManualSessionEntry(entry) {
614824
+ const task = cleanPromptForDiary(entry.task).toLowerCase();
614825
+ const summary = normalizeSessionText(entry.summary || entry.assistantResponse, 160).toLowerCase();
614826
+ return entry.source === "manual" || task === "(manual save)" || entry.toolCalls === 0 && summary.startsWith("manual context save");
614827
+ }
614828
+ function isDeicticContinuationGoal(goal) {
614829
+ const tokens = normalizeSessionText(cleanPromptForDiary(goal), 180).toLowerCase().replace(/[^a-z0-9]+/g, " ").split(/\s+/).filter(Boolean);
614830
+ if (tokens.length === 0 || tokens.length > 14) return false;
614831
+ const hasResumeVerb = tokens.some(
614832
+ (token) => token === "continue" || token === "resume" || token === "proceed" || token === "complete" || token === "finish"
614833
+ );
614834
+ if (!hasResumeVerb) return false;
614835
+ const deicticCount = tokens.filter((token) => DEICTIC_CONTINUATION_TERMS.has(token)).length;
614836
+ return deicticCount / tokens.length >= 0.7;
614837
+ }
614838
+ function readRestoreWorkboard(repoRoot, runId) {
614839
+ if (!runId) return null;
614840
+ return readJsonOrNull(
614841
+ join127(repoRoot, OMNIUS_DIR, "workboards", runId, "active.json")
614842
+ );
614843
+ }
614844
+ function scoreRestoreLedger(ledger, workboard) {
614845
+ const status = ledger.status || "open";
614846
+ if (status === "approved") return -1e3;
614847
+ const evidence = ledger.evidence ?? [];
614848
+ const unresolvedCount = ledger.unresolved?.length ?? 0;
614849
+ const activeCards = (workboard?.cards ?? []).filter(
614850
+ (card) => card.status === "open" || card.status === "in_progress" || card.status === "needs_changes" || card.status === "blocked"
614851
+ ).length;
614852
+ const mutationTools = /* @__PURE__ */ new Set(["file_edit", "file_patch", "batch_edit", "file_write"]);
614853
+ const mutationEvidence = evidence.filter((item) => mutationTools.has(item.toolName || "")).length;
614854
+ const failedMutationEvidence = evidence.filter(
614855
+ (item) => mutationTools.has(item.toolName || "") && item.success === false
614856
+ ).length;
614857
+ const targetPathEvidence = evidence.filter((item) => (item.targetPaths?.length ?? 0) > 0).length;
614858
+ const blockedEvidence = evidence.filter((item) => {
614859
+ const summary = String(item.summary ?? "").toLowerCase();
614860
+ return summary.includes("[focus supervisor block]") || summary.includes("stale") || summary.includes("blocked");
614861
+ }).length;
614862
+ let score = 0;
614863
+ if (status === "open") score += 10;
614864
+ else if (status === "incomplete_verification") score += 18;
614865
+ else if (status === "request_changes" || status === "blocked") score += 16;
614866
+ else score += 4;
614867
+ score += Math.min(evidence.length, 20);
614868
+ score += Math.min(unresolvedCount, 10) * 4;
614869
+ score += Math.min(activeCards, 8) * 3;
614870
+ score += Math.min(mutationEvidence, 8) * 5;
614871
+ score += Math.min(failedMutationEvidence, 8) * 3;
614872
+ score += Math.min(targetPathEvidence, 6) * 2;
614873
+ score += Math.min(blockedEvidence, 6) * 2;
614874
+ const goal = normalizeSessionText(ledger.goal, 260);
614875
+ if (goal.length >= 80) score += 5;
614876
+ if (isDeicticContinuationGoal(goal) && mutationEvidence === 0 && unresolvedCount === 0 && activeCards === 0) {
614877
+ score -= 25;
614878
+ }
614879
+ return score;
614880
+ }
614881
+ function selectActiveTaskAnchor(repoRoot) {
614882
+ const ledgerDir = join127(repoRoot, OMNIUS_DIR, "completion-ledgers");
614883
+ try {
614884
+ if (!existsSync113(ledgerDir)) return null;
614885
+ const candidates = readdirSync39(ledgerDir).filter((name10) => name10.endsWith(".json")).map((name10) => {
614886
+ const filePath = join127(ledgerDir, name10);
614887
+ const ledger = readJsonOrNull(filePath);
614888
+ if (!ledger || !ledger.goal) return null;
614889
+ const runId = ledger.runId || name10.replace(/\.json$/, "");
614890
+ const workboard = readRestoreWorkboard(repoRoot, runId);
614891
+ const score = scoreRestoreLedger(ledger, workboard);
614892
+ const mtimeMs = statSync42(filePath).mtimeMs;
614893
+ return { ledger: { ...ledger, runId }, workboard, score, mtimeMs };
614894
+ }).filter((item) => Boolean(item));
614895
+ candidates.sort((a2, b) => b.score - a2.score || b.mtimeMs - a2.mtimeMs);
614896
+ const selected = candidates.find((candidate) => candidate.score >= 18);
614897
+ return selected ?? null;
614898
+ } catch {
614899
+ return null;
614900
+ }
614901
+ }
614902
+ function buildActiveTaskAnchor(repoRoot) {
614903
+ const selected = selectActiveTaskAnchor(repoRoot);
614904
+ if (!selected) return null;
614905
+ const ledger = selected.ledger;
614906
+ const evidence = ledger.evidence ?? [];
614907
+ const selectedEvidence = [...evidence.slice(0, 2), ...evidence.slice(-4)];
614908
+ const seenEvidence = /* @__PURE__ */ new Set();
614909
+ const evidenceLines = selectedEvidence.flatMap((item) => {
614910
+ const summary = normalizeSessionText(item.summary, 240);
614911
+ if (!summary || seenEvidence.has(summary)) return [];
614912
+ seenEvidence.add(summary);
614913
+ const status = item.success === false ? "failed" : item.success === true ? "ok" : "observed";
614914
+ const tool = item.toolName || "evidence";
614915
+ return [`- ${tool} ${status}: ${summary}`];
614916
+ });
614917
+ const unresolvedLines = (ledger.unresolved ?? []).slice(0, 4).map((item) => `- ${normalizeSessionText(item.text, 180)}`).filter((line) => line !== "- ");
614918
+ const boardCards = (selected.workboard?.cards ?? []).filter((card) => card.status !== "completed" && card.status !== "verified").slice(0, 5).map((card) => {
614919
+ const title = normalizeSessionText(card.title || card.id, 120);
614920
+ const status = card.status || "open";
614921
+ const lane = card.lane ? `/${card.lane}` : "";
614922
+ const evidenceCount = Array.isArray(card.evidence) ? card.evidence.length : 0;
614923
+ return `- ${title} (${status}${lane}, evidence=${evidenceCount})`;
614924
+ });
614925
+ return `<active-task-anchor>
614926
+ Source: completion ledger ${ledger.runId || "(unknown run)"}; status=${ledger.status || "open"}
614927
+ Goal: ${normalizeSessionText(ledger.goal, 420)}
614928
+ Recorded evidence: ${evidence.length}; unresolved items: ${ledger.unresolved?.length ?? 0}
614929
+ ` + (evidenceLines.length > 0 ? `Material evidence:
614930
+ ${evidenceLines.join("\n")}
614931
+ ` : "") + (unresolvedLines.length > 0 ? `Unresolved:
614932
+ ${unresolvedLines.join("\n")}
614933
+ ` : "") + (boardCards.length > 0 ? `Active workboard cards:
614934
+ ${boardCards.join("\n")}
614935
+ ` : "") + `Continuation rule: when the user asks to continue, resume this active task unless the new prompt names a different target.
614936
+ </active-task-anchor>`;
614937
+ }
614785
614938
  function formatSessionHistoryDisplay(ctx3) {
614786
614939
  return buildSessionHistoryBoxLines(
614787
614940
  sessionContextToHistoryBoxData(ctx3),
@@ -614810,18 +614963,23 @@ function sessionContextToHistoryBoxData(ctx3, title = "Session History") {
614810
614963
  function buildContextRestorePrompt(repoRoot) {
614811
614964
  const ctx3 = loadSessionContext(repoRoot);
614812
614965
  const handoffPrompt = buildHandoffPrompt(repoRoot);
614966
+ const activeTaskAnchor = buildActiveTaskAnchor(repoRoot);
614813
614967
  if (handoffPrompt) {
614968
+ const usefulEntries2 = (ctx3?.entries ?? []).filter((entry) => !isManualSessionEntry(entry));
614814
614969
  const baseCtx = ctx3 && ctx3.entries.length > 0 ? `
614815
614970
 
614816
614971
  <session-recap>
614817
- Recent tasks: ${ctx3.entries.slice(-3).map(
614972
+ Recent tasks: ${(usefulEntries2.length > 0 ? usefulEntries2 : ctx3.entries).slice(-3).map(
614818
614973
  (e2) => `[${e2.completed ? "done" : "partial"}] ${normalizeSessionText(e2.summary || e2.task, 80)}`
614819
614974
  ).join(", ")}
614820
614975
  </session-recap>` : "";
614821
- return handoffPrompt + baseCtx;
614976
+ return handoffPrompt + (activeTaskAnchor ? `
614977
+
614978
+ ${activeTaskAnchor}` : "") + baseCtx;
614822
614979
  }
614823
- if (!ctx3 || ctx3.entries.length === 0) return null;
614824
- const recent = ctx3.entries.slice(-5);
614980
+ if (!ctx3 || ctx3.entries.length === 0) return activeTaskAnchor;
614981
+ const usefulEntries = ctx3.entries.filter((entry) => !isManualSessionEntry(entry));
614982
+ const recent = (usefulEntries.length > 0 ? usefulEntries : ctx3.entries).slice(-5);
614825
614983
  const chronology = recent.map((e2) => {
614826
614984
  const status = e2.completed ? "done" : "partial";
614827
614985
  const summary = normalizeSessionText(e2.assistantResponse || e2.summary || e2.task, 140);
@@ -614829,8 +614987,8 @@ Recent tasks: ${ctx3.entries.slice(-3).map(
614829
614987
  const files = e2.filesModified && e2.filesModified.length > 0 ? ` | files: ${e2.filesModified.slice(0, 3).join(", ")}` : "";
614830
614988
  return `[${status}] ${summary}${tools}${files}`;
614831
614989
  });
614832
- const last2 = ctx3.entries[ctx3.entries.length - 1];
614833
- const lastCompleted = [...ctx3.entries].reverse().find((entry) => entry.completed);
614990
+ const last2 = recent[recent.length - 1] ?? ctx3.entries[ctx3.entries.length - 1];
614991
+ const lastCompleted = [...usefulEntries].reverse().find((entry) => entry.completed);
614834
614992
  const latestCompleted = lastCompleted ? `Latest completed task: ${normalizeSessionText(lastCompleted.assistantResponse || lastCompleted.summary || lastCompleted.task, 180)}` : "";
614835
614993
  const recentDialogue = recent.slice(-3).map((entry) => {
614836
614994
  const assistant = normalizeSessionText(entry.assistantResponse || entry.summary, 320) || "(no assistant reply captured)";
@@ -614843,15 +615001,18 @@ Provenance: ${last2.provenance} (file_read to expand)` : "";
614843
615001
  const kg = `
614844
615002
  KG summary: .omnius/context/kg-summary/latest.md (file_read to expand; legacy pointer: .omnius/context/kg-summary-latest.md)`;
614845
615003
  return `<session-recap>
614846
- Project chronology (older to newer):
615004
+ ` + (activeTaskAnchor ? `${activeTaskAnchor}
615005
+
615006
+ ` : "") + `Project chronology (older to newer):
614847
615007
  ${chronology.join("\n")}
614848
615008
  ` + (latestCompleted ? `
614849
615009
  ${latestCompleted}
614850
615010
  ` : "\n") + `
614851
615011
  Most recent exchanges (older to newer):
614852
615012
  ${recentDialogue}
614853
- Continue from the latest exchange and do not repeat completed work.${prov}${kg}
614854
- </session-recap>`;
615013
+ ` + (activeTaskAnchor ? `For continuation prompts, resume the active task anchor above; use chronology only to avoid repeating completed work.${prov}${kg}
615014
+ ` : `Continue from the latest exchange and do not repeat completed work.${prov}${kg}
615015
+ `) + `</session-recap>`;
614855
615016
  }
614856
615017
  function getLastTaskSummary(repoRoot) {
614857
615018
  const ctx3 = loadSessionContext(repoRoot);
@@ -615174,7 +615335,7 @@ function deleteUsageRecord(kind, value2, repoRoot) {
615174
615335
  remove(join127(repoRoot, OMNIUS_DIR, USAGE_HISTORY_FILE));
615175
615336
  }
615176
615337
  }
615177
- var OMNIUS_DIR, LEGACY_DIRS, SUBDIRS, gitignoreWatchers, gitignoreRetryTimers, CONTEXT_FILES, PENDING_TASK_FILE, HANDOFF_FILE, CONTEXT_SAVE_FILE, CONTEXT_LEDGER_FILE, MAX_CONTEXT_ENTRIES, MAX_SESSION_DIARY_ENTRIES, MAX_SESSION_DIARY_DETAILED_ENTRIES, MAX_CONTEXT_LEDGER_LINES, MAX_CONTEXT_LEDGER_BYTES, SAME_TASK_REPLACE_WINDOW_MS, LOCK_TIMEOUT_MS, LOCK_RETRY_MS, LOCK_RETRY_MAX, SESSIONS_DIR, SESSIONS_INDEX, SKIP_DIRS3, HOME_SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
615338
+ var OMNIUS_DIR, LEGACY_DIRS, SUBDIRS, gitignoreWatchers, gitignoreRetryTimers, CONTEXT_FILES, PENDING_TASK_FILE, HANDOFF_FILE, CONTEXT_SAVE_FILE, CONTEXT_LEDGER_FILE, MAX_CONTEXT_ENTRIES, MAX_SESSION_DIARY_ENTRIES, MAX_SESSION_DIARY_DETAILED_ENTRIES, MAX_CONTEXT_LEDGER_LINES, MAX_CONTEXT_LEDGER_BYTES, SAME_TASK_REPLACE_WINDOW_MS, LOCK_TIMEOUT_MS, LOCK_RETRY_MS, LOCK_RETRY_MAX, DEICTIC_CONTINUATION_TERMS, SESSIONS_DIR, SESSIONS_INDEX, SKIP_DIRS3, HOME_SKIP_DIRS, USAGE_HISTORY_FILE, MAX_HISTORY_RECORDS;
615178
615339
  var init_omnius_directory = __esm({
615179
615340
  "packages/cli/src/tui/omnius-directory.ts"() {
615180
615341
  "use strict";
@@ -615207,6 +615368,34 @@ var init_omnius_directory = __esm({
615207
615368
  LOCK_TIMEOUT_MS = 5e3;
615208
615369
  LOCK_RETRY_MS = 50;
615209
615370
  LOCK_RETRY_MAX = 100;
615371
+ DEICTIC_CONTINUATION_TERMS = /* @__PURE__ */ new Set([
615372
+ "again",
615373
+ "and",
615374
+ "back",
615375
+ "carry",
615376
+ "complete",
615377
+ "continue",
615378
+ "finish",
615379
+ "from",
615380
+ "last",
615381
+ "latest",
615382
+ "left",
615383
+ "my",
615384
+ "off",
615385
+ "please",
615386
+ "previous",
615387
+ "prior",
615388
+ "proceed",
615389
+ "request",
615390
+ "resume",
615391
+ "task",
615392
+ "that",
615393
+ "the",
615394
+ "this",
615395
+ "to",
615396
+ "try",
615397
+ "work"
615398
+ ]);
615210
615399
  SESSIONS_DIR = "sessions";
615211
615400
  SESSIONS_INDEX = "sessions-index.json";
615212
615401
  SKIP_DIRS3 = /* @__PURE__ */ new Set([
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.387",
3
+ "version": "1.0.388",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.387",
9
+ "version": "1.0.388",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.387",
3
+ "version": "1.0.388",
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",