omnius 1.0.346 → 1.0.347
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 +88 -17
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -567219,7 +567219,7 @@ function adversarySystemPrompt() {
|
|
|
567219
567219
|
"",
|
|
567220
567220
|
"Given the agent's latest message and recent tool outcomes, decide whether the claim is proven.",
|
|
567221
567221
|
"Respond with ONLY a JSON object, no prose, no code fences:",
|
|
567222
|
-
'{"class":"false_success|unproven_claim|weak_evidence|false_failure|ok",',
|
|
567222
|
+
'{"class":"false_success|unproven_claim|weak_evidence|false_failure|repeated_action|ok",',
|
|
567223
567223
|
' "shortText":"<=12 word headline",',
|
|
567224
567224
|
' "confidence":0.0-1.0, // how strongly the claim is NOT proven',
|
|
567225
567225
|
' "details":"2-4 sentence skeptical critique citing the specific gap",',
|
|
@@ -567232,6 +567232,24 @@ function adversarySystemPrompt() {
|
|
|
567232
567232
|
function buildObservationPrompt(obs, recentLedger) {
|
|
567233
567233
|
const outcomes = obs.recentToolOutcomes.slice(-8).map((o2) => ` - ${o2.tool}: ${o2.succeeded ? "OK" : "FAIL"} — ${o2.preview.slice(0, 120)}`).join("\n");
|
|
567234
567234
|
const priorDoubts = recentLedger.slice(-3).filter((e2) => e2.verdict !== "ok").map((e2) => ` - turn ${e2.turn}: ${e2.verdict} — demanded: ${e2.demand}`).join("\n");
|
|
567235
|
+
if (obs.loopSignal) {
|
|
567236
|
+
const ls2 = obs.loopSignal;
|
|
567237
|
+
return [
|
|
567238
|
+
`The agent has repeated the SAME action ${ls2.count}× this run: ${ls2.tool} on ${ls2.target}.`,
|
|
567239
|
+
`This is a loop. Reason about WHY — for THIS specific call, not generically.`,
|
|
567240
|
+
ls2.alreadyHave ? `Evidence the agent ALREADY obtained from a prior identical call:
|
|
567241
|
+
${ls2.alreadyHave.slice(0, 900)}` : `(No cached result available for the repeated call.)`,
|
|
567242
|
+
"",
|
|
567243
|
+
"Agent's latest message:",
|
|
567244
|
+
obs.assistantText.slice(0, 1200) || "(empty)",
|
|
567245
|
+
"",
|
|
567246
|
+
"Recent tool outcomes:",
|
|
567247
|
+
outcomes || " (none)",
|
|
567248
|
+
"",
|
|
567249
|
+
`Decide: does the agent already HAVE what this repeated call would return (class "repeated_action"), and if so what should it do INSTEAD? Be concrete — cite the specific content above, name the next action. If the repeat is actually justified (state genuinely changed), say class "ok".`,
|
|
567250
|
+
"Return ONLY the JSON object."
|
|
567251
|
+
].join("\n");
|
|
567252
|
+
}
|
|
567235
567253
|
return [
|
|
567236
567254
|
obs.claimsCompletion ? "The agent is asserting COMPLETION this turn." : "The agent produced a progress/success-flavored claim this turn.",
|
|
567237
567255
|
"",
|
|
@@ -567263,6 +567281,7 @@ function parseAdversaryCritique(raw) {
|
|
|
567263
567281
|
}
|
|
567264
567282
|
const cls = String(obj["class"] ?? "").toLowerCase();
|
|
567265
567283
|
const valid = [
|
|
567284
|
+
"repeated_action",
|
|
567266
567285
|
"false_success",
|
|
567267
567286
|
"unproven_claim",
|
|
567268
567287
|
"weak_evidence",
|
|
@@ -567316,17 +567335,22 @@ var init_adversaryStream = __esm({
|
|
|
567316
567335
|
shouldAudit(obs) {
|
|
567317
567336
|
if (obs.claimsCompletion)
|
|
567318
567337
|
return true;
|
|
567338
|
+
if (obs.loopSignal)
|
|
567339
|
+
return true;
|
|
567319
567340
|
return SUCCESS_LANGUAGE.test(obs.assistantText);
|
|
567320
567341
|
}
|
|
567321
567342
|
/** Ingest an observation. Replaces any prior un-audited pending observation. */
|
|
567322
567343
|
observe(obs) {
|
|
567323
567344
|
if (!this.shouldAudit(obs))
|
|
567324
567345
|
return;
|
|
567325
|
-
const
|
|
567346
|
+
const loopKey = obs.loopSignal ? `loop:${obs.loopSignal.tool}:${obs.loopSignal.target}:${obs.loopSignal.count}` : "";
|
|
567347
|
+
const sig = `${obs.turn}:${loopKey}:${obs.assistantText.slice(0, 200)}`;
|
|
567326
567348
|
if (sig === this.lastAuditedSignature)
|
|
567327
567349
|
return;
|
|
567328
567350
|
this.pending = obs;
|
|
567351
|
+
this._pendingSig = sig;
|
|
567329
567352
|
}
|
|
567353
|
+
_pendingSig = "";
|
|
567330
567354
|
/**
|
|
567331
567355
|
* Fire the adversary inference if there is a pending observation and no call
|
|
567332
567356
|
* in flight. Detached/non-blocking — resolves when (or if) a critique lands.
|
|
@@ -567337,21 +567361,23 @@ var init_adversaryStream = __esm({
|
|
|
567337
567361
|
return null;
|
|
567338
567362
|
const obs = this.pending;
|
|
567339
567363
|
this.pending = null;
|
|
567340
|
-
this.lastAuditedSignature = `${obs.turn}:${obs.assistantText.slice(0, 200)}`;
|
|
567364
|
+
this.lastAuditedSignature = this._pendingSig || `${obs.turn}:${obs.assistantText.slice(0, 200)}`;
|
|
567341
567365
|
this.inFlight = true;
|
|
567342
567366
|
try {
|
|
567343
|
-
|
|
567344
|
-
|
|
567345
|
-
|
|
567346
|
-
|
|
567347
|
-
|
|
567348
|
-
|
|
567349
|
-
|
|
567350
|
-
|
|
567351
|
-
|
|
567352
|
-
|
|
567353
|
-
|
|
567354
|
-
|
|
567367
|
+
let critique2 = null;
|
|
567368
|
+
for (let attempt = 0; attempt < 2 && !critique2; attempt++) {
|
|
567369
|
+
const resp = await this.backend.chatCompletion({
|
|
567370
|
+
messages: [
|
|
567371
|
+
{ role: "system", content: adversarySystemPrompt() },
|
|
567372
|
+
{ role: "user", content: buildObservationPrompt(obs, this.ledger) }
|
|
567373
|
+
],
|
|
567374
|
+
tools: [],
|
|
567375
|
+
temperature: 0,
|
|
567376
|
+
maxTokens: 900,
|
|
567377
|
+
timeoutMs: this.timeoutMs
|
|
567378
|
+
});
|
|
567379
|
+
critique2 = parseAdversaryCritique(resp.choices?.[0]?.message?.content ?? "");
|
|
567380
|
+
}
|
|
567355
567381
|
if (!critique2)
|
|
567356
567382
|
return null;
|
|
567357
567383
|
this.ledger.push({
|
|
@@ -570624,6 +570650,29 @@ Your hypotheses MUST address this specific error, not generic causes.
|
|
|
570624
570650
|
}
|
|
570625
570651
|
return best && best.count >= 3 ? best : null;
|
|
570626
570652
|
}
|
|
570653
|
+
/**
|
|
570654
|
+
* Backend adapter for AUXILIARY inference (adversary critiques, branch
|
|
570655
|
+
* extraction) — tool-less, think-off, JSON-shaped calls. The main backend's
|
|
570656
|
+
* chatCompletion routes to Ollama's /v1/chat/completions, where qwen3-family
|
|
570657
|
+
* models IGNORE think:false and /no_think and (with no tools to anchor
|
|
570658
|
+
* output) emit a reasoning-only response that gets stripped to EMPTY. The
|
|
570659
|
+
* native /api/chat path honors think:false. This adapter prefers it and sets
|
|
570660
|
+
* a responseFormat so the native path enforces JSON mode. Falls back to
|
|
570661
|
+
* chatCompletion for non-Ollama backends.
|
|
570662
|
+
*/
|
|
570663
|
+
_auxInferenceBackend() {
|
|
570664
|
+
const b = this.backend;
|
|
570665
|
+
const useNative = typeof b.nativeOllamaChatCompletion === "function";
|
|
570666
|
+
return {
|
|
570667
|
+
chatCompletion: (req3) => {
|
|
570668
|
+
const r2 = {
|
|
570669
|
+
...req3,
|
|
570670
|
+
responseFormat: req3.responseFormat ?? { type: "json_object" }
|
|
570671
|
+
};
|
|
570672
|
+
return useNative ? b.nativeOllamaChatCompletion(r2) : b.chatCompletion(r2);
|
|
570673
|
+
}
|
|
570674
|
+
};
|
|
570675
|
+
}
|
|
570627
570676
|
/**
|
|
570628
570677
|
* Detect a failing approach and return a decisive root-cause directive, or
|
|
570629
570678
|
* null. Fires when a non-transient error recurs ≥3× in the recent window
|
|
@@ -575187,7 +575236,9 @@ TASK: ${scrubbedTask}` : scrubbedTask;
|
|
|
575187
575236
|
if (this.options.disableAdversaryCritic !== true && this.backend && typeof this.backend.chatCompletion === "function") {
|
|
575188
575237
|
const persistPath = this._workingDirectory ? _pathJoin(this._workingDirectory, ".omnius", "memory", "adversary-stream.json") : null;
|
|
575189
575238
|
this._adversaryStream = new AdversaryStream({
|
|
575190
|
-
|
|
575239
|
+
// Native /api/chat (think:false honored) — NOT /v1, which returns empty
|
|
575240
|
+
// for tool-less think-off calls on qwen3-family models.
|
|
575241
|
+
backend: this._auxInferenceBackend(),
|
|
575191
575242
|
persistPath,
|
|
575192
575243
|
onCritique: (critique2, sourceTurn) => {
|
|
575193
575244
|
if (this._adversaryMode === "skillcoach" || this._adversaryMode === "both") {
|
|
@@ -577755,6 +577806,24 @@ Use the saved fact to continue the promised synthesis or next concrete step, or
|
|
|
577755
577806
|
},
|
|
577756
577807
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
577757
577808
|
});
|
|
577809
|
+
if (this._adversaryStream && criticDecision.hitNumber >= 2) {
|
|
577810
|
+
const _args = tc.arguments;
|
|
577811
|
+
const _target = String(_args?.["path"] ?? _args?.["file"] ?? _args?.["command"] ?? JSON.stringify(_args ?? {}).slice(0, 80));
|
|
577812
|
+
this._adversaryStream.observe({
|
|
577813
|
+
turn,
|
|
577814
|
+
assistantText: "",
|
|
577815
|
+
recentToolOutcomes: this._adversaryToolOutcomes.slice(-8).map((o2) => ({ tool: o2.tool, succeeded: o2.succeeded, preview: o2.preview })),
|
|
577816
|
+
claimsCompletion: false,
|
|
577817
|
+
loopSignal: {
|
|
577818
|
+
tool: tc.name,
|
|
577819
|
+
target: _target,
|
|
577820
|
+
count: criticDecision.hitNumber,
|
|
577821
|
+
alreadyHave: _existingFp?.result
|
|
577822
|
+
}
|
|
577823
|
+
});
|
|
577824
|
+
void this._adversaryStream.tick().catch(() => {
|
|
577825
|
+
});
|
|
577826
|
+
}
|
|
577758
577827
|
const _repeatGateMax = this._resolveRepeatGateMax();
|
|
577759
577828
|
const repeatGateEligible = isReadLike || tc.name === "memory_write";
|
|
577760
577829
|
if (repeatGateEligible && _existingFp !== void 0 && _repeatGateMax > 0) {
|
|
@@ -578868,7 +578937,9 @@ Respond with EXACTLY this structure before your next tool call:
|
|
|
578868
578937
|
content: fullContent,
|
|
578869
578938
|
// the REAL body, not the preview
|
|
578870
578939
|
fileVersion: this._worldFacts.files.get(pRaw)?.writeCount ?? 0,
|
|
578871
|
-
|
|
578940
|
+
// Native /api/chat so the extractor LLM fallback isn't
|
|
578941
|
+
// silently empty on qwen3-family models.
|
|
578942
|
+
backend: this._auxInferenceBackend(),
|
|
578872
578943
|
timeoutMs: 3e4
|
|
578873
578944
|
});
|
|
578874
578945
|
output = [
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnius",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.347",
|
|
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.347",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"image-to-ascii"
|
|
12
12
|
],
|
package/package.json
CHANGED