omnius 1.0.663 → 1.0.665
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
|
@@ -63552,6 +63552,30 @@ function pushBounded(buf, item) {
|
|
|
63552
63552
|
if (buf.length > MAX_BUFFER)
|
|
63553
63553
|
buf.splice(0, buf.length - MAX_BUFFER);
|
|
63554
63554
|
}
|
|
63555
|
+
function captureBrowserDiagnosticCursor() {
|
|
63556
|
+
return {
|
|
63557
|
+
startedAtMs: Date.now(),
|
|
63558
|
+
consoleIndex: consoleBuffer.length,
|
|
63559
|
+
networkIndex: networkBuffer.length,
|
|
63560
|
+
errorIndex: errorBuffer.length,
|
|
63561
|
+
websocketIndex: wsBuffer.length,
|
|
63562
|
+
crashCount
|
|
63563
|
+
};
|
|
63564
|
+
}
|
|
63565
|
+
function diagnosticEntriesAfter(entries2, index, startedAtMs) {
|
|
63566
|
+
return index <= entries2.length ? entries2.slice(index) : entries2.filter((entry) => entry.ts >= startedAtMs);
|
|
63567
|
+
}
|
|
63568
|
+
function browserDiagnosticWindow(cursor) {
|
|
63569
|
+
return {
|
|
63570
|
+
startedAtMs: cursor.startedAtMs,
|
|
63571
|
+
endedAtMs: Date.now(),
|
|
63572
|
+
console: diagnosticEntriesAfter(consoleBuffer, cursor.consoleIndex, cursor.startedAtMs),
|
|
63573
|
+
network: diagnosticEntriesAfter(networkBuffer, cursor.networkIndex, cursor.startedAtMs),
|
|
63574
|
+
errors: diagnosticEntriesAfter(errorBuffer, cursor.errorIndex, cursor.startedAtMs),
|
|
63575
|
+
websockets: diagnosticEntriesAfter(wsBuffer, cursor.websocketIndex, cursor.startedAtMs),
|
|
63576
|
+
crashCount: Math.max(0, crashCount - cursor.crashCount)
|
|
63577
|
+
};
|
|
63578
|
+
}
|
|
63555
63579
|
function which(cmd) {
|
|
63556
63580
|
try {
|
|
63557
63581
|
const out = execFileSync("which", [cmd], {
|
|
@@ -63663,6 +63687,11 @@ function asOptionalBoolean(value2) {
|
|
|
63663
63687
|
function defaultPlaywrightHeadless() {
|
|
63664
63688
|
return asOptionalBoolean(process.env["OMNIUS_PLAYWRIGHT_HEADLESS"] ?? process.env["OMNIUS_BROWSER_HEADLESS"]) ?? true;
|
|
63665
63689
|
}
|
|
63690
|
+
function hasGraphicalBrowserDisplay() {
|
|
63691
|
+
if (process.platform !== "linux")
|
|
63692
|
+
return true;
|
|
63693
|
+
return Boolean(process.env["DISPLAY"]?.trim() || process.env["WAYLAND_DISPLAY"]?.trim());
|
|
63694
|
+
}
|
|
63666
63695
|
async function installPlaywrightBrowser() {
|
|
63667
63696
|
try {
|
|
63668
63697
|
mkdirSync18(PLAYWRIGHT_RUNTIME_DIR, { recursive: true });
|
|
@@ -63927,37 +63956,6 @@ function attachDiagnosticListeners(p2) {
|
|
|
63927
63956
|
} catch {
|
|
63928
63957
|
}
|
|
63929
63958
|
});
|
|
63930
|
-
if (!initScriptInstalled) {
|
|
63931
|
-
try {
|
|
63932
|
-
p2.addInitScript(`(() => {
|
|
63933
|
-
if (window.__browserEvents) return;
|
|
63934
|
-
window.__browserEvents = [];
|
|
63935
|
-
const push = (evt) => {
|
|
63936
|
-
window.__browserEvents.push(evt);
|
|
63937
|
-
if (window.__browserEvents.length > 2000) window.__browserEvents.splice(0, window.__browserEvents.length - 2000);
|
|
63938
|
-
};
|
|
63939
|
-
const origError = console.error;
|
|
63940
|
-
console.error = function() {
|
|
63941
|
-
push({ ts: Date.now(), type: "console:error", text: Array.from(arguments).map(String).join(" ").slice(0, 2000) });
|
|
63942
|
-
return origError.apply(console, arguments);
|
|
63943
|
-
};
|
|
63944
|
-
const origWarn = console.warn;
|
|
63945
|
-
console.warn = function() {
|
|
63946
|
-
push({ ts: Date.now(), type: "console:warn", text: Array.from(arguments).map(String).join(" ").slice(0, 2000) });
|
|
63947
|
-
return origWarn.apply(console, arguments);
|
|
63948
|
-
};
|
|
63949
|
-
window.onerror = function(msg, source, lineno, colno, err) {
|
|
63950
|
-
push({ ts: Date.now(), type: "onerror", text: String(msg).slice(0, 2000), stack: err instanceof Error ? (err.stack || "").slice(0, 3000) : "" });
|
|
63951
|
-
};
|
|
63952
|
-
window.onunhandledrejection = function(evt) {
|
|
63953
|
-
const r = evt.reason;
|
|
63954
|
-
push({ ts: Date.now(), type: "unhandledRejection", text: String(r?.message ?? r ?? "unknown").slice(0, 2000), stack: typeof r?.stack === "string" ? r.stack.slice(0, 3000) : "" });
|
|
63955
|
-
};
|
|
63956
|
-
})()`);
|
|
63957
|
-
initScriptInstalled = true;
|
|
63958
|
-
} catch {
|
|
63959
|
-
}
|
|
63960
|
-
}
|
|
63961
63959
|
}
|
|
63962
63960
|
function clearDiagnosticBuffers() {
|
|
63963
63961
|
consoleBuffer = [];
|
|
@@ -64145,6 +64143,9 @@ async function runBrowserLocatorAction(pageHandle, selector, index, timeout2, ac
|
|
|
64145
64143
|
async function waitForBrowserExpectation(pageHandle, expectation, timeout2) {
|
|
64146
64144
|
await pageHandle.locator(expectation).first().waitFor({ state: "visible", timeout: timeout2 });
|
|
64147
64145
|
}
|
|
64146
|
+
async function browserExpectationIsVisible(pageHandle, expectation) {
|
|
64147
|
+
return Boolean(await pageHandle.locator(expectation).first().isVisible().catch(() => false));
|
|
64148
|
+
}
|
|
64148
64149
|
async function runBrowserInteractionWithEvidence(input) {
|
|
64149
64150
|
const before = await captureBrowserInteractionSnapshot(input.pageHandle);
|
|
64150
64151
|
let performed = null;
|
|
@@ -64736,6 +64737,169 @@ async function findBrowserVisualCandidate(pageHandle, target, visualX, visualY,
|
|
|
64736
64737
|
}
|
|
64737
64738
|
return candidates.filter((candidate) => includeOffscreen || candidate["visible"] === true).sort((a2, b) => Number(b["score"] ?? 0) - Number(a2["score"] ?? 0))[0] ?? null;
|
|
64738
64739
|
}
|
|
64740
|
+
async function captureBrowserObservation(input) {
|
|
64741
|
+
const html = await input.pageHandle.content();
|
|
64742
|
+
const readableText = await input.pageHandle.evaluate(`(() => {
|
|
64743
|
+
const clone = document.body ? document.body.cloneNode(true) : document.documentElement.cloneNode(true);
|
|
64744
|
+
clone.querySelectorAll("script, style, noscript, svg, path").forEach(el => el.remove());
|
|
64745
|
+
return clone.innerText || clone.textContent || "";
|
|
64746
|
+
})()`);
|
|
64747
|
+
const summary = downsampleDom(html);
|
|
64748
|
+
lastDomSummarySelectors = extractDomSummarySelectors(summary);
|
|
64749
|
+
const screenshotBuffer = await input.pageHandle.screenshot({
|
|
64750
|
+
fullPage: input.fullPage
|
|
64751
|
+
});
|
|
64752
|
+
const screenshotPath = saveBuffer(input.outputPath || defaultArtifactPath(input.action, "png"), screenshotBuffer);
|
|
64753
|
+
const viewport = input.pageHandle.viewportSize?.() ?? {
|
|
64754
|
+
width: 0,
|
|
64755
|
+
height: 0
|
|
64756
|
+
};
|
|
64757
|
+
const diagnostics = input.cursor ? browserDiagnosticWindow(input.cursor) : {
|
|
64758
|
+
startedAtMs: input.startMs,
|
|
64759
|
+
endedAtMs: Date.now(),
|
|
64760
|
+
console: [...consoleBuffer],
|
|
64761
|
+
network: [...networkBuffer],
|
|
64762
|
+
errors: [...errorBuffer],
|
|
64763
|
+
websockets: [...wsBuffer],
|
|
64764
|
+
crashCount
|
|
64765
|
+
};
|
|
64766
|
+
const consoleErrors = diagnostics.console.filter((entry) => /error/i.test(entry.type)).slice(-30);
|
|
64767
|
+
const consoleWarnings = diagnostics.console.filter((entry) => /warn/i.test(entry.type)).slice(-30);
|
|
64768
|
+
const networkFailures = diagnostics.network.filter((entry) => entry.ok === false || (entry.status ?? 0) >= 400).slice(-30);
|
|
64769
|
+
const pageErrors = diagnostics.errors.slice(-30);
|
|
64770
|
+
const gate = classifyBrowserGate({
|
|
64771
|
+
url: input.pageHandle.url(),
|
|
64772
|
+
html,
|
|
64773
|
+
text: String(readableText ?? ""),
|
|
64774
|
+
network: diagnostics.network,
|
|
64775
|
+
errors: diagnostics.errors
|
|
64776
|
+
});
|
|
64777
|
+
const actualObservationMs = Math.max(0, diagnostics.endedAtMs - diagnostics.startedAtMs);
|
|
64778
|
+
const runtimeFailureCount = consoleErrors.length + pageErrors.length + networkFailures.length + diagnostics.crashCount;
|
|
64779
|
+
const blocked = gate.kind === "captcha" || gate.kind === "bot_challenge";
|
|
64780
|
+
const contradicted = input.expectationSatisfied === false || runtimeFailureCount > 0;
|
|
64781
|
+
const verification = blocked ? {
|
|
64782
|
+
status: "blocked",
|
|
64783
|
+
confidence: gate.confidence,
|
|
64784
|
+
reason: `Browser observation was blocked by gate=${gate.kind}.`
|
|
64785
|
+
} : contradicted ? {
|
|
64786
|
+
status: "contradicted",
|
|
64787
|
+
confidence: 0.96,
|
|
64788
|
+
reason: input.expectationSatisfied === false ? `The declared postcondition was not observed: ${input.expectation}.` : `The browser emitted ${runtimeFailureCount} runtime failure signal(s) during the observation window.`,
|
|
64789
|
+
nextSuggestedObservation: "Fix the concrete console/page/network failure, then rerun validate_lifecycle or observe_window in the same browser mode."
|
|
64790
|
+
} : input.expectationSatisfied === true ? {
|
|
64791
|
+
status: "proven",
|
|
64792
|
+
confidence: 0.9,
|
|
64793
|
+
reason: `The declared postcondition remained visible and no browser runtime failures appeared during the ${actualObservationMs}ms observation window.`
|
|
64794
|
+
} : {
|
|
64795
|
+
status: "inconclusive",
|
|
64796
|
+
confidence: 0.58,
|
|
64797
|
+
reason: `The browser remained under observation for ${actualObservationMs}ms, but no explicit postcondition was evaluated.`,
|
|
64798
|
+
nextSuggestedObservation: "Repeat with expect set to a state-specific selector before making a user-visible success claim."
|
|
64799
|
+
};
|
|
64800
|
+
const mode = browserHeadless === false ? "headed" : "headless";
|
|
64801
|
+
const evidenceEvent = createEvidenceEvent({
|
|
64802
|
+
sessionId: playwrightSessionId ?? void 0,
|
|
64803
|
+
tool: "playwright_browser",
|
|
64804
|
+
action: input.action,
|
|
64805
|
+
surface: "browser",
|
|
64806
|
+
claim: input.expectation ? `Browser postcondition: ${input.expectation}` : "Timed browser runtime observation",
|
|
64807
|
+
after: createEvidenceObservation({
|
|
64808
|
+
screenshotPath,
|
|
64809
|
+
screenshotHash: sha256Buffer(screenshotBuffer),
|
|
64810
|
+
width: viewport.width,
|
|
64811
|
+
height: viewport.height,
|
|
64812
|
+
url: input.pageHandle.url(),
|
|
64813
|
+
title: await input.pageHandle.title(),
|
|
64814
|
+
domSummaryHash: sha256Text(summary),
|
|
64815
|
+
readableTextHash: sha256Text(String(readableText ?? "")),
|
|
64816
|
+
visibleTextExcerpt: clipEvidenceText(readableText, 500),
|
|
64817
|
+
consoleErrorCount: consoleErrors.length,
|
|
64818
|
+
pageErrorCount: pageErrors.length,
|
|
64819
|
+
networkFailureCount: networkFailures.length,
|
|
64820
|
+
gateKind: gate.kind,
|
|
64821
|
+
gateConfidence: gate.confidence,
|
|
64822
|
+
gateEvidence: gate.evidence,
|
|
64823
|
+
metadata: {
|
|
64824
|
+
mode,
|
|
64825
|
+
engine: "playwright",
|
|
64826
|
+
requestedObservationMs: input.requestedObservationMs,
|
|
64827
|
+
actualObservationMs,
|
|
64828
|
+
diagnosticsScope: input.cursor ? "window" : "session",
|
|
64829
|
+
consoleWarningCount: consoleWarnings.length,
|
|
64830
|
+
websocketEventCount: diagnostics.websockets.length,
|
|
64831
|
+
crashCount: diagnostics.crashCount,
|
|
64832
|
+
expectation: input.expectation,
|
|
64833
|
+
expectationSatisfied: input.expectationSatisfied
|
|
64834
|
+
}
|
|
64835
|
+
}),
|
|
64836
|
+
verification
|
|
64837
|
+
});
|
|
64838
|
+
const bundle = {
|
|
64839
|
+
schema: "omnius.browser-observation-window.v1",
|
|
64840
|
+
id: timestampSlug(),
|
|
64841
|
+
engine: "playwright",
|
|
64842
|
+
mode,
|
|
64843
|
+
url: input.pageHandle.url(),
|
|
64844
|
+
title: await input.pageHandle.title(),
|
|
64845
|
+
viewport,
|
|
64846
|
+
screenshotPath,
|
|
64847
|
+
observationWindow: {
|
|
64848
|
+
requestedMs: input.requestedObservationMs,
|
|
64849
|
+
actualMs: actualObservationMs,
|
|
64850
|
+
startedAt: new Date(diagnostics.startedAtMs).toISOString(),
|
|
64851
|
+
endedAt: new Date(diagnostics.endedAtMs).toISOString(),
|
|
64852
|
+
diagnosticsScope: input.cursor ? "window" : "session"
|
|
64853
|
+
},
|
|
64854
|
+
expectation: input.expectation ?? null,
|
|
64855
|
+
expectationSatisfied: input.expectationSatisfied ?? null,
|
|
64856
|
+
expectationError: input.expectationError ?? null,
|
|
64857
|
+
gate,
|
|
64858
|
+
consoleErrors,
|
|
64859
|
+
consoleWarnings,
|
|
64860
|
+
networkFailures,
|
|
64861
|
+
pageErrors,
|
|
64862
|
+
websocketEvents: diagnostics.websockets.slice(-30),
|
|
64863
|
+
crashes: diagnostics.crashCount,
|
|
64864
|
+
domSummary: summary.slice(0, 12e3),
|
|
64865
|
+
evidenceEvents: [evidenceEvent]
|
|
64866
|
+
};
|
|
64867
|
+
const failureDetails = [
|
|
64868
|
+
...consoleErrors.map((entry) => `console ${entry.type}: ${entry.text}${entry.loc ? ` (${entry.loc})` : ""}`),
|
|
64869
|
+
...pageErrors.map((entry) => `page error: ${entry.message}`),
|
|
64870
|
+
...networkFailures.map((entry) => `network: ${entry.method} ${entry.status ?? "FAILED"} ${entry.url}${entry.failure ? ` (${entry.failure})` : ""}`)
|
|
64871
|
+
].slice(0, 30);
|
|
64872
|
+
const output2 = [
|
|
64873
|
+
"Browser observation bundle",
|
|
64874
|
+
`URL: ${bundle.url}`,
|
|
64875
|
+
`Title: ${bundle.title}`,
|
|
64876
|
+
`Mode: ${mode}`,
|
|
64877
|
+
`Observation window: ${actualObservationMs}ms (${input.cursor ? "window-scoped" : "session-scoped"} diagnostics)`,
|
|
64878
|
+
`Viewport: ${viewport.width}x${viewport.height}`,
|
|
64879
|
+
`Screenshot: ${screenshotPath}`,
|
|
64880
|
+
`Gate: ${gate.kind} (${gate.confidence.toFixed(2)})${gate.evidence.length ? ` — ${gate.evidence.join("; ")}` : ""}`,
|
|
64881
|
+
`Console errors: ${consoleErrors.length}`,
|
|
64882
|
+
`Console warnings: ${consoleWarnings.length}`,
|
|
64883
|
+
`Page errors: ${pageErrors.length}`,
|
|
64884
|
+
`Network failures: ${networkFailures.length}`,
|
|
64885
|
+
`Verification: ${verification.status} — ${verification.reason}`,
|
|
64886
|
+
...failureDetails.length > 0 ? ["", "--- Runtime failures ---", ...failureDetails] : [],
|
|
64887
|
+
"",
|
|
64888
|
+
"--- DOM Summary ---",
|
|
64889
|
+
summary.slice(0, 6e3)
|
|
64890
|
+
].join("\n");
|
|
64891
|
+
const shouldFail = input.failOnRuntimeErrors && contradicted;
|
|
64892
|
+
return {
|
|
64893
|
+
success: !shouldFail,
|
|
64894
|
+
output: output2,
|
|
64895
|
+
...shouldFail ? {
|
|
64896
|
+
error: `Browser lifecycle validation failed: ${runtimeFailureCount} runtime failure signal(s)${input.expectationSatisfied === false ? "; declared postcondition was not observed" : ""}.`
|
|
64897
|
+
} : {},
|
|
64898
|
+
llmContent: JSON.stringify(bundle, null, 2),
|
|
64899
|
+
evidenceEvents: [evidenceEvent],
|
|
64900
|
+
durationMs: Date.now() - input.startMs
|
|
64901
|
+
};
|
|
64902
|
+
}
|
|
64739
64903
|
function ok(output2, start2, skipDiag = false) {
|
|
64740
64904
|
const diag = skipDiag ? "" : formatDiagnosticSummary();
|
|
64741
64905
|
return {
|
|
@@ -64748,7 +64912,7 @@ ${diag}` : output2,
|
|
|
64748
64912
|
function fail(error, start2) {
|
|
64749
64913
|
return { success: false, output: "", error, durationMs: Date.now() - start2 };
|
|
64750
64914
|
}
|
|
64751
|
-
var pw, browser, context, page, browserHeadless, playwrightSessionId, playwrightSessionSequence, MAX_BUFFER, consoleBuffer, networkBuffer, errorBuffer, wsBuffer, crashCount,
|
|
64915
|
+
var pw, browser, context, page, browserHeadless, playwrightSessionId, playwrightSessionSequence, MAX_BUFFER, consoleBuffer, networkBuffer, errorBuffer, wsBuffer, crashCount, lastDomSummarySelectors, dynamicImport, PLAYWRIGHT_RUNTIME_DIR, PLAYWRIGHT_BROWSERS_DIR, PLAYWRIGHT_CHROMIUM_INSTALL_ARGS, PlaywrightBrowserTool;
|
|
64752
64916
|
var init_playwright_browser = __esm({
|
|
64753
64917
|
"packages/execution/dist/tools/playwright-browser.js"() {
|
|
64754
64918
|
"use strict";
|
|
@@ -64769,15 +64933,18 @@ var init_playwright_browser = __esm({
|
|
|
64769
64933
|
errorBuffer = [];
|
|
64770
64934
|
wsBuffer = [];
|
|
64771
64935
|
crashCount = 0;
|
|
64772
|
-
initScriptInstalled = false;
|
|
64773
64936
|
lastDomSummarySelectors = /* @__PURE__ */ new Map();
|
|
64774
|
-
dynamicImport =
|
|
64937
|
+
dynamicImport = (mod3) => import(
|
|
64938
|
+
/* @vite-ignore */
|
|
64939
|
+
mod3
|
|
64940
|
+
);
|
|
64775
64941
|
PLAYWRIGHT_RUNTIME_DIR = join22(homedir7(), ".omnius", "playwright-runtime");
|
|
64776
64942
|
PLAYWRIGHT_BROWSERS_DIR = join22(PLAYWRIGHT_RUNTIME_DIR, "browsers");
|
|
64777
64943
|
PLAYWRIGHT_CHROMIUM_INSTALL_ARGS = ["playwright", "install", "chromium"];
|
|
64778
64944
|
PlaywrightBrowserTool = class {
|
|
64779
64945
|
name = "playwright_browser";
|
|
64780
|
-
|
|
64946
|
+
modelFacingSummary = "Validate a live UI in one persistent Playwright session. For GUI, GPU, WebGL, WebGPU, canvas, or animation claims, use validate_lifecycle with headless=false, force_new=true, an explicit expect, and a finite observation_ms. Use observe_window after interactions. Inspect delayed console, page, network, DOM, and screenshot evidence. A clean headless or immediate load is not headed lifecycle proof.";
|
|
64947
|
+
description = "Persistent Playwright browser lifecycle validation with timed console, page-error, network, DOM, and screenshot capture. Launches a persistent headless Chromium session by default, with optional visible/headed mode when a GUI display is available. Beyond navigation/interaction, this tool buffers everything the running app emits (console messages, network requests, JS exceptions, accessibility tree) so the agent can verify what is ACTUALLY happening — not just what the build/test reports. Auto-installs Playwright + Chromium on first use without sudo or OS package manager escalation. Diagnostic actions: validate_lifecycle, observe_window, observe_bundle, dom_summary, dom, console_logs, network_log, page_errors, websocket_log, a11y_snapshot, bounding_box, query_all, performance, cookies, storage, viewport, clear_diagnostics. Interaction actions: navigate, click, visual_click, fill, type, press, select, check, hover. Use fill with a selector or natural-language target for form fields; avoid raw evaluate for form filling because direct .value assignment does not fire app input/change events. For state-changing interactions, pass expect as a Playwright selector for the visible post-action state (for example text=Stop Simulation). A dispatched click without an asserted postcondition is recorded as inconclusive, not completion proof. Selectors are strict by default: when a selector matches more than one element, use a more specific selector or index (zero-based). Detached/re-rendered elements are re-queried once before failing. This is a separate browser/runtime from browser_action; once you start a workflow here, continue here unless you intentionally navigate browser_action to the same URL. Every result carries a typed runtime-session receipt; use hardware_prerequisite before declaring a WebSerial, WebUSB, camera, or microphone interaction blocked by a real device/permission boundary. Capture actions: screenshot, pdf, content, innerText, innerHTML, getAttribute, evaluate. Loopback URLs (localhost, 127.0.0.1, ::1) are allowed for local development servers; private LAN and metadata URLs remain blocked. Workflow for user-facing work: start/serve the system with the stack-native tool, then run validate_lifecycle against the real URL with an explicit expect and observation_ms. For GPU, WebGL, WebGPU, canvas, animation, or failures seen in a normal GUI browser, use headless=false and force_new=true; a clean headless run does not verify headed GPU behavior. Use observe_window after interactions to keep the same browser alive while delayed failures surface, then inspect page_errors, console_logs, network_log, DOM/accessibility, and screenshot evidence before completion. Build/typecheck/test output is only one layer; runtime browser evidence is required when the delivered artifact is a page, app, dashboard, game, form, visualization, or other UI. Repeat navigate/act/observe until the actual user flow is clean.";
|
|
64781
64948
|
parameters = {
|
|
64782
64949
|
type: "object",
|
|
64783
64950
|
properties: {
|
|
@@ -64824,12 +64991,14 @@ var init_playwright_browser = __esm({
|
|
|
64824
64991
|
"storage",
|
|
64825
64992
|
"viewport",
|
|
64826
64993
|
"observe_bundle",
|
|
64994
|
+
"observe_window",
|
|
64995
|
+
"validate_lifecycle",
|
|
64827
64996
|
"visual_click",
|
|
64828
64997
|
"hardware_prerequisite",
|
|
64829
64998
|
"clear_diagnostics",
|
|
64830
64999
|
"close"
|
|
64831
65000
|
],
|
|
64832
|
-
description: "Action to perform:\n- navigate: go to a URL\n- click: click element by selector\n- fill: clear input and type text by selector, or by natural-language target when selector is absent\n- type: type text character by character into a selector, or into the currently focused element after visual_click\n- press: press a key (Enter, Tab, Escape, etc.)\n- screenshot: capture the headless browser page, not the desktop; use value to choose the output file path\n- observe_bundle: capture URL/title/viewport, DOM summary, a11y, diagnostics, screenshot, and gate assessment\n- visual_click: browser screenshot -> Moondream point -> elementFromPoint -> human-like Playwright mouse click -> post-action screenshot\n- hardware_prerequisite: record whether a WebSerial/WebUSB/media flow has the browser capability, secure context, and required physical/user-gesture prerequisite; it never pretends hardware was exercised\n- evaluate: run JavaScript in page context\n- content: get page text content (readable, stripped)\n- dom: get raw page HTML (truncated)\n- dom_summary: compact interactive DOM summary with selectors\n- innerText: get innerText of a specific element\n- select: select dropdown option by value\n- check/uncheck: toggle checkbox\n- hover: hover over element\n- wait: wait for a selector to appear, or sleep for timeout ms when no selector is provided\n- waitForNavigation: wait for page navigation to complete\n- waitForSelector: wait for element matching selector\n- title: get page title\n- url: get current URL\n- getAttribute: get element attribute value\n- innerHTML: get element's innerHTML\n- textContent: get element's textContent\n- goBack/goForward/reload: browser navigation\n- pdf: save page as PDF\n- close: close browser session"
|
|
65001
|
+
description: "Action to perform:\n- navigate: go to a URL\n- click: click element by selector\n- fill: clear input and type text by selector, or by natural-language target when selector is absent\n- type: type text character by character into a selector, or into the currently focused element after visual_click\n- press: press a key (Enter, Tab, Escape, etc.)\n- screenshot: capture the headless browser page, not the desktop; use value to choose the output file path\n- observe_bundle: capture URL/title/viewport, DOM summary, a11y, diagnostics, screenshot, and gate assessment\n- observe_window: keep the current browser/page alive for observation_ms, then return only diagnostics emitted during that time window plus DOM/screenshot evidence\n- validate_lifecycle: start a fresh headed browser by default, clear diagnostics, navigate to url, hold it for observation_ms, and fail on delayed console/page/network errors; use this for GUI/GPU/WebGL validation\n- visual_click: browser screenshot -> Moondream point -> elementFromPoint -> human-like Playwright mouse click -> post-action screenshot\n- hardware_prerequisite: record whether a WebSerial/WebUSB/media flow has the browser capability, secure context, and required physical/user-gesture prerequisite; it never pretends hardware was exercised\n- evaluate: run JavaScript in page context\n- content: get page text content (readable, stripped)\n- dom: get raw page HTML (truncated)\n- dom_summary: compact interactive DOM summary with selectors\n- innerText: get innerText of a specific element\n- select: select dropdown option by value\n- check/uncheck: toggle checkbox\n- hover: hover over element\n- wait: wait for a selector to appear, or sleep for timeout ms when no selector is provided\n- waitForNavigation: wait for page navigation to complete\n- waitForSelector: wait for element matching selector\n- title: get page title\n- url: get current URL\n- getAttribute: get element attribute value\n- innerHTML: get element's innerHTML\n- textContent: get element's textContent\n- goBack/goForward/reload: browser navigation\n- pdf: save page as PDF\n- close: close browser session"
|
|
64833
65002
|
},
|
|
64834
65003
|
url: {
|
|
64835
65004
|
type: "string",
|
|
@@ -64895,6 +65064,14 @@ var init_playwright_browser = __esm({
|
|
|
64895
65064
|
type: "number",
|
|
64896
65065
|
description: "Milliseconds to wait for expect after the action (defaults to timeout)."
|
|
64897
65066
|
},
|
|
65067
|
+
observation_ms: {
|
|
65068
|
+
type: "number",
|
|
65069
|
+
description: "Milliseconds to keep the instantiated page alive while collecting delayed diagnostics. Defaults to 8000 for validate_lifecycle and 5000 for observe_window; maximum 120000."
|
|
65070
|
+
},
|
|
65071
|
+
start_delay_ms: {
|
|
65072
|
+
type: "number",
|
|
65073
|
+
description: "Optional delay before opening an observe_window diagnostic window. Use this only when the requested lifecycle has an explicit warm-up phase; maximum 60000."
|
|
65074
|
+
},
|
|
64898
65075
|
hardware_capability: {
|
|
64899
65076
|
type: "string",
|
|
64900
65077
|
enum: ["web_serial", "web_usb", "camera", "microphone"],
|
|
@@ -64906,7 +65083,7 @@ var init_playwright_browser = __esm({
|
|
|
64906
65083
|
},
|
|
64907
65084
|
headless: {
|
|
64908
65085
|
type: "boolean",
|
|
64909
|
-
description: "Launch mode for a new browser session.
|
|
65086
|
+
description: "Launch mode for a new browser session. Normal actions default to true; validate_lifecycle defaults to false. For GUI/GPU/WebGL claims, set false explicitly. A headless result cannot verify headed graphics behavior."
|
|
64910
65087
|
},
|
|
64911
65088
|
force_new: {
|
|
64912
65089
|
type: "boolean",
|
|
@@ -64948,8 +65125,12 @@ var init_playwright_browser = __esm({
|
|
|
64948
65125
|
const expectationTimeout = typeof args.expect_timeout === "number" ? Math.max(1, Math.min(12e4, Math.round(args.expect_timeout))) : timeout2;
|
|
64949
65126
|
const width = typeof args.width === "number" ? Math.max(320, Math.min(3840, Math.round(args.width))) : void 0;
|
|
64950
65127
|
const height = typeof args.height === "number" ? Math.max(240, Math.min(2160, Math.round(args.height))) : void 0;
|
|
64951
|
-
const
|
|
64952
|
-
const
|
|
65128
|
+
const requestedHeadless = asOptionalBoolean(args.headless);
|
|
65129
|
+
const validatesFullLifecycle = action === "validate_lifecycle";
|
|
65130
|
+
const headless = requestedHeadless ?? (validatesFullLifecycle ? false : void 0);
|
|
65131
|
+
const forceNew = asOptionalBoolean(args.force_new) === true || validatesFullLifecycle;
|
|
65132
|
+
const observationMs = typeof args.observation_ms === "number" ? Math.max(0, Math.min(12e4, Math.round(args.observation_ms))) : validatesFullLifecycle ? 8e3 : 5e3;
|
|
65133
|
+
const startDelayMs = typeof args.start_delay_ms === "number" ? Math.max(0, Math.min(6e4, Math.round(args.start_delay_ms))) : 0;
|
|
64953
65134
|
const visualTarget = typeof args.target === "string" && args.target.trim() ? args.target.trim() : typeof args.text === "string" && args.text.trim() ? args.text.trim() : "";
|
|
64954
65135
|
const preferredVisionModel = normalizeVisionModelName(args.vision_model);
|
|
64955
65136
|
const delayMs = typeof args.delay_ms === "number" ? Math.max(0, Math.min(3e4, Math.round(args.delay_ms))) : 700;
|
|
@@ -64964,6 +65145,9 @@ var init_playwright_browser = __esm({
|
|
|
64964
65145
|
durationMs: Date.now() - start2
|
|
64965
65146
|
};
|
|
64966
65147
|
}
|
|
65148
|
+
if (headless === false && !hasGraphicalBrowserDisplay()) {
|
|
65149
|
+
return fail("Headed Chromium was required, but no graphical DISPLAY or WAYLAND_DISPLAY is available. Report headed GUI/GPU validation as blocked; do not substitute a clean headless run.", start2);
|
|
65150
|
+
}
|
|
64967
65151
|
const err = await ensureBrowser({ headless, forceNew });
|
|
64968
65152
|
if (err)
|
|
64969
65153
|
return {
|
|
@@ -65689,7 +65873,14 @@ ${JSON.stringify(data, null, 2)}`, start2);
|
|
|
65689
65873
|
}
|
|
65690
65874
|
return fail(`viewport: provide "WxH" (e.g. "375x667") or a Playwright device name (e.g. "iPhone 13")`, start2);
|
|
65691
65875
|
}
|
|
65692
|
-
case "
|
|
65876
|
+
case "validate_lifecycle": {
|
|
65877
|
+
if (!url)
|
|
65878
|
+
return fail("url is required", start2);
|
|
65879
|
+
try {
|
|
65880
|
+
await validateNetworkEgressUrl(url, { allowLoopback: true });
|
|
65881
|
+
} catch (err2) {
|
|
65882
|
+
return fail(networkEgressErrorMessage(err2), start2);
|
|
65883
|
+
}
|
|
65693
65884
|
if (width || height) {
|
|
65694
65885
|
const current = page.viewportSize?.() ?? {
|
|
65695
65886
|
width: 1280,
|
|
@@ -65700,87 +65891,107 @@ ${JSON.stringify(data, null, 2)}`, start2);
|
|
|
65700
65891
|
height: height ?? current.height ?? 720
|
|
65701
65892
|
});
|
|
65702
65893
|
}
|
|
65703
|
-
|
|
65704
|
-
const
|
|
65705
|
-
|
|
65706
|
-
|
|
65707
|
-
|
|
65708
|
-
})()`);
|
|
65709
|
-
const summary = downsampleDom(html);
|
|
65710
|
-
lastDomSummarySelectors = extractDomSummarySelectors(summary);
|
|
65711
|
-
const screenshotPath = saveBuffer(outputPath3 || defaultArtifactPath("observe", "png"), await page.screenshot({ fullPage: args.full_page === true }));
|
|
65712
|
-
const viewport = page.viewportSize?.() ?? { width: 0, height: 0 };
|
|
65713
|
-
const gate = classifyBrowserGate({
|
|
65714
|
-
url: page.url(),
|
|
65715
|
-
html,
|
|
65716
|
-
text: String(readableText ?? ""),
|
|
65717
|
-
network: networkBuffer,
|
|
65718
|
-
errors: errorBuffer
|
|
65894
|
+
clearDiagnosticBuffers();
|
|
65895
|
+
const cursor = captureBrowserDiagnosticCursor();
|
|
65896
|
+
await page.goto(url, {
|
|
65897
|
+
waitUntil: "domcontentloaded",
|
|
65898
|
+
timeout: timeout2
|
|
65719
65899
|
});
|
|
65720
|
-
|
|
65721
|
-
|
|
65722
|
-
const
|
|
65723
|
-
|
|
65724
|
-
|
|
65725
|
-
|
|
65726
|
-
|
|
65727
|
-
|
|
65728
|
-
|
|
65729
|
-
|
|
65730
|
-
|
|
65731
|
-
|
|
65732
|
-
|
|
65733
|
-
|
|
65734
|
-
|
|
65735
|
-
}
|
|
65736
|
-
|
|
65737
|
-
|
|
65900
|
+
let expectationSatisfied;
|
|
65901
|
+
let expectationError;
|
|
65902
|
+
const expectationProbe = expectation ? waitForBrowserExpectation(page, expectation, Math.min(expectationTimeout, Math.max(1, observationMs))).then(() => {
|
|
65903
|
+
expectationSatisfied = true;
|
|
65904
|
+
}).catch((err2) => {
|
|
65905
|
+
expectationSatisfied = false;
|
|
65906
|
+
expectationError = err2 instanceof Error ? err2.message : String(err2);
|
|
65907
|
+
}) : Promise.resolve();
|
|
65908
|
+
await Promise.all([
|
|
65909
|
+
page.waitForTimeout(observationMs),
|
|
65910
|
+
expectationProbe
|
|
65911
|
+
]);
|
|
65912
|
+
if (expectation && expectationSatisfied === true && !await browserExpectationIsVisible(page, expectation)) {
|
|
65913
|
+
expectationSatisfied = false;
|
|
65914
|
+
expectationError = "The declared postcondition was visible during the window but was not visible at the end of it.";
|
|
65915
|
+
}
|
|
65916
|
+
return captureBrowserObservation({
|
|
65917
|
+
pageHandle: page,
|
|
65918
|
+
action: "validate_lifecycle",
|
|
65919
|
+
startMs: start2,
|
|
65920
|
+
outputPath: outputPath3,
|
|
65921
|
+
fullPage: args.full_page === true,
|
|
65922
|
+
cursor,
|
|
65923
|
+
requestedObservationMs: observationMs,
|
|
65924
|
+
expectation,
|
|
65925
|
+
expectationSatisfied,
|
|
65926
|
+
expectationError,
|
|
65927
|
+
failOnRuntimeErrors: true
|
|
65928
|
+
});
|
|
65929
|
+
}
|
|
65930
|
+
case "observe_window": {
|
|
65931
|
+
if (startDelayMs > 0)
|
|
65932
|
+
await page.waitForTimeout(startDelayMs);
|
|
65933
|
+
if (width || height) {
|
|
65934
|
+
const current = page.viewportSize?.() ?? {
|
|
65935
|
+
width: 1280,
|
|
65936
|
+
height: 720
|
|
65937
|
+
};
|
|
65938
|
+
await page.setViewportSize({
|
|
65939
|
+
width: width ?? current.width ?? 1280,
|
|
65940
|
+
height: height ?? current.height ?? 720
|
|
65941
|
+
});
|
|
65942
|
+
}
|
|
65943
|
+
const cursor = captureBrowserDiagnosticCursor();
|
|
65944
|
+
let expectationSatisfied;
|
|
65945
|
+
let expectationError;
|
|
65946
|
+
const expectationProbe = expectation ? waitForBrowserExpectation(page, expectation, Math.min(expectationTimeout, Math.max(1, observationMs))).then(() => {
|
|
65947
|
+
expectationSatisfied = true;
|
|
65948
|
+
}).catch((err2) => {
|
|
65949
|
+
expectationSatisfied = false;
|
|
65950
|
+
expectationError = err2 instanceof Error ? err2.message : String(err2);
|
|
65951
|
+
}) : Promise.resolve();
|
|
65952
|
+
await Promise.all([
|
|
65953
|
+
page.waitForTimeout(observationMs),
|
|
65954
|
+
expectationProbe
|
|
65955
|
+
]);
|
|
65956
|
+
if (expectation && expectationSatisfied === true && !await browserExpectationIsVisible(page, expectation)) {
|
|
65957
|
+
expectationSatisfied = false;
|
|
65958
|
+
expectationError = "The declared postcondition was visible during the window but was not visible at the end of it.";
|
|
65959
|
+
}
|
|
65960
|
+
return captureBrowserObservation({
|
|
65961
|
+
pageHandle: page,
|
|
65962
|
+
action: "observe_window",
|
|
65963
|
+
startMs: start2,
|
|
65964
|
+
outputPath: outputPath3,
|
|
65965
|
+
fullPage: args.full_page === true,
|
|
65966
|
+
cursor,
|
|
65967
|
+
requestedObservationMs: observationMs,
|
|
65968
|
+
expectation,
|
|
65969
|
+
expectationSatisfied,
|
|
65970
|
+
expectationError,
|
|
65971
|
+
failOnRuntimeErrors: true
|
|
65972
|
+
});
|
|
65973
|
+
}
|
|
65974
|
+
case "observe_bundle": {
|
|
65975
|
+
if (width || height) {
|
|
65976
|
+
const current = page.viewportSize?.() ?? {
|
|
65977
|
+
width: 1280,
|
|
65978
|
+
height: 720
|
|
65979
|
+
};
|
|
65980
|
+
await page.setViewportSize({
|
|
65981
|
+
width: width ?? current.width ?? 1280,
|
|
65982
|
+
height: height ?? current.height ?? 720
|
|
65983
|
+
});
|
|
65984
|
+
}
|
|
65985
|
+
return captureBrowserObservation({
|
|
65986
|
+
pageHandle: page,
|
|
65738
65987
|
action: "observe_bundle",
|
|
65739
|
-
|
|
65740
|
-
|
|
65741
|
-
|
|
65742
|
-
|
|
65743
|
-
|
|
65744
|
-
|
|
65745
|
-
title: bundle.title,
|
|
65746
|
-
domSummaryHash: sha256Text(summary),
|
|
65747
|
-
readableTextHash: sha256Text(String(readableText ?? "")),
|
|
65748
|
-
visibleTextExcerpt: clipEvidenceText(readableText, 500),
|
|
65749
|
-
consoleErrorCount: bundle.consoleErrors.length,
|
|
65750
|
-
pageErrorCount: errors.length,
|
|
65751
|
-
networkFailureCount: networkFailures.length,
|
|
65752
|
-
gateKind: gate.kind,
|
|
65753
|
-
gateConfidence: gate.confidence,
|
|
65754
|
-
gateEvidence: gate.evidence,
|
|
65755
|
-
metadata: { mode: bundle.mode, engine: "playwright" }
|
|
65756
|
-
}),
|
|
65757
|
-
verification: {
|
|
65758
|
-
status: gate.kind === "captcha" || gate.kind === "bot_challenge" ? "blocked" : "inconclusive",
|
|
65759
|
-
confidence: gate.kind === "captcha" || gate.kind === "bot_challenge" ? gate.confidence : 0.5,
|
|
65760
|
-
reason: gate.kind === "none" ? "Fresh browser observation captured; no specific completion claim was evaluated." : `Fresh browser observation captured with gate=${gate.kind}.`
|
|
65761
|
-
}
|
|
65988
|
+
startMs: start2,
|
|
65989
|
+
outputPath: outputPath3,
|
|
65990
|
+
fullPage: args.full_page === true,
|
|
65991
|
+
requestedObservationMs: 0,
|
|
65992
|
+
expectation,
|
|
65993
|
+
failOnRuntimeErrors: false
|
|
65762
65994
|
});
|
|
65763
|
-
const modelBundle = { ...bundle, evidenceEvents: [evidenceEvent] };
|
|
65764
|
-
return {
|
|
65765
|
-
success: true,
|
|
65766
|
-
output: [
|
|
65767
|
-
"Browser observation bundle",
|
|
65768
|
-
`URL: ${bundle.url}`,
|
|
65769
|
-
`Title: ${bundle.title}`,
|
|
65770
|
-
`Mode: ${bundle.mode}`,
|
|
65771
|
-
`Viewport: ${viewport.width}x${viewport.height}`,
|
|
65772
|
-
`Screenshot: ${screenshotPath}`,
|
|
65773
|
-
`Gate: ${gate.kind} (${gate.confidence.toFixed(2)})${gate.evidence.length ? ` — ${gate.evidence.join("; ")}` : ""}`,
|
|
65774
|
-
`Console warnings/errors: ${bundle.consoleErrors.length}`,
|
|
65775
|
-
`Network failures: ${networkFailures.length}`,
|
|
65776
|
-
"",
|
|
65777
|
-
"--- DOM Summary ---",
|
|
65778
|
-
summary.slice(0, 6e3)
|
|
65779
|
-
].join("\n"),
|
|
65780
|
-
llmContent: JSON.stringify(modelBundle, null, 2),
|
|
65781
|
-
evidenceEvents: [evidenceEvent],
|
|
65782
|
-
durationMs: Date.now() - start2
|
|
65783
|
-
};
|
|
65784
65995
|
}
|
|
65785
65996
|
case "visual_click": {
|
|
65786
65997
|
if (!visualTarget)
|
|
@@ -66068,7 +66279,9 @@ ${JSON.stringify(data, null, 2)}`, start2);
|
|
|
66068
66279
|
].filter(Boolean).join("\n"),
|
|
66069
66280
|
llmContent: JSON.stringify(bundle, null, 2),
|
|
66070
66281
|
evidenceEvents: [evidenceEvent],
|
|
66071
|
-
...expectationSatisfied === false ? {
|
|
66282
|
+
...expectationSatisfied === false ? {
|
|
66283
|
+
error: `Postcondition not observed: ${expectation}. ${expectationError?.slice(0, 500) ?? ""}`.trim()
|
|
66284
|
+
} : {},
|
|
66072
66285
|
durationMs: Date.now() - start2
|
|
66073
66286
|
};
|
|
66074
66287
|
}
|
|
@@ -659396,13 +659609,13 @@ ${context2 ?? ""}`;
|
|
|
659396
659609
|
critique2 = this._buildVisualAdversaryCritique({
|
|
659397
659610
|
evidence: `${inconclusiveEvent.tool}/${inconclusiveEvent.action} produced only inconclusive proof: ${inconclusiveEvent.verification?.reason ?? "no reason"}`,
|
|
659398
659611
|
hypothesis: "The browser action may have worked, but the current evidence is not strong enough to prove the user-visible event.",
|
|
659399
|
-
correctiveAction: 'Run playwright_browser({action:"
|
|
659612
|
+
correctiveAction: 'Run playwright_browser({action:"observe_window", observation_ms:5000, expect:"..."}) after the action. Verify the expected state plus window-scoped console, page, network, DOM, and screenshot evidence.'
|
|
659400
659613
|
});
|
|
659401
659614
|
} else if (events.length === 0) {
|
|
659402
659615
|
critique2 = this._buildVisualAdversaryCritique({
|
|
659403
659616
|
evidence: `${toolName} changed ${surface} state but did not return a structured evidence event.`,
|
|
659404
659617
|
hypothesis: "The agent may be acting from stale visual state after a click/type/submit/navigation action.",
|
|
659405
|
-
correctiveAction: surface === "browser" ? 'Run playwright_browser({action:"
|
|
659618
|
+
correctiveAction: surface === "browser" ? 'Run playwright_browser({action:"observe_window", observation_ms:5000, expect:"..."}) before claiming success. Use a fresh headed validate_lifecycle run when the claim concerns GUI, GPU, WebGL, WebGPU, canvas, or animation behavior.' : 'Run vision_action_loop({action:"observe", goal:"..."}) or desktop_describe before claiming success.'
|
|
659406
659619
|
});
|
|
659407
659620
|
}
|
|
659408
659621
|
if (critique2) {
|
|
@@ -678995,6 +679208,9 @@ Example: ${tool.name}(${JSON.stringify(meta.examples[0].args ?? {})})` : "";
|
|
|
678995
679208
|
"file_explore",
|
|
678996
679209
|
"web_search",
|
|
678997
679210
|
"web_fetch",
|
|
679211
|
+
// Browser evidence must be available without a lexical relevance guess.
|
|
679212
|
+
// Surfaces that do not register this tool do not expose it.
|
|
679213
|
+
"playwright_browser",
|
|
678998
679214
|
"memory_read",
|
|
678999
679215
|
"memory_write",
|
|
679000
679216
|
"working_notes",
|
|
@@ -679112,11 +679328,12 @@ Example: ${tool.name}(${JSON.stringify(meta.examples[0].args ?? {})})` : "";
|
|
|
679112
679328
|
const compressDesc = true;
|
|
679113
679329
|
const defs = dedupedInline.map((tool) => {
|
|
679114
679330
|
const desc = getDesc(tool);
|
|
679331
|
+
const modelFacingDescription = tool.modelFacingSummary?.trim();
|
|
679115
679332
|
return {
|
|
679116
679333
|
type: "function",
|
|
679117
679334
|
function: {
|
|
679118
679335
|
name: tool.name,
|
|
679119
|
-
description: compressDesc ? (desc.split(/\.\s/)[0]?.slice(0, 120) ?? desc.slice(0, 120)) + "." : desc,
|
|
679336
|
+
description: modelFacingDescription ? modelFacingDescription.slice(0, 420) : compressDesc ? (desc.split(/\.\s/)[0]?.slice(0, 120) ?? desc.slice(0, 120)) + "." : desc,
|
|
679120
679337
|
parameters: this._publicToolParameters(tool.parameters)
|
|
679121
679338
|
}
|
|
679122
679339
|
};
|
|
@@ -686617,11 +686834,11 @@ var init_workerSkillStandard = __esm({
|
|
|
686617
686834
|
{
|
|
686618
686835
|
stepNumber: 3,
|
|
686619
686836
|
title: "Validate every requested browser flow in one Playwright session",
|
|
686620
|
-
description: "Use playwright_browser
|
|
686837
|
+
description: "Use playwright_browser validate_lifecycle -> action -> state-based postcondition -> observe_window. Set a finite observation_ms so delayed errors can surface. For GUI, GPU, WebGL, WebGPU, canvas, or animation claims, use a fresh headed browser. A clean headless load is not headed rendering evidence. Prefer data-testid or role/name locators. A click receipt or screenshot alone is not a pass. Re-query after a detached-element error; record each requested interaction as passed, failed, blocked, not_applicable, or inconclusive with the concrete state and diagnostics.",
|
|
686621
686838
|
tools: ["playwright_browser"],
|
|
686622
686839
|
skills: ["browser-interaction-validation"],
|
|
686623
686840
|
output: "One claim-scoped browser evidence entry per requested interaction, separate from static test evidence",
|
|
686624
|
-
verification: "Every interaction has an observed postcondition or a precise failed/blocked/not-applicable outcome; page errors, console errors,
|
|
686841
|
+
verification: "Every interaction has an observed postcondition or a precise failed/blocked/not-applicable outcome; delayed page errors, console errors, failed network requests, DOM state, and screenshots are reviewed from the relevant observation window"
|
|
686625
686842
|
},
|
|
686626
686843
|
{
|
|
686627
686844
|
stepNumber: 4,
|
|
@@ -692429,10 +692646,12 @@ FOR SCREEN / DESKTOP UI (what is on this computer display, clicking, navigating)
|
|
|
692429
692646
|
desktop_click({ target: "element" }) - Click a UI element by description.
|
|
692430
692647
|
vision_action_loop({ goal: "task", action: "observe" }) - Persistent screenshot/OCR/point/action loop with previewable screenshots.
|
|
692431
692648
|
|
|
692432
|
-
FOR BROWSER PAGE / WEB GUI RENDERS
|
|
692649
|
+
FOR BROWSER PAGE / WEB GUI RENDERS:
|
|
692433
692650
|
browser_action({ action: "screenshot", width: 1280, height: 720, output_path: ".omnius/browser/page.png" }) - Render the current headless browser page and return an image input.
|
|
692434
692651
|
playwright_browser({ action: "viewport", text: "1280x720" }) then playwright_browser({ action: "screenshot", value: ".omnius/browser/page.png" }) - Playwright diagnostic browser capture.
|
|
692435
|
-
playwright_browser({ action: "
|
|
692652
|
+
playwright_browser({ action: "validate_lifecycle", url: "http://127.0.0.1:3000", headless: false, force_new: true, observation_ms: 8000, expect: "text=Ready" }) - Start diagnostics before navigation and hold a fresh GUI browser open for delayed rendering failures.
|
|
692653
|
+
playwright_browser({ action: "observe_window", observation_ms: 5000, expect: "text=Updated" }) - Keep the current page alive and return diagnostics emitted during the post-action window.
|
|
692654
|
+
playwright_browser({ action: "observe_bundle" }) - Capture current session diagnostics and page state when a timed window is not required.
|
|
692436
692655
|
playwright_browser({ action: "visual_click", target: "button or field", vision_model: "moondream" }) - Browser screenshot -> Moondream point -> DOM candidate -> click -> post-action screenshot.
|
|
692437
692656
|
|
|
692438
692657
|
RULES:
|
|
@@ -692441,6 +692660,7 @@ RULES:
|
|
|
692441
692660
|
- For seeing the screen, use screenshot, desktop_describe, or vision_action_loop, not camera_capture.
|
|
692442
692661
|
- For image files, use image_read or vision, not desktop_describe.
|
|
692443
692662
|
- For browser GUI action when selectors are unknown, use playwright_browser visual_click before desktop-level clicking.
|
|
692663
|
+
- Match the browser mode to the claim. A clean immediate or headless run does not verify delayed headed GPU/WebGL behavior.
|
|
692444
692664
|
- Do not claim you cannot see visual content until the relevant visual tool has failed.
|
|
692445
692665
|
</visual-and-sensor-tools>`;
|
|
692446
692666
|
}
|
|
@@ -701137,6 +701357,7 @@ function adaptExecutionTool(tool, options2 = {}) {
|
|
|
701137
701357
|
name: tool.name,
|
|
701138
701358
|
aliases: tool.aliases,
|
|
701139
701359
|
description: tool.description,
|
|
701360
|
+
modelFacingSummary: tool.modelFacingSummary,
|
|
701140
701361
|
parameters: tool.parameters,
|
|
701141
701362
|
inputSchema: tool.inputSchema,
|
|
701142
701363
|
maxResultSizeChars: tool.maxResultSizeChars,
|
|
@@ -773624,6 +773845,157 @@ function codeBlock(code8, language = "") {
|
|
|
773624
773845
|
const inner = escapeHtml2(String(code8 ?? "").replace(/\s+$/, ""));
|
|
773625
773846
|
return language ? `<pre><code class="language-${escapeHtml2(language)}">${inner}</code></pre>` : `<pre>${inner}</pre>`;
|
|
773626
773847
|
}
|
|
773848
|
+
function telegramRichText(text3) {
|
|
773849
|
+
return escapeHtml2(text3).replace(/\r?\n/g, "<br>");
|
|
773850
|
+
}
|
|
773851
|
+
function renderTelegramPanelPage(input) {
|
|
773852
|
+
const metadata = (input.metadata ?? []).map((item) => ({
|
|
773853
|
+
label: String(item.label ?? "").trim(),
|
|
773854
|
+
value: String(item.value ?? "").trim()
|
|
773855
|
+
})).filter((item) => item.label && item.value);
|
|
773856
|
+
const sections = input.sections.map((section) => ({
|
|
773857
|
+
title: section.title?.trim() || "",
|
|
773858
|
+
packets: section.packets.map((packet) => ({
|
|
773859
|
+
title: packet.title.trim() || "Details",
|
|
773860
|
+
body: packet.body.trim(),
|
|
773861
|
+
open: packet.open === true
|
|
773862
|
+
})).filter((packet) => packet.body)
|
|
773863
|
+
})).filter((section) => section.packets.length > 0);
|
|
773864
|
+
const emptyText = input.emptyText?.trim() || "No data is available yet.";
|
|
773865
|
+
const fallback = [`<b>${escapeHtml2(input.title)}</b>`];
|
|
773866
|
+
if (input.subtitle?.trim()) {
|
|
773867
|
+
fallback.push(`<i>${escapeHtml2(input.subtitle.trim())}</i>`);
|
|
773868
|
+
}
|
|
773869
|
+
if (metadata.length > 0) {
|
|
773870
|
+
fallback.push(
|
|
773871
|
+
"<b>Details</b>",
|
|
773872
|
+
`<blockquote>${escapeHtml2(metadata.map((item) => `${item.label}: ${item.value}`).join("\n"))}</blockquote>`
|
|
773873
|
+
);
|
|
773874
|
+
}
|
|
773875
|
+
if (sections.length === 0) {
|
|
773876
|
+
fallback.push(`<i>${escapeHtml2(emptyText)}</i>`);
|
|
773877
|
+
} else {
|
|
773878
|
+
for (const section of sections) {
|
|
773879
|
+
if (section.title) fallback.push(`<b>${escapeHtml2(section.title)}</b>`);
|
|
773880
|
+
for (const packet of section.packets) {
|
|
773881
|
+
const expandable = !packet.open && (packet.body.length > 180 || packet.body.split(/\r?\n/).length > 3);
|
|
773882
|
+
fallback.push(
|
|
773883
|
+
`<b>${escapeHtml2(packet.title)}</b>`,
|
|
773884
|
+
`<blockquote${expandable ? " expandable" : ""}>${escapeHtml2(packet.body)}</blockquote>`
|
|
773885
|
+
);
|
|
773886
|
+
}
|
|
773887
|
+
}
|
|
773888
|
+
}
|
|
773889
|
+
if (input.footer?.trim()) {
|
|
773890
|
+
fallback.push(`<i>${escapeHtml2(input.footer.trim())}</i>`);
|
|
773891
|
+
}
|
|
773892
|
+
const rich = [`<h3>${escapeHtml2(input.title)}</h3>`];
|
|
773893
|
+
if (input.subtitle?.trim()) {
|
|
773894
|
+
rich.push(`<p><i>${telegramRichText(input.subtitle.trim())}</i></p>`);
|
|
773895
|
+
}
|
|
773896
|
+
if (metadata.length > 0) {
|
|
773897
|
+
rich.push(
|
|
773898
|
+
[
|
|
773899
|
+
"<table bordered striped compact>",
|
|
773900
|
+
"<tr><th>Field</th><th>Value</th></tr>",
|
|
773901
|
+
...metadata.map(
|
|
773902
|
+
(item) => `<tr><td>${telegramRichText(item.label)}</td><td>${telegramRichText(item.value)}</td></tr>`
|
|
773903
|
+
),
|
|
773904
|
+
"</table>"
|
|
773905
|
+
].join("")
|
|
773906
|
+
);
|
|
773907
|
+
}
|
|
773908
|
+
if (sections.length === 0) {
|
|
773909
|
+
rich.push(`<p><i>${telegramRichText(emptyText)}</i></p>`);
|
|
773910
|
+
} else {
|
|
773911
|
+
for (const section of sections) {
|
|
773912
|
+
if (section.title) rich.push(`<h4>${escapeHtml2(section.title)}</h4>`);
|
|
773913
|
+
for (const packet of section.packets) {
|
|
773914
|
+
rich.push(
|
|
773915
|
+
`<details${packet.open ? " open" : ""}><summary>${escapeHtml2(packet.title)}</summary><p>${telegramRichText(packet.body)}</p></details>`
|
|
773916
|
+
);
|
|
773917
|
+
}
|
|
773918
|
+
}
|
|
773919
|
+
}
|
|
773920
|
+
if (input.footer?.trim()) {
|
|
773921
|
+
rich.push(`<footer>${telegramRichText(input.footer.trim())}</footer>`);
|
|
773922
|
+
}
|
|
773923
|
+
return { html: fallback.join("\n\n"), richHtml: rich.join("\n") };
|
|
773924
|
+
}
|
|
773925
|
+
function telegramTitledTextPackets(text3, fallbackTitle = "Details", maxPackets = 16) {
|
|
773926
|
+
const source = String(text3 ?? "").trim();
|
|
773927
|
+
if (!source) return [];
|
|
773928
|
+
const packets = [];
|
|
773929
|
+
let currentTitle = "";
|
|
773930
|
+
let currentLines = [];
|
|
773931
|
+
const flush3 = () => {
|
|
773932
|
+
const body = currentLines.join("\n").trim();
|
|
773933
|
+
if (body) {
|
|
773934
|
+
packets.push({
|
|
773935
|
+
title: currentTitle || fallbackTitle,
|
|
773936
|
+
body
|
|
773937
|
+
});
|
|
773938
|
+
}
|
|
773939
|
+
currentTitle = "";
|
|
773940
|
+
currentLines = [];
|
|
773941
|
+
};
|
|
773942
|
+
for (const line of source.split(/\r?\n/)) {
|
|
773943
|
+
const heading = line.match(/^([^:\n]{1,100}):\s*$/);
|
|
773944
|
+
if (heading) {
|
|
773945
|
+
flush3();
|
|
773946
|
+
currentTitle = heading[1].trim();
|
|
773947
|
+
} else {
|
|
773948
|
+
currentLines.push(line);
|
|
773949
|
+
}
|
|
773950
|
+
}
|
|
773951
|
+
flush3();
|
|
773952
|
+
if (packets.length <= 1 && !/^([^:\n]{1,100}):\s*$/m.test(source)) {
|
|
773953
|
+
const paragraphs = source.split(/\r?\n\s*\r?\n+/).map((paragraph) => paragraph.trim()).filter(Boolean);
|
|
773954
|
+
packets.length = 0;
|
|
773955
|
+
packets.push(
|
|
773956
|
+
...paragraphs.map((paragraph, index) => ({
|
|
773957
|
+
title: paragraphs.length === 1 ? fallbackTitle : `${fallbackTitle} ${index + 1}`,
|
|
773958
|
+
body: paragraph
|
|
773959
|
+
}))
|
|
773960
|
+
);
|
|
773961
|
+
}
|
|
773962
|
+
if (packets.length <= maxPackets) return packets;
|
|
773963
|
+
const retained = packets.slice(0, Math.max(1, maxPackets - 1));
|
|
773964
|
+
retained.push({
|
|
773965
|
+
title: `${fallbackTitle} ${maxPackets}`,
|
|
773966
|
+
body: packets.slice(Math.max(1, maxPackets - 1)).map((packet) => `${packet.title}
|
|
773967
|
+
${packet.body}`).join("\n\n")
|
|
773968
|
+
});
|
|
773969
|
+
return retained;
|
|
773970
|
+
}
|
|
773971
|
+
function splitTelegramPlainText(text3, maxLength = 2500) {
|
|
773972
|
+
const chunks = [];
|
|
773973
|
+
let remaining = String(text3 ?? "").trim();
|
|
773974
|
+
const limit2 = Math.max(200, Math.floor(maxLength));
|
|
773975
|
+
while (remaining.length > limit2) {
|
|
773976
|
+
let cut = remaining.lastIndexOf("\n\n", limit2);
|
|
773977
|
+
if (cut < limit2 * 0.4) cut = remaining.lastIndexOf("\n", limit2);
|
|
773978
|
+
if (cut < limit2 * 0.4) cut = remaining.lastIndexOf(". ", limit2);
|
|
773979
|
+
if (cut < limit2 * 0.4) cut = remaining.lastIndexOf(" ", limit2);
|
|
773980
|
+
if (cut < limit2 * 0.4) cut = limit2;
|
|
773981
|
+
const chunk = remaining.slice(0, cut).trim();
|
|
773982
|
+
if (chunk) chunks.push(chunk);
|
|
773983
|
+
remaining = remaining.slice(cut).trim();
|
|
773984
|
+
}
|
|
773985
|
+
if (remaining || chunks.length === 0) chunks.push(remaining);
|
|
773986
|
+
return chunks;
|
|
773987
|
+
}
|
|
773988
|
+
function telegramHtmlToPlainText(html) {
|
|
773989
|
+
return String(html ?? "").replace(/<br\s*\/?>/gi, "\n").replace(
|
|
773990
|
+
/<\/(?:p|h[1-6]|blockquote|details|summary|table|tr|ul|ol|li|footer)>/gi,
|
|
773991
|
+
"\n"
|
|
773992
|
+
).replace(/<hr\s*\/?>/gi, "\n").replace(/<[^>]+>/g, "").replace(/&#(x[0-9a-f]+|\d+);/gi, (_match, value2) => {
|
|
773993
|
+
const radix = value2[0]?.toLowerCase() === "x" ? 16 : 10;
|
|
773994
|
+
const raw = radix === 16 ? value2.slice(1) : value2;
|
|
773995
|
+
const codePoint = Number.parseInt(raw, radix);
|
|
773996
|
+
return Number.isFinite(codePoint) ? String.fromCodePoint(codePoint) : "";
|
|
773997
|
+
}).replace(/"/g, '"').replace(/'/g, "'").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&").replace(/\n[ \t]+/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
773998
|
+
}
|
|
773627
773999
|
function safeJson(v, pretty) {
|
|
773628
774000
|
try {
|
|
773629
774001
|
return pretty ? JSON.stringify(v, null, 2) : JSON.stringify(v);
|
|
@@ -773637,11 +774009,14 @@ function tokenizeTelegramHtml(html) {
|
|
|
773637
774009
|
let last2 = 0;
|
|
773638
774010
|
let m2;
|
|
773639
774011
|
while ((m2 = re.exec(html)) !== null) {
|
|
773640
|
-
if (m2.index > last2)
|
|
774012
|
+
if (m2.index > last2)
|
|
774013
|
+
tokens3.push({ type: "text", raw: html.slice(last2, m2.index) });
|
|
773641
774014
|
const closing = m2[1] === "/";
|
|
773642
774015
|
const tag = (m2[2] || "").toLowerCase();
|
|
773643
774016
|
if (SPAN_TAGS.has(tag)) {
|
|
773644
|
-
tokens3.push(
|
|
774017
|
+
tokens3.push(
|
|
774018
|
+
closing ? { type: "close", tag, raw: m2[0] } : { type: "open", tag, raw: m2[0] }
|
|
774019
|
+
);
|
|
773645
774020
|
} else {
|
|
773646
774021
|
tokens3.push({ type: "text", raw: m2[0] });
|
|
773647
774022
|
}
|
|
@@ -781284,6 +781659,30 @@ function parseTelegramSilentReflectionNotes(text3) {
|
|
|
781284
781659
|
}
|
|
781285
781660
|
return null;
|
|
781286
781661
|
}
|
|
781662
|
+
function telegramInteractionDecisionResponseFormatForPacket(packet) {
|
|
781663
|
+
const format3 = structuredClone(
|
|
781664
|
+
TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT
|
|
781665
|
+
);
|
|
781666
|
+
const properties = format3.json_schema.schema.properties;
|
|
781667
|
+
properties.input_id = {
|
|
781668
|
+
type: "string",
|
|
781669
|
+
enum: [packet.inputId]
|
|
781670
|
+
};
|
|
781671
|
+
properties.addressed_actor_keys = {
|
|
781672
|
+
type: "array",
|
|
781673
|
+
items: { type: "string", enum: packet.actorKeys },
|
|
781674
|
+
maxItems: 12
|
|
781675
|
+
};
|
|
781676
|
+
properties.evidence_ids = {
|
|
781677
|
+
type: "array",
|
|
781678
|
+
items: {
|
|
781679
|
+
type: "string",
|
|
781680
|
+
enum: packet.evidence.map((entry) => entry.id)
|
|
781681
|
+
},
|
|
781682
|
+
maxItems: 16
|
|
781683
|
+
};
|
|
781684
|
+
return format3;
|
|
781685
|
+
}
|
|
781287
781686
|
function extractPartialTelegramReplyJson(buffer2) {
|
|
781288
781687
|
const stripped = stripTelegramHiddenThinking(buffer2).trimStart();
|
|
781289
781688
|
if (!stripped.startsWith("{")) {
|
|
@@ -781818,10 +782217,7 @@ function formatTelegramSteeringReconciliationHTML(values) {
|
|
|
781818
782217
|
if (values.length === 0) return "";
|
|
781819
782218
|
const sections = values.slice(-4).map((value2) => {
|
|
781820
782219
|
const status = value2.status.replaceAll("_", " ");
|
|
781821
|
-
const constraints = value2.changedConstraints.length ? [
|
|
781822
|
-
"Changes:",
|
|
781823
|
-
...value2.changedConstraints.map((item) => `• ${item}`)
|
|
781824
|
-
] : ["Changes: none"];
|
|
782220
|
+
const constraints = value2.changedConstraints.length ? ["Changes:", ...value2.changedConstraints.map((item) => `• ${item}`)] : ["Changes: none"];
|
|
781825
782221
|
return [
|
|
781826
782222
|
`Status: ${status}`,
|
|
781827
782223
|
...constraints,
|
|
@@ -782395,11 +782791,78 @@ function telegramAdminLivePanelPageLabel(page2) {
|
|
|
782395
782791
|
if (page2 === "evidence") return "Evidence";
|
|
782396
782792
|
return "Context";
|
|
782397
782793
|
}
|
|
782794
|
+
function telegramPanelHtmlFallback(html) {
|
|
782795
|
+
const chunks = segmentTelegramHtml(html, 3600);
|
|
782796
|
+
if (chunks.length <= 1) return chunks[0] ?? "";
|
|
782797
|
+
return `${chunks[0]}
|
|
782798
|
+
|
|
782799
|
+
<i>... (additional packet detail requires Rich Message support)</i>`;
|
|
782800
|
+
}
|
|
782801
|
+
function telegramAdminLinePackets(lines, fallbackTitle) {
|
|
782802
|
+
return lines.map((line, index) => {
|
|
782803
|
+
const structured = line.match(
|
|
782804
|
+
/^([→✓✗])\s+([^\s:]+)(?::\s*|\s+)?([\s\S]*)$/
|
|
782805
|
+
);
|
|
782806
|
+
if (!structured) {
|
|
782807
|
+
return { title: `${fallbackTitle} ${index + 1}`, body: line };
|
|
782808
|
+
}
|
|
782809
|
+
const marker = structured[1];
|
|
782810
|
+
const toolName = structured[2] || "tool";
|
|
782811
|
+
const detail = structured[3]?.trim();
|
|
782812
|
+
const phase = marker === "→" ? "Call" : marker === "✓" ? "Result" : "Failure";
|
|
782813
|
+
return {
|
|
782814
|
+
title: `${phase} · ${toolName}`,
|
|
782815
|
+
body: detail || (marker === "→" ? "Request admitted." : marker === "✓" ? "Completed." : "The tool reported a failure.")
|
|
782816
|
+
};
|
|
782817
|
+
});
|
|
782818
|
+
}
|
|
782819
|
+
function telegramContextMetadata(page2, pageIndex, pageCount) {
|
|
782820
|
+
return [
|
|
782821
|
+
{ label: "Packet", value: `${pageIndex + 1} / ${pageCount}` },
|
|
782822
|
+
{ label: "Source", value: page2.source },
|
|
782823
|
+
...page2.metadata.map((line, index) => {
|
|
782824
|
+
const equalsAt = line.indexOf("=");
|
|
782825
|
+
return equalsAt > 0 ? {
|
|
782826
|
+
label: line.slice(0, equalsAt).trim(),
|
|
782827
|
+
value: line.slice(equalsAt + 1).trim()
|
|
782828
|
+
} : { label: `Detail ${index + 1}`, value: line };
|
|
782829
|
+
})
|
|
782830
|
+
];
|
|
782831
|
+
}
|
|
782832
|
+
function renderTelegramContextExplorerPagePayload(page2, pageIndex, pageCount, title = "Context used for this reply") {
|
|
782833
|
+
if (!page2) {
|
|
782834
|
+
const empty2 = renderTelegramPanelPage({
|
|
782835
|
+
title,
|
|
782836
|
+
sections: [],
|
|
782837
|
+
emptyText: "No context packets are available."
|
|
782838
|
+
});
|
|
782839
|
+
return { text: empty2.html, rich_html: empty2.richHtml };
|
|
782840
|
+
}
|
|
782841
|
+
const rendered = renderTelegramPanelPage({
|
|
782842
|
+
title,
|
|
782843
|
+
subtitle: page2.title,
|
|
782844
|
+
metadata: telegramContextMetadata(page2, pageIndex, pageCount),
|
|
782845
|
+
sections: [
|
|
782846
|
+
{
|
|
782847
|
+
packets: telegramTitledTextPackets(page2.body, "Content")
|
|
782848
|
+
}
|
|
782849
|
+
],
|
|
782850
|
+
emptyText: "This context packet is empty.",
|
|
782851
|
+
footer: `Context packet ${pageIndex + 1} of ${pageCount}`
|
|
782852
|
+
});
|
|
782853
|
+
return {
|
|
782854
|
+
text: telegramPanelHtmlFallback(rendered.html),
|
|
782855
|
+
rich_html: rendered.richHtml
|
|
782856
|
+
};
|
|
782857
|
+
}
|
|
782398
782858
|
function trimTelegramAdminPanelLines(lines, max = 80) {
|
|
782399
782859
|
if (lines.length > max) lines.splice(0, lines.length - max);
|
|
782400
782860
|
}
|
|
782401
782861
|
function pushTelegramAdminPanelLine(state5, page2, line) {
|
|
782402
|
-
const clean7 =
|
|
782862
|
+
const clean7 = sanitizeTelegramProgressText(
|
|
782863
|
+
stripTelegramHiddenThinking(line).replace(/\s+/g, " ").trim(),
|
|
782864
|
+
1e3
|
|
782865
|
+
);
|
|
782403
782866
|
if (!clean7) return;
|
|
782404
782867
|
const target = page2 === "tools" ? state5.toolLines : page2 === "logs" ? state5.logLines : state5.mutationLines;
|
|
782405
782868
|
if (target[target.length - 1] !== clean7) target.push(clean7);
|
|
@@ -782408,7 +782871,10 @@ function pushTelegramAdminPanelLine(state5, page2, line) {
|
|
|
782408
782871
|
if (state5.activePage !== page2) state5.dirtyPages[page2] = true;
|
|
782409
782872
|
}
|
|
782410
782873
|
function pushTelegramAdminPanelMutationLine(state5, line) {
|
|
782411
|
-
const clean7 =
|
|
782874
|
+
const clean7 = sanitizeTelegramProgressText(
|
|
782875
|
+
stripTelegramHiddenThinking(line).replace(/\s+/g, " ").trim(),
|
|
782876
|
+
1e3
|
|
782877
|
+
);
|
|
782412
782878
|
if (!clean7) return;
|
|
782413
782879
|
if (state5.mutationLines[state5.mutationLines.length - 1] !== clean7)
|
|
782414
782880
|
state5.mutationLines.push(clean7);
|
|
@@ -782428,6 +782894,37 @@ function telegramAdminLivePanelIntakeText(requestPreview) {
|
|
|
782428
782894
|
void requestPreview;
|
|
782429
782895
|
return "";
|
|
782430
782896
|
}
|
|
782897
|
+
function telegramAdminEventTurn(event) {
|
|
782898
|
+
const turn = event.turn;
|
|
782899
|
+
return typeof turn === "number" && Number.isFinite(turn) ? turn : void 0;
|
|
782900
|
+
}
|
|
782901
|
+
function syncTelegramAdminResponseText(state5) {
|
|
782902
|
+
state5.responseText = state5.responseSegments.map(
|
|
782903
|
+
(segment) => cleanTelegramVisibleReply(segment.rawText, {
|
|
782904
|
+
suppressPotentialNoReplyPrefix: true
|
|
782905
|
+
})
|
|
782906
|
+
).filter(Boolean).join("\n\n");
|
|
782907
|
+
}
|
|
782908
|
+
function upsertTelegramAdminResponseSegment(state5, key, turn, rawText, complete) {
|
|
782909
|
+
const existing = state5.responseSegments.find(
|
|
782910
|
+
(segment) => segment.key === key
|
|
782911
|
+
);
|
|
782912
|
+
if (existing) {
|
|
782913
|
+
existing.rawText = rawText;
|
|
782914
|
+
existing.complete = complete;
|
|
782915
|
+
} else {
|
|
782916
|
+
state5.responseSegments.push({
|
|
782917
|
+
key,
|
|
782918
|
+
...turn !== void 0 ? { turn } : {},
|
|
782919
|
+
rawText,
|
|
782920
|
+
complete
|
|
782921
|
+
});
|
|
782922
|
+
}
|
|
782923
|
+
if (state5.responseSegments.length > 8) {
|
|
782924
|
+
state5.responseSegments.splice(0, state5.responseSegments.length - 8);
|
|
782925
|
+
}
|
|
782926
|
+
syncTelegramAdminResponseText(state5);
|
|
782927
|
+
}
|
|
782431
782928
|
function renderTelegramHalftoneProgressBar(elapsedSec, width = 12) {
|
|
782432
782929
|
const safeWidth = Math.max(1, Math.floor(width));
|
|
782433
782930
|
const phase = Math.max(0, elapsedSec) % 60 / 60 * safeWidth;
|
|
@@ -782460,6 +782957,8 @@ function createTelegramAdminLivePanelState(args) {
|
|
|
782460
782957
|
requestPreview,
|
|
782461
782958
|
intakeText: telegramAdminLivePanelIntakeText(requestPreview),
|
|
782462
782959
|
responseText: "",
|
|
782960
|
+
responseSegments: [],
|
|
782961
|
+
responseSegmentSequence: 0,
|
|
782463
782962
|
steeringReconciliations: [],
|
|
782464
782963
|
evidenceText: "",
|
|
782465
782964
|
toolLines: [],
|
|
@@ -782470,24 +782969,40 @@ function createTelegramAdminLivePanelState(args) {
|
|
|
782470
782969
|
};
|
|
782471
782970
|
}
|
|
782472
782971
|
function applyTelegramAdminLivePanelEvent(state5, event) {
|
|
782972
|
+
if (event.type === "stream_start") {
|
|
782973
|
+
const turn = telegramAdminEventTurn(event);
|
|
782974
|
+
const key = turn !== void 0 ? `turn:${turn}` : `stream:${++state5.responseSegmentSequence}`;
|
|
782975
|
+
upsertTelegramAdminResponseSegment(state5, key, turn, "", false);
|
|
782976
|
+
state5.activeResponseSegmentKey = key;
|
|
782977
|
+
return;
|
|
782978
|
+
}
|
|
782473
782979
|
if (event.type === "stream_token" && event.streamKind === "content" && event.content) {
|
|
782474
|
-
const
|
|
782475
|
-
|
|
782476
|
-
|
|
782980
|
+
const turn = telegramAdminEventTurn(event);
|
|
782981
|
+
const key = state5.activeResponseSegmentKey ?? (turn !== void 0 ? `turn:${turn}` : `stream:${++state5.responseSegmentSequence}`);
|
|
782982
|
+
const existing = state5.responseSegments.find(
|
|
782983
|
+
(segment) => segment.key === key
|
|
782984
|
+
);
|
|
782985
|
+
upsertTelegramAdminResponseSegment(
|
|
782986
|
+
state5,
|
|
782987
|
+
key,
|
|
782988
|
+
turn,
|
|
782989
|
+
`${existing?.rawText ?? ""}${event.content}`,
|
|
782990
|
+
false
|
|
782477
782991
|
);
|
|
782478
|
-
if (
|
|
782479
|
-
state5.responseText = next;
|
|
782992
|
+
if (state5.responseText) {
|
|
782480
782993
|
state5.updatedAt = Date.now();
|
|
782481
782994
|
if (state5.activePage !== "response") state5.dirtyPages.response = true;
|
|
782482
782995
|
}
|
|
782483
782996
|
return;
|
|
782484
782997
|
}
|
|
782485
782998
|
if ((event.type === "assistant_text" || event.type === "stream_end") && event.content) {
|
|
782486
|
-
const
|
|
782487
|
-
|
|
782488
|
-
|
|
782489
|
-
if (
|
|
782490
|
-
state5.
|
|
782999
|
+
const turn = telegramAdminEventTurn(event);
|
|
783000
|
+
const key = turn !== void 0 ? `turn:${turn}` : state5.activeResponseSegmentKey ?? `event:${++state5.responseSegmentSequence}`;
|
|
783001
|
+
upsertTelegramAdminResponseSegment(state5, key, turn, event.content, true);
|
|
783002
|
+
if (state5.activeResponseSegmentKey === key) {
|
|
783003
|
+
state5.activeResponseSegmentKey = void 0;
|
|
783004
|
+
}
|
|
783005
|
+
if (state5.responseText) {
|
|
782491
783006
|
state5.updatedAt = Date.now();
|
|
782492
783007
|
if (state5.activePage !== "response") state5.dirtyPages.response = true;
|
|
782493
783008
|
}
|
|
@@ -782530,12 +783045,12 @@ function applyTelegramAdminLivePanelEvent(state5, event) {
|
|
|
782530
783045
|
}
|
|
782531
783046
|
}
|
|
782532
783047
|
function renderTelegramAdminLivePanelPayload(state5) {
|
|
782533
|
-
|
|
782534
|
-
|
|
782535
|
-
|
|
782536
|
-
|
|
782537
|
-
].filter(Boolean).join("\n");
|
|
783048
|
+
const metadata = [
|
|
783049
|
+
{ label: "Run status", value: state5.status },
|
|
783050
|
+
...state5.requestPreview ? [{ label: "Request", value: state5.requestPreview }] : []
|
|
783051
|
+
];
|
|
782538
783052
|
let body;
|
|
783053
|
+
let richHtml;
|
|
782539
783054
|
if (state5.activePage === "response") {
|
|
782540
783055
|
const response = state5.responseText.trim();
|
|
782541
783056
|
const clipped = response.length > 2600 ? `${response.slice(0, 2597).trimEnd()}...` : response;
|
|
@@ -782548,15 +783063,53 @@ function renderTelegramAdminLivePanelPayload(state5) {
|
|
|
782548
783063
|
].filter(Boolean).join("\n\n");
|
|
782549
783064
|
} else if (state5.activePage === "tools") {
|
|
782550
783065
|
const lines = state5.toolLines.slice(-12);
|
|
782551
|
-
|
|
783066
|
+
const rendered = renderTelegramPanelPage({
|
|
783067
|
+
title: "Tools",
|
|
783068
|
+
subtitle: `${lines.length} recent tool event${lines.length === 1 ? "" : "s"}. Newest is last.`,
|
|
783069
|
+
metadata,
|
|
783070
|
+
sections: [{ packets: telegramAdminLinePackets(lines, "Tool event") }],
|
|
783071
|
+
emptyText: "No tool calls yet.",
|
|
783072
|
+
footer: "Page 2 of 5 · Tools"
|
|
783073
|
+
});
|
|
783074
|
+
body = telegramPanelHtmlFallback(rendered.html);
|
|
783075
|
+
richHtml = rendered.richHtml;
|
|
782552
783076
|
} else if (state5.activePage === "logs") {
|
|
782553
|
-
const
|
|
782554
|
-
|
|
782555
|
-
|
|
782556
|
-
|
|
782557
|
-
|
|
783077
|
+
const mutations = state5.mutationLines.slice(-8);
|
|
783078
|
+
const logs = state5.logLines.slice(-10);
|
|
783079
|
+
const rendered = renderTelegramPanelPage({
|
|
783080
|
+
title: "Activity",
|
|
783081
|
+
subtitle: `${mutations.length} workspace change event${mutations.length === 1 ? "" : "s"}; ${logs.length} runner event${logs.length === 1 ? "" : "s"}.`,
|
|
783082
|
+
metadata,
|
|
783083
|
+
sections: [
|
|
783084
|
+
{
|
|
783085
|
+
title: "Workspace changes",
|
|
783086
|
+
packets: telegramAdminLinePackets(mutations, "Change")
|
|
783087
|
+
},
|
|
783088
|
+
{
|
|
783089
|
+
title: "Run activity",
|
|
783090
|
+
packets: telegramAdminLinePackets(logs, "Event")
|
|
783091
|
+
}
|
|
783092
|
+
],
|
|
783093
|
+
emptyText: "No workspace changes or runner activity yet.",
|
|
783094
|
+
footer: "Page 3 of 5 · Activity"
|
|
783095
|
+
});
|
|
783096
|
+
body = telegramPanelHtmlFallback(rendered.html);
|
|
783097
|
+
richHtml = rendered.richHtml;
|
|
782558
783098
|
} else if (state5.activePage === "evidence") {
|
|
782559
|
-
|
|
783099
|
+
const packets = telegramTitledTextPackets(
|
|
783100
|
+
state5.evidenceText,
|
|
783101
|
+
"Completion evidence"
|
|
783102
|
+
);
|
|
783103
|
+
const rendered = renderTelegramPanelPage({
|
|
783104
|
+
title: "Evidence",
|
|
783105
|
+
subtitle: `${packets.length} completion evidence packet${packets.length === 1 ? "" : "s"}.`,
|
|
783106
|
+
metadata,
|
|
783107
|
+
sections: [{ packets }],
|
|
783108
|
+
emptyText: "No completion evidence yet.",
|
|
783109
|
+
footer: "Page 4 of 5 · Evidence"
|
|
783110
|
+
});
|
|
783111
|
+
body = telegramPanelHtmlFallback(rendered.html);
|
|
783112
|
+
richHtml = rendered.richHtml;
|
|
782560
783113
|
} else {
|
|
782561
783114
|
const pageCount = state5.contextPages.length;
|
|
782562
783115
|
const pageIndex = Math.min(
|
|
@@ -782565,36 +783118,20 @@ function renderTelegramAdminLivePanelPayload(state5) {
|
|
|
782565
783118
|
);
|
|
782566
783119
|
state5.contextPageIndex = pageIndex;
|
|
782567
783120
|
const page2 = state5.contextPages[pageIndex];
|
|
782568
|
-
|
|
782569
|
-
|
|
782570
|
-
|
|
782571
|
-
|
|
782572
|
-
|
|
782573
|
-
|
|
782574
|
-
|
|
782575
|
-
|
|
782576
|
-
"",
|
|
782577
|
-
`<i>Context ${pageIndex + 1}/${pageCount}</i>`
|
|
782578
|
-
].filter(Boolean).join("\n");
|
|
782579
|
-
} else {
|
|
782580
|
-
body = "<i>Full context has not been captured yet.</i>";
|
|
782581
|
-
}
|
|
783121
|
+
const rendered = renderTelegramContextExplorerPagePayload(
|
|
783122
|
+
page2,
|
|
783123
|
+
pageIndex,
|
|
783124
|
+
pageCount,
|
|
783125
|
+
"Context"
|
|
783126
|
+
);
|
|
783127
|
+
body = rendered.text;
|
|
783128
|
+
richHtml = rendered.rich_html;
|
|
782582
783129
|
}
|
|
782583
|
-
const
|
|
782584
|
-
header,
|
|
782585
|
-
"",
|
|
782586
|
-
body,
|
|
782587
|
-
"",
|
|
782588
|
-
`<i>Page ${TELEGRAM_ADMIN_LIVE_PANEL_PAGES.indexOf(state5.activePage) + 1}/${TELEGRAM_ADMIN_LIVE_PANEL_PAGES.length}: ${telegramAdminLivePanelPageLabel(state5.activePage)}</i>`
|
|
782589
|
-
].join("\n");
|
|
782590
|
-
const text3 = truncateTelegramUrlSafe(
|
|
782591
|
-
panelText,
|
|
782592
|
-
3900,
|
|
782593
|
-
"\n\n<i>... (panel clipped)</i>"
|
|
782594
|
-
);
|
|
783130
|
+
const text3 = body;
|
|
782595
783131
|
const pageButtons = TELEGRAM_ADMIN_LIVE_PANEL_PAGES.map((page2) => ({
|
|
782596
783132
|
text: `${page2 === state5.activePage ? "●" : "○"} ${telegramAdminLivePanelPageLabel(page2)}${state5.dirtyPages[page2] ? " *" : ""}`,
|
|
782597
|
-
callback_data: `omni:v1:tgadmin:${state5.nonce}:page:${page2}
|
|
783133
|
+
callback_data: `omni:v1:tgadmin:${state5.nonce}:page:${page2}`,
|
|
783134
|
+
...page2 === state5.activePage ? { style: "primary" } : {}
|
|
782598
783135
|
}));
|
|
782599
783136
|
const keyboard = [
|
|
782600
783137
|
pageButtons.slice(0, 3),
|
|
@@ -782606,19 +783143,28 @@ function renderTelegramAdminLivePanelPayload(state5) {
|
|
|
782606
783143
|
keyboard.push([
|
|
782607
783144
|
{
|
|
782608
783145
|
text: "Prev",
|
|
782609
|
-
|
|
783146
|
+
...pageIndex > 0 ? {
|
|
783147
|
+
callback_data: `omni:v1:tgadmin:${state5.nonce}:ctx:${pageIndex - 1}`
|
|
783148
|
+
} : { disabled: {} }
|
|
782610
783149
|
},
|
|
782611
783150
|
{
|
|
782612
783151
|
text: `${pageIndex + 1}/${lastPage + 1}`,
|
|
782613
|
-
|
|
783152
|
+
disabled: {},
|
|
783153
|
+
style: "primary"
|
|
782614
783154
|
},
|
|
782615
783155
|
{
|
|
782616
783156
|
text: "Next",
|
|
782617
|
-
|
|
783157
|
+
...pageIndex < lastPage ? {
|
|
783158
|
+
callback_data: `omni:v1:tgadmin:${state5.nonce}:ctx:${pageIndex + 1}`
|
|
783159
|
+
} : { disabled: {} }
|
|
782618
783160
|
}
|
|
782619
783161
|
]);
|
|
782620
783162
|
}
|
|
782621
|
-
return {
|
|
783163
|
+
return {
|
|
783164
|
+
text: text3,
|
|
783165
|
+
...richHtml ? { rich_html: richHtml } : {},
|
|
783166
|
+
reply_markup: { inline_keyboard: keyboard }
|
|
783167
|
+
};
|
|
782622
783168
|
}
|
|
782623
783169
|
function splitTelegramReminderDue(raw) {
|
|
782624
783170
|
const text3 = raw.trim().replace(/^set\s+/i, "").trim();
|
|
@@ -785865,8 +786411,8 @@ ${context2}` : context2;
|
|
|
785865
786411
|
}
|
|
785866
786412
|
await this.transitionTelegramIntake(
|
|
785867
786413
|
intakeRecord,
|
|
785868
|
-
"consumed",
|
|
785869
|
-
"attention router retained active-runner input as context without reply authority",
|
|
786414
|
+
decision2.source === "inference-unavailable" ? "failed" : "consumed",
|
|
786415
|
+
decision2.source === "inference-unavailable" ? "attention router could not produce a valid input-bound decision" : "attention router retained active-runner input as context without reply authority",
|
|
785870
786416
|
{ runId: sameRunner ? currentSubAgent.runId : expectedSubAgent.runId }
|
|
785871
786417
|
);
|
|
785872
786418
|
return;
|
|
@@ -788945,6 +789491,8 @@ ${antecedents.join("\n")}` : "Immediate antecedents: none.",
|
|
|
788945
789491
|
scenarioConfidence: decision2.scenarioConfidence,
|
|
788946
789492
|
scenarioObjective: decision2.scenarioObjective,
|
|
788947
789493
|
scenarioStateLoop: decision2.scenarioStateLoop,
|
|
789494
|
+
diagnosticNote: decision2.diagnosticNote,
|
|
789495
|
+
validationIssueCodes: decision2.validationIssueCodes,
|
|
788948
789496
|
salienceSignals,
|
|
788949
789497
|
self: this.telegramSelfSocialActorInput(),
|
|
788950
789498
|
daydreamOpportunities
|
|
@@ -791345,10 +791893,7 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`
|
|
|
791345
791893
|
id2,
|
|
791346
791894
|
`broker queue admission deadline expired for ${deadline.request_id}${queueSummary ? ` (${queueSummary})` : ""}; re-entering after ${(delayMs / 1e3).toFixed(1)}s, attempt ${brokerQueueRetryAttempt}`
|
|
791347
791895
|
);
|
|
791348
|
-
await this.waitForTelegramBrokerQueueRetry(
|
|
791349
|
-
delayMs,
|
|
791350
|
-
lifecycleSignal
|
|
791351
|
-
);
|
|
791896
|
+
await this.waitForTelegramBrokerQueueRetry(delayMs, lifecycleSignal);
|
|
791352
791897
|
}
|
|
791353
791898
|
}
|
|
791354
791899
|
const usage = result.usage;
|
|
@@ -791731,6 +792276,15 @@ arguments=` : ""}` + (chunk.toolCallArgs ?? "");
|
|
|
791731
792276
|
getTelegramThinkingVisible() {
|
|
791732
792277
|
return this.telegramThinkingVisible;
|
|
791733
792278
|
}
|
|
792279
|
+
telegramMentionActorIsSelf(actor) {
|
|
792280
|
+
const selfUserId = this.currentTelegramBotUserId();
|
|
792281
|
+
if (selfUserId !== void 0 && actor.userId !== void 0 && actor.userId === selfUserId) {
|
|
792282
|
+
return true;
|
|
792283
|
+
}
|
|
792284
|
+
const selfUsername = this.state.botUsername.trim().replace(/^@/, "").toLowerCase();
|
|
792285
|
+
const actorUsername = actor.username?.trim().replace(/^@/, "").toLowerCase();
|
|
792286
|
+
return Boolean(selfUsername && actorUsername === selfUsername);
|
|
792287
|
+
}
|
|
791734
792288
|
buildTelegramInteractionEvidencePacket(msg) {
|
|
791735
792289
|
const sessionKey = this.sessionKeyForMessage(msg);
|
|
791736
792290
|
const selfActorKey = telegramSocialActorKey(
|
|
@@ -791756,7 +792310,7 @@ arguments=` : ""}` + (chunk.toolCallArgs ?? "");
|
|
|
791756
792310
|
];
|
|
791757
792311
|
const mentionedActors = msg.mentionedActors ?? (msg.mentionedUsernames ?? []).map((username) => ({ username }));
|
|
791758
792312
|
mentionedActors.forEach((actor, index) => {
|
|
791759
|
-
const actorKey = telegramSocialActorKey(actor);
|
|
792313
|
+
const actorKey = this.telegramMentionActorIsSelf(actor) ? selfActorKey : telegramSocialActorKey(actor);
|
|
791760
792314
|
if (actorKey === "unknown") return;
|
|
791761
792315
|
actorKeys.add(actorKey);
|
|
791762
792316
|
evidence.push({
|
|
@@ -791796,33 +792350,103 @@ arguments=` : ""}` + (chunk.toolCallArgs ?? "");
|
|
|
791796
792350
|
evidence
|
|
791797
792351
|
};
|
|
791798
792352
|
}
|
|
791799
|
-
|
|
791800
|
-
|
|
791801
|
-
if (!decision2.
|
|
792353
|
+
validateTelegramInteractionDecisionDetailed(decision2, packet) {
|
|
792354
|
+
const issues = [];
|
|
792355
|
+
if (!decision2.inputId) {
|
|
792356
|
+
issues.push({
|
|
792357
|
+
code: "missing_input_id",
|
|
792358
|
+
message: `input_id must be ${JSON.stringify(packet.inputId)}.`
|
|
792359
|
+
});
|
|
792360
|
+
} else if (decision2.inputId !== packet.inputId) {
|
|
792361
|
+
issues.push({
|
|
792362
|
+
code: "input_id_mismatch",
|
|
792363
|
+
message: `input_id must be ${JSON.stringify(packet.inputId)}.`
|
|
792364
|
+
});
|
|
792365
|
+
}
|
|
792366
|
+
if (!decision2.selfRole) {
|
|
792367
|
+
issues.push({
|
|
792368
|
+
code: "missing_self_role",
|
|
792369
|
+
message: "self_role is required."
|
|
792370
|
+
});
|
|
792371
|
+
}
|
|
792372
|
+
if (!decision2.replyBasis) {
|
|
792373
|
+
issues.push({
|
|
792374
|
+
code: "missing_reply_basis",
|
|
792375
|
+
message: "reply_basis is required."
|
|
792376
|
+
});
|
|
792377
|
+
}
|
|
791802
792378
|
const addressed = decision2.addressedActorKeys ?? [];
|
|
791803
792379
|
const evidenceIds = decision2.evidenceIds ?? [];
|
|
791804
792380
|
const allowedActors = new Set(packet.actorKeys);
|
|
791805
792381
|
const allowedEvidence = new Set(packet.evidence.map((entry) => entry.id));
|
|
791806
|
-
|
|
791807
|
-
if (
|
|
792382
|
+
const unknownActors = addressed.filter((key) => !allowedActors.has(key));
|
|
792383
|
+
if (unknownActors.length > 0) {
|
|
792384
|
+
issues.push({
|
|
792385
|
+
code: "unknown_addressed_actor",
|
|
792386
|
+
message: `addressed_actor_keys contains unknown values ${JSON.stringify(unknownActors)}. Allowed values: ${JSON.stringify(packet.actorKeys)}.`
|
|
792387
|
+
});
|
|
792388
|
+
}
|
|
792389
|
+
const unknownEvidence = evidenceIds.filter(
|
|
792390
|
+
(id2) => !allowedEvidence.has(id2)
|
|
792391
|
+
);
|
|
792392
|
+
if (unknownEvidence.length > 0) {
|
|
792393
|
+
issues.push({
|
|
792394
|
+
code: "unknown_evidence_id",
|
|
792395
|
+
message: `evidence_ids contains unknown values ${JSON.stringify(unknownEvidence)}. Allowed values: ${JSON.stringify([...allowedEvidence])}.`
|
|
792396
|
+
});
|
|
792397
|
+
}
|
|
791808
792398
|
if (decision2.selfRole === "addressee") {
|
|
791809
|
-
if (!addressed.includes(packet.selfActorKey))
|
|
792399
|
+
if (!addressed.includes(packet.selfActorKey)) {
|
|
792400
|
+
issues.push({
|
|
792401
|
+
code: "addressee_missing_self_actor",
|
|
792402
|
+
message: `self_role=addressee requires addressed_actor_keys to include ${JSON.stringify(packet.selfActorKey)}.`
|
|
792403
|
+
});
|
|
792404
|
+
}
|
|
791810
792405
|
} else if (decision2.selfRole === "observer") {
|
|
791811
|
-
if (addressed.includes(packet.selfActorKey))
|
|
792406
|
+
if (addressed.includes(packet.selfActorKey)) {
|
|
792407
|
+
issues.push({
|
|
792408
|
+
code: "observer_addresses_self",
|
|
792409
|
+
message: `self_role=observer cannot address ${JSON.stringify(packet.selfActorKey)}.`
|
|
792410
|
+
});
|
|
792411
|
+
}
|
|
791812
792412
|
}
|
|
791813
792413
|
if (decision2.shouldReply) {
|
|
791814
|
-
if (decision2.replyBasis === "none" || decision2.replyBasis === "uncertain"
|
|
791815
|
-
|
|
792414
|
+
if (decision2.replyBasis === "none" || decision2.replyBasis === "uncertain") {
|
|
792415
|
+
issues.push({
|
|
792416
|
+
code: "reply_basis_not_authorized",
|
|
792417
|
+
message: "should_reply=true requires reply_basis direct_turn, ongoing_self_task, or social_intervention."
|
|
792418
|
+
});
|
|
791816
792419
|
}
|
|
791817
|
-
if (
|
|
791818
|
-
|
|
792420
|
+
if (evidenceIds.length === 0) {
|
|
792421
|
+
issues.push({
|
|
792422
|
+
code: "reply_missing_evidence",
|
|
792423
|
+
message: "should_reply=true requires at least one evidence_id."
|
|
792424
|
+
});
|
|
792425
|
+
}
|
|
792426
|
+
if (decision2.replyBasis === "direct_turn") {
|
|
792427
|
+
if (decision2.selfRole !== "addressee") {
|
|
792428
|
+
issues.push({
|
|
792429
|
+
code: "direct_turn_self_not_addressee",
|
|
792430
|
+
message: "reply_basis=direct_turn requires self_role=addressee."
|
|
792431
|
+
});
|
|
792432
|
+
}
|
|
792433
|
+
if (!addressed.includes(packet.selfActorKey)) {
|
|
792434
|
+
issues.push({
|
|
792435
|
+
code: "direct_turn_missing_self_actor",
|
|
792436
|
+
message: `reply_basis=direct_turn requires addressed_actor_keys to include ${JSON.stringify(packet.selfActorKey)}.`
|
|
792437
|
+
});
|
|
792438
|
+
}
|
|
791819
792439
|
}
|
|
791820
792440
|
if (decision2.replyBasis === "ongoing_self_task" && !packet.evidence.some(
|
|
791821
792441
|
(entry) => entry.kind === "active_task" && evidenceIds.includes(entry.id)
|
|
791822
792442
|
)) {
|
|
791823
|
-
|
|
792443
|
+
issues.push({
|
|
792444
|
+
code: "ongoing_task_missing_active_task_evidence",
|
|
792445
|
+
message: "reply_basis=ongoing_self_task requires the active_task evidence ID."
|
|
792446
|
+
});
|
|
791824
792447
|
}
|
|
791825
792448
|
}
|
|
792449
|
+
if (issues.length > 0) return { decision: null, issues };
|
|
791826
792450
|
const decisionId = `tgdec-${createHash74("sha256").update(
|
|
791827
792451
|
JSON.stringify({
|
|
791828
792452
|
inputId: packet.inputId,
|
|
@@ -791834,7 +792458,10 @@ arguments=` : ""}` + (chunk.toolCallArgs ?? "");
|
|
|
791834
792458
|
evidenceIds
|
|
791835
792459
|
})
|
|
791836
792460
|
).digest("hex").slice(0, 20)}`;
|
|
791837
|
-
return { ...decision2, decisionId };
|
|
792461
|
+
return { decision: { ...decision2, decisionId }, issues: [] };
|
|
792462
|
+
}
|
|
792463
|
+
validateTelegramInteractionDecision(decision2, packet) {
|
|
792464
|
+
return this.validateTelegramInteractionDecisionDetailed(decision2, packet).decision;
|
|
791838
792465
|
}
|
|
791839
792466
|
bindTrustedTelegramDecision(decision2, packet) {
|
|
791840
792467
|
const bound = {
|
|
@@ -791847,13 +792474,20 @@ arguments=` : ""}` + (chunk.toolCallArgs ?? "");
|
|
|
791847
792474
|
};
|
|
791848
792475
|
return this.validateTelegramInteractionDecision(bound, packet) ?? bound;
|
|
791849
792476
|
}
|
|
791850
|
-
async retryTelegramInteractionDecisionStrict(backend, userPrompt, forcedRoute, timeoutMs, diagnostics, sessionKey = "__router__", evidencePacket) {
|
|
792477
|
+
async retryTelegramInteractionDecisionStrict(backend, userPrompt, forcedRoute, timeoutMs, diagnostics, sessionKey = "__router__", evidencePacket, validationIssues = []) {
|
|
791851
792478
|
const routeInstruction = forcedRoute ? `The operator selected Telegram mode "${forcedRoute}". The route field must be "${forcedRoute}", but should_reply must still be inferred from context.` : `Infer route live from context.`;
|
|
791852
792479
|
const retryPrompt = [
|
|
791853
792480
|
`A prior attempt failed the typed Telegram attention-decision contract and was discarded.`,
|
|
791854
792481
|
`Make a fresh model-derived attention decision from the complete clean context below.`,
|
|
791855
792482
|
`Return exactly one JSON object and no prose. No <think> tags. No commentary.`,
|
|
791856
792483
|
routeInstruction,
|
|
792484
|
+
...validationIssues.length > 0 ? [
|
|
792485
|
+
`The host rejected the prior semantic contract for these exact reasons:`,
|
|
792486
|
+
...validationIssues.map(
|
|
792487
|
+
(issue2) => `- ${issue2.code}: ${issue2.message}`
|
|
792488
|
+
),
|
|
792489
|
+
`Correct every listed issue. Do not repeat a rejected identifier.`
|
|
792490
|
+
] : [],
|
|
791857
792491
|
``,
|
|
791858
792492
|
`Required schema: ${TELEGRAM_INTERACTION_DECISION_MINIMAL_SCHEMA}`,
|
|
791859
792493
|
``,
|
|
@@ -791876,7 +792510,7 @@ arguments=` : ""}` + (chunk.toolCallArgs ?? "");
|
|
|
791876
792510
|
maxTokens: 700,
|
|
791877
792511
|
timeoutMs: telegramRouterTimeoutMs(timeoutMs, 8e3, 15e3),
|
|
791878
792512
|
think: false,
|
|
791879
|
-
responseFormat: TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT
|
|
792513
|
+
responseFormat: evidencePacket ? telegramInteractionDecisionResponseFormatForPacket(evidencePacket) : TELEGRAM_INTERACTION_DECISION_RESPONSE_FORMAT
|
|
791880
792514
|
},
|
|
791881
792515
|
diagnostics,
|
|
791882
792516
|
"router-strict-retry",
|
|
@@ -791892,11 +792526,19 @@ arguments=` : ""}` + (chunk.toolCallArgs ?? "");
|
|
|
791892
792526
|
defaultShouldReply: false,
|
|
791893
792527
|
requireShouldReply: true
|
|
791894
792528
|
});
|
|
791895
|
-
|
|
792529
|
+
if (parsed && evidencePacket) parsed.inputId = evidencePacket.inputId;
|
|
792530
|
+
const validation = parsed && evidencePacket ? this.validateTelegramInteractionDecisionDetailed(
|
|
792531
|
+
parsed,
|
|
792532
|
+
evidencePacket
|
|
792533
|
+
) : { decision: parsed, issues: [] };
|
|
792534
|
+
const validated = validation.decision;
|
|
791896
792535
|
if (!validated) {
|
|
791897
792536
|
if (diagnostics) {
|
|
791898
792537
|
const cleaned = stripTelegramHiddenThinking(retryText).trim();
|
|
791899
|
-
diagnostics.strictRetryStatus = cleaned ? "unparseable" : "empty";
|
|
792538
|
+
diagnostics.strictRetryStatus = parsed && validation.issues.length > 0 ? "semantic-invalid" : cleaned ? "unparseable" : "empty";
|
|
792539
|
+
diagnostics.strictRetryValidationIssues = validation.issues.map(
|
|
792540
|
+
(issue2) => issue2.code
|
|
792541
|
+
);
|
|
791900
792542
|
}
|
|
791901
792543
|
return null;
|
|
791902
792544
|
}
|
|
@@ -792449,7 +793091,7 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`
|
|
|
792449
793091
|
maxTokens: 360,
|
|
792450
793092
|
timeoutMs: telegramRouterTimeoutMs(config.timeoutMs, 8e3, 3e4),
|
|
792451
793093
|
think: false,
|
|
792452
|
-
responseFormat:
|
|
793094
|
+
responseFormat: telegramInteractionDecisionResponseFormatForPacket(evidencePacket)
|
|
792453
793095
|
},
|
|
792454
793096
|
diagnostics,
|
|
792455
793097
|
"router",
|
|
@@ -792479,7 +793121,20 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`
|
|
|
792479
793121
|
defaultShouldReply: false,
|
|
792480
793122
|
requireShouldReply: true
|
|
792481
793123
|
});
|
|
792482
|
-
|
|
793124
|
+
if (parsed) parsed.inputId = evidencePacket.inputId;
|
|
793125
|
+
const initialValidation = parsed ? this.validateTelegramInteractionDecisionDetailed(
|
|
793126
|
+
parsed,
|
|
793127
|
+
evidencePacket
|
|
793128
|
+
) : {
|
|
793129
|
+
decision: null,
|
|
793130
|
+
issues: []
|
|
793131
|
+
};
|
|
793132
|
+
if (diagnostics) {
|
|
793133
|
+
diagnostics.validationIssues = initialValidation.issues.map(
|
|
793134
|
+
(issue2) => issue2.code
|
|
793135
|
+
);
|
|
793136
|
+
}
|
|
793137
|
+
const validated = initialValidation.decision;
|
|
792483
793138
|
if (validated) {
|
|
792484
793139
|
return withRouterTelemetry(
|
|
792485
793140
|
this.applyTelegramSilentReflectionNotes(validated, reflectionNotes)
|
|
@@ -792511,7 +793166,8 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`
|
|
|
792511
793166
|
config.timeoutMs ?? 3e4,
|
|
792512
793167
|
diagnostics,
|
|
792513
793168
|
sessionKey,
|
|
792514
|
-
evidencePacket
|
|
793169
|
+
evidencePacket,
|
|
793170
|
+
initialValidation.issues
|
|
792515
793171
|
);
|
|
792516
793172
|
if (strictRetry) {
|
|
792517
793173
|
return withRouterTelemetry(
|
|
@@ -792525,20 +793181,26 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`
|
|
|
792525
793181
|
) || telegramRouterErrorLooksLikeBackendLiveness(
|
|
792526
793182
|
diagnostics.strictRetryError ?? ""
|
|
792527
793183
|
);
|
|
792528
|
-
const fallback =
|
|
792529
|
-
this.
|
|
792530
|
-
|
|
792531
|
-
|
|
792532
|
-
|
|
792533
|
-
|
|
792534
|
-
|
|
792535
|
-
|
|
792536
|
-
|
|
792537
|
-
|
|
792538
|
-
|
|
792539
|
-
|
|
792540
|
-
|
|
792541
|
-
|
|
793184
|
+
const fallback = {
|
|
793185
|
+
...this.applyTelegramSilentReflectionNotes(
|
|
793186
|
+
this.buildTelegramRouterUnavailableDecision(msg, toolContext, {
|
|
793187
|
+
reason: backendLivenessFailure ? "router recovery hit a backend liveness failure; no model-derived reply decision" : dualEmptyVisible ? "router returned no visible decision content in JSON or plain mode; no model-derived reply decision" : "router output failed the typed decision contract and the fresh retry; no model-derived reply decision",
|
|
793188
|
+
silentDisposition: reflectionNotes.silentDisposition,
|
|
793189
|
+
diagnosticNote: this.composeTelegramRouterDiagnosticNote(
|
|
793190
|
+
invalidRouterPreview,
|
|
793191
|
+
failureNarrative,
|
|
793192
|
+
backendLivenessFailure ? "router backend failed during attention-decision recovery; no usable router decision was available" : dualEmptyVisible ? "router returned no visible decision content in JSON or plain mode; fresh typed retry did not recover it" : invalidRouterPreview ? "router produced an invalid attention decision payload; the quarantined fresh retry did not recover it" : "router produced an empty attention decision payload; the fresh typed retry did not recover it",
|
|
793193
|
+
diagnostics
|
|
793194
|
+
),
|
|
793195
|
+
raw: text3
|
|
793196
|
+
}),
|
|
793197
|
+
reflectionNotes
|
|
793198
|
+
),
|
|
793199
|
+
validationIssueCodes: [
|
|
793200
|
+
...diagnostics.validationIssues ?? [],
|
|
793201
|
+
...diagnostics.strictRetryValidationIssues ?? []
|
|
793202
|
+
].filter((code8, index, all2) => all2.indexOf(code8) === index)
|
|
793203
|
+
};
|
|
792542
793204
|
return withRouterTelemetry(fallback);
|
|
792543
793205
|
} catch (err) {
|
|
792544
793206
|
if (err instanceof TelegramBridgeStoppedError) throw err;
|
|
@@ -792617,7 +793279,7 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`
|
|
|
792617
793279
|
`empty visible content after <think> strip during ${affected}`
|
|
792618
793280
|
);
|
|
792619
793281
|
}
|
|
792620
|
-
if (visibleAttempts.length > 0 && diag.strictRetryStatus !== "recovered") {
|
|
793282
|
+
if (visibleAttempts.length > 0 && (diag.validationIssues ?? []).length === 0 && diag.strictRetryStatus !== "recovered") {
|
|
792621
793283
|
parts.push(`visible router text remained unparseable`);
|
|
792622
793284
|
}
|
|
792623
793285
|
if (skippedAttempts.length > 0) {
|
|
@@ -792668,6 +793330,10 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`
|
|
|
792668
793330
|
detailParts.push(
|
|
792669
793331
|
`strict-retry: unparseable (preview="${diag.strictRetryPreview ?? ""}")`
|
|
792670
793332
|
);
|
|
793333
|
+
} else if (diag.strictRetryStatus === "semantic-invalid") {
|
|
793334
|
+
detailParts.push(
|
|
793335
|
+
`strict-retry: semantic-invalid (${(diag.strictRetryValidationIssues ?? []).join(", ") || "no issue codes"})`
|
|
793336
|
+
);
|
|
792671
793337
|
} else if (diag.strictRetryStatus === "threw") {
|
|
792672
793338
|
detailParts.push(
|
|
792673
793339
|
`strict-retry: threw (${diag.strictRetryError ?? "no detail"})`
|
|
@@ -792679,6 +793345,19 @@ ${this.quoteTelegramContextBlock(msg.text, 1200)}`
|
|
|
792679
793345
|
} else if (diag.strictRetryStatus === "recovered") {
|
|
792680
793346
|
detailParts.push(`strict-retry: recovered`);
|
|
792681
793347
|
}
|
|
793348
|
+
if ((diag.validationIssues ?? []).length > 0) {
|
|
793349
|
+
parts.push(
|
|
793350
|
+
`router semantic contract rejected (${diag.validationIssues.join(", ")})`
|
|
793351
|
+
);
|
|
793352
|
+
detailParts.push(
|
|
793353
|
+
`router-validation: ${diag.validationIssues.join(", ")}`
|
|
793354
|
+
);
|
|
793355
|
+
}
|
|
793356
|
+
if ((diag.strictRetryValidationIssues ?? []).length > 0) {
|
|
793357
|
+
detailParts.push(
|
|
793358
|
+
`strict-retry-validation: ${diag.strictRetryValidationIssues.join(", ")}`
|
|
793359
|
+
);
|
|
793360
|
+
}
|
|
792682
793361
|
let operatorHint;
|
|
792683
793362
|
if (networkErrorSeen) {
|
|
792684
793363
|
operatorHint = this.telegramRouterBackendLivenessHint(timeoutSeen);
|
|
@@ -793540,10 +794219,14 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`
|
|
|
793540
794219
|
* Send a placeholder message that will be progressively edited with
|
|
793541
794220
|
* streamed content. Returns the message_id for subsequent edits.
|
|
793542
794221
|
*/
|
|
793543
|
-
async sendLiveMessage(chatId, initialText, replyToMessageId, replyMarkup) {
|
|
794222
|
+
async sendLiveMessage(chatId, initialText, replyToMessageId, replyMarkup, richHtml) {
|
|
793544
794223
|
const normalizedInitialText = normalizeTelegramOutboundLinks(initialText);
|
|
794224
|
+
const normalizedRichHtml = richHtml ? normalizeTelegramOutboundLinks(richHtml) : "";
|
|
793545
794225
|
try {
|
|
793546
|
-
const body = {
|
|
794226
|
+
const body = normalizedRichHtml ? {
|
|
794227
|
+
chat_id: chatId,
|
|
794228
|
+
rich_message: { html: normalizedRichHtml }
|
|
794229
|
+
} : {
|
|
793547
794230
|
chat_id: chatId,
|
|
793548
794231
|
text: normalizedInitialText,
|
|
793549
794232
|
parse_mode: "HTML"
|
|
@@ -793551,15 +794234,16 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`
|
|
|
793551
794234
|
const replyParameters = telegramReplyParameters(replyToMessageId);
|
|
793552
794235
|
if (replyParameters) body["reply_parameters"] = replyParameters;
|
|
793553
794236
|
if (replyMarkup) body["reply_markup"] = replyMarkup;
|
|
793554
|
-
const
|
|
794237
|
+
const method = normalizedRichHtml ? "sendRichMessage" : "sendMessage";
|
|
794238
|
+
const result = await this.apiCall(method, body);
|
|
793555
794239
|
if (result.ok === false) {
|
|
793556
794240
|
throw new Error(
|
|
793557
|
-
String(result.description ||
|
|
794241
|
+
String(result.description || `Telegram ${method} failed`)
|
|
793558
794242
|
);
|
|
793559
794243
|
}
|
|
793560
794244
|
const messageId = result.result?.message_id;
|
|
793561
794245
|
if (!Number.isInteger(messageId)) {
|
|
793562
|
-
throw new Error(
|
|
794246
|
+
throw new Error(`Telegram ${method} returned no valid message_id`);
|
|
793563
794247
|
}
|
|
793564
794248
|
this.state.messagesSent++;
|
|
793565
794249
|
this.updateTelegramTextDeliveryCapability(chatId, {
|
|
@@ -793569,10 +794253,43 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`
|
|
|
793569
794253
|
});
|
|
793570
794254
|
return messageId;
|
|
793571
794255
|
} catch {
|
|
794256
|
+
if (normalizedRichHtml) {
|
|
794257
|
+
try {
|
|
794258
|
+
const body = {
|
|
794259
|
+
chat_id: chatId,
|
|
794260
|
+
text: normalizedInitialText,
|
|
794261
|
+
parse_mode: "HTML"
|
|
794262
|
+
};
|
|
794263
|
+
const replyParameters = telegramReplyParameters(replyToMessageId);
|
|
794264
|
+
if (replyParameters) body["reply_parameters"] = replyParameters;
|
|
794265
|
+
if (replyMarkup) body["reply_markup"] = replyMarkup;
|
|
794266
|
+
const result = await this.apiCall("sendMessage", body);
|
|
794267
|
+
if (result.ok === false) {
|
|
794268
|
+
throw new Error(
|
|
794269
|
+
String(result.description || "Telegram sendMessage failed")
|
|
794270
|
+
);
|
|
794271
|
+
}
|
|
794272
|
+
const messageId = result.result?.message_id;
|
|
794273
|
+
if (!Number.isInteger(messageId)) {
|
|
794274
|
+
throw new Error(
|
|
794275
|
+
"Telegram sendMessage returned no valid message_id"
|
|
794276
|
+
);
|
|
794277
|
+
}
|
|
794278
|
+
this.state.messagesSent++;
|
|
794279
|
+
this.updateTelegramTextDeliveryCapability(chatId, {
|
|
794280
|
+
status: "allowed",
|
|
794281
|
+
canSendText: true,
|
|
794282
|
+
source: "sendLiveMessage.html_fallback"
|
|
794283
|
+
});
|
|
794284
|
+
return messageId;
|
|
794285
|
+
} catch {
|
|
794286
|
+
}
|
|
794287
|
+
}
|
|
793572
794288
|
try {
|
|
794289
|
+
const readablePlain = telegramHtmlToPlainText(normalizedInitialText);
|
|
793573
794290
|
const body = {
|
|
793574
794291
|
chat_id: chatId,
|
|
793575
|
-
text:
|
|
794292
|
+
text: readablePlain || "No displayable content."
|
|
793576
794293
|
};
|
|
793577
794294
|
const replyParameters = telegramReplyParameters(replyToMessageId);
|
|
793578
794295
|
if (replyParameters) body["reply_parameters"] = replyParameters;
|
|
@@ -793620,19 +794337,18 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`
|
|
|
793620
794337
|
* Edit a live message with updated content. Used for progressive streaming.
|
|
793621
794338
|
* Handles rate limits and Telegram's "message is not modified" error silently.
|
|
793622
794339
|
*/
|
|
793623
|
-
async editLiveMessage(chatId, messageId, html, replyMarkup) {
|
|
794340
|
+
async editLiveMessage(chatId, messageId, html, replyMarkup, richHtml) {
|
|
793624
794341
|
const normalizedHtml = normalizeTelegramOutboundLinks(html);
|
|
793625
|
-
const
|
|
793626
|
-
|
|
793627
|
-
|
|
793628
|
-
|
|
793629
|
-
|
|
794342
|
+
const normalizedRichHtml = richHtml ? normalizeTelegramOutboundLinks(richHtml) : "";
|
|
794343
|
+
const htmlSegments = segmentTelegramHtml(normalizedHtml, 3600);
|
|
794344
|
+
const truncated = htmlSegments.length > 1 ? `${htmlSegments[0]}
|
|
794345
|
+
|
|
794346
|
+
<i>... (additional detail clipped)</i>` : htmlSegments[0] ?? normalizedHtml;
|
|
793630
794347
|
try {
|
|
793631
794348
|
const result = await this.apiCall("editMessageText", {
|
|
793632
794349
|
chat_id: chatId,
|
|
793633
794350
|
message_id: messageId,
|
|
793634
|
-
text: truncated,
|
|
793635
|
-
parse_mode: "HTML",
|
|
794351
|
+
...normalizedRichHtml ? { rich_message: { html: normalizedRichHtml } } : { text: truncated, parse_mode: "HTML" },
|
|
793636
794352
|
...replyMarkup ? { reply_markup: replyMarkup } : {}
|
|
793637
794353
|
});
|
|
793638
794354
|
if (result.error_code === 400 && result.description?.includes("not modified"))
|
|
@@ -793644,8 +794360,24 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`
|
|
|
793644
794360
|
);
|
|
793645
794361
|
return true;
|
|
793646
794362
|
} catch {
|
|
794363
|
+
if (normalizedRichHtml) {
|
|
794364
|
+
try {
|
|
794365
|
+
const result = await this.apiCall("editMessageText", {
|
|
794366
|
+
chat_id: chatId,
|
|
794367
|
+
message_id: messageId,
|
|
794368
|
+
text: truncated,
|
|
794369
|
+
parse_mode: "HTML",
|
|
794370
|
+
...replyMarkup ? { reply_markup: replyMarkup } : {}
|
|
794371
|
+
});
|
|
794372
|
+
if (result.error_code === 400 && result.description?.includes("not modified"))
|
|
794373
|
+
return true;
|
|
794374
|
+
if (result.error_code === 429) return false;
|
|
794375
|
+
if (result.ok !== false) return true;
|
|
794376
|
+
} catch {
|
|
794377
|
+
}
|
|
794378
|
+
}
|
|
793647
794379
|
try {
|
|
793648
|
-
const plain = normalizedHtml
|
|
794380
|
+
const plain = telegramHtmlToPlainText(normalizedHtml);
|
|
793649
794381
|
const truncPlain = plain.length > 4e3 ? truncateTelegramUrlSafe(plain, 4e3, "\n\n... (streaming)") : plain;
|
|
793650
794382
|
const result = await this.apiCall("editMessageText", {
|
|
793651
794383
|
chat_id: chatId,
|
|
@@ -793760,20 +794492,25 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`
|
|
|
793760
794492
|
async renderTelegramAdminLivePanel(state5, replyToMessageId) {
|
|
793761
794493
|
const payload = renderTelegramAdminLivePanelPayload(state5);
|
|
793762
794494
|
if (state5.messageId !== void 0) {
|
|
793763
|
-
|
|
794495
|
+
const delivered = await this.editLiveMessage(
|
|
793764
794496
|
state5.chatId,
|
|
793765
794497
|
state5.messageId,
|
|
793766
794498
|
payload.text,
|
|
793767
|
-
payload.reply_markup
|
|
794499
|
+
payload.reply_markup,
|
|
794500
|
+
payload.rich_html
|
|
793768
794501
|
);
|
|
794502
|
+
if (delivered) state5.dirtyPages[state5.activePage] = false;
|
|
794503
|
+
return delivered;
|
|
793769
794504
|
}
|
|
793770
794505
|
const messageId = await this.sendLiveMessage(
|
|
793771
794506
|
state5.chatId,
|
|
793772
794507
|
payload.text,
|
|
793773
794508
|
replyToMessageId,
|
|
793774
|
-
payload.reply_markup
|
|
794509
|
+
payload.reply_markup,
|
|
794510
|
+
payload.rich_html
|
|
793775
794511
|
);
|
|
793776
794512
|
state5.messageId = messageId;
|
|
794513
|
+
state5.dirtyPages[state5.activePage] = false;
|
|
793777
794514
|
return true;
|
|
793778
794515
|
}
|
|
793779
794516
|
updateTelegramAdminLivePanelFromEvent(subAgent, msg, event) {
|
|
@@ -793808,12 +794545,14 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`
|
|
|
793808
794545
|
...subAgent.steeringReconciliations.values()
|
|
793809
794546
|
];
|
|
793810
794547
|
state5.responseText = replyText || (status === "failed" ? "I couldn't complete that request." : "Done.");
|
|
794548
|
+
state5.responseSegments = [];
|
|
794549
|
+
state5.activeResponseSegmentKey = void 0;
|
|
793811
794550
|
if (evidenceText.trim()) {
|
|
793812
794551
|
state5.evidenceText = evidenceText.trim();
|
|
793813
794552
|
state5.dirtyPages.evidence = true;
|
|
793814
794553
|
}
|
|
793815
|
-
state5.activePage
|
|
793816
|
-
state5.dirtyPages.response =
|
|
794554
|
+
if (state5.activePage === "response") state5.dirtyPages.response = false;
|
|
794555
|
+
else state5.dirtyPages.response = true;
|
|
793817
794556
|
state5.updatedAt = Date.now();
|
|
793818
794557
|
this.refreshTelegramAdminLivePanelContextPages(state5, subAgent, msg);
|
|
793819
794558
|
if (subAgent.liveMessagePromise)
|
|
@@ -793948,6 +794687,7 @@ ${signals || summary || "Canonical runner status reported completed."}`
|
|
|
793948
794687
|
[
|
|
793949
794688
|
{
|
|
793950
794689
|
text: "Admin context",
|
|
794690
|
+
style: "primary",
|
|
793951
794691
|
callback_data: this.telegramContextExplorerCallbackData(
|
|
793952
794692
|
id2,
|
|
793953
794693
|
"open",
|
|
@@ -793966,35 +794706,36 @@ ${signals || summary || "Canonical runner status reported completed."}`
|
|
|
793966
794706
|
[
|
|
793967
794707
|
{
|
|
793968
794708
|
text: "Prev",
|
|
793969
|
-
|
|
793970
|
-
|
|
793971
|
-
|
|
793972
|
-
|
|
793973
|
-
|
|
794709
|
+
...page2 > 0 ? {
|
|
794710
|
+
callback_data: this.telegramContextExplorerCallbackData(
|
|
794711
|
+
state5.id,
|
|
794712
|
+
"page",
|
|
794713
|
+
page2 - 1
|
|
794714
|
+
)
|
|
794715
|
+
} : { disabled: {} }
|
|
793974
794716
|
},
|
|
793975
794717
|
{
|
|
793976
794718
|
text: `${page2 + 1}/${lastPage + 1}`,
|
|
793977
|
-
|
|
793978
|
-
|
|
793979
|
-
"noop",
|
|
793980
|
-
page2
|
|
793981
|
-
)
|
|
794719
|
+
disabled: {},
|
|
794720
|
+
style: "primary"
|
|
793982
794721
|
},
|
|
793983
794722
|
{
|
|
793984
794723
|
text: "Next",
|
|
793985
|
-
|
|
793986
|
-
|
|
793987
|
-
|
|
793988
|
-
|
|
793989
|
-
|
|
794724
|
+
...page2 < lastPage ? {
|
|
794725
|
+
callback_data: this.telegramContextExplorerCallbackData(
|
|
794726
|
+
state5.id,
|
|
794727
|
+
"page",
|
|
794728
|
+
page2 + 1
|
|
794729
|
+
)
|
|
794730
|
+
} : { disabled: {} }
|
|
793990
794731
|
}
|
|
793991
794732
|
],
|
|
793992
794733
|
[
|
|
793993
794734
|
{
|
|
793994
|
-
text: "
|
|
794735
|
+
text: "Close context",
|
|
793995
794736
|
callback_data: this.telegramContextExplorerCallbackData(
|
|
793996
794737
|
state5.id,
|
|
793997
|
-
"
|
|
794738
|
+
"close",
|
|
793998
794739
|
page2
|
|
793999
794740
|
)
|
|
794000
794741
|
}
|
|
@@ -794005,7 +794746,7 @@ ${signals || summary || "Canonical runner status reported completed."}`
|
|
|
794005
794746
|
splitTelegramContextBody(text3, maxLength = 2500) {
|
|
794006
794747
|
const cleaned = stripTelegramHiddenThinking(text3 || "").trim();
|
|
794007
794748
|
if (!cleaned) return [""];
|
|
794008
|
-
return
|
|
794749
|
+
return splitTelegramPlainText(cleaned, maxLength);
|
|
794009
794750
|
}
|
|
794010
794751
|
addTelegramContextExplorerPages(pages, title, source, body, metadata) {
|
|
794011
794752
|
const chunks = this.splitTelegramContextBody(body);
|
|
@@ -794045,7 +794786,7 @@ ${signals || summary || "Canonical runner status reported completed."}`
|
|
|
794045
794786
|
"",
|
|
794046
794787
|
"Visible reply preview:",
|
|
794047
794788
|
cleanTelegramVisibleReply(finalText).slice(0, 900) || "(empty)"
|
|
794048
|
-
].
|
|
794789
|
+
].join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
794049
794790
|
pages.push({
|
|
794050
794791
|
title: "Overview",
|
|
794051
794792
|
source: "telegram.final_reply",
|
|
@@ -794056,6 +794797,23 @@ ${signals || summary || "Canonical runner status reported completed."}`
|
|
|
794056
794797
|
`chat_id=${String(msg.chatId)}`
|
|
794057
794798
|
]
|
|
794058
794799
|
});
|
|
794800
|
+
const reconciliations = [...subAgent.steeringReconciliations.values()];
|
|
794801
|
+
if (reconciliations.length > 0) {
|
|
794802
|
+
this.addTelegramContextExplorerPages(
|
|
794803
|
+
pages,
|
|
794804
|
+
"Plan updates",
|
|
794805
|
+
"runner.steering_reconciliation",
|
|
794806
|
+
reconciliations.map(
|
|
794807
|
+
(value2, index) => [
|
|
794808
|
+
`Update ${index + 1}:`,
|
|
794809
|
+
`Status: ${value2.status.replaceAll("_", " ")}`,
|
|
794810
|
+
...value2.changedConstraints.length > 0 ? value2.changedConstraints.map((item) => `Change: ${item}`) : ["Change: none"],
|
|
794811
|
+
`Next: ${value2.revisedNextAction}`
|
|
794812
|
+
].join("\n")
|
|
794813
|
+
).join("\n\n"),
|
|
794814
|
+
[`count=${reconciliations.length}`, "visibility=admin-only"]
|
|
794815
|
+
);
|
|
794816
|
+
}
|
|
794059
794817
|
if (frame2) {
|
|
794060
794818
|
for (const section of frame2.sections) {
|
|
794061
794819
|
this.addTelegramContextExplorerPages(
|
|
@@ -794146,23 +794904,43 @@ ${signals || summary || "Canonical runner status reported completed."}`
|
|
|
794146
794904
|
[`count=${prompt.toolNames.length}`]
|
|
794147
794905
|
);
|
|
794148
794906
|
}
|
|
794149
|
-
|
|
794907
|
+
const redactor = getSecretRedactor();
|
|
794908
|
+
const redactedPages = pages.map((page2) => ({
|
|
794909
|
+
title: redactor.redactText(page2.title),
|
|
794910
|
+
source: redactor.redactText(page2.source),
|
|
794911
|
+
body: redactor.redactText(page2.body),
|
|
794912
|
+
metadata: page2.metadata.map((line) => redactor.redactText(line))
|
|
794913
|
+
}));
|
|
794914
|
+
const maxPages = 64;
|
|
794915
|
+
if (redactedPages.length <= maxPages) return redactedPages;
|
|
794916
|
+
const omitted = redactedPages.length - (maxPages - 1);
|
|
794917
|
+
return [
|
|
794918
|
+
...redactedPages.slice(0, maxPages - 1),
|
|
794919
|
+
{
|
|
794920
|
+
title: "Omitted context packets",
|
|
794921
|
+
source: "telegram.context_budget",
|
|
794922
|
+
body: `${omitted} additional packet${omitted === 1 ? " was" : "s were"} omitted from this interactive view.`,
|
|
794923
|
+
metadata: [
|
|
794924
|
+
`retained=${maxPages - 1}`,
|
|
794925
|
+
`omitted=${omitted}`,
|
|
794926
|
+
`total=${redactedPages.length}`
|
|
794927
|
+
]
|
|
794928
|
+
}
|
|
794929
|
+
];
|
|
794150
794930
|
}
|
|
794151
|
-
buildTelegramContextExplorerState(msg, subAgent,
|
|
794931
|
+
buildTelegramContextExplorerState(msg, subAgent, finalText) {
|
|
794152
794932
|
const pages = this.buildTelegramContextExplorerPages(
|
|
794153
794933
|
msg,
|
|
794154
794934
|
subAgent,
|
|
794155
794935
|
finalText
|
|
794156
794936
|
);
|
|
794157
794937
|
if (pages.length === 0) return null;
|
|
794158
|
-
const finalHtmlFirstChunk = splitTelegramMessageText(finalHtml, 3900)[0] ?? finalHtml;
|
|
794159
794938
|
const id2 = randomBytes29(6).toString("hex");
|
|
794160
794939
|
const now2 = Date.now();
|
|
794161
794940
|
return {
|
|
794162
794941
|
id: id2,
|
|
794163
|
-
|
|
794164
|
-
|
|
794165
|
-
finalHtml: finalHtmlFirstChunk,
|
|
794942
|
+
sourceChatId: msg.chatId,
|
|
794943
|
+
sourceMessageId: null,
|
|
794166
794944
|
activePage: 0,
|
|
794167
794945
|
pages,
|
|
794168
794946
|
createdAtMs: now2,
|
|
@@ -794175,20 +794953,10 @@ ${signals || summary || "Canonical runner status reported completed."}`
|
|
|
794175
794953
|
Math.max(0, state5.pages.length - 1)
|
|
794176
794954
|
);
|
|
794177
794955
|
const page2 = state5.pages[pageIndex];
|
|
794178
|
-
|
|
794179
|
-
|
|
794180
|
-
|
|
794181
|
-
|
|
794182
|
-
[
|
|
794183
|
-
`<b>Context frame</b>`,
|
|
794184
|
-
`<i>Page ${pageIndex + 1}/${state5.pages.length}: ${escapeTelegramHTML(page2.title)}</i>`,
|
|
794185
|
-
`Source: <code>${escapeTelegramHTML(page2.source)}</code>`,
|
|
794186
|
-
meta,
|
|
794187
|
-
"",
|
|
794188
|
-
body
|
|
794189
|
-
].filter(Boolean).join("\n"),
|
|
794190
|
-
3900,
|
|
794191
|
-
"\n\n<i>... (context page clipped)</i>"
|
|
794956
|
+
return renderTelegramContextExplorerPagePayload(
|
|
794957
|
+
page2,
|
|
794958
|
+
pageIndex,
|
|
794959
|
+
state5.pages.length
|
|
794192
794960
|
);
|
|
794193
794961
|
}
|
|
794194
794962
|
async handleTelegramContextExplorerCallback(callback) {
|
|
@@ -794215,36 +794983,94 @@ ${signals || summary || "Canonical runner status reported completed."}`
|
|
|
794215
794983
|
}
|
|
794216
794984
|
const action = parts[4];
|
|
794217
794985
|
const requestedPage = Number.parseInt(parts[5] ?? "0", 10);
|
|
794218
|
-
|
|
794219
|
-
|
|
794220
|
-
|
|
794986
|
+
if (action === "open") {
|
|
794987
|
+
if (callback.chatId !== state5.sourceChatId || callback.messageId !== state5.sourceMessageId) {
|
|
794988
|
+
answerText = "This context button is not bound to this message.";
|
|
794989
|
+
alert = true;
|
|
794990
|
+
return;
|
|
794991
|
+
}
|
|
794992
|
+
const maxPage2 = Math.max(0, state5.pages.length - 1);
|
|
794993
|
+
const nextPage2 = Number.isFinite(requestedPage) ? Math.min(maxPage2, Math.max(0, requestedPage)) : 0;
|
|
794994
|
+
const previousPage2 = state5.activePage;
|
|
794995
|
+
state5.activePage = nextPage2;
|
|
794996
|
+
const payload2 = this.renderTelegramContextExplorerPage(state5);
|
|
794997
|
+
const markup = this.telegramContextExplorerPageMarkup(state5);
|
|
794998
|
+
try {
|
|
794999
|
+
if (state5.panelMessageId !== void 0 && state5.panelChatId === callback.fromUserId) {
|
|
795000
|
+
const edited2 = await this.editLiveMessage(
|
|
795001
|
+
callback.fromUserId,
|
|
795002
|
+
state5.panelMessageId,
|
|
795003
|
+
payload2.text,
|
|
795004
|
+
markup,
|
|
795005
|
+
payload2.rich_html
|
|
795006
|
+
);
|
|
795007
|
+
if (!edited2) throw new Error("Telegram did not apply the DM edit");
|
|
795008
|
+
} else {
|
|
795009
|
+
state5.panelMessageId = await this.sendLiveMessage(
|
|
795010
|
+
callback.fromUserId,
|
|
795011
|
+
payload2.text,
|
|
795012
|
+
void 0,
|
|
795013
|
+
markup,
|
|
795014
|
+
payload2.rich_html
|
|
795015
|
+
);
|
|
795016
|
+
}
|
|
795017
|
+
} catch {
|
|
795018
|
+
state5.activePage = previousPage2;
|
|
795019
|
+
answerText = `Open a private chat with @${this.state.botUsername || "omnius_agent_bot"}, press Start, then try again.`;
|
|
795020
|
+
alert = true;
|
|
795021
|
+
return;
|
|
795022
|
+
}
|
|
795023
|
+
state5.viewerUserId = callback.fromUserId;
|
|
795024
|
+
state5.panelChatId = callback.fromUserId;
|
|
795025
|
+
answerText = "Opened the context packets in your private chat.";
|
|
795026
|
+
return;
|
|
795027
|
+
}
|
|
795028
|
+
const panelChatId = state5.panelChatId;
|
|
795029
|
+
const panelMessageId = state5.panelMessageId;
|
|
795030
|
+
if (state5.viewerUserId !== callback.fromUserId || panelChatId === void 0 || panelMessageId === void 0 || callback.chatId !== panelChatId || callback.messageId !== panelMessageId) {
|
|
795031
|
+
answerText = "This private context panel is not bound to this callback.";
|
|
794221
795032
|
alert = true;
|
|
794222
795033
|
return;
|
|
794223
795034
|
}
|
|
794224
|
-
state5.messageId = messageId;
|
|
794225
795035
|
if (action === "noop") return;
|
|
794226
|
-
if (action === "
|
|
794227
|
-
await this.editLiveMessage(
|
|
794228
|
-
|
|
794229
|
-
|
|
794230
|
-
|
|
794231
|
-
this.telegramContextExplorerReplyMarkup(state5.id)
|
|
795036
|
+
if (action === "close") {
|
|
795037
|
+
const closed = await this.editLiveMessage(
|
|
795038
|
+
panelChatId,
|
|
795039
|
+
panelMessageId,
|
|
795040
|
+
"<b>Context panel closed.</b>"
|
|
794232
795041
|
);
|
|
795042
|
+
if (!closed) {
|
|
795043
|
+
answerText = "Telegram did not close this context panel. Try again.";
|
|
795044
|
+
alert = true;
|
|
795045
|
+
return;
|
|
795046
|
+
}
|
|
795047
|
+
state5.panelMessageId = void 0;
|
|
795048
|
+
state5.panelChatId = void 0;
|
|
795049
|
+
state5.viewerUserId = void 0;
|
|
794233
795050
|
return;
|
|
794234
795051
|
}
|
|
794235
|
-
if (action !== "
|
|
795052
|
+
if (action !== "page") {
|
|
794236
795053
|
answerText = "Unknown context frame action.";
|
|
794237
795054
|
alert = true;
|
|
794238
795055
|
return;
|
|
794239
795056
|
}
|
|
794240
795057
|
const maxPage = Math.max(0, state5.pages.length - 1);
|
|
794241
|
-
|
|
794242
|
-
|
|
794243
|
-
|
|
794244
|
-
|
|
794245
|
-
|
|
794246
|
-
|
|
795058
|
+
const nextPage = Number.isFinite(requestedPage) ? Math.min(maxPage, Math.max(0, requestedPage)) : 0;
|
|
795059
|
+
const previousPage = state5.activePage;
|
|
795060
|
+
state5.activePage = nextPage;
|
|
795061
|
+
const payload = this.renderTelegramContextExplorerPage(state5);
|
|
795062
|
+
const edited = await this.editLiveMessage(
|
|
795063
|
+
panelChatId,
|
|
795064
|
+
panelMessageId,
|
|
795065
|
+
payload.text,
|
|
795066
|
+
this.telegramContextExplorerPageMarkup(state5),
|
|
795067
|
+
payload.rich_html
|
|
794247
795068
|
);
|
|
795069
|
+
if (!edited) {
|
|
795070
|
+
state5.activePage = previousPage;
|
|
795071
|
+
answerText = "Telegram did not apply this context page. Try again.";
|
|
795072
|
+
alert = true;
|
|
795073
|
+
}
|
|
794248
795074
|
} catch (err) {
|
|
794249
795075
|
answerText = err instanceof Error ? err.message : String(err);
|
|
794250
795076
|
alert = true;
|
|
@@ -794697,8 +795523,8 @@ Join: ${newUrl}`
|
|
|
794697
795523
|
work.intakeRecords.map(
|
|
794698
795524
|
(intake) => this.transitionTelegramIntake(
|
|
794699
795525
|
intake,
|
|
794700
|
-
"consumed",
|
|
794701
|
-
"Telegram attention router retained intake without visible reply"
|
|
795526
|
+
decision2.source === "inference-unavailable" ? "failed" : "consumed",
|
|
795527
|
+
decision2.source === "inference-unavailable" ? "Telegram attention router could not produce a valid input-bound decision" : "Telegram attention router retained intake without visible reply"
|
|
794702
795528
|
)
|
|
794703
795529
|
)
|
|
794704
795530
|
);
|
|
@@ -795005,14 +795831,12 @@ Join: ${newUrl}`
|
|
|
795005
795831
|
}
|
|
795006
795832
|
const deliveredFinalText = finalText;
|
|
795007
795833
|
const adminEvidenceText = isAdminDM ? this.telegramAdminCompletionRunText(subAgent, finalText) : "";
|
|
795008
|
-
const finalHtml = composeTelegramReplyWithSteeringHTML(
|
|
795009
|
-
|
|
795010
|
-
|
|
795011
|
-
);
|
|
795834
|
+
const finalHtml = isAdminDM ? composeTelegramReplyWithSteeringHTML(deliveredFinalText, [
|
|
795835
|
+
...subAgent.steeringReconciliations.values()
|
|
795836
|
+
]) : convertMarkdownToTelegramHTML(deliveredFinalText);
|
|
795012
795837
|
const contextExplorerState = !isAdminDM && msg.chatType !== "private" && !msg.guestQueryId ? this.buildTelegramContextExplorerState(
|
|
795013
795838
|
msg,
|
|
795014
795839
|
subAgent,
|
|
795015
|
-
finalHtml,
|
|
795016
795840
|
deliveredFinalText
|
|
795017
795841
|
) : null;
|
|
795018
795842
|
const contextExplorerReplyMarkup = contextExplorerState ? this.telegramContextExplorerReplyMarkup(contextExplorerState.id) : void 0;
|
|
@@ -795030,7 +795854,7 @@ Join: ${newUrl}`
|
|
|
795030
795854
|
);
|
|
795031
795855
|
if (contextExplorerState && sentMessageId !== null) {
|
|
795032
795856
|
this.pruneTelegramContextExplorers();
|
|
795033
|
-
contextExplorerState.
|
|
795857
|
+
contextExplorerState.sourceMessageId = sentMessageId;
|
|
795034
795858
|
this.telegramContextExplorerStates.set(
|
|
795035
795859
|
contextExplorerState.id,
|
|
795036
795860
|
contextExplorerState
|
|
@@ -796086,8 +796910,7 @@ ${creativeWorkspace}` : ""
|
|
|
796086
796910
|
}
|
|
796087
796911
|
const html = renderTelegramLiveProgressHTML(
|
|
796088
796912
|
subAgent.intermediateLines,
|
|
796089
|
-
subAgent.visibleReplyText || subAgent.accumulated
|
|
796090
|
-
[...subAgent.steeringReconciliations.values()]
|
|
796913
|
+
subAgent.visibleReplyText || subAgent.accumulated
|
|
796091
796914
|
);
|
|
796092
796915
|
if (!html.trim()) return;
|
|
796093
796916
|
const now2 = Date.now();
|
|
@@ -799922,8 +800745,14 @@ ${this.quoteTelegramContextBlock(msg.text, 800)}`,
|
|
|
799922
800745
|
return;
|
|
799923
800746
|
}
|
|
799924
800747
|
state5.messageId = messageId;
|
|
799925
|
-
await this.renderTelegramAdminLivePanel(state5);
|
|
799926
|
-
|
|
800748
|
+
const delivered = await this.renderTelegramAdminLivePanel(state5);
|
|
800749
|
+
if (!delivered) {
|
|
800750
|
+
state5.dirtyPages[state5.activePage] = true;
|
|
800751
|
+
answerText2 = "Telegram did not apply this panel update. Try again.";
|
|
800752
|
+
alert2 = true;
|
|
800753
|
+
} else {
|
|
800754
|
+
answerText2 = "";
|
|
800755
|
+
}
|
|
799927
800756
|
} catch (err) {
|
|
799928
800757
|
answerText2 = err instanceof Error ? err.message : String(err);
|
|
799929
800758
|
alert2 = true;
|