Files
openclaw/src/agents/accepted-session-spawn.ts
clawsweeper[bot] 7f4bd454fe fix(agents): preserve accepted spawn terminal success (#85135)
Summary:
- The branch adds accepted `sessions_spawn` tracking through embedded Pi subscribe, runner, fallback, replay, lifecycle, tests, deadcode allowlist, and changelog surfaces.
- Reproducibility: yes. at source level. Current main documents accepted `sessions_spawn` results but the pre- ...  and classifier paths do not carry that accepted child-run fact into incomplete-turn or fallback decisions.

Automerge notes:
- PR branch already contained follow-up commit before automerge: test(qa-lab): allow codex fixtures in deadcode
- PR branch already contained follow-up commit before automerge: fix(agents): preserve accepted spawn terminal success

Validation:
- ClawSweeper review passed for head 0f6d92b8cd.
- Required merge gates passed before the squash merge.

Prepared head SHA: 0f6d92b8cd
Review: https://github.com/openclaw/openclaw/pull/85135#issuecomment-4513861326

Co-authored-by: samzong <samzong.lu@gmail.com>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: takhoffman
Co-authored-by: takhoffman <781889+takhoffman@users.noreply.github.com>
2026-05-22 01:16:41 +00:00

38 lines
1.2 KiB
TypeScript

import { normalizeOptionalString } from "../shared/string-coerce.js";
export type AcceptedSessionSpawn = {
runId: string;
childSessionKey: string;
};
function asRecord(value: unknown): Record<string, unknown> | undefined {
return value && typeof value === "object" && !Array.isArray(value)
? (value as Record<string, unknown>)
: undefined;
}
export function normalizeAcceptedSessionSpawnResult(result: unknown): AcceptedSessionSpawn | null {
const details = asRecord(asRecord(result)?.details);
if (!details || details.status !== "accepted") {
return null;
}
const runId = normalizeOptionalString(details.runId);
const childSessionKey = normalizeOptionalString(details.childSessionKey);
if (!runId || !childSessionKey) {
return null;
}
return { runId, childSessionKey };
}
export function hasAcceptedSessionSpawn(acceptedSessionSpawns?: readonly unknown[]): boolean {
return (acceptedSessionSpawns ?? []).some((spawn) => {
const record = asRecord(spawn);
if (!record) {
return false;
}
return Boolean(
normalizeOptionalString(record.runId) && normalizeOptionalString(record.childSessionKey),
);
});
}