Gate inbox delivery on worker-side steer ACK
Replace the fire-and-forget steer with a correlated ACK round-trip so main only marks an inbox row delivered once the worker confirms the message landed on the live Agent. Steer against a run that is still in the `preparing` window or has already started `closing` now falls back to the wake + inbox projection path instead of being silently dropped. Worker publishes `run-agent-state` transitions at Agent construction and teardown; main tracks these on `ActiveRunContext.state` and refuses to steer runs that are not `agent_active`. A rejected or timed-out ACK triggers `wakeAgentIfPossible` so the next `prepareRun` replays the row.
This commit is contained in:
1 parent
ad9205fcc9
commit
e917c614c9
12 files changed
+264
-57
No files matched your search
@@ -7,6 +7,7 @@ import type { createBudgetEnforcementService } from "../budget-enforcement-servi
|
||||
import type { createSessionManagementService } from "../session-management-service";
|
||||
import type { PiRuntimeServices } from "../service-graph-pi-runtime";
|
||||
import type { NotificationOptions } from "../notification-service";
|
||||
import type { RuntimeMessageInjector } from "../agent-runtime";
|
||||
import type { LateBinding } from "./late-binding";
|
||||
|
||||
export interface WorkerServiceDeps {
|
||||
@@ -29,6 +30,12 @@ export interface WorkerServiceDeps {
|
||||
budgetService: ReturnType<typeof createBudgetEnforcementService>;
|
||||
sessionService: ReturnType<typeof createSessionManagementService>;
|
||||
piRuntimeRef: { current: PiRuntimeServices | null };
|
||||
/**
|
||||
* Resolver for the late-constructed runtime message injector. The worker
|
||||
* message handler needs it to route `steer-ack` child messages, but the
|
||||
* injector is assembled after the worker service itself.
|
||||
*/
|
||||
getRuntimeMessageInjector: () => RuntimeMessageInjector | null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,6 +59,7 @@ export function buildWorkerService(deps: WorkerServiceDeps) {
|
||||
budgetService,
|
||||
sessionService,
|
||||
piRuntimeRef,
|
||||
getRuntimeMessageInjector,
|
||||
} = deps;
|
||||
|
||||
const wakeAgentIfPossible = (agentId: string | null | undefined, companyId: string, trigger: string) =>
|
||||
@@ -83,5 +91,6 @@ export function buildWorkerService(deps: WorkerServiceDeps) {
|
||||
budgetService,
|
||||
sessionService,
|
||||
getRuntimeBridge: () => piRuntimeRef.current?.runtimeBridge ?? null,
|
||||
getRuntimeMessageInjector,
|
||||
});
|
||||
}
|
||||
@@ -26,6 +26,10 @@ export class LateBinding<T> {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
isAssigned(): boolean {
|
||||
return this.assigned;
|
||||
}
|
||||
|
||||
clear(): void {
|
||||
this.value = null;
|
||||
this.assigned = false;
|
||||
|
||||
Reference in new issue
Block a user