fix(todo-continuation): cancel stale ULW countdown
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -67,4 +67,35 @@ describe("handleNonIdleEvent", () => {
|
||||
expect(state.wasCancelled).toBe(true)
|
||||
expect(state.tokenLimitDetected).toBe(true)
|
||||
})
|
||||
|
||||
test("given ultrawork loop continuation user message update, cancels stale todo continuation countdown", () => {
|
||||
// given
|
||||
const sessionID = "ses_ulw_todo_overlap"
|
||||
const state = sessionStateStore.getState(sessionID)
|
||||
state.countdownStartedAt = Date.now() - 10_000
|
||||
state.wasCancelled = true
|
||||
state.tokenLimitDetected = true
|
||||
|
||||
// when
|
||||
handleNonIdleEvent({
|
||||
eventType: "message.updated",
|
||||
properties: {
|
||||
sessionID,
|
||||
info: { role: "user" },
|
||||
parts: [
|
||||
{
|
||||
type: "text",
|
||||
text: `ultrawork [SYSTEM DIRECTIVE: OH-MY-OPENCODE - RALPH LOOP 2/500]\ncontinue\n${OMO_INTERNAL_INITIATOR_MARKER}`,
|
||||
synthetic: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
sessionStateStore,
|
||||
})
|
||||
|
||||
// then
|
||||
expect(state.countdownStartedAt).toBeUndefined()
|
||||
expect(state.wasCancelled).toBe(true)
|
||||
expect(state.tokenLimitDetected).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,6 +2,7 @@ import { resolveMessageEventSessionID, resolveSessionEventID } from "../../share
|
||||
import type { InternalInitiatorTextPartLike } from "../../shared/internal-initiator-marker"
|
||||
import { isSyntheticOrInternalOnlyTextParts } from "../../shared/internal-initiator-marker"
|
||||
import { log } from "../../shared/logger"
|
||||
import { isSystemDirective } from "../../shared/system-directive"
|
||||
|
||||
import { COUNTDOWN_GRACE_PERIOD_MS, HOOK_NAME } from "./constants"
|
||||
import type { SessionStateStore } from "./session-state"
|
||||
@@ -34,6 +35,14 @@ function resolveEventParts(
|
||||
return parts
|
||||
}
|
||||
|
||||
function hasInternalSystemDirective(parts: InternalInitiatorTextPartLike[] | undefined): boolean {
|
||||
return (parts ?? []).some(
|
||||
(part) => part.type === "text"
|
||||
&& typeof part.text === "string"
|
||||
&& isSystemDirective(part.text),
|
||||
)
|
||||
}
|
||||
|
||||
export function handleNonIdleEvent(args: {
|
||||
eventType: string
|
||||
properties: Record<string, unknown> | undefined
|
||||
@@ -50,6 +59,11 @@ export function handleNonIdleEvent(args: {
|
||||
if (role === "user") {
|
||||
const parts = resolveEventParts(properties)
|
||||
if (isSyntheticOrInternalOnlyTextParts(parts)) {
|
||||
const state = sessionStateStore.getExistingState(sessionID)
|
||||
if (state?.countdownStartedAt && hasInternalSystemDirective(parts)) {
|
||||
sessionStateStore.cancelCountdown(sessionID)
|
||||
log(`[${HOOK_NAME}] Cancelled countdown for internal continuation message`, { sessionID })
|
||||
}
|
||||
log(`[${HOOK_NAME}] Ignoring synthetic/internal user message event`, { sessionID })
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user