omnius 1.0.444 → 1.0.446
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 +417 -73
- package/dist/scripts/live-whisper.py +83 -10
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -298591,13 +298591,29 @@ Mark tasks complete IMMEDIATELY after finishing — don't batch. Never mark comp
|
|
|
298591
298591
|
durationMs: performance.now() - start2
|
|
298592
298592
|
};
|
|
298593
298593
|
}
|
|
298594
|
+
const inProgressIndexes = incoming.map((todo, index) => todo.status === "in_progress" ? index : -1).filter((index) => index >= 0);
|
|
298595
|
+
if (inProgressIndexes.length === 0) {
|
|
298596
|
+
const firstPending = incoming.findIndex((todo) => todo.status === "pending");
|
|
298597
|
+
if (firstPending >= 0) {
|
|
298598
|
+
incoming[firstPending] = { ...incoming[firstPending], status: "in_progress" };
|
|
298599
|
+
repairNotes.push("promoted first pending todo to in_progress because a non-empty active checklist must name the current task");
|
|
298600
|
+
}
|
|
298601
|
+
} else if (inProgressIndexes.length > 1) {
|
|
298602
|
+
const keep = inProgressIndexes[0];
|
|
298603
|
+
for (const index of inProgressIndexes.slice(1)) {
|
|
298604
|
+
incoming[index] = { ...incoming[index], status: "pending" };
|
|
298605
|
+
}
|
|
298606
|
+
repairNotes.push(`kept todo ${keep + 1} in_progress and demoted extra in_progress todos to pending`);
|
|
298607
|
+
}
|
|
298594
298608
|
const sessionId = typeof args["session_id"] === "string" && args["session_id"].trim() ? args["session_id"].trim() : typeof args["sessionId"] === "string" && args["sessionId"].trim() ? args["sessionId"].trim() : getTodoSessionId();
|
|
298595
298609
|
const oldTodos = readTodos(sessionId);
|
|
298596
298610
|
const canonicalize2 = (todos) => JSON.stringify(todos.map((t2) => ({
|
|
298597
298611
|
content: t2.content,
|
|
298598
298612
|
status: t2.status,
|
|
298599
298613
|
parentId: t2.parentId ?? null,
|
|
298600
|
-
blocker: t2.blocker ?? null
|
|
298614
|
+
blocker: t2.blocker ?? null,
|
|
298615
|
+
verifyCommand: t2.verifyCommand ?? null,
|
|
298616
|
+
declaredArtifacts: Array.isArray(t2.declaredArtifacts) ? [...t2.declaredArtifacts].sort() : null
|
|
298601
298617
|
})));
|
|
298602
298618
|
const oldKey = canonicalize2(oldTodos);
|
|
298603
298619
|
const newKey = canonicalize2(incoming);
|
|
@@ -298607,8 +298623,10 @@ Mark tasks complete IMMEDIATELY after finishing — don't batch. Never mark comp
|
|
|
298607
298623
|
output: JSON.stringify({
|
|
298608
298624
|
reminder: "[NO-OP] You called todo_write with the same plan you already have. The list is unchanged. Use todo_write ONLY to add new tasks, mark a task in_progress / completed, or record a blocker — not as a way to re-read your plan (use todo_read for that, but the current plan is also surfaced automatically in your context). Proceed with the current in_progress task.",
|
|
298609
298625
|
todos: oldTodos,
|
|
298610
|
-
noop: true
|
|
298626
|
+
noop: true,
|
|
298627
|
+
noProgress: true
|
|
298611
298628
|
}),
|
|
298629
|
+
noop: true,
|
|
298612
298630
|
durationMs: performance.now() - start2
|
|
298613
298631
|
};
|
|
298614
298632
|
}
|
|
@@ -572729,6 +572747,7 @@ var init_context_fabric = __esm({
|
|
|
572729
572747
|
"use strict";
|
|
572730
572748
|
PRIORITY = {
|
|
572731
572749
|
GOAL: 100,
|
|
572750
|
+
ACTION_CONTRACT: 98,
|
|
572732
572751
|
USER_STEERING: 95,
|
|
572733
572752
|
TASK_STATE: 80,
|
|
572734
572753
|
KNOWN_FILES: 70,
|
|
@@ -572746,6 +572765,7 @@ var init_context_fabric = __esm({
|
|
|
572746
572765
|
KIND_ORDER = [
|
|
572747
572766
|
"goal",
|
|
572748
572767
|
"user_steering",
|
|
572768
|
+
"action_contract",
|
|
572749
572769
|
"task_state",
|
|
572750
572770
|
"known_files",
|
|
572751
572771
|
"recent_failure",
|
|
@@ -572762,6 +572782,7 @@ var init_context_fabric = __esm({
|
|
|
572762
572782
|
KIND_LABELS = {
|
|
572763
572783
|
goal: "Goal",
|
|
572764
572784
|
user_steering: "User Steering",
|
|
572785
|
+
action_contract: "Next Action Contract",
|
|
572765
572786
|
task_state: "Task State",
|
|
572766
572787
|
known_files: "Known Files",
|
|
572767
572788
|
recent_failure: "Recent Failures",
|
|
@@ -572778,6 +572799,7 @@ var init_context_fabric = __esm({
|
|
|
572778
572799
|
DEFAULT_KIND_CHAR_BUDGET = {
|
|
572779
572800
|
goal: 900,
|
|
572780
572801
|
user_steering: 1400,
|
|
572802
|
+
action_contract: 1800,
|
|
572781
572803
|
task_state: 1800,
|
|
572782
572804
|
known_files: 2400,
|
|
572783
572805
|
recent_failure: 2600,
|
|
@@ -574715,6 +574737,11 @@ var init_focusSupervisor = __esm({
|
|
|
574715
574737
|
return;
|
|
574716
574738
|
}
|
|
574717
574739
|
if (input.toolName === "todo_write" && input.success) {
|
|
574740
|
+
if (input.noop) {
|
|
574741
|
+
this.lastDecision = "todo_noop_not_satisfied";
|
|
574742
|
+
this.lastReason = "todo_write returned no-op; checklist state did not change";
|
|
574743
|
+
return;
|
|
574744
|
+
}
|
|
574718
574745
|
this.clearSatisfiedDirective("todo plan updated", input.turn);
|
|
574719
574746
|
return;
|
|
574720
574747
|
}
|
|
@@ -578304,23 +578331,248 @@ ${parts.join("\n")}
|
|
|
578304
578331
|
}
|
|
578305
578332
|
return null;
|
|
578306
578333
|
}
|
|
578334
|
+
_currentWorkboardSnapshotForFrame() {
|
|
578335
|
+
const dir = this._workboardDir();
|
|
578336
|
+
const fromDisk = readActiveWorkboardSnapshot(dir, this._sessionId);
|
|
578337
|
+
if (fromDisk) {
|
|
578338
|
+
this._workboard = fromDisk;
|
|
578339
|
+
return fromDisk;
|
|
578340
|
+
}
|
|
578341
|
+
if (this._workboard)
|
|
578342
|
+
return this._workboard;
|
|
578343
|
+
const goal = this._taskState.originalGoal || this._taskState.goal || "";
|
|
578344
|
+
if (this._initialWorkboardCardsForGoal(goal).length === 0)
|
|
578345
|
+
return null;
|
|
578346
|
+
return this.getOrCreateWorkboard();
|
|
578347
|
+
}
|
|
578348
|
+
_workboardEvidenceCount(card) {
|
|
578349
|
+
return card?.evidence?.length ?? 0;
|
|
578350
|
+
}
|
|
578351
|
+
_workboardHasEditEvidence(card) {
|
|
578352
|
+
if (!card)
|
|
578353
|
+
return false;
|
|
578354
|
+
const editTools = /* @__PURE__ */ new Set(["file_write", "file_edit", "batch_edit", "file_patch"]);
|
|
578355
|
+
return card.evidence.some((e2) => {
|
|
578356
|
+
if (typeof e2.tool === "string" && editTools.has(e2.tool))
|
|
578357
|
+
return true;
|
|
578358
|
+
return e2.tool === "shell" && /filesystem mutation/i.test(e2.summary ?? "");
|
|
578359
|
+
});
|
|
578360
|
+
}
|
|
578361
|
+
_workboardHasVerificationEvidence(card) {
|
|
578362
|
+
if (!card)
|
|
578363
|
+
return false;
|
|
578364
|
+
return card.evidence.some((e2) => e2.tool === "shell" || e2.tool === "background_run");
|
|
578365
|
+
}
|
|
578366
|
+
_deriveWorkboardActionContract(snapshot) {
|
|
578367
|
+
if (snapshot.cards.length === 0)
|
|
578368
|
+
return null;
|
|
578369
|
+
const byId = new Map(snapshot.cards.map((card) => [card.id, card]));
|
|
578370
|
+
const discovery = byId.get("discover-current-state");
|
|
578371
|
+
const implementation2 = byId.get("implement-repair");
|
|
578372
|
+
const integration = byId.get("integrate-and-run");
|
|
578373
|
+
const verification = byId.get("verify-observed-outcome");
|
|
578374
|
+
const discoveryEvidence = this._workboardEvidenceCount(discovery);
|
|
578375
|
+
const hasImplementationEvidence = this._workboardHasEditEvidence(implementation2);
|
|
578376
|
+
const hasVerificationEvidence = this._workboardHasVerificationEvidence(integration);
|
|
578377
|
+
if (hasImplementationEvidence && !hasVerificationEvidence && integration) {
|
|
578378
|
+
return {
|
|
578379
|
+
cardId: integration.id,
|
|
578380
|
+
title: integration.title,
|
|
578381
|
+
reason: "implementation evidence exists; exercise the changed runtime path before more discovery",
|
|
578382
|
+
preferredTools: ["shell"]
|
|
578383
|
+
};
|
|
578384
|
+
}
|
|
578385
|
+
if (hasVerificationEvidence && verification) {
|
|
578386
|
+
return {
|
|
578387
|
+
cardId: verification.id,
|
|
578388
|
+
title: verification.title,
|
|
578389
|
+
reason: "verification evidence exists; reconcile outcome, todos, and blockers",
|
|
578390
|
+
preferredTools: ["todo_write", "task_complete"]
|
|
578391
|
+
};
|
|
578392
|
+
}
|
|
578393
|
+
if (discoveryEvidence > 0 && !hasImplementationEvidence && implementation2) {
|
|
578394
|
+
return {
|
|
578395
|
+
cardId: implementation2.id,
|
|
578396
|
+
title: implementation2.title,
|
|
578397
|
+
reason: "discovery evidence is already present; land the smallest concrete repair",
|
|
578398
|
+
preferredTools: ["file_write", "file_edit", "batch_edit", "file_patch"]
|
|
578399
|
+
};
|
|
578400
|
+
}
|
|
578401
|
+
const active = snapshot.cards.find((card) => card.status === "in_progress") ?? snapshot.cards.find((card) => card.status === "needs_changes") ?? snapshot.cards.find((card) => card.status === "open") ?? discovery;
|
|
578402
|
+
if (!active)
|
|
578403
|
+
return null;
|
|
578404
|
+
return {
|
|
578405
|
+
cardId: active.id,
|
|
578406
|
+
title: active.title,
|
|
578407
|
+
reason: active.id === "discover-current-state" ? "no authoritative target evidence is recorded yet" : "workboard card is the next unresolved card",
|
|
578408
|
+
preferredTools: active.id === "discover-current-state" ? ["file_read", "grep_search", "list_directory", "shell"] : ["file_write", "file_edit", "batch_edit", "file_patch", "shell"]
|
|
578409
|
+
};
|
|
578410
|
+
}
|
|
578411
|
+
_focusToolsForRequiredAction(action) {
|
|
578412
|
+
switch (action) {
|
|
578413
|
+
case "update_todos":
|
|
578414
|
+
return "todo_write with a changed plan/status, or a real file edit if that is the active work";
|
|
578415
|
+
case "read_authoritative_target":
|
|
578416
|
+
case "use_cached_evidence":
|
|
578417
|
+
return "use cached evidence or one authoritative file_read/read-only shell, then act";
|
|
578418
|
+
case "edit_different_target":
|
|
578419
|
+
return "file_write, file_edit, batch_edit, or file_patch on a different supported target";
|
|
578420
|
+
case "run_verification":
|
|
578421
|
+
return "shell running the verification/runtime command";
|
|
578422
|
+
case "report_blocked":
|
|
578423
|
+
case "report_incomplete":
|
|
578424
|
+
return "task_complete with the concrete blocker/incomplete evidence";
|
|
578425
|
+
default:
|
|
578426
|
+
return "choose the narrowest tool that advances the current card";
|
|
578427
|
+
}
|
|
578428
|
+
}
|
|
578429
|
+
_renderNextActionContract(turn) {
|
|
578430
|
+
const lines = ["[NEXT ACTION CONTRACT]", `turn=${turn}`];
|
|
578431
|
+
const focus = this._focusSupervisor?.snapshot().directive ?? null;
|
|
578432
|
+
if (focus) {
|
|
578433
|
+
lines.push(`focus_required_next_action=${focus.requiredNextAction}`);
|
|
578434
|
+
lines.push(`focus_valid_tools=${this._focusToolsForRequiredAction(focus.requiredNextAction)}`);
|
|
578435
|
+
lines.push(`focus_reason=${focus.reason}`);
|
|
578436
|
+
}
|
|
578437
|
+
const snapshot = this._currentWorkboardSnapshotForFrame();
|
|
578438
|
+
const action = snapshot ? this._deriveWorkboardActionContract(snapshot) : null;
|
|
578439
|
+
if (snapshot && action) {
|
|
578440
|
+
const byId = new Map(snapshot.cards.map((card) => [card.id, card]));
|
|
578441
|
+
const discovery = byId.get("discover-current-state");
|
|
578442
|
+
const implementation2 = byId.get("implement-repair");
|
|
578443
|
+
const integration = byId.get("integrate-and-run");
|
|
578444
|
+
const verification = byId.get("verify-observed-outcome");
|
|
578445
|
+
lines.push(`workboard_current_card=${action.cardId} (${action.title})`);
|
|
578446
|
+
lines.push(`workboard_preferred_tools=${action.preferredTools.join(", ")}`);
|
|
578447
|
+
lines.push(`workboard_reason=${action.reason}`);
|
|
578448
|
+
lines.push(`workboard_evidence_counts=discover:${this._workboardEvidenceCount(discovery)} implement:${this._workboardEvidenceCount(implementation2)} integrate:${this._workboardEvidenceCount(integration)} verify:${this._workboardEvidenceCount(verification)}`);
|
|
578449
|
+
if (this._workboardHasEditEvidence(implementation2)) {
|
|
578450
|
+
lines.push("implementation_state=mutation evidence is already recorded; do not treat discovery as the active phase");
|
|
578451
|
+
}
|
|
578452
|
+
}
|
|
578453
|
+
const todos = this.readSessionTodos() ?? [];
|
|
578454
|
+
if (todos.length > 0) {
|
|
578455
|
+
const inProgress = todos.filter((todo) => todo.status === "in_progress");
|
|
578456
|
+
const pending2 = todos.filter((todo) => todo.status === "pending");
|
|
578457
|
+
const blocked = todos.filter((todo) => todo.status === "blocked");
|
|
578458
|
+
lines.push(`todo_counts=in_progress:${inProgress.length} pending:${pending2.length} blocked:${blocked.length}`);
|
|
578459
|
+
if (inProgress[0]) {
|
|
578460
|
+
lines.push(`todo_current=${inProgress[0].content.slice(0, 180)}`);
|
|
578461
|
+
} else if (pending2.length > 0) {
|
|
578462
|
+
lines.push("todo_contract=mark exactly one pending todo in_progress before using the checklist as progress");
|
|
578463
|
+
}
|
|
578464
|
+
}
|
|
578465
|
+
if (lines.length === 2)
|
|
578466
|
+
return null;
|
|
578467
|
+
lines.push("not_progress=repeat unchanged todo_write; repeat broad discovery already represented in this frame; keep discovery active after a real mutation");
|
|
578468
|
+
return lines.join("\n");
|
|
578469
|
+
}
|
|
578470
|
+
_workboardTargetCardId(snapshot, toolName, result, meta = {}) {
|
|
578471
|
+
const byId = new Map(snapshot.cards.map((card) => [card.id, card]));
|
|
578472
|
+
if (this._isProjectEditTool(toolName) && this._isRealProjectMutation(toolName, result)) {
|
|
578473
|
+
return byId.has("implement-repair") ? "implement-repair" : null;
|
|
578474
|
+
}
|
|
578475
|
+
if (toolName === "shell" && meta.shellFilesystemMutation === true) {
|
|
578476
|
+
return byId.has("implement-repair") ? "implement-repair" : null;
|
|
578477
|
+
}
|
|
578478
|
+
if (toolName === "shell" || toolName === "background_run") {
|
|
578479
|
+
const implementation2 = byId.get("implement-repair");
|
|
578480
|
+
const target = this._workboardHasEditEvidence(implementation2) ? "integrate-and-run" : "discover-current-state";
|
|
578481
|
+
return byId.has(target) ? target : null;
|
|
578482
|
+
}
|
|
578483
|
+
if (toolName === "file_read" || toolName === "file_explore" || toolName === "list_directory" || toolName === "grep_search" || toolName === "find_files" || toolName === "web_search") {
|
|
578484
|
+
return byId.has("discover-current-state") ? "discover-current-state" : null;
|
|
578485
|
+
}
|
|
578486
|
+
const active = snapshot.cards.find((card) => card.status === "in_progress");
|
|
578487
|
+
return active?.id ?? null;
|
|
578488
|
+
}
|
|
578489
|
+
_refreshWorkboardSnapshot(snapshot) {
|
|
578490
|
+
const refreshed = readActiveWorkboardSnapshot(this._workboardDir(), this._sessionId) ?? snapshot;
|
|
578491
|
+
this._workboard = refreshed;
|
|
578492
|
+
return refreshed;
|
|
578493
|
+
}
|
|
578494
|
+
_advanceWorkboardForTool(snapshot, toolName, result, actor, meta = {}) {
|
|
578495
|
+
const dir = this._workboardDir();
|
|
578496
|
+
let current = snapshot;
|
|
578497
|
+
const byId = () => new Map(current.cards.map((card) => [card.id, card]));
|
|
578498
|
+
const editMutation = this._isProjectEditTool(toolName) && this._isRealProjectMutation(toolName, result) || toolName === "shell" && result?.success === true && meta.shellFilesystemMutation === true;
|
|
578499
|
+
try {
|
|
578500
|
+
if (editMutation) {
|
|
578501
|
+
let cards = byId();
|
|
578502
|
+
const discovery = cards.get("discover-current-state");
|
|
578503
|
+
if (discovery && discovery.status !== "verified" && discovery.evidence.length > 0) {
|
|
578504
|
+
const completed = completeWorkboardCard(dir, {
|
|
578505
|
+
runId: this._sessionId,
|
|
578506
|
+
cardId: discovery.id,
|
|
578507
|
+
actor,
|
|
578508
|
+
outcome: "completed",
|
|
578509
|
+
reason: "Implementation started after authoritative discovery evidence was recorded."
|
|
578510
|
+
});
|
|
578511
|
+
current = completed.snapshot;
|
|
578512
|
+
cards = byId();
|
|
578513
|
+
const completedDiscovery = cards.get("discover-current-state");
|
|
578514
|
+
if (completedDiscovery?.status === "completed") {
|
|
578515
|
+
const verified = completeWorkboardCard(dir, {
|
|
578516
|
+
runId: this._sessionId,
|
|
578517
|
+
cardId: completedDiscovery.id,
|
|
578518
|
+
actor,
|
|
578519
|
+
outcome: "verified",
|
|
578520
|
+
reason: "Discovery evidence was sufficient to select and mutate the implementation target."
|
|
578521
|
+
});
|
|
578522
|
+
current = verified.snapshot;
|
|
578523
|
+
cards = byId();
|
|
578524
|
+
}
|
|
578525
|
+
}
|
|
578526
|
+
const implementation2 = cards.get("implement-repair");
|
|
578527
|
+
if (implementation2 && (implementation2.status === "open" || implementation2.status === "needs_changes")) {
|
|
578528
|
+
current = updateWorkboardCard(dir, {
|
|
578529
|
+
runId: this._sessionId,
|
|
578530
|
+
cardId: implementation2.id,
|
|
578531
|
+
actor,
|
|
578532
|
+
updates: { status: "in_progress", lane: "worker" },
|
|
578533
|
+
decisionReason: "Real project mutation landed; implementation is now the active phase."
|
|
578534
|
+
});
|
|
578535
|
+
}
|
|
578536
|
+
}
|
|
578537
|
+
if (toolName === "shell" || toolName === "background_run") {
|
|
578538
|
+
const cards = byId();
|
|
578539
|
+
const implementation2 = cards.get("implement-repair");
|
|
578540
|
+
const integration = cards.get("integrate-and-run");
|
|
578541
|
+
if (integration && this._workboardHasEditEvidence(implementation2) && (integration.status === "open" || integration.status === "needs_changes")) {
|
|
578542
|
+
current = updateWorkboardCard(dir, {
|
|
578543
|
+
runId: this._sessionId,
|
|
578544
|
+
cardId: integration.id,
|
|
578545
|
+
actor,
|
|
578546
|
+
updates: { status: "in_progress", lane: "verification" },
|
|
578547
|
+
decisionReason: "Runtime or verification command ran after implementation evidence."
|
|
578548
|
+
});
|
|
578549
|
+
}
|
|
578550
|
+
}
|
|
578551
|
+
} catch {
|
|
578552
|
+
}
|
|
578553
|
+
return this._refreshWorkboardSnapshot(current);
|
|
578554
|
+
}
|
|
578307
578555
|
/**
|
|
578308
578556
|
* Record evidence from a tool call against the active workboard.
|
|
578309
578557
|
* Matches by card assignee when the card is in progress.
|
|
578310
578558
|
* Non-fatal: failures to attach evidence are silently caught.
|
|
578311
578559
|
*/
|
|
578312
|
-
recordWorkboardToolCall(toolName, args, success, output, result) {
|
|
578560
|
+
recordWorkboardToolCall(toolName, args, success, output, result, meta = {}) {
|
|
578313
578561
|
const board = this._workboard ?? this.getOrCreateWorkboard();
|
|
578314
578562
|
if (!board)
|
|
578315
578563
|
return;
|
|
578316
578564
|
if (toolName === "task_complete" || toolName === "workboard_create")
|
|
578317
578565
|
return;
|
|
578566
|
+
if (meta.repeatShortCircuit || result?.runtimeAuthored)
|
|
578567
|
+
return;
|
|
578568
|
+
if (meta.focusDecisionKind === "block_tool_call")
|
|
578569
|
+
return;
|
|
578318
578570
|
if (result?.success === true && this._isProjectEditTool(toolName) && !this._isRealProjectMutation(toolName, result)) {
|
|
578319
578571
|
return;
|
|
578320
578572
|
}
|
|
578321
578573
|
const dir = this._workboardDir();
|
|
578322
578574
|
try {
|
|
578323
|
-
const evidenceSummary = `${toolName} ${success ? "ok" : "fail"}`;
|
|
578575
|
+
const evidenceSummary = toolName === "shell" && meta.shellFilesystemMutation ? `shell filesystem mutation ${success ? "ok" : "fail"}` : `${toolName} ${success ? "ok" : "fail"}`;
|
|
578324
578576
|
const rawEvidenceOutput = typeof output === "string" && output.length > 0 ? output : result?.output || result?.error || "";
|
|
578325
578577
|
const evidenceContent = rawEvidenceOutput.slice(0, 1e3);
|
|
578326
578578
|
const evidence = {
|
|
@@ -578332,24 +578584,23 @@ ${parts.join("\n")}
|
|
|
578332
578584
|
ref: typeof args["path"] === "string" ? args["path"]?.slice(0, 200) : void 0
|
|
578333
578585
|
};
|
|
578334
578586
|
const actor = this.options.subAgent ? "sub-agent" : "agent";
|
|
578335
|
-
|
|
578336
|
-
|
|
578337
|
-
|
|
578338
|
-
|
|
578339
|
-
|
|
578340
|
-
|
|
578341
|
-
|
|
578342
|
-
|
|
578343
|
-
|
|
578344
|
-
if (toolName === "file_read" && !card.evidenceRequirements.some((r2) => r2.toLowerCase().includes("read") || r2.toLowerCase().includes("explor") || r2.toLowerCase().includes("understand")))
|
|
578345
|
-
continue;
|
|
578346
|
-
attachWorkboardEvidence(dir, {
|
|
578347
|
-
runId: this._sessionId,
|
|
578348
|
-
cardId: card.id,
|
|
578349
|
-
actor,
|
|
578350
|
-
evidence
|
|
578351
|
-
});
|
|
578587
|
+
const advanced = this._advanceWorkboardForTool(board, toolName, result, actor, meta);
|
|
578588
|
+
const targetCardId = this._workboardTargetCardId(advanced, toolName, result, meta);
|
|
578589
|
+
if (!targetCardId)
|
|
578590
|
+
return;
|
|
578591
|
+
const targetCard = advanced.cards.find((card) => card.id === targetCardId);
|
|
578592
|
+
if (!targetCard)
|
|
578593
|
+
return;
|
|
578594
|
+
if (targetCard.assignee && targetCard.assignee !== actor && targetCard.assignee !== "any") {
|
|
578595
|
+
return;
|
|
578352
578596
|
}
|
|
578597
|
+
attachWorkboardEvidence(dir, {
|
|
578598
|
+
runId: this._sessionId,
|
|
578599
|
+
cardId: targetCard.id,
|
|
578600
|
+
actor,
|
|
578601
|
+
evidence
|
|
578602
|
+
});
|
|
578603
|
+
this._refreshWorkboardSnapshot(advanced);
|
|
578353
578604
|
} catch {
|
|
578354
578605
|
}
|
|
578355
578606
|
}
|
|
@@ -579814,6 +580065,21 @@ Pick the SMALLEST concrete deliverable from the spec — typically the project e
|
|
|
579814
580065
|
return false;
|
|
579815
580066
|
return true;
|
|
579816
580067
|
}
|
|
580068
|
+
_isTodoWriteNoopResult(result) {
|
|
580069
|
+
if (!result)
|
|
580070
|
+
return false;
|
|
580071
|
+
if (result.noop === true)
|
|
580072
|
+
return true;
|
|
580073
|
+
const text2 = String(result.output ?? result.llmContent ?? "");
|
|
580074
|
+
if (!text2 || !/"noop"\s*:\s*true/.test(text2))
|
|
580075
|
+
return false;
|
|
580076
|
+
try {
|
|
580077
|
+
const parsed = JSON.parse(text2);
|
|
580078
|
+
return parsed?.noop === true;
|
|
580079
|
+
} catch {
|
|
580080
|
+
return true;
|
|
580081
|
+
}
|
|
580082
|
+
}
|
|
579817
580083
|
_toolEvidencePreview(result, displayOutput, max = 500, toolName) {
|
|
579818
580084
|
const modelVisible = result.llmContent ?? result.output ?? displayOutput ?? "";
|
|
579819
580085
|
const failurePrefix = result.success === false && result.error ? `Error: ${result.error}` : "";
|
|
@@ -582535,6 +582801,7 @@ ${chunk.content}`, {
|
|
|
582535
582801
|
const failureBlock = this._renderRecentFailuresBlock(turn);
|
|
582536
582802
|
const churnBlock = this._renderWriteChurnBlock(turn);
|
|
582537
582803
|
const focusBlock = this._focusSupervisor?.renderFrame() ?? null;
|
|
582804
|
+
const actionContractBlock = this._renderNextActionContract(turn);
|
|
582538
582805
|
const toolCacheBlock = recentToolResults ? this._renderKnowledgeBlock(recentToolResults) : null;
|
|
582539
582806
|
const anchorsBlock = this.surfaceAnchors(messages2);
|
|
582540
582807
|
const pprMemoryBlock = this._lastPprMemoryLines.length > 0 ? `[Associative Memory - related prior experience]
|
|
@@ -582572,6 +582839,13 @@ ${this._lastPprMemoryLines.slice(0, 5).join("\n")}` : null;
|
|
|
582572
582839
|
createdTurn: turn,
|
|
582573
582840
|
ttlTurns: 1
|
|
582574
582841
|
}),
|
|
582842
|
+
signalFromBlock("action_contract", "turn.next-action-contract", actionContractBlock, {
|
|
582843
|
+
id: "next-action-contract",
|
|
582844
|
+
dedupeKey: "turn.next-action-contract",
|
|
582845
|
+
priority: PRIORITY.ACTION_CONTRACT,
|
|
582846
|
+
createdTurn: turn,
|
|
582847
|
+
ttlTurns: 1
|
|
582848
|
+
}),
|
|
582575
582849
|
signalFromBlock("task_state", "turn.todos", todoBlock, {
|
|
582576
582850
|
id: "todo-state",
|
|
582577
582851
|
dedupeKey: "turn.todos",
|
|
@@ -587486,7 +587760,9 @@ Read the current file if needed, make a different concrete edit, or move to veri
|
|
|
587486
587760
|
success: true,
|
|
587487
587761
|
output: `[STOP RE-READING — you have requested this exact read ${criticDecision.hitNumber}× and you ALREADY HAVE its full content, shown again below. Do NOT read it again. Act on it: edit the file, run a verification, or call task_complete. If a previous edit failed with "old_string not found", your old_string did not match the file — copy it EXACTLY (including indentation) from the content below.]
|
|
587488
587762
|
|
|
587489
|
-
` + cachedResult
|
|
587763
|
+
` + cachedResult,
|
|
587764
|
+
runtimeAuthored: true,
|
|
587765
|
+
noop: true
|
|
587490
587766
|
};
|
|
587491
587767
|
} else if (isFailedShellRepeat) {
|
|
587492
587768
|
repeatShortCircuit = {
|
|
@@ -587513,7 +587789,9 @@ ${cachedResult}`,
|
|
|
587513
587789
|
runtimeAuthored: true
|
|
587514
587790
|
} : {
|
|
587515
587791
|
success: true,
|
|
587516
|
-
output: cachedResult
|
|
587792
|
+
output: cachedResult,
|
|
587793
|
+
runtimeAuthored: true,
|
|
587794
|
+
noop: true
|
|
587517
587795
|
};
|
|
587518
587796
|
}
|
|
587519
587797
|
}
|
|
@@ -587847,7 +588125,7 @@ Respond with EXACTLY this structure before your next tool call:
|
|
|
587847
588125
|
}
|
|
587848
588126
|
}
|
|
587849
588127
|
}
|
|
587850
|
-
if (tc.name === "todo_write" && result.success) {
|
|
588128
|
+
if (tc.name === "todo_write" && result.success && !this._isTodoWriteNoopResult(result)) {
|
|
587851
588129
|
if (this._progressGateActive) {
|
|
587852
588130
|
this.emit({
|
|
587853
588131
|
type: "status",
|
|
@@ -588430,7 +588708,7 @@ Respond with EXACTLY this structure before your next tool call:
|
|
|
588430
588708
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
588431
588709
|
});
|
|
588432
588710
|
}
|
|
588433
|
-
if (!this._newFieldNudgeFired) {
|
|
588711
|
+
if (!this._newFieldNudgeFired && !this._isTodoWriteNoopResult(result)) {
|
|
588434
588712
|
this._todoWritesObservedForNudge++;
|
|
588435
588713
|
const _anyFieldUsed = _todosNow.some((t2) => typeof t2.verifyCommand === "string" || Array.isArray(t2.declaredArtifacts));
|
|
588436
588714
|
if (this._todoWritesObservedForNudge >= 2 && !_anyFieldUsed) {
|
|
@@ -588918,7 +589196,6 @@ Evidence: ${evidencePreview}`.slice(0, 500);
|
|
|
588918
589196
|
turn,
|
|
588919
589197
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
588920
589198
|
});
|
|
588921
|
-
this.recordWorkboardToolCall(tc.name, tc.arguments, result.success, result.output || result.error || output, result);
|
|
588922
589199
|
this._taskState.toolCallCount++;
|
|
588923
589200
|
if (realFileMutation) {
|
|
588924
589201
|
this._lastFileWriteTurn = turn;
|
|
@@ -589047,7 +589324,8 @@ Evidence: ${evidencePreview}`.slice(0, 500);
|
|
|
589047
589324
|
output: result.output ?? result.llmContent ?? "",
|
|
589048
589325
|
error: result.error ?? "",
|
|
589049
589326
|
mutated: realFileMutation || shellFilesystemMutation,
|
|
589050
|
-
isReadLike
|
|
589327
|
+
isReadLike,
|
|
589328
|
+
noop: tc.name === "todo_write" ? this._isTodoWriteNoopResult(result) : result.noop
|
|
589051
589329
|
});
|
|
589052
589330
|
const focusSnapshotAfter = this._focusSupervisor?.snapshot();
|
|
589053
589331
|
focusAfterToolResult = focusSnapshotAfter ?? void 0;
|
|
@@ -589094,7 +589372,12 @@ Evidence: ${evidencePreview}`.slice(0, 500);
|
|
|
589094
589372
|
});
|
|
589095
589373
|
} catch {
|
|
589096
589374
|
}
|
|
589097
|
-
|
|
589375
|
+
this.recordWorkboardToolCall(tc.name, tc.arguments, result.success, result.output || result.error || output, result, {
|
|
589376
|
+
repeatShortCircuit: Boolean(repeatShortCircuit),
|
|
589377
|
+
focusDecisionKind: focusDecision?.kind,
|
|
589378
|
+
shellFilesystemMutation
|
|
589379
|
+
});
|
|
589380
|
+
if (tc.name === "todo_write" && !this._isTodoWriteNoopResult(result)) {
|
|
589098
589381
|
this._lastTodoWriteTurn = turn;
|
|
589099
589382
|
}
|
|
589100
589383
|
if (tc.name === "file_read" || tc.name === "list_directory" || tc.name === "find_files" || tc.name === "grep_search") {
|
|
@@ -604602,12 +604885,14 @@ var init_py_embed = __esm({
|
|
|
604602
604885
|
var listen_exports = {};
|
|
604603
604886
|
__export(listen_exports, {
|
|
604604
604887
|
ListenEngine: () => ListenEngine,
|
|
604888
|
+
asrConsensusEnabled: () => asrConsensusEnabled,
|
|
604605
604889
|
ensureTranscribeCliBackground: () => ensureTranscribeCliBackground,
|
|
604606
604890
|
getListenEngine: () => getListenEngine,
|
|
604607
604891
|
getListenLiveState: () => getListenLiveState,
|
|
604608
604892
|
isAudioPath: () => isAudioPath,
|
|
604609
604893
|
isTranscribablePath: () => isTranscribablePath,
|
|
604610
604894
|
isVideoPath: () => isVideoPath,
|
|
604895
|
+
resolveAsrConsensusModel: () => resolveAsrConsensusModel,
|
|
604611
604896
|
transcribeFileViaWhisper: () => transcribeFileViaWhisper,
|
|
604612
604897
|
waitForTranscribeCli: () => waitForTranscribeCli
|
|
604613
604898
|
});
|
|
@@ -605012,9 +605297,25 @@ function defaultConsensusModel(primaryModel) {
|
|
|
605012
605297
|
if (model === "large-v3" || model === "large") return "small";
|
|
605013
605298
|
return "base";
|
|
605014
605299
|
}
|
|
605015
|
-
function
|
|
605016
|
-
const
|
|
605017
|
-
|
|
605300
|
+
function resolveAsrConsensusModel(primaryModel) {
|
|
605301
|
+
const disabled = String(process.env["OMNIUS_ASR_DISABLE_CONSENSUS"] ?? "").trim().toLowerCase();
|
|
605302
|
+
if (disabled === "1" || disabled === "true" || disabled === "yes" || disabled === "on") {
|
|
605303
|
+
return "off";
|
|
605304
|
+
}
|
|
605305
|
+
const consensusEnv = String(
|
|
605306
|
+
process.env["OMNIUS_ASR_CONSENSUS"] ?? process.env["OMNIUS_ASR_CONSENSUS_MODEL"] ?? ""
|
|
605307
|
+
).trim().toLowerCase();
|
|
605308
|
+
if (!consensusEnv) return "off";
|
|
605309
|
+
if (["0", "off", "false", "no", "none", "disabled"].includes(consensusEnv)) {
|
|
605310
|
+
return "off";
|
|
605311
|
+
}
|
|
605312
|
+
if (["1", "on", "true", "yes", "enabled", "auto"].includes(consensusEnv)) {
|
|
605313
|
+
return defaultConsensusModel(primaryModel);
|
|
605314
|
+
}
|
|
605315
|
+
return consensusEnv;
|
|
605316
|
+
}
|
|
605317
|
+
function asrConsensusEnabled(primaryModel = "base") {
|
|
605318
|
+
return resolveAsrConsensusModel(primaryModel) !== "off";
|
|
605018
605319
|
}
|
|
605019
605320
|
function liveAsrUseTranscribeCli() {
|
|
605020
605321
|
const value2 = String(process.env["OMNIUS_ASR_USE_TRANSCRIBE_CLI"] ?? "").trim().toLowerCase();
|
|
@@ -605247,8 +605548,7 @@ var init_listen = __esm({
|
|
|
605247
605548
|
model: this.model,
|
|
605248
605549
|
lastStatus: `loading whisper ${this.model} model...`
|
|
605249
605550
|
});
|
|
605250
|
-
const
|
|
605251
|
-
const consensusModel = consensusEnv === "0" || consensusEnv === "off" || consensusEnv === "false" ? "off" : consensusEnv || defaultConsensusModel(this.model);
|
|
605551
|
+
const consensusModel = resolveAsrConsensusModel(this.model);
|
|
605252
605552
|
const consensusThreshold = String(process.env["OMNIUS_ASR_CONSENSUS_THRESHOLD"] ?? "0.45");
|
|
605253
605553
|
const silenceMs = String(process.env["OMNIUS_ASR_SILENCE_MS"] ?? "3000");
|
|
605254
605554
|
this.process = spawn29(
|
|
@@ -605312,7 +605612,9 @@ var init_listen = __esm({
|
|
|
605312
605612
|
updateListenLiveState({
|
|
605313
605613
|
lastStatus: message2
|
|
605314
605614
|
});
|
|
605315
|
-
|
|
605615
|
+
if (process.env["OMNIUS_ASR_VERBOSE_CONSENSUS"] === "1") {
|
|
605616
|
+
this.emit("status", message2);
|
|
605617
|
+
}
|
|
605316
605618
|
}
|
|
605317
605619
|
break;
|
|
605318
605620
|
case "vad": {
|
|
@@ -605665,7 +605967,7 @@ var init_listen = __esm({
|
|
|
605665
605967
|
updateListenLiveState({ phase: "error", lastStatus: "no mic capture tool (arecord/sox/ffmpeg)" });
|
|
605666
605968
|
return "No microphone capture tool found. Install arecord (Linux), sox (macOS), or ffmpeg.";
|
|
605667
605969
|
}
|
|
605668
|
-
const consensusEnabled = asrConsensusEnabled();
|
|
605970
|
+
const consensusEnabled = asrConsensusEnabled(this.config.model);
|
|
605669
605971
|
const useTranscribeCli = liveAsrUseTranscribeCli() && !consensusEnabled;
|
|
605670
605972
|
const preferWhisperFallback = !useTranscribeCli;
|
|
605671
605973
|
if (preferWhisperFallback) {
|
|
@@ -605959,7 +606261,7 @@ transcribe-cli error: ${transcribeCliError}` : "";
|
|
|
605959
606261
|
* Caller is responsible for calling .stop() when done.
|
|
605960
606262
|
*/
|
|
605961
606263
|
async createCallTranscriber() {
|
|
605962
|
-
const requireConsensus = asrConsensusEnabled();
|
|
606264
|
+
const requireConsensus = asrConsensusEnabled(this.config.model);
|
|
605963
606265
|
const useTranscribeCli = liveAsrUseTranscribeCli() && !requireConsensus;
|
|
605964
606266
|
let tc = useTranscribeCli ? await this.loadTranscribeCli() : null;
|
|
605965
606267
|
if (useTranscribeCli && !tc && _bgInstallPromise) {
|
|
@@ -609467,7 +609769,7 @@ var init_live_sensors = __esm({
|
|
|
609467
609769
|
inferEnabled: true,
|
|
609468
609770
|
clipEnabled: true,
|
|
609469
609771
|
audioEnabled: true,
|
|
609470
|
-
asrEnabled: true,
|
|
609772
|
+
asrEnabled: options2.asr ?? true,
|
|
609471
609773
|
audioAnalysisEnabled: true,
|
|
609472
609774
|
videoIntervalMs: options2.lowLatency === false ? this.config.videoIntervalMs : Math.min(this.config.videoIntervalMs, LOW_LATENCY_VIDEO_INTERVAL_MS),
|
|
609473
609775
|
audioIntervalMs: options2.lowLatency === false ? this.config.audioIntervalMs : Math.min(this.config.audioIntervalMs, LOW_LATENCY_AUDIO_INTERVAL_MS)
|
|
@@ -610051,7 +610353,7 @@ ${output}`).join("\n\n");
|
|
|
610051
610353
|
transcript = cleanPreview(liveAsr.lastPartialTranscript, 1600);
|
|
610052
610354
|
asrBackend = [liveAsr.backend, liveAsr.model, "streaming-partial"].filter(Boolean).join(" ");
|
|
610053
610355
|
} else if (liveAsr.phase === "idle") {
|
|
610054
|
-
audioErrors.push("Streaming ASR is not
|
|
610356
|
+
audioErrors.push("Streaming ASR is not active yet; live sound analysis is continuing without a fresh transcript.");
|
|
610055
610357
|
} else if (liveAsr.lastStatus) {
|
|
610056
610358
|
audioErrors.push(`Streaming ASR status: ${liveAsr.lastStatus}`);
|
|
610057
610359
|
}
|
|
@@ -661253,11 +661555,24 @@ function attachLiveSinks(ctx3, manager, agentEnabled = false, speechEnabledOverr
|
|
|
661253
661555
|
}
|
|
661254
661556
|
}
|
|
661255
661557
|
async function ensureLiveStreamingAsr(ctx3, manager, force = false) {
|
|
661256
|
-
if (!force && !manager.getConfig().asrEnabled) return;
|
|
661257
|
-
if (!ctx3.listenStart)
|
|
661258
|
-
|
|
661259
|
-
|
|
661260
|
-
|
|
661558
|
+
if (!force && !manager.getConfig().asrEnabled) return Boolean(ctx3.listenIsActive?.());
|
|
661559
|
+
if (!ctx3.listenStart) {
|
|
661560
|
+
renderWarning("Live ASR auto-start is unavailable in this command context; live audio analysis will continue without transcript intake.");
|
|
661561
|
+
return false;
|
|
661562
|
+
}
|
|
661563
|
+
try {
|
|
661564
|
+
ctx3.listenSetMode?.("auto");
|
|
661565
|
+
const msg = await ctx3.listenStart("live");
|
|
661566
|
+
const active = Boolean(ctx3.listenIsActive?.()) || /already active|listening with|already listening/i.test(msg);
|
|
661567
|
+
if (!/already active/i.test(msg)) {
|
|
661568
|
+
const render2 = active ? renderInfo : renderWarning;
|
|
661569
|
+
render2(`${active ? "Live ASR" : "Live ASR startup"}: ${msg}`);
|
|
661570
|
+
}
|
|
661571
|
+
return active;
|
|
661572
|
+
} catch (err) {
|
|
661573
|
+
renderWarning(`Live ASR startup failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
661574
|
+
return false;
|
|
661575
|
+
}
|
|
661261
661576
|
}
|
|
661262
661577
|
async function releaseLiveStreamingAsr(ctx3) {
|
|
661263
661578
|
try {
|
|
@@ -661514,8 +661829,8 @@ async function handleLiveCommand(ctx3, arg) {
|
|
|
661514
661829
|
renderWarning("Live PFC agent review is unavailable in this context; starting visual/audio feedback only.");
|
|
661515
661830
|
}
|
|
661516
661831
|
await ensureLiveInventory(manager);
|
|
661517
|
-
await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
661518
|
-
renderInfo(manager.startRunMode({ agent: effectiveAgent, lowLatency: true, speech: effectiveAgent && Boolean(ctx3.voiceSpeak) }));
|
|
661832
|
+
const asrStarted = await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
661833
|
+
renderInfo(manager.startRunMode({ agent: effectiveAgent, lowLatency: true, speech: effectiveAgent && Boolean(ctx3.voiceSpeak), asr: asrStarted }));
|
|
661519
661834
|
return;
|
|
661520
661835
|
}
|
|
661521
661836
|
if (sub2 === "chat" || sub2 === "voicechat" || sub2 === "voice") {
|
|
@@ -661616,12 +661931,14 @@ async function handleLiveCommand(ctx3, arg) {
|
|
|
661616
661931
|
if (sub2 === "asr") {
|
|
661617
661932
|
const cfg = manager.getConfig();
|
|
661618
661933
|
const enabled2 = setBool(value2, !cfg.asrEnabled);
|
|
661619
|
-
|
|
661620
|
-
audioEnabled: true,
|
|
661621
|
-
|
|
661622
|
-
|
|
661623
|
-
|
|
661624
|
-
|
|
661934
|
+
if (enabled2) {
|
|
661935
|
+
manager.configure({ audioEnabled: true, asrEnabled: false });
|
|
661936
|
+
const asrStarted = await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
661937
|
+
manager.configure({ asrEnabled: asrStarted });
|
|
661938
|
+
} else {
|
|
661939
|
+
manager.configure({ audioEnabled: true, asrEnabled: false });
|
|
661940
|
+
await releaseLiveStreamingAsr(ctx3);
|
|
661941
|
+
}
|
|
661625
661942
|
renderInfo(formatLiveStatus(manager.getSnapshot()));
|
|
661626
661943
|
return;
|
|
661627
661944
|
}
|
|
@@ -661674,8 +661991,9 @@ async function handleLiveCommand(ctx3, arg) {
|
|
|
661674
661991
|
}
|
|
661675
661992
|
if (sub2 === "sample" || sub2 === "hear") {
|
|
661676
661993
|
await ensureLiveInventory(manager);
|
|
661677
|
-
manager.configure({ audioEnabled: true, asrEnabled:
|
|
661678
|
-
await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
661994
|
+
manager.configure({ audioEnabled: true, asrEnabled: false, audioAnalysisEnabled: false });
|
|
661995
|
+
const asrStarted = await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
661996
|
+
manager.configure({ asrEnabled: asrStarted, audioAnalysisEnabled: true });
|
|
661679
661997
|
renderInfo("Sampling live audio...");
|
|
661680
661998
|
renderInfo(await manager.sampleAudioNow());
|
|
661681
661999
|
return;
|
|
@@ -661911,8 +662229,8 @@ async function showLiveMenu(ctx3, manager) {
|
|
|
661911
662229
|
await ensureLiveInventory(manager);
|
|
661912
662230
|
if (!manager.isRunning()) {
|
|
661913
662231
|
attachLiveSinks(ctx3, manager, false);
|
|
661914
|
-
await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
661915
|
-
renderInfo(manager.startRunMode({ agent: false, lowLatency: true, speech: false }));
|
|
662232
|
+
const asrStarted = await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
662233
|
+
renderInfo(manager.startRunMode({ agent: false, lowLatency: true, speech: false, asr: asrStarted }));
|
|
661916
662234
|
}
|
|
661917
662235
|
while (true) {
|
|
661918
662236
|
await refreshLiveResourceModelSnapshot().catch(() => void 0);
|
|
@@ -662070,19 +662388,21 @@ async function showLiveMenu(ctx3, manager) {
|
|
|
662070
662388
|
case "toggle-video":
|
|
662071
662389
|
manager.configure({ videoEnabled: !cfg.videoEnabled });
|
|
662072
662390
|
continue;
|
|
662073
|
-
case "run-live":
|
|
662391
|
+
case "run-live": {
|
|
662074
662392
|
attachLiveSinks(ctx3, manager, false);
|
|
662075
|
-
await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
662076
|
-
renderInfo(manager.startRunMode({ agent: false, lowLatency: true, speech: false }));
|
|
662393
|
+
const asrStarted = await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
662394
|
+
renderInfo(manager.startRunMode({ agent: false, lowLatency: true, speech: false, asr: asrStarted }));
|
|
662077
662395
|
continue;
|
|
662078
|
-
|
|
662396
|
+
}
|
|
662397
|
+
case "run-agent": {
|
|
662079
662398
|
attachLiveSinks(ctx3, manager, true);
|
|
662080
662399
|
if (!ctx3.startBackgroundPrompt) {
|
|
662081
662400
|
renderWarning("Live PFC agent review is unavailable in this context; starting visual/audio feedback only.");
|
|
662082
662401
|
}
|
|
662083
|
-
await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
662084
|
-
renderInfo(manager.startRunMode({ agent: Boolean(ctx3.startBackgroundPrompt), lowLatency: true, speech: Boolean(ctx3.startBackgroundPrompt && ctx3.voiceSpeak) }));
|
|
662402
|
+
const asrStarted = await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
662403
|
+
renderInfo(manager.startRunMode({ agent: Boolean(ctx3.startBackgroundPrompt), lowLatency: true, speech: Boolean(ctx3.startBackgroundPrompt && ctx3.voiceSpeak), asr: asrStarted }));
|
|
662085
662404
|
continue;
|
|
662405
|
+
}
|
|
662086
662406
|
case "run-chat":
|
|
662087
662407
|
await startLiveVoicechat(ctx3, manager);
|
|
662088
662408
|
continue;
|
|
@@ -662099,9 +662419,14 @@ async function showLiveMenu(ctx3, manager) {
|
|
|
662099
662419
|
manager.configure({ videoEnabled: true, clipEnabled: !cfg.clipEnabled });
|
|
662100
662420
|
continue;
|
|
662101
662421
|
case "toggle-asr":
|
|
662102
|
-
|
|
662103
|
-
|
|
662104
|
-
|
|
662422
|
+
if (!cfg.asrEnabled) {
|
|
662423
|
+
manager.configure({ audioEnabled: true, asrEnabled: false });
|
|
662424
|
+
const asrStarted = await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
662425
|
+
manager.configure({ asrEnabled: asrStarted });
|
|
662426
|
+
} else {
|
|
662427
|
+
manager.configure({ audioEnabled: true, asrEnabled: false });
|
|
662428
|
+
await releaseLiveStreamingAsr(ctx3);
|
|
662429
|
+
}
|
|
662105
662430
|
continue;
|
|
662106
662431
|
case "toggle-sounds":
|
|
662107
662432
|
manager.configure({ audioEnabled: true, audioAnalysisEnabled: !cfg.audioAnalysisEnabled });
|
|
@@ -662149,12 +662474,14 @@ Previewing microphone activity...`);
|
|
|
662149
662474
|
renderInfo("Sampling camera inference...");
|
|
662150
662475
|
renderInfo(await manager.sampleVideoNow(true));
|
|
662151
662476
|
continue;
|
|
662152
|
-
case "sample-audio":
|
|
662153
|
-
manager.configure({ audioEnabled: true, asrEnabled:
|
|
662154
|
-
await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
662477
|
+
case "sample-audio": {
|
|
662478
|
+
manager.configure({ audioEnabled: true, asrEnabled: false, audioAnalysisEnabled: false });
|
|
662479
|
+
const asrStarted = await ensureLiveStreamingAsr(ctx3, manager, true);
|
|
662480
|
+
manager.configure({ asrEnabled: asrStarted, audioAnalysisEnabled: true });
|
|
662155
662481
|
renderInfo("Sampling live audio...");
|
|
662156
662482
|
renderInfo(await manager.sampleAudioNow());
|
|
662157
662483
|
continue;
|
|
662484
|
+
}
|
|
662158
662485
|
case "listen-mode":
|
|
662159
662486
|
if (ctx3.listenToggle) {
|
|
662160
662487
|
ctx3.listenSetMode?.("auto");
|
|
@@ -702138,6 +702465,25 @@ function buildSyntheticContext(config, repoRoot) {
|
|
|
702138
702465
|
renderError(`voice model ${TUI_ONLY_HINT}`);
|
|
702139
702466
|
return "";
|
|
702140
702467
|
},
|
|
702468
|
+
listenStart: async (owner = "live") => {
|
|
702469
|
+
const engine = getDaemonListenEngine();
|
|
702470
|
+
const available = await engine.isAvailable();
|
|
702471
|
+
if (!available) {
|
|
702472
|
+
return "ASR runtime unavailable. Omnius attempted managed Whisper setup; check ~/.omnius/runtimes/asr and CUDA PyTorch.";
|
|
702473
|
+
}
|
|
702474
|
+
engine.setMode("auto");
|
|
702475
|
+
return engine.acquire(owner);
|
|
702476
|
+
},
|
|
702477
|
+
listenRelease: async (owner = "live") => {
|
|
702478
|
+
const engine = getDaemonListenEngine();
|
|
702479
|
+
return engine.release(owner);
|
|
702480
|
+
},
|
|
702481
|
+
listenIsActive: () => getDaemonListenEngine().isActive,
|
|
702482
|
+
listenSetMode: (mode) => {
|
|
702483
|
+
const engine = getDaemonListenEngine();
|
|
702484
|
+
engine.setMode(mode);
|
|
702485
|
+
return mode === "auto" ? "Auto mode: transcriptions auto-submit after 3s silence" : "Manual mode: press Enter to submit transcriptions (auto-submit off)";
|
|
702486
|
+
},
|
|
702141
702487
|
getColors: () => colorsEnabled,
|
|
702142
702488
|
setColors: (enabled2) => {
|
|
702143
702489
|
colorsEnabled = enabled2;
|
|
@@ -738430,13 +738776,14 @@ This is an independent background session started from /background.`
|
|
|
738430
738776
|
headerBtnQueue = command;
|
|
738431
738777
|
return;
|
|
738432
738778
|
}
|
|
738433
|
-
const
|
|
738779
|
+
const normalizedHeaderCommand = command.replace(/^\/+/, "");
|
|
738780
|
+
const commandToRun = normalizedHeaderCommand === "live" ? isLiveSensorActiveForRepo(repoRoot) ? "live stop" : "live run" : command;
|
|
738434
738781
|
if (headerBtnActive && headerBtnActive !== command) {
|
|
738435
738782
|
headerBtnQueue = command;
|
|
738436
738783
|
return;
|
|
738437
738784
|
}
|
|
738438
738785
|
if (headerBtnActive === command) {
|
|
738439
|
-
if (
|
|
738786
|
+
if (normalizedHeaderCommand === "live") headerBtnQueue = command;
|
|
738440
738787
|
return;
|
|
738441
738788
|
}
|
|
738442
738789
|
headerBtnActive = command;
|
|
@@ -740566,10 +740913,7 @@ Respond concisely and safely. Remember: you are talking to the general public.`;
|
|
|
740566
740913
|
sharedTranscriber: null
|
|
740567
740914
|
};
|
|
740568
740915
|
const engine = getListenEngine();
|
|
740569
|
-
const callConsensusRequired = (
|
|
740570
|
-
const env2 = String(process.env["OMNIUS_ASR_CONSENSUS"] ?? "").trim().toLowerCase();
|
|
740571
|
-
return !(env2 === "0" || env2 === "off" || env2 === "false");
|
|
740572
|
-
})();
|
|
740916
|
+
const callConsensusRequired = asrConsensusEnabled();
|
|
740573
740917
|
const recentCallFinals = [];
|
|
740574
740918
|
const normalizeCallTranscript = (value2) => value2.toLowerCase().replace(/[^\p{L}\p{N}\s']/gu, " ").replace(/\s+/g, " ").trim();
|
|
740575
740919
|
const isLikelyCallAsrHallucination = (normalized) => /^(thanks|thank you) for watching(?: this video)?$/.test(normalized) || /^thanks for watching and/.test(normalized) || /\bdon't forget to (like|subscribe)\b/.test(normalized);
|
|
@@ -14,8 +14,8 @@ Architecture (EGG voice/whisper lineage):
|
|
|
14
14
|
(USB 2886:0018), the XMOS DSP's SPEECHDETECTED register gates utterances,
|
|
15
15
|
on-chip echo cancellation is enabled, and the DOA angle is attached to
|
|
16
16
|
transcripts. Falls back to adaptive energy VAD otherwise.
|
|
17
|
-
-
|
|
18
|
-
utterances
|
|
17
|
+
- Optional dual-model consensus: a second whisper model can validate
|
|
18
|
+
finalized utterances when explicitly enabled.
|
|
19
19
|
|
|
20
20
|
Protocol:
|
|
21
21
|
stdin — raw PCM16 audio (16kHz, mono, 16-bit signed LE)
|
|
@@ -58,6 +58,23 @@ SAMPLE_WIDTH = 2 # 16-bit
|
|
|
58
58
|
BLOCK_SECONDS = 0.2
|
|
59
59
|
BLOCK_SAMPLES = int(SAMPLE_RATE * BLOCK_SECONDS)
|
|
60
60
|
|
|
61
|
+
|
|
62
|
+
def env_float(name: str, default: float) -> float:
|
|
63
|
+
raw = os.environ.get(name, "").strip()
|
|
64
|
+
if not raw:
|
|
65
|
+
return default
|
|
66
|
+
try:
|
|
67
|
+
return float(raw)
|
|
68
|
+
except ValueError:
|
|
69
|
+
return default
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def env_bool(name: str, default: bool = False) -> bool:
|
|
73
|
+
raw = os.environ.get(name, "").strip().lower()
|
|
74
|
+
if not raw:
|
|
75
|
+
return default
|
|
76
|
+
return raw in ("1", "true", "yes", "on", "enabled")
|
|
77
|
+
|
|
61
78
|
# ---------------------------------------------------------------------------
|
|
62
79
|
# Output helpers (JSON lines to stdout)
|
|
63
80
|
# ---------------------------------------------------------------------------
|
|
@@ -450,7 +467,7 @@ def main():
|
|
|
450
467
|
parser.add_argument("--chunk-seconds", type=float, default=3, help=argparse.SUPPRESS)
|
|
451
468
|
parser.add_argument("--window-seconds", type=float, default=10, help=argparse.SUPPRESS)
|
|
452
469
|
parser.add_argument("--language", default=None, help="Language code (e.g. en, es, fr). Auto-detect if omitted.")
|
|
453
|
-
parser.add_argument("--consensus-model", default="
|
|
470
|
+
parser.add_argument("--consensus-model", default="off",
|
|
454
471
|
help="Second whisper model run in parallel on finalized utterances; transcripts are only emitted when both models agree. 'off' disables.")
|
|
455
472
|
parser.add_argument("--consensus-threshold", type=float, default=0.55,
|
|
456
473
|
help="Token similarity (0-1) required between the two models' transcripts.")
|
|
@@ -460,6 +477,18 @@ def main():
|
|
|
460
477
|
help="Audio kept from before speech onset.")
|
|
461
478
|
parser.add_argument("--max-utterance-seconds", type=float, default=22,
|
|
462
479
|
help="Force-finalize utterances longer than this.")
|
|
480
|
+
parser.add_argument("--partials", action="store_true", default=env_bool("OMNIUS_ASR_PARTIALS", False),
|
|
481
|
+
help="Emit interim Whisper transcripts during long utterances. Disabled by default to avoid silence/noise hallucinations.")
|
|
482
|
+
parser.add_argument("--min-speech-ms", type=float, default=env_float("OMNIUS_ASR_MIN_SPEECH_MS", 450.0),
|
|
483
|
+
help="Minimum VAD-positive speech duration required before an utterance is sent to Whisper.")
|
|
484
|
+
parser.add_argument("--start-rms", type=float, default=env_float("OMNIUS_ASR_START_RMS", 0.0025),
|
|
485
|
+
help="Minimum block RMS required for software VAD speech start.")
|
|
486
|
+
parser.add_argument("--energy-ratio", type=float, default=env_float("OMNIUS_ASR_ENERGY_RATIO", 3.5),
|
|
487
|
+
help="Software VAD speech gate as a multiple of the adaptive noise floor.")
|
|
488
|
+
parser.add_argument("--min-utterance-rms", type=float, default=env_float("OMNIUS_ASR_MIN_UTTERANCE_RMS", 0.003),
|
|
489
|
+
help="Minimum loud-block RMS required before final transcription.")
|
|
490
|
+
parser.add_argument("--min-utterance-peak", type=float, default=env_float("OMNIUS_ASR_MIN_UTTERANCE_PEAK", 0.015),
|
|
491
|
+
help="Minimum utterance peak amplitude required when RMS is low.")
|
|
463
492
|
args = parser.parse_args()
|
|
464
493
|
|
|
465
494
|
import whisper
|
|
@@ -543,6 +572,9 @@ def main():
|
|
|
543
572
|
utterance = [] # list of float32 blocks while capturing
|
|
544
573
|
capturing = False
|
|
545
574
|
silence_run = 0
|
|
575
|
+
speech_blocks = 0
|
|
576
|
+
utterance_rms_values = []
|
|
577
|
+
utterance_peak = 0.0
|
|
546
578
|
noise_floor = None
|
|
547
579
|
last_partial_at = 0.0
|
|
548
580
|
last_final_text = ""
|
|
@@ -558,7 +590,7 @@ def main():
|
|
|
558
590
|
noise_floor = 0.7 * noise_floor + 0.3 * block_rms # drop fast
|
|
559
591
|
else:
|
|
560
592
|
noise_floor = 0.995 * noise_floor + 0.005 * block_rms # creep up slowly
|
|
561
|
-
gate = max(
|
|
593
|
+
gate = max(float(args.start_rms), noise_floor * float(args.energy_ratio))
|
|
562
594
|
return block_rms >= gate
|
|
563
595
|
|
|
564
596
|
def transcribe_partial(samples):
|
|
@@ -574,9 +606,31 @@ def main():
|
|
|
574
606
|
except Exception as e:
|
|
575
607
|
emit_error(f"Transcription error: {e}")
|
|
576
608
|
|
|
577
|
-
def
|
|
578
|
-
nonlocal last_final_text
|
|
609
|
+
def utterance_quality_ok(samples, speech_block_count, rms_values, peak) -> bool:
|
|
579
610
|
if len(samples) < int(0.4 * SAMPLE_RATE):
|
|
611
|
+
return False
|
|
612
|
+
speech_ms = speech_block_count * BLOCK_SECONDS * 1000.0
|
|
613
|
+
if speech_ms < float(args.min_speech_ms):
|
|
614
|
+
if env_bool("OMNIUS_ASR_VERBOSE_VAD", False):
|
|
615
|
+
emit_status(f"Dropped short VAD blob before Whisper: speech_ms={speech_ms:.0f}")
|
|
616
|
+
return False
|
|
617
|
+
if rms_values:
|
|
618
|
+
ordered = sorted(float(v) for v in rms_values)
|
|
619
|
+
loud_half = ordered[len(ordered) // 2:] or ordered
|
|
620
|
+
loud_rms = loud_half[len(loud_half) // 2]
|
|
621
|
+
else:
|
|
622
|
+
loud_rms = float(np.sqrt(np.mean(samples ** 2))) if len(samples) else 0.0
|
|
623
|
+
if loud_rms < float(args.min_utterance_rms) and peak < float(args.min_utterance_peak):
|
|
624
|
+
if env_bool("OMNIUS_ASR_VERBOSE_VAD", False):
|
|
625
|
+
emit_status(
|
|
626
|
+
f"Dropped low-energy VAD blob before Whisper: loud_rms={loud_rms:.5f} peak={peak:.5f}"
|
|
627
|
+
)
|
|
628
|
+
return False
|
|
629
|
+
return True
|
|
630
|
+
|
|
631
|
+
def transcribe_final(samples, speech_block_count=0, rms_values=None, peak=0.0):
|
|
632
|
+
nonlocal last_final_text
|
|
633
|
+
if not utterance_quality_ok(samples, speech_block_count, rms_values or [], peak):
|
|
580
634
|
return
|
|
581
635
|
samples = amplify(samples)
|
|
582
636
|
try:
|
|
@@ -612,7 +666,9 @@ def main():
|
|
|
612
666
|
last_final_text = primary_text
|
|
613
667
|
emit_transcript(primary_text, is_final=True, doa=primary_doa, consensus=True)
|
|
614
668
|
except Exception as e:
|
|
615
|
-
|
|
669
|
+
emit_consensus_rejected(primary_text, "", "validator_error")
|
|
670
|
+
if env_bool("OMNIUS_ASR_VERBOSE_CONSENSUS", False):
|
|
671
|
+
emit_status(f"Consensus validation error: {e}")
|
|
616
672
|
|
|
617
673
|
threading.Thread(
|
|
618
674
|
target=validate_consensus,
|
|
@@ -664,12 +720,18 @@ def main():
|
|
|
664
720
|
if speech:
|
|
665
721
|
capturing = True
|
|
666
722
|
silence_run = 0
|
|
723
|
+
speech_blocks = 1
|
|
724
|
+
utterance_rms_values = [block_rms]
|
|
725
|
+
utterance_peak = float(np.max(np.abs(block))) if len(block) else 0.0
|
|
667
726
|
utterance = list(preroll)
|
|
668
727
|
preroll.clear()
|
|
669
728
|
continue
|
|
670
729
|
|
|
671
730
|
utterance.append(block)
|
|
731
|
+
utterance_rms_values.append(block_rms)
|
|
732
|
+
utterance_peak = max(utterance_peak, float(np.max(np.abs(block))) if len(block) else 0.0)
|
|
672
733
|
if speech:
|
|
734
|
+
speech_blocks += 1
|
|
673
735
|
silence_run = 0
|
|
674
736
|
else:
|
|
675
737
|
silence_run += 1
|
|
@@ -677,11 +739,17 @@ def main():
|
|
|
677
739
|
utter_samples = sum(len(b) for b in utterance)
|
|
678
740
|
if silence_run >= finalize_blocks or utter_samples >= max_utter_samples:
|
|
679
741
|
samples = np.concatenate(utterance)
|
|
742
|
+
final_speech_blocks = speech_blocks
|
|
743
|
+
final_rms_values = list(utterance_rms_values)
|
|
744
|
+
final_peak = utterance_peak
|
|
680
745
|
capturing = False
|
|
681
746
|
utterance = []
|
|
682
747
|
silence_run = 0
|
|
683
|
-
|
|
684
|
-
|
|
748
|
+
speech_blocks = 0
|
|
749
|
+
utterance_rms_values = []
|
|
750
|
+
utterance_peak = 0.0
|
|
751
|
+
transcribe_final(samples, final_speech_blocks, final_rms_values, final_peak)
|
|
752
|
+
elif args.partials and utter_samples >= int(3.5 * SAMPLE_RATE) and now - last_partial_at >= 2.5:
|
|
685
753
|
last_partial_at = now
|
|
686
754
|
transcribe_partial(np.concatenate(utterance))
|
|
687
755
|
except KeyboardInterrupt:
|
|
@@ -690,7 +758,12 @@ def main():
|
|
|
690
758
|
# EOF: finalize any in-flight utterance.
|
|
691
759
|
if utterance:
|
|
692
760
|
try:
|
|
693
|
-
transcribe_final(
|
|
761
|
+
transcribe_final(
|
|
762
|
+
np.concatenate(utterance),
|
|
763
|
+
speech_blocks,
|
|
764
|
+
list(utterance_rms_values),
|
|
765
|
+
utterance_peak,
|
|
766
|
+
)
|
|
694
767
|
except Exception:
|
|
695
768
|
pass
|
|
696
769
|
if tuning is not None:
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnius",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.446",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omnius",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.446",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"image-to-ascii"
|
|
12
12
|
],
|
package/package.json
CHANGED