omnius 1.0.539 → 1.0.541

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -573266,6 +573266,9 @@ function trajectoryCheckpointFingerprint(checkpoint) {
573266
573266
  checkpoint.goal,
573267
573267
  checkpoint.phase ?? "",
573268
573268
  checkpoint.currentStep ?? "",
573269
+ checkpoint.situationAssessment ?? "",
573270
+ checkpoint.groundingSource ?? "",
573271
+ checkpoint.groundingEvidenceRefs?.join("") ?? "",
573269
573272
  checkpoint.completedWork.join(""),
573270
573273
  checkpoint.groundedFacts.map((fact) => `${fact.statement}\0${fact.evidence}\0${fact.freshness}`).join(""),
573271
573274
  checkpoint.openQuestions.join(""),
@@ -573381,19 +573384,39 @@ function buildTrajectoryCheckpoint(input) {
573381
573384
  if (state.pendingSteps.length > 0 && !state.nextAction.trim()) {
573382
573385
  openQuestions.push(`Choose the next pending task: ${sanitizeTrajectoryText(state.pendingSteps[0], 180)}`);
573383
573386
  }
573387
+ const generated = input.generatedGrounding ?? null;
573388
+ const canUseGenerated = Boolean(generated?.situationAssessment);
573389
+ const groundingSource = canUseGenerated ? "model" : "deterministic";
573390
+ const situationAssessment = canUseGenerated ? sanitizeTrajectoryText(generated?.situationAssessment, 420) : deterministicSituationAssessment({
573391
+ goal,
573392
+ outcomeText,
573393
+ focus,
573394
+ assessment,
573395
+ targetPath
573396
+ });
573397
+ const currentStep = canUseGenerated && generated?.currentStep ? sanitizeTrajectoryText(generated.currentStep, 180) : sanitizeTrajectoryText(state.currentStep, 180);
573398
+ const generatedOpenQuestions = canUseGenerated ? generated.openQuestions.map((value2) => sanitizeTrajectoryText(value2, 180)) : [];
573399
+ const generatedConstraints = canUseGenerated ? generated.doNotRepeat.map((value2) => sanitizeTrajectoryText(value2, 220)) : [];
573400
+ if (canUseGenerated && assessment === "on_trajectory") {
573401
+ nextAction = sanitizeTrajectoryText(generated?.nextAction, 320) || nextAction;
573402
+ successEvidence = sanitizeTrajectoryText(generated?.successEvidence, 280) || successEvidence;
573403
+ }
573384
573404
  const checkpointWithoutIdentity = {
573385
573405
  schemaVersion: 1,
573386
573406
  trigger: sanitizeTrajectoryText(input.trigger || inferTrigger(outcome), 80),
573387
573407
  assessment,
573388
573408
  goal,
573389
573409
  phase: sanitizeTrajectoryText(state.phase, 60) || void 0,
573390
- currentStep: sanitizeTrajectoryText(state.currentStep, 180) || void 0,
573410
+ currentStep: currentStep || void 0,
573411
+ situationAssessment,
573412
+ groundingSource,
573413
+ groundingEvidenceRefs: canUseGenerated ? unique2(generated.evidenceRefs, MAX_FACTS) : void 0,
573391
573414
  completedWork,
573392
573415
  groundedFacts: groundedFacts.slice(0, MAX_FACTS),
573393
- openQuestions: unique2(openQuestions, 2),
573416
+ openQuestions: unique2([...openQuestions, ...generatedOpenQuestions], 2),
573394
573417
  nextAction: sanitizeTrajectoryText(nextAction, 320),
573395
573418
  successEvidence: sanitizeTrajectoryText(successEvidence, 280),
573396
- doNotRepeat: unique2(doNotRepeat, MAX_CONSTRAINTS)
573419
+ doNotRepeat: unique2([...doNotRepeat, ...generatedConstraints], MAX_CONSTRAINTS)
573397
573420
  };
573398
573421
  const fingerprint = trajectoryCheckpointFingerprint(checkpointWithoutIdentity);
573399
573422
  return {
@@ -573411,19 +573434,87 @@ function renderTrajectoryCheckpoint(checkpoint, maxChars = 1100) {
573411
573434
  `Assessment: ${checkpoint.assessment}`,
573412
573435
  checkpoint.phase ? `Phase: ${checkpoint.phase}` : null,
573413
573436
  checkpoint.currentStep ? `Current step: ${checkpoint.currentStep}` : null,
573437
+ // Keep the action contract ahead of explanatory evidence so truncation can
573438
+ // never hide the guard that the main agent must follow.
573439
+ `Required next action: ${checkpoint.nextAction}`,
573440
+ `Success evidence: ${checkpoint.successEvidence}`,
573441
+ checkpoint.situationAssessment ? `${checkpoint.groundingSource === "model" ? "Reasoned situation" : "Safety orientation"}: ${checkpoint.situationAssessment}` : null,
573442
+ checkpoint.groundingEvidenceRefs?.length ? `Grounding evidence: ${checkpoint.groundingEvidenceRefs.join(", ")}` : null,
573414
573443
  checkpoint.completedWork.length > 0 ? `Completed evidence-backed work: ${checkpoint.completedWork.join("; ")}` : null,
573415
573444
  checkpoint.groundedFacts.length > 0 ? "Grounded facts:" : null,
573416
573445
  ...checkpoint.groundedFacts.map((fact) => `- [${fact.evidence}; ${fact.freshness}] ${fact.statement}`),
573417
573446
  checkpoint.openQuestions.length > 0 ? "Open questions:" : null,
573418
573447
  ...checkpoint.openQuestions.map((question) => `- ${question}`),
573419
- `Required next action: ${checkpoint.nextAction}`,
573420
- `Success evidence: ${checkpoint.successEvidence}`,
573421
573448
  checkpoint.doNotRepeat.length > 0 ? "Do not repeat:" : null,
573422
573449
  ...checkpoint.doNotRepeat.map((constraint) => `- ${constraint}`),
573423
573450
  "Attention rule: reconcile the next tool call with this checkpoint. Treat stale or unknown evidence as a reason to read or verify. Do not quote this checkpoint or produce a reasoning transcript."
573424
573451
  ].filter((line) => Boolean(line));
573425
573452
  return truncate(lines.join("\n"), maxChars);
573426
573453
  }
573454
+ function buildTrajectoryGroundingPrompt(checkpoint, supplementalEvidence = []) {
573455
+ const evidenceRefs = [
573456
+ "goal",
573457
+ ...checkpoint.groundedFacts.map((fact) => fact.evidence),
573458
+ "unknown"
573459
+ ];
573460
+ const evidence = supplementalEvidence.map((value2) => sanitizeTrajectoryText(value2, 700)).filter(Boolean).slice(0, 6);
573461
+ return [
573462
+ "[TRAJECTORY GROUNDING REQUEST]",
573463
+ "Before the main agent takes its first action, form a compact, task-specific orientation from the supplied evidence.",
573464
+ "Reason about what is known, what remains unknown, and why the next action is the best immediate move. Do not use generic filler such as 'take a narrow action'.",
573465
+ "Do not invent files, source contents, tool results, verification results, or completed work. Do not reveal private chain-of-thought; provide only a concise, auditable situation assessment.",
573466
+ "The deterministic assessment and constraints below are safety facts. You may refine the plan, but never weaken a recovery, verification, or blocker constraint.",
573467
+ "Return ONLY JSON with this schema:",
573468
+ JSON.stringify({
573469
+ situation_assessment: "1-3 concise, evidence-bound sentences",
573470
+ current_step: "optional concrete current phase",
573471
+ open_questions: ["specific unknown that gates the next action"],
573472
+ next_action: "one concrete next action",
573473
+ success_evidence: "what observable result proves the action helped",
573474
+ do_not_repeat: ["specific unsafe or ungrounded retry to avoid"],
573475
+ evidence_refs: ["one or more labels from allowed_evidence_refs"]
573476
+ }),
573477
+ "Authoritative trajectory input:",
573478
+ JSON.stringify({
573479
+ goal: checkpoint.goal,
573480
+ assessment: checkpoint.assessment,
573481
+ current_step: checkpoint.currentStep,
573482
+ completed_work: checkpoint.completedWork,
573483
+ grounded_facts: checkpoint.groundedFacts,
573484
+ open_questions: checkpoint.openQuestions,
573485
+ required_next_action: checkpoint.nextAction,
573486
+ success_evidence: checkpoint.successEvidence,
573487
+ do_not_repeat: checkpoint.doNotRepeat,
573488
+ allowed_evidence_refs: evidenceRefs,
573489
+ supplemental_evidence: evidence
573490
+ }, null, 2)
573491
+ ].join("\n\n");
573492
+ }
573493
+ function parseTrajectoryGeneratedGrounding(raw, allowedEvidenceRefs) {
573494
+ const parsed = parseJsonObject3(raw);
573495
+ if (!parsed)
573496
+ return null;
573497
+ const situationAssessment = sanitizeTrajectoryText(parsed["situation_assessment"] ?? parsed["situationAssessment"], 420);
573498
+ if (!situationAssessment)
573499
+ return null;
573500
+ const allowed = /* @__PURE__ */ new Set([
573501
+ "goal",
573502
+ "unknown",
573503
+ ...allowedEvidenceRefs.map((value2) => sanitizeTrajectoryText(value2, 160))
573504
+ ]);
573505
+ const refs = stringArray3(parsed["evidence_refs"] ?? parsed["evidenceRefs"], 5).filter((value2) => allowed.has(value2));
573506
+ return {
573507
+ situationAssessment,
573508
+ currentStep: sanitizeTrajectoryText(parsed["current_step"] ?? parsed["currentStep"], 180) || void 0,
573509
+ openQuestions: stringArray3(parsed["open_questions"] ?? parsed["openQuestions"], 3),
573510
+ nextAction: sanitizeTrajectoryText(parsed["next_action"] ?? parsed["nextAction"], 320) || void 0,
573511
+ successEvidence: sanitizeTrajectoryText(parsed["success_evidence"] ?? parsed["successEvidence"], 280) || void 0,
573512
+ doNotRepeat: stringArray3(parsed["do_not_repeat"] ?? parsed["doNotRepeat"], MAX_CONSTRAINTS),
573513
+ // A goal is always an allowed fact; retain it as a conservative fallback
573514
+ // for models that omit the optional citation field.
573515
+ evidenceRefs: refs.length > 0 ? unique2(refs, MAX_FACTS) : ["goal"]
573516
+ };
573517
+ }
573427
573518
  function scopeTrajectoryCheckpoint(checkpoint, delegatedScope, exitEvidence) {
573428
573519
  if (!checkpoint)
573429
573520
  return null;
@@ -573521,6 +573612,41 @@ function extractFocusNextAction(value2) {
573521
573612
  function unique2(values, limit) {
573522
573613
  return [...new Set(values.map((value2) => sanitizeTrajectoryText(value2)).filter(Boolean))].slice(0, limit);
573523
573614
  }
573615
+ function deterministicSituationAssessment(input) {
573616
+ if (input.outcomeText) {
573617
+ return `The latest observed result is ${input.outcomeText}. The next step must respond to that evidence rather than assume the task state changed.`;
573618
+ }
573619
+ if (input.focus) {
573620
+ return `An active recovery directive is present: ${input.focus}. It takes precedence over a generic continuation plan.`;
573621
+ }
573622
+ if (input.assessment !== "on_trajectory") {
573623
+ return `The runner has classified this task as ${input.assessment.replace(/_/g, " ")}${input.targetPath ? ` around ${input.targetPath}` : ""}; preserve the stated safety contract while collecting the next observation.`;
573624
+ }
573625
+ return `No file, tool, or verifier observation has been recorded yet for "${input.goal}". Treat the user goal as the only established fact until the first project observation is made.`;
573626
+ }
573627
+ function parseJsonObject3(raw) {
573628
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
573629
+ return raw;
573630
+ }
573631
+ const text2 = String(raw ?? "").trim();
573632
+ if (!text2)
573633
+ return null;
573634
+ const start2 = text2.indexOf("{");
573635
+ const end = text2.lastIndexOf("}");
573636
+ if (start2 < 0 || end <= start2)
573637
+ return null;
573638
+ try {
573639
+ const parsed = JSON.parse(text2.slice(start2, end + 1));
573640
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
573641
+ } catch {
573642
+ return null;
573643
+ }
573644
+ }
573645
+ function stringArray3(value2, limit) {
573646
+ if (!Array.isArray(value2))
573647
+ return [];
573648
+ return unique2(value2.map((item) => sanitizeTrajectoryText(item, 280)), limit);
573649
+ }
573524
573650
  function truncate(value2, max) {
573525
573651
  const clean5 = String(value2 ?? "").trim();
573526
573652
  return clean5.length > max ? `${clean5.slice(0, Math.max(0, max - 1))}…` : clean5;
@@ -579225,6 +579351,9 @@ function recordDebugTrajectoryCheckpoint(input) {
579225
579351
  trajectory: {
579226
579352
  revision: checkpoint.revision,
579227
579353
  assessment: checkpoint.assessment,
579354
+ groundingSource: checkpoint.groundingSource,
579355
+ situationAssessment: checkpoint.situationAssessment ? trim(checkpoint.situationAssessment, 700) : void 0,
579356
+ groundingEvidenceRefs: checkpoint.groundingEvidenceRefs?.slice(0, 5).map((value2) => trim(value2, 160)),
579228
579357
  nextAction: trim(checkpoint.nextAction, 500),
579229
579358
  successEvidence: trim(checkpoint.successEvidence, 500),
579230
579359
  doNotRepeat: checkpoint.doNotRepeat.slice(0, 3).map((value2) => trim(value2, 300))
@@ -585808,6 +585937,16 @@ function resolveTrajectoryCheckpointCadence(explicit) {
585808
585937
  const candidate = typeof explicit === "number" ? explicit : Number(process.env["OMNIUS_TRAJECTORY_CHECKPOINT_EVERY_TURNS"] ?? 4);
585809
585938
  return Number.isFinite(candidate) ? Math.max(1, Math.min(32, Math.floor(candidate))) : 4;
585810
585939
  }
585940
+ function resolveTrajectoryGroundingMode(explicit, subAgent) {
585941
+ if (explicit === "off" || explicit === "initial" || explicit === "adaptive") {
585942
+ return explicit;
585943
+ }
585944
+ const env2 = String(process.env["OMNIUS_TRAJECTORY_GROUNDING"] ?? "").trim().toLowerCase();
585945
+ if (env2 === "off" || env2 === "initial" || env2 === "adaptive") {
585946
+ return env2;
585947
+ }
585948
+ return subAgent ? "off" : "adaptive";
585949
+ }
585811
585950
  function upsertContextFrame(messages2, frame, marker = "[ACTIVE CONTEXT FRAME]") {
585812
585951
  for (let i2 = messages2.length - 1; i2 >= 0; i2--) {
585813
585952
  const m2 = messages2[i2];
@@ -586673,6 +586812,9 @@ var init_agenticRunner = __esm({
586673
586812
  _trajectoryRevision = 0;
586674
586813
  _trajectoryDirtyCauses = /* @__PURE__ */ new Set();
586675
586814
  _trajectoryLastEmittedToolCall = -1;
586815
+ _trajectoryGroundingAttemptedFingerprint = "";
586816
+ _trajectoryGroundingFingerprint = "";
586817
+ _trajectoryGeneratedGrounding = null;
586676
586818
  // -- File State Registry (SWE-agent inspired) --
586677
586819
  _fileRegistry = /* @__PURE__ */ new Map();
586678
586820
  // -- Memex Experience Archive (arXiv:2603.04257 inspired) --
@@ -588115,6 +588257,7 @@ ${parts.join("\n")}
588115
588257
  focusSupervisor: resolveFocusSupervisorMode(options2?.focusSupervisor),
588116
588258
  trajectoryCheckpoint: resolveTrajectoryCheckpointMode(options2?.trajectoryCheckpoint),
588117
588259
  trajectoryCheckpointEveryTurns: resolveTrajectoryCheckpointCadence(options2?.trajectoryCheckpointEveryTurns),
588260
+ trajectoryGrounding: resolveTrajectoryGroundingMode(options2?.trajectoryGrounding, options2?.subAgent),
588118
588261
  supervisorModel: options2?.supervisorModel ?? process.env["OMNIUS_SUPERVISOR_MODEL"] ?? "",
588119
588262
  supervisorTimeoutMs: options2?.supervisorTimeoutMs ?? Number(process.env["OMNIUS_SUPERVISOR_TIMEOUT_MS"] ?? 2e4),
588120
588263
  supervisorMaxTokens: options2?.supervisorMaxTokens ?? 900,
@@ -593645,7 +593788,16 @@ ${String(concreteGoal).replace(/\s+/g, " ").trim().slice(0, 1200)}` : null
593645
593788
  const churnBlock = this._renderWriteChurnBlock(turn);
593646
593789
  const focusBlock = this._focusSupervisor?.renderFrame() ?? null;
593647
593790
  const actionContractBlock = this._renderNextActionContract(turn);
593648
- const trajectoryCheckpoint = this._refreshTrajectoryCheckpoint(turn, focusBlock);
593791
+ const trajectoryCheckpoint = await this._refreshTrajectoryCheckpoint(turn, focusBlock, [
593792
+ workspaceTreeBlock,
593793
+ filesystemBlock,
593794
+ todoBlock,
593795
+ gitBlock,
593796
+ failureBlock,
593797
+ churnBlock,
593798
+ actionContractBlock,
593799
+ environmentBlock ?? null
593800
+ ].filter((block) => Boolean(block)));
593649
593801
  const trajectoryBlock = this.options.trajectoryCheckpoint === "shadow" ? null : trajectoryCheckpoint ? renderTrajectoryCheckpoint(trajectoryCheckpoint) : null;
593650
593802
  const toolCacheBlock = recentToolResults ? this._renderKnowledgeBlock(recentToolResults) : null;
593651
593803
  const anchorsBlock = this.surfaceAnchors(messages2);
@@ -594320,12 +594472,13 @@ ${blob}
594320
594472
  this._readCoverage.set(iv.key, pruned.slice(0, 8));
594321
594473
  }
594322
594474
  _dedupeToolCallsForResponse(toolCalls, turn) {
594323
- if (toolCalls.length <= 1)
594324
- return toolCalls;
594475
+ const idDeduped = this._dedupeRepeatedToolCallIdsForResponse(toolCalls, turn);
594476
+ if (idDeduped.length <= 1)
594477
+ return idDeduped;
594325
594478
  const seen = /* @__PURE__ */ new Set();
594326
594479
  const deduped = [];
594327
594480
  let dropped = 0;
594328
- for (const tc of toolCalls) {
594481
+ for (const tc of idDeduped) {
594329
594482
  const fp = this._buildToolFingerprint(tc.name, tc.arguments ?? {});
594330
594483
  if (seen.has(fp)) {
594331
594484
  dropped++;
@@ -594343,6 +594496,36 @@ ${blob}
594343
594496
  }
594344
594497
  return deduped;
594345
594498
  }
594499
+ /**
594500
+ * A provider must never reuse a tool-call ID in one assistant response.
594501
+ * Keep the first occurrence as the canonical call and drop later copies
594502
+ * before either execution or transcript construction. This is deliberately
594503
+ * narrower than fingerprint dedupe: the brute-force loop must still permit
594504
+ * legitimate fresh reads that use distinct call IDs.
594505
+ */
594506
+ _dedupeRepeatedToolCallIdsForResponse(toolCalls, turn) {
594507
+ if (toolCalls.length <= 1)
594508
+ return toolCalls;
594509
+ const seenIds = /* @__PURE__ */ new Set();
594510
+ const deduped = [];
594511
+ let dropped = 0;
594512
+ for (const tc of toolCalls) {
594513
+ if (seenIds.has(tc.id)) {
594514
+ dropped++;
594515
+ continue;
594516
+ }
594517
+ seenIds.add(tc.id);
594518
+ deduped.push(tc);
594519
+ }
594520
+ if (dropped > 0) {
594521
+ this.emit({
594522
+ type: "status",
594523
+ content: `Response ID dedupe: dropped ${dropped} repeated tool call ID${dropped === 1 ? "" : "s"} before execution (turn ${turn})`,
594524
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
594525
+ });
594526
+ }
594527
+ return deduped;
594528
+ }
594346
594529
  _decodeToolFingerprint(fingerprint) {
594347
594530
  const colonIdx = fingerprint.indexOf(":");
594348
594531
  const toolName = colonIdx > 0 ? fingerprint.slice(0, colonIdx) : fingerprint;
@@ -595112,11 +595295,11 @@ ${notice}`;
595112
595295
  * _buildTurnContextFrame(), preventing separate prompt injections from
595113
595296
  * drifting apart or accumulating in history.
595114
595297
  */
595115
- _refreshTrajectoryCheckpoint(turn, focusDirective) {
595298
+ async _refreshTrajectoryCheckpoint(turn, focusDirective, supplementalEvidence = []) {
595116
595299
  if (this.options.trajectoryCheckpoint === "off")
595117
595300
  return null;
595118
595301
  const trigger = [...this._trajectoryDirtyCauses].join(",") || (this._trajectoryCheckpoint ? "cadence" : "task_start");
595119
- const provisional = buildTrajectoryCheckpoint({
595302
+ const buildInput = (generatedGrounding2) => ({
595120
595303
  turn,
595121
595304
  revision: Math.max(1, this._trajectoryRevision || 1),
595122
595305
  trigger,
@@ -595126,8 +595309,12 @@ ${notice}`;
595126
595309
  focusDirective,
595127
595310
  lastVerifier: this._worldFacts.lastTest,
595128
595311
  lastMutationTurn: this._lastFileWriteTurn,
595129
- evidenceFreshness: (path16) => this._trajectoryEvidenceFreshness(path16)
595312
+ evidenceFreshness: (path16) => this._trajectoryEvidenceFreshness(path16),
595313
+ generatedGrounding: generatedGrounding2
595130
595314
  });
595315
+ const deterministic = buildTrajectoryCheckpoint(buildInput());
595316
+ const generatedGrounding = await this._resolveTrajectoryGrounding(deterministic, trigger, turn, supplementalEvidence);
595317
+ const provisional = buildTrajectoryCheckpoint(buildInput(generatedGrounding));
595131
595318
  const { id: _id2, revision: _revision, turn: _turn, ...fingerprintInput } = provisional;
595132
595319
  const fingerprint = trajectoryCheckpointFingerprint(fingerprintInput);
595133
595320
  const changed = fingerprint !== this._trajectoryFingerprint;
@@ -595136,16 +595323,8 @@ ${notice}`;
595136
595323
  this._trajectoryFingerprint = fingerprint;
595137
595324
  }
595138
595325
  const checkpoint = buildTrajectoryCheckpoint({
595139
- turn,
595140
- revision: Math.max(1, this._trajectoryRevision),
595141
- trigger,
595142
- taskState: this._taskState,
595143
- observations: this._trajectoryObservations,
595144
- recentFailures: this._recentFailures,
595145
- focusDirective,
595146
- lastVerifier: this._worldFacts.lastTest,
595147
- lastMutationTurn: this._lastFileWriteTurn,
595148
- evidenceFreshness: (path16) => this._trajectoryEvidenceFreshness(path16)
595326
+ ...buildInput(generatedGrounding),
595327
+ revision: Math.max(1, this._trajectoryRevision)
595149
595328
  });
595150
595329
  this._trajectoryCheckpoint = checkpoint;
595151
595330
  const cadenceReached = this._taskState.toolCallCount - this._trajectoryLastEmittedToolCall >= this.options.trajectoryCheckpointEveryTurns;
@@ -595182,6 +595361,84 @@ ${notice}`;
595182
595361
  }
595183
595362
  return checkpoint;
595184
595363
  }
595364
+ /**
595365
+ * Run one bounded, tool-less orientation pass before the main agent acts.
595366
+ * Its output is treated as advisory language over an authoritative
595367
+ * deterministic safety checkpoint, so it can improve attention without
595368
+ * inventing a new file state or bypassing a recovery constraint.
595369
+ */
595370
+ async _resolveTrajectoryGrounding(checkpoint, trigger, turn, supplementalEvidence) {
595371
+ if (this.options.trajectoryCheckpoint === "shadow" || this.options.trajectoryGrounding === "off") {
595372
+ return null;
595373
+ }
595374
+ const { id: _id2, revision: _revision, turn: _turn, ...base3 } = checkpoint;
595375
+ const baseFingerprint = trajectoryCheckpointFingerprint(base3);
595376
+ if (this._trajectoryGroundingFingerprint === baseFingerprint) {
595377
+ return this._trajectoryGeneratedGrounding;
595378
+ }
595379
+ if (this._trajectoryGroundingAttemptedFingerprint === baseFingerprint) {
595380
+ return null;
595381
+ }
595382
+ const isInitial = !this._trajectoryCheckpoint || /(?:^|,)task_start(?:,|$)/.test(trigger);
595383
+ const assessmentChanged = checkpoint.assessment !== this._trajectoryCheckpoint?.assessment;
595384
+ const materialTrigger = /tool_failure|(?:^|,)error(?:,|$)|user_steering|compaction|status_change/.test(trigger);
595385
+ if (!isInitial && (this.options.trajectoryGrounding === "initial" || !assessmentChanged && !materialTrigger)) {
595386
+ return null;
595387
+ }
595388
+ this._trajectoryGroundingAttemptedFingerprint = baseFingerprint;
595389
+ try {
595390
+ this._emitModelResolutionTelemetry("trajectory_grounding", turn);
595391
+ const backend = this._auxInferenceBackend({
595392
+ dumpStage: "trajectory_grounding"
595393
+ });
595394
+ const response = await backend.chatCompletion({
595395
+ messages: [
595396
+ {
595397
+ role: "system",
595398
+ content: "You are Omnius's pre-action trajectory grounder. Return only the requested JSON. Produce a concrete, evidence-bound orientation, not generic process advice and not private chain-of-thought."
595399
+ },
595400
+ {
595401
+ role: "user",
595402
+ content: buildTrajectoryGroundingPrompt(checkpoint, supplementalEvidence)
595403
+ }
595404
+ ],
595405
+ tools: [],
595406
+ temperature: 0.15,
595407
+ maxTokens: 900,
595408
+ timeoutMs: Math.max(5e3, Math.min(this.options.requestTimeoutMs, 3e4)),
595409
+ // The output is an explicit concise assessment, not a hidden-think
595410
+ // transcript. Keep Qwen's structured response path reliable.
595411
+ think: false
595412
+ });
595413
+ const generated = parseTrajectoryGeneratedGrounding(response.choices?.[0]?.message?.content ?? "", checkpoint.groundedFacts.map((fact) => fact.evidence));
595414
+ if (!generated) {
595415
+ this.emit({
595416
+ type: "status",
595417
+ content: "Trajectory grounding returned no usable assessment; retaining deterministic safety orientation",
595418
+ turn,
595419
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
595420
+ });
595421
+ return null;
595422
+ }
595423
+ this._trajectoryGroundingFingerprint = baseFingerprint;
595424
+ this._trajectoryGeneratedGrounding = generated;
595425
+ this.emit({
595426
+ type: "status",
595427
+ content: `Trajectory grounding: model assessed ${isInitial ? "the initial task state" : "the changed task state"}`,
595428
+ turn,
595429
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
595430
+ });
595431
+ return generated;
595432
+ } catch {
595433
+ this.emit({
595434
+ type: "status",
595435
+ content: "Trajectory grounding unavailable; retaining deterministic safety orientation",
595436
+ turn,
595437
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
595438
+ });
595439
+ return null;
595440
+ }
595441
+ }
595185
595442
  emit(event) {
595186
595443
  this._observeTrajectoryEvent(event);
595187
595444
  for (const handler of this.handlers) {
@@ -595481,6 +595738,9 @@ Respond with your assessment, then take action.`;
595481
595738
  this._trajectoryRevision = 0;
595482
595739
  this._trajectoryDirtyCauses = /* @__PURE__ */ new Set(["task_start"]);
595483
595740
  this._trajectoryLastEmittedToolCall = -1;
595741
+ this._trajectoryGroundingAttemptedFingerprint = "";
595742
+ this._trajectoryGroundingFingerprint = "";
595743
+ this._trajectoryGeneratedGrounding = null;
595484
595744
  this._runStartTime = Date.now();
595485
595745
  this._runErrorCount = 0;
595486
595746
  this._runErrorPatterns = [];
@@ -602249,7 +602509,7 @@ ${this.options.maxTurns && this.options.maxTurns > 0 ? `You have ${this.options.
602249
602509
  if (msg.toolCalls && msg.toolCalls.length > 0) {
602250
602510
  consecutiveTextOnly = 0;
602251
602511
  consecutiveThinkOnly = 0;
602252
- msg.toolCalls = msg.toolCalls;
602512
+ msg.toolCalls = this._dedupeRepeatedToolCallIdsForResponse(msg.toolCalls, turn);
602253
602513
  if (msg.toolCalls.length === 0) {
602254
602514
  messages2.push({
602255
602515
  role: "system",
@@ -615856,6 +616116,7 @@ __export(dist_exports3, {
615856
616116
  buildSteeringPacket: () => buildSteeringPacket,
615857
616117
  buildSubAgentSystemPrompt: () => buildSubAgentSystemPrompt,
615858
616118
  buildTrajectoryCheckpoint: () => buildTrajectoryCheckpoint,
616119
+ buildTrajectoryGroundingPrompt: () => buildTrajectoryGroundingPrompt,
615859
616120
  buildUnitTodos: () => buildUnitTodos,
615860
616121
  checkMilestoneComplete: () => checkMilestoneComplete,
615861
616122
  chooseCheapModelRoute: () => chooseCheapModelRoute,
@@ -616002,6 +616263,7 @@ __export(dist_exports3, {
616002
616263
  parseMetaCritique: () => parseMetaCritique,
616003
616264
  parsePlan: () => parsePlan,
616004
616265
  parseTextToolCalls: () => parseTextToolCalls,
616266
+ parseTrajectoryGeneratedGrounding: () => parseTrajectoryGeneratedGrounding,
616005
616267
  partitionToolCalls: () => partitionToolCalls,
616006
616268
  persistAgentTaskSidecar: () => persistAgentTaskSidecar,
616007
616269
  persistPlannerArtefacts: () => persistPlannerArtefacts,
@@ -619993,7 +620255,7 @@ function mergeRecentById(existing, incoming, limit) {
619993
620255
  for (const item of [...existing ?? [], ...incoming]) merged.set(item.id, item);
619994
620256
  return [...merged.values()].sort((a2, b) => b.observedAt - a2.observedAt).slice(0, limit);
619995
620257
  }
619996
- function parseJsonObject3(value2) {
620258
+ function parseJsonObject4(value2) {
619997
620259
  if (typeof value2 !== "string" || !value2.trim()) return null;
619998
620260
  try {
619999
620261
  const parsed = JSON.parse(value2);
@@ -620003,7 +620265,7 @@ function parseJsonObject3(value2) {
620003
620265
  }
620004
620266
  }
620005
620267
  function parseJsonObjectFromText(value2) {
620006
- const direct = parseJsonObject3(value2);
620268
+ const direct = parseJsonObject4(value2);
620007
620269
  if (direct) return direct;
620008
620270
  const text2 = String(value2 ?? "");
620009
620271
  const candidates = [];
@@ -620041,7 +620303,7 @@ function parseJsonObjectFromText(value2) {
620041
620303
  }
620042
620304
  }
620043
620305
  for (const candidate of candidates.reverse()) {
620044
- const parsed = parseJsonObject3(candidate);
620306
+ const parsed = parseJsonObject4(candidate);
620045
620307
  if (parsed) return parsed;
620046
620308
  }
620047
620309
  return null;
@@ -621052,7 +621314,7 @@ function formatLiveDashboardFromSnapshot(snapshot, opts = {}) {
621052
621314
  return lines;
621053
621315
  }
621054
621316
  function parseLiveMediaPayload(value2) {
621055
- const parsed = parseJsonObject3(value2);
621317
+ const parsed = parseJsonObject4(value2);
621056
621318
  if (!parsed) return null;
621057
621319
  if (!Array.isArray(parsed["objects"]) && !Array.isArray(parsed["tracks"]) && !Array.isArray(parsed["faces"]) && !Array.isArray(parsed["segments"])) return null;
621058
621320
  return parsed;
@@ -621073,7 +621335,7 @@ function parseFaceIdentity(face) {
621073
621335
  };
621074
621336
  }
621075
621337
  const raw = face.identity_candidates;
621076
- const parsed = typeof raw === "string" ? parseJsonObject3(raw) : typeof raw === "object" && raw !== null ? raw : null;
621338
+ const parsed = typeof raw === "string" ? parseJsonObject4(raw) : typeof raw === "object" && raw !== null ? raw : null;
621077
621339
  const faces = Array.isArray(parsed?.["faces"]) ? parsed["faces"] : [];
621078
621340
  const identified = faces.find((candidate) => candidate["identified"] === true && typeof candidate["name"] === "string" && candidate["name"]);
621079
621341
  if (identified) {
@@ -641939,6 +642201,17 @@ function buildTrajectoryLiveBlockLines(checkpoint, width, phase, truecolor = sup
641939
642201
  const bottom = `╰${"─".repeat(Math.max(0, w - 2))}╯`;
641940
642202
  const lines = [paint2(top, stage2, phase, 0, truecolor)];
641941
642203
  lines.push(row(`Goal: ${checkpoint.goal}`, inner, stage2, phase, truecolor));
642204
+ if (checkpoint.situationAssessment) {
642205
+ lines.push(
642206
+ row(
642207
+ `${checkpoint.groundingSource === "model" ? "Reasoned" : "Safety"}: ${checkpoint.situationAssessment}`,
642208
+ inner,
642209
+ stage2,
642210
+ phase,
642211
+ truecolor
642212
+ )
642213
+ );
642214
+ }
641942
642215
  lines.push(
641943
642216
  row(
641944
642217
  `Next: ${checkpoint.nextAction}`,
@@ -696209,7 +696482,7 @@ function numberArray(value2) {
696209
696482
  if (!Array.isArray(value2)) return [];
696210
696483
  return [...new Set(value2.map((item) => Number(item)).filter((item) => Number.isFinite(item)).map((item) => Math.trunc(item)))];
696211
696484
  }
696212
- function stringArray3(value2) {
696485
+ function stringArray4(value2) {
696213
696486
  if (!Array.isArray(value2)) return [];
696214
696487
  return [...new Set(value2.map((item) => clean4(item, 180)).filter(Boolean))];
696215
696488
  }
@@ -696280,7 +696553,7 @@ function buildTelegramReflectionExtractionPrompt(options2) {
696280
696553
  episodes || "none"
696281
696554
  ].join("\n");
696282
696555
  }
696283
- function parseJsonObject4(raw) {
696556
+ function parseJsonObject5(raw) {
696284
696557
  const text2 = raw.trim();
696285
696558
  if (!text2) return null;
696286
696559
  const fenced = text2.match(/```(?:json)?\s*([\s\S]*?)```/i)?.[1]?.trim();
@@ -696294,7 +696567,7 @@ function parseJsonObject4(raw) {
696294
696567
  }
696295
696568
  }
696296
696569
  function parseTelegramReflectionExtraction(raw) {
696297
- const parsed = parseJsonObject4(raw);
696570
+ const parsed = parseJsonObject5(raw);
696298
696571
  if (!parsed) return null;
696299
696572
  const tags = Array.isArray(parsed.tags) ? parsed.tags.map((item) => {
696300
696573
  const obj = item;
@@ -696303,8 +696576,8 @@ function parseTelegramReflectionExtraction(raw) {
696303
696576
  kind: clean4(obj.kind, 40) || "topic",
696304
696577
  confidence: clampConfidence(obj.confidence),
696305
696578
  sourceMessageIds: numberArray(obj.source_message_ids ?? obj.sourceMessageIds),
696306
- targetEpisodeIds: stringArray3(obj.target_episode_ids ?? obj.targetEpisodeIds),
696307
- targetNodeIds: stringArray3(obj.target_node_ids ?? obj.targetNodeIds)
696579
+ targetEpisodeIds: stringArray4(obj.target_episode_ids ?? obj.targetEpisodeIds),
696580
+ targetNodeIds: stringArray4(obj.target_node_ids ?? obj.targetNodeIds)
696308
696581
  };
696309
696582
  }).filter((item) => item.label) : [];
696310
696583
  const summaries = Array.isArray(parsed.summaries) ? parsed.summaries.map((item) => {
@@ -696315,7 +696588,7 @@ function parseTelegramReflectionExtraction(raw) {
696315
696588
  text: clean4(obj.text, 1200),
696316
696589
  confidence: clampConfidence(obj.confidence),
696317
696590
  sourceMessageIds: numberArray(obj.source_message_ids ?? obj.sourceMessageIds),
696318
- targetEpisodeIds: stringArray3(obj.target_episode_ids ?? obj.targetEpisodeIds)
696591
+ targetEpisodeIds: stringArray4(obj.target_episode_ids ?? obj.targetEpisodeIds)
696319
696592
  };
696320
696593
  }).filter((item) => item.title && item.text) : [];
696321
696594
  const titles = Array.isArray(parsed.titles) ? parsed.titles.map((item) => {
@@ -696325,7 +696598,7 @@ function parseTelegramReflectionExtraction(raw) {
696325
696598
  target: clean4(obj.target, 60) || "artifact",
696326
696599
  confidence: clampConfidence(obj.confidence),
696327
696600
  sourceMessageIds: numberArray(obj.source_message_ids ?? obj.sourceMessageIds),
696328
- targetEpisodeIds: stringArray3(obj.target_episode_ids ?? obj.targetEpisodeIds)
696601
+ targetEpisodeIds: stringArray4(obj.target_episode_ids ?? obj.targetEpisodeIds)
696329
696602
  };
696330
696603
  }).filter((item) => item.title) : [];
696331
696604
  const extractions = Array.isArray(parsed.extractions) ? parsed.extractions.map((item) => {
@@ -696335,8 +696608,8 @@ function parseTelegramReflectionExtraction(raw) {
696335
696608
  text: clean4(obj.text, 1e3),
696336
696609
  confidence: clampConfidence(obj.confidence),
696337
696610
  sourceMessageIds: numberArray(obj.source_message_ids ?? obj.sourceMessageIds),
696338
- targetEpisodeIds: stringArray3(obj.target_episode_ids ?? obj.targetEpisodeIds),
696339
- targetNodeIds: stringArray3(obj.target_node_ids ?? obj.targetNodeIds)
696611
+ targetEpisodeIds: stringArray4(obj.target_episode_ids ?? obj.targetEpisodeIds),
696612
+ targetNodeIds: stringArray4(obj.target_node_ids ?? obj.targetNodeIds)
696340
696613
  };
696341
696614
  }).filter((item) => item.text) : [];
696342
696615
  const links2 = Array.isArray(parsed.links) ? parsed.links.map((item) => {
@@ -696348,7 +696621,7 @@ function parseTelegramReflectionExtraction(raw) {
696348
696621
  confidence: clampConfidence(obj.confidence),
696349
696622
  fact: clean4(obj.fact, 500),
696350
696623
  sourceMessageIds: numberArray(obj.source_message_ids ?? obj.sourceMessageIds),
696351
- targetEpisodeIds: stringArray3(obj.target_episode_ids ?? obj.targetEpisodeIds)
696624
+ targetEpisodeIds: stringArray4(obj.target_episode_ids ?? obj.targetEpisodeIds)
696352
696625
  };
696353
696626
  }).filter((item) => item.srcNodeText && item.dstNodeText) : [];
696354
696627
  const followups = Array.isArray(parsed.followups) ? parsed.followups.map((item) => {
@@ -751627,7 +751900,10 @@ Only tools allowed by this profile are visible and executable.`
751627
751900
  personality: personality ? getPreset(personality) : void 0,
751628
751901
  personalityName: personality ?? void 0,
751629
751902
  identityInjection,
751630
- environmentProvider
751903
+ environmentProvider,
751904
+ // A real pre-action orientation is required before the main TUI agent
751905
+ // chooses its first tool; later failure/direction changes re-ground it.
751906
+ trajectoryGrounding: "adaptive"
751631
751907
  // Text tool mode is set dynamically after runner creation (async check)
751632
751908
  // The runner also auto-detects this when Ollama returns HTTP 400 for tools
751633
751909
  });
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.539",
3
+ "version": "1.0.541",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "omnius",
9
- "version": "1.0.539",
9
+ "version": "1.0.541",
10
10
  "bundleDependencies": [
11
11
  "image-to-ascii"
12
12
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "omnius",
3
- "version": "1.0.539",
3
+ "version": "1.0.541",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) — interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",