omnius 1.0.387 → 1.0.389
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 +449 -27
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
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
|
|
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("
|
|
25078
|
+
lines.push("Discovered child paths (data only):");
|
|
25079
25079
|
if (dirs.length > 0) {
|
|
25080
|
-
|
|
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
|
-
|
|
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:
|
|
25121
|
+
` latest generated summary path: ${latestPath}`
|
|
25130
25122
|
];
|
|
25131
25123
|
return { entries: remaining, syntheticLines };
|
|
25132
25124
|
}
|
|
@@ -572467,11 +572459,86 @@ function computeEffectiveThink(params) {
|
|
|
572467
572459
|
return params.defaultThink;
|
|
572468
572460
|
}
|
|
572469
572461
|
function sanitizeHistoryThink(messages2) {
|
|
572470
|
-
|
|
572462
|
+
const referencedToolCallIds = /* @__PURE__ */ new Set();
|
|
572463
|
+
for (const message2 of messages2) {
|
|
572464
|
+
if (message2.role === "tool" && message2.tool_call_id) {
|
|
572465
|
+
referencedToolCallIds.add(message2.tool_call_id);
|
|
572466
|
+
}
|
|
572467
|
+
}
|
|
572468
|
+
const stripped = messages2.map((m2) => {
|
|
572471
572469
|
if (m2.role !== "assistant" || typeof m2.content !== "string")
|
|
572472
572470
|
return m2;
|
|
572473
572471
|
return { ...m2, content: stripThinkBlocks(m2.content) };
|
|
572474
572472
|
});
|
|
572473
|
+
const sanitized = [];
|
|
572474
|
+
for (let i2 = 0; i2 < stripped.length; i2++) {
|
|
572475
|
+
const current = stripped[i2];
|
|
572476
|
+
const next = stripped[i2 + 1];
|
|
572477
|
+
if (isOrphanDuplicateAssistantToolAnchor(current, next, referencedToolCallIds)) {
|
|
572478
|
+
continue;
|
|
572479
|
+
}
|
|
572480
|
+
sanitized.push(current);
|
|
572481
|
+
}
|
|
572482
|
+
return sanitized;
|
|
572483
|
+
}
|
|
572484
|
+
function isOrphanDuplicateAssistantToolAnchor(current, next, referencedToolCallIds) {
|
|
572485
|
+
if (!next)
|
|
572486
|
+
return false;
|
|
572487
|
+
if (current.role !== "assistant" || next.role !== "assistant")
|
|
572488
|
+
return false;
|
|
572489
|
+
if (!Array.isArray(current.tool_calls) || !Array.isArray(next.tool_calls)) {
|
|
572490
|
+
return false;
|
|
572491
|
+
}
|
|
572492
|
+
if (current.tool_calls.length === 0 || next.tool_calls.length === 0) {
|
|
572493
|
+
return false;
|
|
572494
|
+
}
|
|
572495
|
+
if (assistantVisibleText(current).length > 0)
|
|
572496
|
+
return false;
|
|
572497
|
+
if (toolCallsFingerprint(current.tool_calls) !== toolCallsFingerprint(next.tool_calls)) {
|
|
572498
|
+
return false;
|
|
572499
|
+
}
|
|
572500
|
+
const currentIds = current.tool_calls.map((call) => call.id).filter(Boolean);
|
|
572501
|
+
const nextIds = next.tool_calls.map((call) => call.id).filter(Boolean);
|
|
572502
|
+
const currentReferenced = currentIds.some((id) => referencedToolCallIds.has(id));
|
|
572503
|
+
const nextReferenced = nextIds.some((id) => referencedToolCallIds.has(id));
|
|
572504
|
+
return !currentReferenced && (nextReferenced || currentIds.length > 0);
|
|
572505
|
+
}
|
|
572506
|
+
function assistantVisibleText(message2) {
|
|
572507
|
+
if (typeof message2.content === "string")
|
|
572508
|
+
return message2.content.trim();
|
|
572509
|
+
if (!Array.isArray(message2.content))
|
|
572510
|
+
return "";
|
|
572511
|
+
return message2.content.map((part) => part.type === "text" ? part.text ?? "" : "").join("").trim();
|
|
572512
|
+
}
|
|
572513
|
+
function toolCallsFingerprint(calls) {
|
|
572514
|
+
return calls.map((call) => {
|
|
572515
|
+
const args = normalizeToolCallArgumentString(call.function.arguments);
|
|
572516
|
+
return `${call.function.name}:${args}`;
|
|
572517
|
+
}).join("|");
|
|
572518
|
+
}
|
|
572519
|
+
function normalizeToolCallArgumentString(args) {
|
|
572520
|
+
try {
|
|
572521
|
+
return JSON.stringify(JSON.parse(args));
|
|
572522
|
+
} catch {
|
|
572523
|
+
return args.replace(/\s+/g, " ").trim();
|
|
572524
|
+
}
|
|
572525
|
+
}
|
|
572526
|
+
function normalizeEditComparable(text2) {
|
|
572527
|
+
return text2.replace(/\r\n/g, "\n").trim();
|
|
572528
|
+
}
|
|
572529
|
+
function previewInline(text2, max = 140) {
|
|
572530
|
+
const normalized = text2.replace(/\s+/g, " ").trim();
|
|
572531
|
+
if (normalized.length <= max)
|
|
572532
|
+
return JSON.stringify(normalized);
|
|
572533
|
+
return JSON.stringify(`${normalized.slice(0, max - 18)}...#${quickTextHash(normalized)}`);
|
|
572534
|
+
}
|
|
572535
|
+
function quickTextHash(input) {
|
|
572536
|
+
let hash = 2166136261;
|
|
572537
|
+
for (let index = 0; index < input.length; index++) {
|
|
572538
|
+
hash ^= input.charCodeAt(index);
|
|
572539
|
+
hash = Math.imul(hash, 16777619) >>> 0;
|
|
572540
|
+
}
|
|
572541
|
+
return hash.toString(16).padStart(8, "0");
|
|
572475
572542
|
}
|
|
572476
572543
|
function applyMemoryPrefixToMessages(messages2, memoryPrefix) {
|
|
572477
572544
|
const prefix = memoryPrefix?.trim();
|
|
@@ -572946,6 +573013,8 @@ var init_agenticRunner = __esm({
|
|
|
572946
573013
|
_completionCaveat = null;
|
|
572947
573014
|
_completionLedger = null;
|
|
572948
573015
|
_staleEditFamilies = /* @__PURE__ */ new Map();
|
|
573016
|
+
_lastReadTurnByPathKey = /* @__PURE__ */ new Map();
|
|
573017
|
+
_recentSuccessfulReplacements = [];
|
|
572949
573018
|
// ── WO-AM-01/04/10: Associative memory stores ──
|
|
572950
573019
|
// Episode store: every tool call → persistent episode with importance + decay
|
|
572951
573020
|
// Temporal KG: entities + relations with temporal validity (valid_from/valid_until)
|
|
@@ -573194,7 +573263,7 @@ var init_agenticRunner = __esm({
|
|
|
573194
573263
|
if (this.options.subAgent || this.options.recursionDepth > 0)
|
|
573195
573264
|
return [];
|
|
573196
573265
|
const normalizedGoal = goal.replace(/\s+/g, " ").trim();
|
|
573197
|
-
if (normalizedGoal.length < 120)
|
|
573266
|
+
if (normalizedGoal.length < 120 && !this._isContinuationResumeGoal(normalizedGoal))
|
|
573198
573267
|
return [];
|
|
573199
573268
|
return [
|
|
573200
573269
|
{
|
|
@@ -573258,6 +573327,44 @@ var init_agenticRunner = __esm({
|
|
|
573258
573327
|
}
|
|
573259
573328
|
];
|
|
573260
573329
|
}
|
|
573330
|
+
_isContinuationResumeGoal(goal) {
|
|
573331
|
+
const tokens = goal.toLowerCase().replace(/[^a-z0-9]+/g, " ").split(/\s+/).filter(Boolean);
|
|
573332
|
+
if (tokens.length === 0 || tokens.length > 14)
|
|
573333
|
+
return false;
|
|
573334
|
+
const continuationTerms = /* @__PURE__ */ new Set([
|
|
573335
|
+
"again",
|
|
573336
|
+
"and",
|
|
573337
|
+
"back",
|
|
573338
|
+
"carry",
|
|
573339
|
+
"complete",
|
|
573340
|
+
"continue",
|
|
573341
|
+
"finish",
|
|
573342
|
+
"from",
|
|
573343
|
+
"last",
|
|
573344
|
+
"latest",
|
|
573345
|
+
"left",
|
|
573346
|
+
"my",
|
|
573347
|
+
"off",
|
|
573348
|
+
"please",
|
|
573349
|
+
"previous",
|
|
573350
|
+
"prior",
|
|
573351
|
+
"proceed",
|
|
573352
|
+
"request",
|
|
573353
|
+
"resume",
|
|
573354
|
+
"task",
|
|
573355
|
+
"that",
|
|
573356
|
+
"the",
|
|
573357
|
+
"this",
|
|
573358
|
+
"to",
|
|
573359
|
+
"try",
|
|
573360
|
+
"work"
|
|
573361
|
+
]);
|
|
573362
|
+
const hasResumeVerb = tokens.some((token) => token === "continue" || token === "resume" || token === "proceed" || token === "complete" || token === "finish");
|
|
573363
|
+
if (!hasResumeVerb)
|
|
573364
|
+
return false;
|
|
573365
|
+
const continuationTokenCount = tokens.filter((token) => continuationTerms.has(token)).length;
|
|
573366
|
+
return continuationTokenCount / tokens.length >= 0.7;
|
|
573367
|
+
}
|
|
573261
573368
|
/**
|
|
573262
573369
|
* Build a compact workboard context string for injection into the
|
|
573263
573370
|
* system prompt. Returns null when no active board exists or when
|
|
@@ -578763,6 +578870,8 @@ Respond with your assessment, then take action.`;
|
|
|
578763
578870
|
this._completionLedger = null;
|
|
578764
578871
|
this._focusTerminalLedgerRecorded = false;
|
|
578765
578872
|
this._staleEditFamilies.clear();
|
|
578873
|
+
this._lastReadTurnByPathKey.clear();
|
|
578874
|
+
this._recentSuccessfulReplacements = [];
|
|
578766
578875
|
this._lastWorldStateTurn = -1;
|
|
578767
578876
|
this._fileWritesSinceLastWorldState = 0;
|
|
578768
578877
|
this._resetVisualEvidenceState();
|
|
@@ -581153,7 +581262,7 @@ ${memoryLines.join("\n")}`
|
|
|
581153
581262
|
this.proactivePrune(compacted, turn);
|
|
581154
581263
|
this.microcompact(compacted, recentToolResults);
|
|
581155
581264
|
this._insertContextFrame(compacted, await this._buildTurnContextFrame(turn, compacted, recentToolResults, environmentBlock));
|
|
581156
|
-
let requestMessages = compacted;
|
|
581265
|
+
let requestMessages = sanitizeHistoryThink(compacted);
|
|
581157
581266
|
{
|
|
581158
581267
|
const _limits = this.contextLimits();
|
|
581159
581268
|
const ceInput = {
|
|
@@ -581189,6 +581298,7 @@ ${memoryLines.join("\n")}`
|
|
|
581189
581298
|
}
|
|
581190
581299
|
}
|
|
581191
581300
|
const { maxOutputTokens: effectiveMaxTokens } = this.contextLimits();
|
|
581301
|
+
requestMessages = sanitizeHistoryThink(requestMessages);
|
|
581192
581302
|
const chatRequest = {
|
|
581193
581303
|
messages: requestMessages,
|
|
581194
581304
|
tools: toolDefs,
|
|
@@ -582148,6 +582258,69 @@ Use the saved fact to continue the promised synthesis or next concrete step, or
|
|
|
582148
582258
|
systemGuidance: staleRewriteOutput
|
|
582149
582259
|
};
|
|
582150
582260
|
}
|
|
582261
|
+
const editReversalBlock = this.editReversalPreflightBlock(tc.name, tc.arguments ?? {}, turn);
|
|
582262
|
+
if (editReversalBlock) {
|
|
582263
|
+
const focusDecision2 = this._focusSupervisor?.evaluateProposedCall({
|
|
582264
|
+
turn,
|
|
582265
|
+
toolName: tc.name,
|
|
582266
|
+
args: tc.arguments ?? {},
|
|
582267
|
+
fingerprint: toolFingerprint,
|
|
582268
|
+
isReadLike: false,
|
|
582269
|
+
stalePreflightMessage: editReversalBlock,
|
|
582270
|
+
context: this._buildFocusContextSnapshot()
|
|
582271
|
+
});
|
|
582272
|
+
const reversalOutput = focusDecision2?.kind === "block_tool_call" ? focusDecision2.message : editReversalBlock;
|
|
582273
|
+
if (focusDecision2 && focusDecision2.kind !== "pass") {
|
|
582274
|
+
this._emitFocusSupervisorEvent({
|
|
582275
|
+
decision: focusDecision2.kind,
|
|
582276
|
+
state: focusDecision2.state,
|
|
582277
|
+
directiveId: focusDecision2.directive.id,
|
|
582278
|
+
reason: focusDecision2.directive.reason,
|
|
582279
|
+
requiredNextAction: focusDecision2.directive.requiredNextAction,
|
|
582280
|
+
blockedTool: tc.name,
|
|
582281
|
+
turn
|
|
582282
|
+
});
|
|
582283
|
+
this._maybeMarkFocusTerminalIncomplete({
|
|
582284
|
+
decision: focusDecision2,
|
|
582285
|
+
blockedTool: tc.name,
|
|
582286
|
+
turn
|
|
582287
|
+
});
|
|
582288
|
+
}
|
|
582289
|
+
this.emit({
|
|
582290
|
+
type: "tool_call",
|
|
582291
|
+
toolName: tc.name,
|
|
582292
|
+
toolArgs: tc.arguments,
|
|
582293
|
+
turn,
|
|
582294
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
582295
|
+
});
|
|
582296
|
+
this.emit({
|
|
582297
|
+
type: "tool_result",
|
|
582298
|
+
toolName: tc.name,
|
|
582299
|
+
success: false,
|
|
582300
|
+
content: reversalOutput.slice(0, 120),
|
|
582301
|
+
turn,
|
|
582302
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
582303
|
+
});
|
|
582304
|
+
this._tagSyntheticFailure({
|
|
582305
|
+
mode: "step_repetition",
|
|
582306
|
+
rationale: "edit attempted to reverse a recent successful replacement without fresh evidence"
|
|
582307
|
+
});
|
|
582308
|
+
if (this._completionLedger) {
|
|
582309
|
+
this._completionLedger = recordToolEvidence(this._completionLedger, {
|
|
582310
|
+
name: tc.name,
|
|
582311
|
+
success: false,
|
|
582312
|
+
outputPreview: reversalOutput.slice(0, 500),
|
|
582313
|
+
argsKey: tc.arguments ? JSON.stringify(tc.arguments).slice(0, 300) : ""
|
|
582314
|
+
});
|
|
582315
|
+
this._saveCompletionLedgerSafe();
|
|
582316
|
+
}
|
|
582317
|
+
return {
|
|
582318
|
+
tc,
|
|
582319
|
+
output: reversalOutput,
|
|
582320
|
+
success: false,
|
|
582321
|
+
systemGuidance: reversalOutput
|
|
582322
|
+
};
|
|
582323
|
+
}
|
|
582151
582324
|
const baseIsReadLike = ![
|
|
582152
582325
|
"file_write",
|
|
582153
582326
|
"file_edit",
|
|
@@ -583782,6 +583955,7 @@ Evidence: ${evidencePreview}`.slice(0, 500);
|
|
|
583782
583955
|
const filePath = typeof tc.arguments?.path === "string" ? tc.arguments.path : "";
|
|
583783
583956
|
recordToolExecution(this._appState, tc.name, performance.now() - toolStart, result.success, filePath || void 0);
|
|
583784
583957
|
this.noteStaleEditGuardOutcome(tc.name, tc.arguments ?? {}, result, turn);
|
|
583958
|
+
this.noteEditReversalOutcome(tc.name, tc.arguments ?? {}, result, turn);
|
|
583785
583959
|
{
|
|
583786
583960
|
const beforeDirective = this._focusSupervisor?.snapshot().directive?.id ?? null;
|
|
583787
583961
|
this._focusSupervisor?.observeToolResult({
|
|
@@ -584846,8 +585020,9 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
|
|
|
584846
585020
|
}
|
|
584847
585021
|
}
|
|
584848
585022
|
this._insertContextFrame(compactedMsgs, await this._buildTurnContextFrame(turn, compactedMsgs, void 0, bfEnvironmentBlock));
|
|
585023
|
+
const modelFacingMessages = sanitizeHistoryThink(compactedMsgs);
|
|
584849
585024
|
const chatRequest = {
|
|
584850
|
-
messages:
|
|
585025
|
+
messages: modelFacingMessages,
|
|
584851
585026
|
tools: toolDefs,
|
|
584852
585027
|
temperature: this.options.temperature,
|
|
584853
585028
|
maxTokens: this.options.maxTokens,
|
|
@@ -586431,6 +586606,94 @@ ${marker}` : marker);
|
|
|
586431
586606
|
`Stale target preview: ${active.preview}`
|
|
586432
586607
|
].join("\n");
|
|
586433
586608
|
}
|
|
586609
|
+
editReversalPreflightBlock(toolName, args, turn) {
|
|
586610
|
+
if (process.env["OMNIUS_ALLOW_BLIND_EDIT_REVERSAL"] === "1")
|
|
586611
|
+
return null;
|
|
586612
|
+
const replacements = this.extractReplacementEdits(toolName, args);
|
|
586613
|
+
if (replacements.length === 0)
|
|
586614
|
+
return null;
|
|
586615
|
+
for (const replacement of replacements) {
|
|
586616
|
+
const prior = [...this._recentSuccessfulReplacements].reverse().find((entry) => entry.pathKey === replacement.pathKey && entry.oldHash === replacement.newHash && entry.newHash === replacement.oldHash && turn - entry.turn <= 8);
|
|
586617
|
+
if (!prior)
|
|
586618
|
+
continue;
|
|
586619
|
+
const lastReadTurn = this._lastReadTurnByPathKey.get(replacement.pathKey) ?? -1;
|
|
586620
|
+
if (lastReadTurn > prior.turn)
|
|
586621
|
+
continue;
|
|
586622
|
+
return [
|
|
586623
|
+
`[EDIT REVERSAL BLOCKED] ${toolName} would exactly reverse a recent successful edit on ${replacement.path}.`,
|
|
586624
|
+
`Prior edit at turn ${prior.turn}: ${previewInline(prior.oldText)} -> ${previewInline(prior.newText)}.`,
|
|
586625
|
+
`Proposed edit: ${previewInline(replacement.oldText)} -> ${previewInline(replacement.newText)}.`,
|
|
586626
|
+
``,
|
|
586627
|
+
`Do not toggle a target back and forth after verification fails. First file_read the authoritative current file once, then choose one:`,
|
|
586628
|
+
`1. make a different edit based on the fresh file and the latest failure output,`,
|
|
586629
|
+
`2. run a verification command if the current file is already correct, or`,
|
|
586630
|
+
`3. report incomplete/blocked with the concrete failing evidence.`
|
|
586631
|
+
].join("\n");
|
|
586632
|
+
}
|
|
586633
|
+
return null;
|
|
586634
|
+
}
|
|
586635
|
+
noteEditReversalOutcome(toolName, args, result, turn) {
|
|
586636
|
+
const path12 = this.extractPrimaryToolPath(args);
|
|
586637
|
+
if (toolName === "file_read" && path12 && result.success) {
|
|
586638
|
+
this._lastReadTurnByPathKey.set(this.staleEditPathKey(path12), turn);
|
|
586639
|
+
return;
|
|
586640
|
+
}
|
|
586641
|
+
if (!result.success || result.mutated === false)
|
|
586642
|
+
return;
|
|
586643
|
+
const replacements = this.extractReplacementEdits(toolName, args);
|
|
586644
|
+
if (replacements.length === 0)
|
|
586645
|
+
return;
|
|
586646
|
+
for (const replacement of replacements) {
|
|
586647
|
+
this._recentSuccessfulReplacements.push({
|
|
586648
|
+
...replacement,
|
|
586649
|
+
tool: toolName,
|
|
586650
|
+
turn
|
|
586651
|
+
});
|
|
586652
|
+
}
|
|
586653
|
+
if (this._recentSuccessfulReplacements.length > 40) {
|
|
586654
|
+
this._recentSuccessfulReplacements = this._recentSuccessfulReplacements.slice(-40);
|
|
586655
|
+
}
|
|
586656
|
+
}
|
|
586657
|
+
extractReplacementEdits(toolName, args) {
|
|
586658
|
+
if (!args)
|
|
586659
|
+
return [];
|
|
586660
|
+
const out = [];
|
|
586661
|
+
const add3 = (path12, oldText, newText) => {
|
|
586662
|
+
if (typeof path12 !== "string" || !path12.trim())
|
|
586663
|
+
return;
|
|
586664
|
+
if (typeof oldText !== "string" || typeof newText !== "string")
|
|
586665
|
+
return;
|
|
586666
|
+
const normalizedOld = normalizeEditComparable(oldText);
|
|
586667
|
+
const normalizedNew = normalizeEditComparable(newText);
|
|
586668
|
+
if (!normalizedOld || !normalizedNew || normalizedOld === normalizedNew)
|
|
586669
|
+
return;
|
|
586670
|
+
out.push({
|
|
586671
|
+
path: path12.trim(),
|
|
586672
|
+
pathKey: this.staleEditPathKey(path12),
|
|
586673
|
+
oldText: normalizedOld,
|
|
586674
|
+
newText: normalizedNew,
|
|
586675
|
+
oldHash: this.quickHash(normalizedOld),
|
|
586676
|
+
newHash: this.quickHash(normalizedNew)
|
|
586677
|
+
});
|
|
586678
|
+
};
|
|
586679
|
+
if (toolName === "file_edit") {
|
|
586680
|
+
add3(this.extractPrimaryToolPath(args), args["old_string"] ?? args["oldString"] ?? args["oldText"], args["new_string"] ?? args["newString"] ?? args["newText"]);
|
|
586681
|
+
return out;
|
|
586682
|
+
}
|
|
586683
|
+
if (toolName === "batch_edit") {
|
|
586684
|
+
const fallbackPath = this.extractPrimaryToolPath(args);
|
|
586685
|
+
const edits = args["edits"];
|
|
586686
|
+
if (!Array.isArray(edits))
|
|
586687
|
+
return out;
|
|
586688
|
+
for (const edit of edits) {
|
|
586689
|
+
if (!edit || typeof edit !== "object")
|
|
586690
|
+
continue;
|
|
586691
|
+
const rec = edit;
|
|
586692
|
+
add3(rec["path"] ?? rec["file"] ?? rec["filePath"] ?? rec["file_path"] ?? fallbackPath, rec["old_string"] ?? rec["oldString"] ?? rec["oldText"], rec["new_string"] ?? rec["newString"] ?? rec["newText"]);
|
|
586693
|
+
}
|
|
586694
|
+
}
|
|
586695
|
+
return out;
|
|
586696
|
+
}
|
|
586434
586697
|
noteStaleEditGuardOutcome(toolName, args, result, turn) {
|
|
586435
586698
|
const path12 = this.extractPrimaryToolPath(args);
|
|
586436
586699
|
const pathKey = path12 ? this.staleEditPathKey(path12) : "";
|
|
@@ -614782,6 +615045,129 @@ function loadSessionContext(repoRoot) {
|
|
|
614782
615045
|
return null;
|
|
614783
615046
|
}
|
|
614784
615047
|
}
|
|
615048
|
+
function readJsonOrNull(filePath) {
|
|
615049
|
+
try {
|
|
615050
|
+
if (!existsSync113(filePath)) return null;
|
|
615051
|
+
return JSON.parse(readFileSync90(filePath, "utf-8"));
|
|
615052
|
+
} catch {
|
|
615053
|
+
return null;
|
|
615054
|
+
}
|
|
615055
|
+
}
|
|
615056
|
+
function isManualSessionEntry(entry) {
|
|
615057
|
+
const task = cleanPromptForDiary(entry.task).toLowerCase();
|
|
615058
|
+
const summary = normalizeSessionText(entry.summary || entry.assistantResponse, 160).toLowerCase();
|
|
615059
|
+
return entry.source === "manual" || task === "(manual save)" || entry.toolCalls === 0 && summary.startsWith("manual context save");
|
|
615060
|
+
}
|
|
615061
|
+
function isDeicticContinuationGoal(goal) {
|
|
615062
|
+
const tokens = normalizeSessionText(cleanPromptForDiary(goal), 180).toLowerCase().replace(/[^a-z0-9]+/g, " ").split(/\s+/).filter(Boolean);
|
|
615063
|
+
if (tokens.length === 0 || tokens.length > 14) return false;
|
|
615064
|
+
const hasResumeVerb = tokens.some(
|
|
615065
|
+
(token) => token === "continue" || token === "resume" || token === "proceed" || token === "complete" || token === "finish"
|
|
615066
|
+
);
|
|
615067
|
+
if (!hasResumeVerb) return false;
|
|
615068
|
+
const deicticCount = tokens.filter((token) => DEICTIC_CONTINUATION_TERMS.has(token)).length;
|
|
615069
|
+
return deicticCount / tokens.length >= 0.7;
|
|
615070
|
+
}
|
|
615071
|
+
function readRestoreWorkboard(repoRoot, runId) {
|
|
615072
|
+
if (!runId) return null;
|
|
615073
|
+
return readJsonOrNull(
|
|
615074
|
+
join127(repoRoot, OMNIUS_DIR, "workboards", runId, "active.json")
|
|
615075
|
+
);
|
|
615076
|
+
}
|
|
615077
|
+
function scoreRestoreLedger(ledger, workboard) {
|
|
615078
|
+
const status = ledger.status || "open";
|
|
615079
|
+
if (status === "approved") return -1e3;
|
|
615080
|
+
const evidence = ledger.evidence ?? [];
|
|
615081
|
+
const unresolvedCount = ledger.unresolved?.length ?? 0;
|
|
615082
|
+
const activeCards = (workboard?.cards ?? []).filter(
|
|
615083
|
+
(card) => card.status === "open" || card.status === "in_progress" || card.status === "needs_changes" || card.status === "blocked"
|
|
615084
|
+
).length;
|
|
615085
|
+
const mutationTools = /* @__PURE__ */ new Set(["file_edit", "file_patch", "batch_edit", "file_write"]);
|
|
615086
|
+
const mutationEvidence = evidence.filter((item) => mutationTools.has(item.toolName || "")).length;
|
|
615087
|
+
const failedMutationEvidence = evidence.filter(
|
|
615088
|
+
(item) => mutationTools.has(item.toolName || "") && item.success === false
|
|
615089
|
+
).length;
|
|
615090
|
+
const targetPathEvidence = evidence.filter((item) => (item.targetPaths?.length ?? 0) > 0).length;
|
|
615091
|
+
const blockedEvidence = evidence.filter((item) => {
|
|
615092
|
+
const summary = String(item.summary ?? "").toLowerCase();
|
|
615093
|
+
return summary.includes("[focus supervisor block]") || summary.includes("stale") || summary.includes("blocked");
|
|
615094
|
+
}).length;
|
|
615095
|
+
let score = 0;
|
|
615096
|
+
if (status === "open") score += 10;
|
|
615097
|
+
else if (status === "incomplete_verification") score += 18;
|
|
615098
|
+
else if (status === "request_changes" || status === "blocked") score += 16;
|
|
615099
|
+
else score += 4;
|
|
615100
|
+
score += Math.min(evidence.length, 20);
|
|
615101
|
+
score += Math.min(unresolvedCount, 10) * 4;
|
|
615102
|
+
score += Math.min(activeCards, 8) * 3;
|
|
615103
|
+
score += Math.min(mutationEvidence, 8) * 5;
|
|
615104
|
+
score += Math.min(failedMutationEvidence, 8) * 3;
|
|
615105
|
+
score += Math.min(targetPathEvidence, 6) * 2;
|
|
615106
|
+
score += Math.min(blockedEvidence, 6) * 2;
|
|
615107
|
+
const goal = normalizeSessionText(ledger.goal, 260);
|
|
615108
|
+
if (goal.length >= 80) score += 5;
|
|
615109
|
+
if (isDeicticContinuationGoal(goal) && mutationEvidence === 0 && unresolvedCount === 0 && activeCards === 0) {
|
|
615110
|
+
score -= 25;
|
|
615111
|
+
}
|
|
615112
|
+
return score;
|
|
615113
|
+
}
|
|
615114
|
+
function selectActiveTaskAnchor(repoRoot) {
|
|
615115
|
+
const ledgerDir = join127(repoRoot, OMNIUS_DIR, "completion-ledgers");
|
|
615116
|
+
try {
|
|
615117
|
+
if (!existsSync113(ledgerDir)) return null;
|
|
615118
|
+
const candidates = readdirSync39(ledgerDir).filter((name10) => name10.endsWith(".json")).map((name10) => {
|
|
615119
|
+
const filePath = join127(ledgerDir, name10);
|
|
615120
|
+
const ledger = readJsonOrNull(filePath);
|
|
615121
|
+
if (!ledger || !ledger.goal) return null;
|
|
615122
|
+
const runId = ledger.runId || name10.replace(/\.json$/, "");
|
|
615123
|
+
const workboard = readRestoreWorkboard(repoRoot, runId);
|
|
615124
|
+
const score = scoreRestoreLedger(ledger, workboard);
|
|
615125
|
+
const mtimeMs = statSync42(filePath).mtimeMs;
|
|
615126
|
+
return { ledger: { ...ledger, runId }, workboard, score, mtimeMs };
|
|
615127
|
+
}).filter((item) => Boolean(item));
|
|
615128
|
+
candidates.sort((a2, b) => b.score - a2.score || b.mtimeMs - a2.mtimeMs);
|
|
615129
|
+
const selected = candidates.find((candidate) => candidate.score >= 18);
|
|
615130
|
+
return selected ?? null;
|
|
615131
|
+
} catch {
|
|
615132
|
+
return null;
|
|
615133
|
+
}
|
|
615134
|
+
}
|
|
615135
|
+
function buildActiveTaskAnchor(repoRoot) {
|
|
615136
|
+
const selected = selectActiveTaskAnchor(repoRoot);
|
|
615137
|
+
if (!selected) return null;
|
|
615138
|
+
const ledger = selected.ledger;
|
|
615139
|
+
const evidence = ledger.evidence ?? [];
|
|
615140
|
+
const selectedEvidence = [...evidence.slice(0, 2), ...evidence.slice(-4)];
|
|
615141
|
+
const seenEvidence = /* @__PURE__ */ new Set();
|
|
615142
|
+
const evidenceLines = selectedEvidence.flatMap((item) => {
|
|
615143
|
+
const summary = normalizeSessionText(item.summary, 240);
|
|
615144
|
+
if (!summary || seenEvidence.has(summary)) return [];
|
|
615145
|
+
seenEvidence.add(summary);
|
|
615146
|
+
const status = item.success === false ? "failed" : item.success === true ? "ok" : "observed";
|
|
615147
|
+
const tool = item.toolName || "evidence";
|
|
615148
|
+
return [`- ${tool} ${status}: ${summary}`];
|
|
615149
|
+
});
|
|
615150
|
+
const unresolvedLines = (ledger.unresolved ?? []).slice(0, 4).map((item) => `- ${normalizeSessionText(item.text, 180)}`).filter((line) => line !== "- ");
|
|
615151
|
+
const boardCards = (selected.workboard?.cards ?? []).filter((card) => card.status !== "completed" && card.status !== "verified").slice(0, 5).map((card) => {
|
|
615152
|
+
const title = normalizeSessionText(card.title || card.id, 120);
|
|
615153
|
+
const status = card.status || "open";
|
|
615154
|
+
const lane = card.lane ? `/${card.lane}` : "";
|
|
615155
|
+
const evidenceCount = Array.isArray(card.evidence) ? card.evidence.length : 0;
|
|
615156
|
+
return `- ${title} (${status}${lane}, evidence=${evidenceCount})`;
|
|
615157
|
+
});
|
|
615158
|
+
return `<active-task-anchor>
|
|
615159
|
+
Source: completion ledger ${ledger.runId || "(unknown run)"}; status=${ledger.status || "open"}
|
|
615160
|
+
Goal: ${normalizeSessionText(ledger.goal, 420)}
|
|
615161
|
+
Recorded evidence: ${evidence.length}; unresolved items: ${ledger.unresolved?.length ?? 0}
|
|
615162
|
+
` + (evidenceLines.length > 0 ? `Material evidence:
|
|
615163
|
+
${evidenceLines.join("\n")}
|
|
615164
|
+
` : "") + (unresolvedLines.length > 0 ? `Unresolved:
|
|
615165
|
+
${unresolvedLines.join("\n")}
|
|
615166
|
+
` : "") + (boardCards.length > 0 ? `Active workboard cards:
|
|
615167
|
+
${boardCards.join("\n")}
|
|
615168
|
+
` : "") + `Continuation rule: when the user asks to continue, resume this active task unless the new prompt names a different target.
|
|
615169
|
+
</active-task-anchor>`;
|
|
615170
|
+
}
|
|
614785
615171
|
function formatSessionHistoryDisplay(ctx3) {
|
|
614786
615172
|
return buildSessionHistoryBoxLines(
|
|
614787
615173
|
sessionContextToHistoryBoxData(ctx3),
|
|
@@ -614810,18 +615196,23 @@ function sessionContextToHistoryBoxData(ctx3, title = "Session History") {
|
|
|
614810
615196
|
function buildContextRestorePrompt(repoRoot) {
|
|
614811
615197
|
const ctx3 = loadSessionContext(repoRoot);
|
|
614812
615198
|
const handoffPrompt = buildHandoffPrompt(repoRoot);
|
|
615199
|
+
const activeTaskAnchor = buildActiveTaskAnchor(repoRoot);
|
|
614813
615200
|
if (handoffPrompt) {
|
|
615201
|
+
const usefulEntries2 = (ctx3?.entries ?? []).filter((entry) => !isManualSessionEntry(entry));
|
|
614814
615202
|
const baseCtx = ctx3 && ctx3.entries.length > 0 ? `
|
|
614815
615203
|
|
|
614816
615204
|
<session-recap>
|
|
614817
|
-
Recent tasks: ${ctx3.entries.slice(-3).map(
|
|
615205
|
+
Recent tasks: ${(usefulEntries2.length > 0 ? usefulEntries2 : ctx3.entries).slice(-3).map(
|
|
614818
615206
|
(e2) => `[${e2.completed ? "done" : "partial"}] ${normalizeSessionText(e2.summary || e2.task, 80)}`
|
|
614819
615207
|
).join(", ")}
|
|
614820
615208
|
</session-recap>` : "";
|
|
614821
|
-
return handoffPrompt +
|
|
615209
|
+
return handoffPrompt + (activeTaskAnchor ? `
|
|
615210
|
+
|
|
615211
|
+
${activeTaskAnchor}` : "") + baseCtx;
|
|
614822
615212
|
}
|
|
614823
|
-
if (!ctx3 || ctx3.entries.length === 0) return
|
|
614824
|
-
const
|
|
615213
|
+
if (!ctx3 || ctx3.entries.length === 0) return activeTaskAnchor;
|
|
615214
|
+
const usefulEntries = ctx3.entries.filter((entry) => !isManualSessionEntry(entry));
|
|
615215
|
+
const recent = (usefulEntries.length > 0 ? usefulEntries : ctx3.entries).slice(-5);
|
|
614825
615216
|
const chronology = recent.map((e2) => {
|
|
614826
615217
|
const status = e2.completed ? "done" : "partial";
|
|
614827
615218
|
const summary = normalizeSessionText(e2.assistantResponse || e2.summary || e2.task, 140);
|
|
@@ -614829,8 +615220,8 @@ Recent tasks: ${ctx3.entries.slice(-3).map(
|
|
|
614829
615220
|
const files = e2.filesModified && e2.filesModified.length > 0 ? ` | files: ${e2.filesModified.slice(0, 3).join(", ")}` : "";
|
|
614830
615221
|
return `[${status}] ${summary}${tools}${files}`;
|
|
614831
615222
|
});
|
|
614832
|
-
const last2 = ctx3.entries[ctx3.entries.length - 1];
|
|
614833
|
-
const lastCompleted = [...
|
|
615223
|
+
const last2 = recent[recent.length - 1] ?? ctx3.entries[ctx3.entries.length - 1];
|
|
615224
|
+
const lastCompleted = [...usefulEntries].reverse().find((entry) => entry.completed);
|
|
614834
615225
|
const latestCompleted = lastCompleted ? `Latest completed task: ${normalizeSessionText(lastCompleted.assistantResponse || lastCompleted.summary || lastCompleted.task, 180)}` : "";
|
|
614835
615226
|
const recentDialogue = recent.slice(-3).map((entry) => {
|
|
614836
615227
|
const assistant = normalizeSessionText(entry.assistantResponse || entry.summary, 320) || "(no assistant reply captured)";
|
|
@@ -614843,15 +615234,18 @@ Provenance: ${last2.provenance} (file_read to expand)` : "";
|
|
|
614843
615234
|
const kg = `
|
|
614844
615235
|
KG summary: .omnius/context/kg-summary/latest.md (file_read to expand; legacy pointer: .omnius/context/kg-summary-latest.md)`;
|
|
614845
615236
|
return `<session-recap>
|
|
614846
|
-
|
|
615237
|
+
` + (activeTaskAnchor ? `${activeTaskAnchor}
|
|
615238
|
+
|
|
615239
|
+
` : "") + `Project chronology (older to newer):
|
|
614847
615240
|
${chronology.join("\n")}
|
|
614848
615241
|
` + (latestCompleted ? `
|
|
614849
615242
|
${latestCompleted}
|
|
614850
615243
|
` : "\n") + `
|
|
614851
615244
|
Most recent exchanges (older to newer):
|
|
614852
615245
|
${recentDialogue}
|
|
614853
|
-
|
|
614854
|
-
|
|
615246
|
+
` + (activeTaskAnchor ? `For continuation prompts, resume the active task anchor above; use chronology only to avoid repeating completed work.${prov}${kg}
|
|
615247
|
+
` : `Continue from the latest exchange and do not repeat completed work.${prov}${kg}
|
|
615248
|
+
`) + `</session-recap>`;
|
|
614855
615249
|
}
|
|
614856
615250
|
function getLastTaskSummary(repoRoot) {
|
|
614857
615251
|
const ctx3 = loadSessionContext(repoRoot);
|
|
@@ -615174,7 +615568,7 @@ function deleteUsageRecord(kind, value2, repoRoot) {
|
|
|
615174
615568
|
remove(join127(repoRoot, OMNIUS_DIR, USAGE_HISTORY_FILE));
|
|
615175
615569
|
}
|
|
615176
615570
|
}
|
|
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;
|
|
615571
|
+
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
615572
|
var init_omnius_directory = __esm({
|
|
615179
615573
|
"packages/cli/src/tui/omnius-directory.ts"() {
|
|
615180
615574
|
"use strict";
|
|
@@ -615207,6 +615601,34 @@ var init_omnius_directory = __esm({
|
|
|
615207
615601
|
LOCK_TIMEOUT_MS = 5e3;
|
|
615208
615602
|
LOCK_RETRY_MS = 50;
|
|
615209
615603
|
LOCK_RETRY_MAX = 100;
|
|
615604
|
+
DEICTIC_CONTINUATION_TERMS = /* @__PURE__ */ new Set([
|
|
615605
|
+
"again",
|
|
615606
|
+
"and",
|
|
615607
|
+
"back",
|
|
615608
|
+
"carry",
|
|
615609
|
+
"complete",
|
|
615610
|
+
"continue",
|
|
615611
|
+
"finish",
|
|
615612
|
+
"from",
|
|
615613
|
+
"last",
|
|
615614
|
+
"latest",
|
|
615615
|
+
"left",
|
|
615616
|
+
"my",
|
|
615617
|
+
"off",
|
|
615618
|
+
"please",
|
|
615619
|
+
"previous",
|
|
615620
|
+
"prior",
|
|
615621
|
+
"proceed",
|
|
615622
|
+
"request",
|
|
615623
|
+
"resume",
|
|
615624
|
+
"task",
|
|
615625
|
+
"that",
|
|
615626
|
+
"the",
|
|
615627
|
+
"this",
|
|
615628
|
+
"to",
|
|
615629
|
+
"try",
|
|
615630
|
+
"work"
|
|
615631
|
+
]);
|
|
615210
615632
|
SESSIONS_DIR = "sessions";
|
|
615211
615633
|
SESSIONS_INDEX = "sessions-index.json";
|
|
615212
615634
|
SKIP_DIRS3 = /* @__PURE__ */ new Set([
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnius",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.389",
|
|
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.389",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"image-to-ascii"
|
|
12
12
|
],
|
package/package.json
CHANGED