mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-02 21:11:40 +00:00
* feat(cron): move heartbeat context into database-backed per-job cron scratch - new additive cron_job_scratch SQLite table (revision tombstones keep compare-and-swap monotonic across unset/recreate; 256KiB cap) - heartbeat runner reads monitor scratch instead of workspace HEARTBEAT.md; heartbeat_respond gains a private scratch replacement parameter - openclaw doctor --fix migrates HEARTBEAT.md into scratch (hash-verified, archived under state backups, idempotent, symlink-contained) - gateway cron.scratch.get/set admin RPCs + openclaw cron scratch CLI - workspace bootstrap no longer seeds HEARTBEAT.md; Codex heartbeat file guidance removed; docs and prompt snapshots updated * fix(cron): review round 2 — shared-workspace heartbeat migration and non-default agent monitors - doctor migration groups agents by heartbeat source file and imports into every monitor before archiving/removing the shared file once - exempt heartbeat payloads from the main-session default-agent restriction: monitors only poke the wake bus, so non-default agents converge again - document why disabled monitors retain their last cadence (config default already resolves before the fallback) * fix(cron): honor configured cron store, legacy heartbeat fallback, and safer doctor claim * fix(cron): claim HEARTBEAT.md before committing scratch and restore without clobbering * fix(cron): pin migration CAS to precondition revision, re-verify claim on release, archive first, report scratch as pending * docs(heartbeat): remove retired config options * fix(cron): crash-recoverable migration claims, partial-import rollback, latest-response scratch pairing * test(heartbeat): keep latest scratch proposal paired * fix(cron): roll back committed scratch on changed-claim release and restore no-row state * fix(cron): revision-guarded rollback delete and recreated-file detection on claim release * fix(cron): treat every failed claim re-verification as a migration conflict * test(heartbeat): rename ack test after ackMaxChars retirement * fix(heartbeat): keep monitor scratch out of bypass-scope runs * fix(cron): resolve claimed symlinks on release and gate legacy fallback on proven scratch state * fix(cron): strict claim-name recovery and per-entry migration grouping * fix(ci): heartbeat scratch gate repairs — lint causes, dead exports, since-train, inventory path, prompt snapshot, regenerated docs map, SDK baseline, protocol bindings * fix(cron): live-owner claim guard and canonical entry-key migration grouping * fix(cron): archive claimed inode on release and flag orphan claims beside recreated files * docs(cron): document process-global state-db invariant for scratch service ops * chore(i18n): refresh native inventory line numbers after protocol binding regen
103 lines
3.6 KiB
TypeScript
103 lines
3.6 KiB
TypeScript
/**
|
|
* Test-only helpers for producing Codex app-server prompt snapshots and dynamic
|
|
* tool specs without starting a live app-server.
|
|
*/
|
|
import type {
|
|
AnyAgentTool,
|
|
EmbeddedRunAttemptParams,
|
|
} from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
import {
|
|
type CodexAppServerRuntimeOptions,
|
|
resolveCodexAppServerRuntimeOptions,
|
|
} from "./src/app-server/config.js";
|
|
import type { CodexPluginConfig } from "./src/app-server/config.js";
|
|
import { filterCodexDynamicTools } from "./src/app-server/dynamic-tool-profile.js";
|
|
import { createCodexDynamicToolBridge } from "./src/app-server/dynamic-tools.js";
|
|
import type { CodexDynamicToolSpec, JsonObject } from "./src/app-server/protocol.js";
|
|
import {
|
|
buildDeveloperInstructions,
|
|
buildThreadResumeParams,
|
|
buildThreadStartParams,
|
|
buildTurnStartParams,
|
|
} from "./src/app-server/thread-lifecycle.js";
|
|
|
|
type CodexHarnessPromptSnapshot = {
|
|
developerInstructions: string;
|
|
threadStartParams: ReturnType<typeof buildThreadStartParams>;
|
|
threadResumeParams: ReturnType<typeof buildThreadResumeParams>;
|
|
turnStartParams: ReturnType<typeof buildTurnStartParams>;
|
|
};
|
|
|
|
/** Resolves deterministic app-server options for prompt snapshot tests. */
|
|
export function resolveCodexPromptSnapshotAppServerOptions(
|
|
pluginConfig?: unknown,
|
|
): CodexAppServerRuntimeOptions {
|
|
return resolveCodexAppServerRuntimeOptions({
|
|
pluginConfig,
|
|
env: {},
|
|
requirementsToml: null,
|
|
});
|
|
}
|
|
|
|
/** Builds thread/resume/turn prompt payload snapshots for a Codex harness attempt. */
|
|
export function buildCodexHarnessPromptSnapshot(params: {
|
|
attempt: EmbeddedRunAttemptParams;
|
|
cwd: string;
|
|
threadId: string;
|
|
dynamicTools: CodexDynamicToolSpec[];
|
|
appServer: CodexAppServerRuntimeOptions;
|
|
config?: JsonObject;
|
|
promptText?: string;
|
|
developerInstructionAdditions?: string;
|
|
turnScopedDeveloperInstructions?: string;
|
|
}): CodexHarnessPromptSnapshot {
|
|
const developerInstructions = joinPresentSections(
|
|
buildDeveloperInstructions(params.attempt, {
|
|
dynamicTools: params.dynamicTools,
|
|
}),
|
|
params.developerInstructionAdditions,
|
|
);
|
|
return {
|
|
developerInstructions,
|
|
threadStartParams: buildThreadStartParams(params.attempt, {
|
|
cwd: params.cwd,
|
|
dynamicTools: params.dynamicTools,
|
|
appServer: params.appServer,
|
|
developerInstructions,
|
|
config: params.config,
|
|
}),
|
|
threadResumeParams: buildThreadResumeParams(params.attempt, {
|
|
threadId: params.threadId,
|
|
appServer: params.appServer,
|
|
developerInstructions,
|
|
config: params.config,
|
|
}),
|
|
turnStartParams: buildTurnStartParams(params.attempt, {
|
|
threadId: params.threadId,
|
|
cwd: params.cwd,
|
|
appServer: params.appServer,
|
|
promptText: params.promptText,
|
|
turnScopedDeveloperInstructions: params.turnScopedDeveloperInstructions,
|
|
}),
|
|
};
|
|
}
|
|
|
|
function joinPresentSections(...sections: Array<string | undefined>): string {
|
|
return sections.filter((section): section is string => Boolean(section?.trim())).join("\n\n");
|
|
}
|
|
|
|
/** Converts harness tools into Codex dynamic-tool specs for prompt snapshot tests. */
|
|
export function createCodexDynamicToolSpecsForPromptSnapshot(params: {
|
|
tools: AnyAgentTool[];
|
|
pluginConfig?: Pick<CodexPluginConfig, "codexDynamicToolsLoading" | "codexDynamicToolsExclude">;
|
|
directToolNames?: Iterable<string>;
|
|
}): CodexDynamicToolSpec[] {
|
|
const filteredTools = filterCodexDynamicTools(params.tools, params.pluginConfig ?? {});
|
|
return createCodexDynamicToolBridge({
|
|
tools: filteredTools,
|
|
signal: new AbortController().signal,
|
|
loading: params.pluginConfig?.codexDynamicToolsLoading ?? "searchable",
|
|
directToolNames: params.directToolNames,
|
|
}).specs;
|
|
}
|