omnius 1.0.339 → 1.0.341

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
@@ -560736,7 +560736,7 @@ var init_critic = __esm({
560736
560736
  function extractSubject(errorText) {
560737
560737
  if (!errorText)
560738
560738
  return null;
560739
- const PATTERNS = [
560739
+ const PATTERNS2 = [
560740
560740
  // Quoted module / type / symbol after recognizable phrases
560741
560741
  /cannot find (?:module|name|type|symbol|reference|file|namespace)\s+['"`]([^'"`\n]{1,80})['"`]/i,
560742
560742
  /(?:undefined|unresolved)\s+(?:reference|import|symbol)\s+(?:to\s+)?['"`]([^'"`\n]{1,80})['"`]/i,
@@ -560751,7 +560751,7 @@ function extractSubject(errorText) {
560751
560751
  /\bcannot resolve\s+['"`]?([^'"`\n\s]{1,120})['"`]?/i,
560752
560752
  /\bmodule not found:?\s+['"`]?([^'"`\n\s]{1,120})['"`]?/i
560753
560753
  ];
560754
- for (const re of PATTERNS) {
560754
+ for (const re of PATTERNS2) {
560755
560755
  const m2 = errorText.match(re);
560756
560756
  if (m2 && m2[1]) {
560757
560757
  const subj = m2[1].trim();
@@ -565070,6 +565070,79 @@ var init_consolidation_runtime = __esm({
565070
565070
  }
565071
565071
  });
565072
565072
 
565073
+ // packages/orchestrator/dist/completion-evidence-gate.js
565074
+ function classifyCompletionClaim(text2) {
565075
+ const t2 = String(text2 || "");
565076
+ for (const p2 of PATTERNS) {
565077
+ if (p2.re.test(t2)) {
565078
+ return { category: p2.category, requiresIndependentEvidence: true, requiredCheck: p2.check };
565079
+ }
565080
+ }
565081
+ return { category: null, requiresIndependentEvidence: false, requiredCheck: "" };
565082
+ }
565083
+ function detectExitCodeMisread(text2) {
565084
+ const t2 = String(text2 || "");
565085
+ const nonzeroExit = /\bexit(?:ed|s)?\b[^.\n]{0,20}?\b(?:code\s*)?(?:[1-9]\d*|non-?zero)\b/i;
565086
+ const successWord = /\b(success(?:ful|fully|ed)?|succeeded|done|passed|works?|working|fine|ok|complete[d]?)\b/i;
565087
+ if (nonzeroExit.test(t2) && successWord.test(t2))
565088
+ return true;
565089
+ if (/\|\|\s*true\b|\bset \+e\b|2>\/dev\/null\s*;\s*(echo|exit 0)/i.test(t2))
565090
+ return true;
565091
+ return false;
565092
+ }
565093
+ function auditCompletionClaims(claims) {
565094
+ const blockers = [];
565095
+ for (const c8 of claims || []) {
565096
+ const cls = classifyCompletionClaim(c8.text);
565097
+ if (!cls.requiresIndependentEvidence || !cls.category)
565098
+ continue;
565099
+ if (c8.status !== "supported") {
565100
+ blockers.push({ claim: String(c8.text || "").slice(0, 160), category: cls.category, requiredCheck: cls.requiredCheck });
565101
+ }
565102
+ }
565103
+ return { ok: blockers.length === 0, blockers };
565104
+ }
565105
+ function completionEvidenceDirective() {
565106
+ return [
565107
+ "[Evidence-gated completion — do not pretend success]",
565108
+ "Before you claim a task is done, optimize for 'is the end state actually correct?', NOT 'did I make the change?'. Each of these claim types REQUIRES an independent check from a DIFFERENT command than the one that made the change:",
565109
+ "- A process is 'running/started/up' → re-probe liveness after a short delay (ps/pgrep, a health endpoint, or the listening port). A PID file or a launcher log is NOT proof it stayed alive — 'started' ≠ 'running'.",
565110
+ "- Something is 'installed/available' → verify with `command -v`/`--version`/a package query, NOT the installer's own log.",
565111
+ "- A bug is 'fixed' → re-run the ORIGINAL failing command/test and watch it pass, not just confirm the edit landed.",
565112
+ "- A success in simulation/mock/dry-run mode → label it as SIMULATED; never present it as the real capability.",
565113
+ "Exit codes: a non-zero exit is NOT success; a zero exit from a wrapper / `|| true` / `set +e` is NOT proof the underlying thing worked — inspect what actually happened.",
565114
+ "If you cannot produce the independent evidence, say so plainly and mark the item unverified or partial — never report a success state you have not verified."
565115
+ ].join("\n");
565116
+ }
565117
+ var PATTERNS;
565118
+ var init_completion_evidence_gate = __esm({
565119
+ "packages/orchestrator/dist/completion-evidence-gate.js"() {
565120
+ "use strict";
565121
+ PATTERNS = [
565122
+ {
565123
+ category: "process_liveness",
565124
+ re: /\b(running|started|launched|spun up|brought up|is up|listening|serving|alive|daemon (is|now)|service (is|now)|server (is|now)|booted|online)\b/i,
565125
+ check: "Independently probe liveness AFTER a short delay: ps/pgrep for the actual process, a health endpoint, or `ss -ltnp` for the port — NOT the launcher log or a PID file (a PID file can exist while the process is dead)."
565126
+ },
565127
+ {
565128
+ category: "installation",
565129
+ re: /\b(installed|available in PATH|on the PATH|set up|provisioned|configured and ready|now available|dependency (is )?(present|installed))\b/i,
565130
+ check: "Independently confirm presence: `command -v <bin>` / `<bin> --version` / package manager query (e.g. `apt-cache policy`, `pip show`) — NOT the installer's own success log."
565131
+ },
565132
+ {
565133
+ category: "fix_confirmation",
565134
+ re: /\b(fixed|resolved|corrected|patched|repaired|no longer (fails|errors|crashes)|works now|issue (is )?gone)\b/i,
565135
+ check: "Re-run the ORIGINAL failing command/test and observe it now passes — an independent reproduction, not just confirming the edit was written."
565136
+ },
565137
+ {
565138
+ category: "reality",
565139
+ re: /\b(simulat\w+|mock\w*|stub\w*|fake|dry[- ]?run|--sim|placeholder mode|fallback mode)\b/i,
565140
+ check: "This was a SIMULATED/mock run. Label it explicitly as simulated and do NOT present it as the real capability; verify against the real system before claiming the real success."
565141
+ }
565142
+ ];
565143
+ }
565144
+ });
565145
+
565073
565146
  // packages/orchestrator/dist/tool-batching.js
565074
565147
  function isConcurrencySafe(toolName, readOnlyHints) {
565075
565148
  if (CONCURRENT_SAFE_TOOLS.has(toolName))
@@ -568620,6 +568693,7 @@ var init_agenticRunner = __esm({
568620
568693
  init_dist5();
568621
568694
  init_exploration_fanout();
568622
568695
  init_consolidation_runtime();
568696
+ init_completion_evidence_gate();
568623
568697
  init_tool_batching();
568624
568698
  init_hooks2();
568625
568699
  init_todo_context_chunker();
@@ -570710,6 +570784,18 @@ ${input.answerText ?? ""}`.toLowerCase().trim();
570710
570784
  this._completionLedger = reconcileClaimsWithEvidence(this._completionLedger);
570711
570785
  this._saveCompletionLedgerSafe();
570712
570786
  }
570787
+ try {
570788
+ const _audit = auditCompletionClaims(this._completionLedger.proposedClaims.map((c8) => ({ text: c8.text, status: c8.status })));
570789
+ if (!_audit.ok) {
570790
+ const _checks = _audit.blockers.map((b) => `• [${b.category}] "${b.claim}" → ${b.requiredCheck}`).join("\n");
570791
+ this._completionCaveat = [
570792
+ this._completionCaveat || "",
570793
+ `[UNVERIFIED SUCCESS — run these independent checks before claiming done]
570794
+ ${_checks}`
570795
+ ].filter(Boolean).join("\n\n");
570796
+ }
570797
+ } catch {
570798
+ }
570713
570799
  }
570714
570800
  const optOverride = this.options.backwardPassReview;
570715
570801
  const raw = (process.env["OMNIUS_BACKWARD_PASS"] || "on").toLowerCase();
@@ -573943,6 +574029,12 @@ Respond with your assessment, then take action.`;
573943
574029
  }
573944
574030
  const contextComposition = await this.assembleContext(task, context2);
573945
574031
  let systemPrompt = contextComposition.assembled;
574032
+ try {
574033
+ systemPrompt = `${systemPrompt}
574034
+
574035
+ ${completionEvidenceDirective()}`;
574036
+ } catch {
574037
+ }
573946
574038
  try {
573947
574039
  const _cap = getMediaCapability();
573948
574040
  const _tier = this.options.modelTier ?? "large";
@@ -590380,6 +590472,7 @@ __export(dist_exports3, {
590380
590472
  appendSteeringLedgerEntry: () => appendSteeringLedgerEntry,
590381
590473
  appendSteeringOutcome: () => appendSteeringOutcome,
590382
590474
  arcSummary: () => arcSummary,
590475
+ auditCompletionClaims: () => auditCompletionClaims,
590383
590476
  buildAgentNotification: () => buildAgentNotification,
590384
590477
  buildAgentTypeSummary: () => buildAgentTypeSummary,
590385
590478
  buildCompletionScenarioDecomposition: () => buildCompletionScenarioDecomposition,
@@ -590400,6 +590493,7 @@ __export(dist_exports3, {
590400
590493
  chooseCheapModelRoute: () => chooseCheapModelRoute,
590401
590494
  claimAssertion: () => claimAssertion,
590402
590495
  classifyBreadth: () => classifyBreadth,
590496
+ classifyCompletionClaim: () => classifyCompletionClaim,
590403
590497
  classifyHandoff: () => classifyHandoff,
590404
590498
  classifyOllamaProcesses: () => classifyOllamaProcesses,
590405
590499
  cleanForStorage: () => cleanForStorage,
@@ -590408,6 +590502,7 @@ __export(dist_exports3, {
590408
590502
  clearTurnState: () => clearTurnState,
590409
590503
  combineValidatorResults: () => combineValidatorResults,
590410
590504
  compilePersonalityPrompt: () => compilePersonalityPrompt,
590505
+ completionEvidenceDirective: () => completionEvidenceDirective,
590411
590506
  compressFindings: () => compressFindings,
590412
590507
  computeArc: () => computeArc,
590413
590508
  computeStabilityHash: () => computeStabilityHash,
@@ -590425,6 +590520,7 @@ __export(dist_exports3, {
590425
590520
  decomposeSpec: () => decomposeSpec,
590426
590521
  deleteAgentTaskSidecar: () => deleteAgentTaskSidecar,
590427
590522
  deriveClaimsFromProposedText: () => deriveClaimsFromProposedText,
590523
+ detectExitCodeMisread: () => detectExitCodeMisread,
590428
590524
  detectExplorationIntent: () => detectExplorationIntent,
590429
590525
  detectPressure: () => detectPressure,
590430
590526
  detectTaskType: () => detectTaskType,
@@ -590638,6 +590734,7 @@ var init_dist8 = __esm({
590638
590734
  init_memory_consolidation();
590639
590735
  init_exploration_fanout();
590640
590736
  init_consolidation_runtime();
590737
+ init_completion_evidence_gate();
590641
590738
  }
590642
590739
  });
590643
590740
 
@@ -689463,6 +689560,41 @@ window.__omniusStores = {
689463
689560
 
689464
689561
  const conv = document.getElementById('conversation');
689465
689562
  const input = document.getElementById('input-area');
689563
+ // SUGGESTED FOLLOW-UP — ghost text (placeholder-grey) shown after a reply
689564
+ // completes; Tab accepts it as real text, typing dismisses it.
689565
+ const DEFAULT_INPUT_PLACEHOLDER = 'Type a message...';
689566
+ let chatFollowup = null;
689567
+ function setFollowupSuggestion(text) {
689568
+ text = (text || '').trim();
689569
+ if (!text || streaming) return;
689570
+ if (input.value.trim().length > 0) return; // don't clobber what the user is typing
689571
+ chatFollowup = text;
689572
+ input.placeholder = text + ' (Tab \\u21E5)';
689573
+ }
689574
+ function clearFollowupSuggestion() {
689575
+ if (chatFollowup !== null) { chatFollowup = null; input.placeholder = DEFAULT_INPUT_PLACEHOLDER; }
689576
+ }
689577
+ function acceptFollowupSuggestion() {
689578
+ if (chatFollowup === null || input.value.trim().length > 0) return false;
689579
+ const t = chatFollowup;
689580
+ clearFollowupSuggestion();
689581
+ input.value = t;
689582
+ try { input.dispatchEvent(new Event('input')); } catch (e) {}
689583
+ input.focus();
689584
+ try { input.setSelectionRange(t.length, t.length); } catch (e) {}
689585
+ return true;
689586
+ }
689587
+ async function fetchFollowupSuggestion() {
689588
+ try {
689589
+ if (!chatSessionId || input.value.trim().length > 0) return;
689590
+ const r = await fetch('/v1/chat/suggest-followup', {
689591
+ method: 'POST', headers: headers(), body: JSON.stringify({ session_id: chatSessionId }),
689592
+ });
689593
+ if (!r.ok) return;
689594
+ const d = await r.json();
689595
+ if (d && d.suggestion) setFollowupSuggestion(d.suggestion);
689596
+ } catch (e) { /* best-effort */ }
689597
+ }
689466
689598
  const sendBtn = document.getElementById('send-btn');
689467
689599
  const modelSelect = document.getElementById('model-select');
689468
689600
  // Persist the selected model on every change so a browser refresh /
@@ -689567,6 +689699,8 @@ if (conv) {
689567
689699
 
689568
689700
  // Auto-resize textarea + WO-CHAT-CHECKIN typing detection
689569
689701
  input.addEventListener('input', () => {
689702
+ // Dismiss the suggested follow-up the moment the user starts typing.
689703
+ if (input.value.length > 0) clearFollowupSuggestion();
689570
689704
  input.style.height = 'auto';
689571
689705
  // OWUI-4: bump max from 120 (~6 lines) to 240 (~12 lines).
689572
689706
  input.style.height = Math.min(input.scrollHeight, 240) + 'px';
@@ -689597,6 +689731,10 @@ input.addEventListener('keydown', (e) => {
689597
689731
  if (e.key === 'Tab') { e.preventDefault(); _slashPaletteAccept(); return; }
689598
689732
  if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); _slashPaletteAccept(); return; }
689599
689733
  }
689734
+ // Suggested follow-up: Tab accepts the ghost text as real input.
689735
+ if (e.key === 'Tab' && !e.shiftKey && chatFollowup !== null && input.value.trim().length === 0) {
689736
+ if (acceptFollowupSuggestion()) { e.preventDefault(); return; }
689737
+ }
689600
689738
  // OWUI-4: Cmd/Ctrl+Enter — always sends, never inserts a newline.
689601
689739
  if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
689602
689740
  e.preventDefault();
@@ -690309,6 +690447,7 @@ async function runSlashCommandInline(rawInput) {
690309
690447
  async function sendMessage() {
690310
690448
  const text = input.value.trim();
690311
690449
  if (!text || streaming) return;
690450
+ clearFollowupSuggestion(); // a real send supersedes any ghost suggestion
690312
690451
 
690313
690452
  // ─── Slash command passthrough ────────────────────────────────────────
690314
690453
  // /foo args → POST /v1/command, render result inline as a system
@@ -690686,6 +690825,8 @@ async function sendMessage() {
690686
690825
  chatAbortController = null;
690687
690826
  document.getElementById('send-btn').style.display = 'inline-block';
690688
690827
  document.getElementById('stop-btn').style.display = 'none';
690828
+ // Reply finished — offer a suggested follow-up as ghost text in the input.
690829
+ try { fetchFollowupSuggestion(); } catch (e) {}
690689
690830
  // OWUI-3: belt-and-braces — make sure the indicator is gone if we
690690
690831
  // reach this finally{} via an error path before the success branch
690691
690832
  // had a chance to call hideStreamingIndicator.
@@ -697329,6 +697470,7 @@ function getOpenApiSpec() {
697329
697470
  },
697330
697471
  "/v1/chat/sessions": { get: { summary: "List active chat sessions", tags: ["Chat"], responses: { 200: { description: "Session list" } } } },
697331
697472
  "/v1/chat/sessions/{id}/summarize": { post: { summary: "Generate + cache an inference-based title/summary for a session — body {force?, root?}", tags: ["Chat"], responses: { 200: { description: "Title + summary" }, 500: { description: "Generation failed" } } } },
697473
+ "/v1/chat/suggest-followup": { post: { summary: "Suggest one short next-message follow-up for a session (ghost-text input) — body {session_id}", tags: ["Chat"], responses: { 200: { description: "{ suggestion }" } } } },
697332
697474
  "/v1/chat/sessions/{id}/status": { get: { summary: "Reactive recall: is this session running right now + unseen deltas since ?since=<seq> (running, phase, seq, partial, deltas[])", tags: ["Chat"], responses: { 200: { description: "Live run status + catch-up deltas" } } } },
697333
697475
  // ───── AIWG cascade ─────
697334
697476
  "/v1/aiwg": { get: { summary: "AIWG installation root + control map", tags: ["AIWG"], responses: { 200: { description: "AIWG installation summary" } } } },
@@ -698184,6 +698326,62 @@ var init_chat_run_registry = __esm({
698184
698326
  }
698185
698327
  });
698186
698328
 
698329
+ // packages/cli/src/api/chat-followup.ts
698330
+ function normalizeBaseUrl2(url) {
698331
+ let u = (url || "").trim().replace(/\/+$/, "");
698332
+ if (u.endsWith("/v1")) u = u.slice(0, -3);
698333
+ return u;
698334
+ }
698335
+ function cleanSuggestion(raw) {
698336
+ let s2 = (raw || "").trim();
698337
+ s2 = s2.split("\n")[0].trim();
698338
+ s2 = s2.replace(/^["'`*\-\d.\s]+/, "").replace(/["'`]+$/, "").trim();
698339
+ if (/^(none|n\/?a|no follow|nothing)\b/i.test(s2)) return "";
698340
+ return s2.length > 140 ? s2.slice(0, 139).trimEnd() + "…" : s2;
698341
+ }
698342
+ async function suggestFollowup(args) {
698343
+ const turns = (args.turns || []).filter((t2) => t2 && t2.content && (t2.role === "user" || t2.role === "assistant"));
698344
+ if (!turns.length || !args.config.model || !args.config.backendUrl) return "";
698345
+ const transcript = turns.slice(-6).map((t2) => `${t2.role === "user" ? "User" : "Assistant"}: ${String(t2.content).slice(0, 800)}`).join("\n");
698346
+ try {
698347
+ const url = normalizeBaseUrl2(args.config.backendUrl) + "/v1/chat/completions";
698348
+ const headers = { "Content-Type": "application/json" };
698349
+ if (args.config.apiKey) headers["Authorization"] = `Bearer ${args.config.apiKey}`;
698350
+ const body = {
698351
+ model: args.config.model,
698352
+ messages: [
698353
+ {
698354
+ role: "system",
698355
+ content: "You suggest the single most likely NEXT message the user would send to continue this conversation. Write it in the user's voice (imperative, first person), as if they typed it. Reply with ONLY that one short prompt — no quotes, no preamble, no markdown, max ~12 words. If no natural follow-up exists, reply with exactly: NONE."
698356
+ },
698357
+ { role: "user", content: `Conversation so far:
698358
+ ${transcript}
698359
+
698360
+ The user's likely next message:` }
698361
+ ],
698362
+ temperature: 0.4,
698363
+ max_tokens: 40,
698364
+ stream: false
698365
+ };
698366
+ const resp = await fetch(url, {
698367
+ method: "POST",
698368
+ headers,
698369
+ body: JSON.stringify(body),
698370
+ signal: AbortSignal.timeout(args.timeoutMs ?? 12e3)
698371
+ });
698372
+ if (!resp.ok) return "";
698373
+ const data = await resp.json();
698374
+ return cleanSuggestion(data?.choices?.[0]?.message?.content ?? "");
698375
+ } catch {
698376
+ return "";
698377
+ }
698378
+ }
698379
+ var init_chat_followup = __esm({
698380
+ "packages/cli/src/api/chat-followup.ts"() {
698381
+ "use strict";
698382
+ }
698383
+ });
698384
+
698187
698385
  // packages/cli/src/docker.ts
698188
698386
  import { execSync as execSync59, spawn as spawn32 } from "node:child_process";
698189
698387
  import { existsSync as existsSync158, mkdirSync as mkdirSync99, writeFileSync as writeFileSync84 } from "node:fs";
@@ -706426,6 +706624,24 @@ ${historyLines}
706426
706624
  });
706427
706625
  return;
706428
706626
  }
706627
+ if (pathname === "/v1/chat/suggest-followup" && method === "POST") {
706628
+ if (!checkAuth(req3, res, "read")) return;
706629
+ const fbBody = await parseJsonBody(req3);
706630
+ const sid = fbBody?.session_id ? String(fbBody.session_id) : "";
706631
+ const session = sid ? lookupSession(sid) : null;
706632
+ const turns = session ? session.messages.filter((m2) => m2 && (m2.role === "user" || m2.role === "assistant") && typeof m2.content === "string").map((m2) => ({ role: m2.role, content: m2.content })) : [];
706633
+ if (turns.length === 0) {
706634
+ jsonResponse(res, 200, { suggestion: "" });
706635
+ return;
706636
+ }
706637
+ const cfg = loadConfig();
706638
+ const suggestion = await suggestFollowup({
706639
+ turns,
706640
+ config: { backendUrl: cfg.backendUrl, model: cfg.model, apiKey: cfg.apiKey }
706641
+ });
706642
+ jsonResponse(res, 200, { suggestion });
706643
+ return;
706644
+ }
706429
706645
  const chatSessionMatch = pathname.match(/^\/v1\/chat\/sessions\/([^/]+)$/);
706430
706646
  if (chatSessionMatch) {
706431
706647
  const sid = decodeURIComponent(chatSessionMatch[1]);
@@ -709080,6 +709296,7 @@ var init_serve = __esm({
709080
709296
  init_omnius_directory();
709081
709297
  init_session_summary();
709082
709298
  init_chat_run_registry();
709299
+ init_chat_followup();
709083
709300
  init_omnius_directory();
709084
709301
  init_command_registry();
709085
709302
  init_profiles();
@@ -52,6 +52,7 @@ pnpm docs:check
52
52
  | `GET` | `/api/tags` | Ollama-compatible model tags |
53
53
  | `GET` | `/v1/chat/sessions` | Active chat sessions |
54
54
  | `POST` | `/v1/chat/sessions/{id}/summarize` | Generate + cache an inference-based session title/summary |
55
+ | `POST` | `/v1/chat/suggest-followup` | Suggest one short next-message follow-up (ghost-text input) |
55
56
  | `GET` | `/v1/chat/sessions/{id}/status` | Reactive recall: live run status + unseen deltas (`?since=<seq>`) |
56
57
  | `POST` | `/v1/chat/check-in` | Steering check-in for active chat |
57
58
 
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.339",
3
+ "version": "1.0.341",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.339",
9
+ "version": "1.0.341",
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.339",
3
+ "version": "1.0.341",
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",