From 59c1d2481eeb356be1f8027143d0161e47e0d00a Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Mon, 1 Jun 2026 15:53:39 -0600 Subject: [PATCH 1/2] Fix self-send wake rendering --- packages/agents-runtime/src/entity-schema.ts | 8 +++ .../src/components/EntityTimeline.tsx | 69 +++++++++++++++++-- packages/agents-server/src/wake-registry.ts | 33 ++++++--- .../agents-server/test/wake-registry.test.ts | 33 +++++++++ 4 files changed, 125 insertions(+), 18 deletions(-) diff --git a/packages/agents-runtime/src/entity-schema.ts b/packages/agents-runtime/src/entity-schema.ts index cc10a379e6..2610cdb4ff 100644 --- a/packages/agents-runtime/src/entity-schema.ts +++ b/packages/agents-runtime/src/entity-schema.ts @@ -79,6 +79,10 @@ type WakeChangeEntryValue = { collection: string kind: `insert` | `update` | `delete` key: string + from?: string + payload?: unknown + timestamp?: string + message_type?: string } type WakeFinishedChildEntryValue = { url: string @@ -370,6 +374,10 @@ function createWakeChangeSchema(): Schema { collection: z.string(), kind: z.enum([`insert`, `update`, `delete`]), key: z.string(), + from: z.string().optional(), + payload: z.unknown().optional(), + timestamp: z.string().optional(), + message_type: z.string().optional(), }) } diff --git a/packages/agents-server-ui/src/components/EntityTimeline.tsx b/packages/agents-server-ui/src/components/EntityTimeline.tsx index 1d2dd98863..eab8926c87 100644 --- a/packages/agents-server-ui/src/components/EntityTimeline.tsx +++ b/packages/agents-server-ui/src/components/EntityTimeline.tsx @@ -258,8 +258,40 @@ function timelineRowLabel(row: RenderTimelineRow): string { return `Agent response` } -function wakeReason(section: WakeSection): string { +function firstSelfSendWakeChange( + section: WakeSection, + entityUrl?: string | null +): WakeSection[`payload`][`changes`][number] | null { + if (!entityUrl || section.payload.source !== entityUrl) return null + return ( + section.payload.changes.find((change) => change.collection === `inbox`) ?? + null + ) +} + +function isSelfSendWake( + section: WakeSection, + entityUrl?: string | null +): boolean { + return firstSelfSendWakeChange(section, entityUrl) !== null +} + +function wakeSelfSendMessage( + section: WakeSection, + entityUrl?: string | null +): string | null { + const change = firstSelfSendWakeChange(section, entityUrl) + if (!change) return null + const payload = change.payload + if (payload == null) return `` + return typeof payload === `string` + ? payload + : JSON.stringify(payload, null, 2) +} + +function wakeReason(section: WakeSection, entityUrl?: string | null): string { const { payload } = section + if (isSelfSendWake(section, entityUrl)) return `sent to itself` if (payload.timeout) return `timeout` if (payload.finished_child) { return `child ${payload.finished_child.run_status}` @@ -273,10 +305,13 @@ function wakeReason(section: WakeSection): string { return payload.source } -function wakeSectionText(section: WakeSection): string { +function wakeSectionText( + section: WakeSection, + entityUrl?: string | null +): string { return [ `woke`, - wakeReason(section), + wakeReason(section, entityUrl), section.payload.source, ...wakeDetails(section).map((detail) => `${detail.label} ${detail.value}`), ].join(` `) @@ -284,12 +319,15 @@ function wakeSectionText(section: WakeSection): string { function WakeTimelineRow({ section, + entityUrl, }: { section: WakeSection + entityUrl?: string | null }): React.ReactElement { - const reason = wakeReason(section) - const details = wakeDetails(section) + const reason = wakeReason(section, entityUrl) + const details = wakeDetails(section, entityUrl) const childOutput = wakeChildOutput(section) + const selfSendMessage = wakeSelfSendMessage(section, entityUrl) return (
))}
+ {selfSendMessage ? ( +
{selfSendMessage}
+ ) : null} {childOutput ? (
{childOutput.value}
) : null} @@ -364,15 +405,28 @@ function signalSummary( } function wakeDetails( - section: WakeSection + section: WakeSection, + entityUrl?: string | null ): Array<{ label: string; value: string }> { const { payload } = section + const selfSendChange = firstSelfSendWakeChange(section, entityUrl) const details = [ { label: `Source`, value: payload.source }, - { label: `Trigger`, value: wakeReason(section) }, + { label: `Trigger`, value: wakeReason(section, entityUrl) }, { label: `Time`, value: formatAbsoluteDateTimeVerbose(section.timestamp) }, ] + if (selfSendChange) { + details.push({ + label: `From`, + value: selfSendChange.from ?? payload.source, + }) + const message = wakeSelfSendMessage(section, entityUrl) + if (message) { + details.push({ label: `Message`, value: message }) + } + } + if (payload.changes.length > 0) { details.push({ label: `Changes`, @@ -845,6 +899,7 @@ const TimelineRow = memo(function TimelineRow({ payload: row.wake.payload, timestamp: Date.parse(row.wake.payload.timestamp), }} + entityUrl={entityUrl} /> ) } diff --git a/packages/agents-server/src/wake-registry.ts b/packages/agents-server/src/wake-registry.ts index cf6c75fa7a..1ca37d9595 100644 --- a/packages/agents-server/src/wake-registry.ts +++ b/packages/agents-server/src/wake-registry.ts @@ -41,6 +41,10 @@ export interface WakeEvalResult { collection: string kind: `insert` | `update` | `delete` key: string + from?: string + payload?: unknown + timestamp?: string + message_type?: string }> } runFinishedStatus?: `completed` | `failed` @@ -885,11 +889,7 @@ export class WakeRegistry { reg: WakeRegistration, event: Record ): { - change: { - collection: string - kind: `insert` | `update` | `delete` - key: string - } + change: WakeEvalResult[`wakeMessage`][`changes`][number] runFinishedStatus?: `completed` | `failed` } | null { if (reg.condition === `runFinished`) { @@ -935,12 +935,23 @@ export class WakeRegistry { return null } - return { - change: { - collection: eventType, - kind, - key: (event.key as string) || ``, - }, + const change: WakeEvalResult[`wakeMessage`][`changes`][number] = { + collection: eventType, + kind, + key: (event.key as string) || ``, } + + if (eventType === `inbox`) { + const value = event.value as Record | undefined + if (typeof value?.from === `string`) change.from = value.from + if (`payload` in (value ?? {})) change.payload = value?.payload + if (typeof value?.timestamp === `string`) + change.timestamp = value.timestamp + if (typeof value?.message_type === `string`) { + change.message_type = value.message_type + } + } + + return { change } } } diff --git a/packages/agents-server/test/wake-registry.test.ts b/packages/agents-server/test/wake-registry.test.ts index f7e05fefbd..11b48d41e2 100644 --- a/packages/agents-server/test/wake-registry.test.ts +++ b/packages/agents-server/test/wake-registry.test.ts @@ -277,6 +277,39 @@ describe(`Wake Registry`, () => { expect(results[0]!.wakeMessage.changes[0]!.kind).toBe(`insert`) }) + it(`includes inbox message details in wake changes`, async () => { + const registry = new WakeRegistry(createMockDb()) + await registry.register({ + subscriberUrl: `/agent/self`, + sourceUrl: `/agent/self`, + condition: { on: `change`, collections: [`inbox`] }, + oneShot: false, + }) + + const results = registry.evaluate(`/agent/self`, { + type: `inbox`, + key: `msg-1`, + value: { + from: `/principal/agent%3Aself`, + payload: { text: `wake up` }, + timestamp: `2026-01-01T00:00:00.000Z`, + message_type: `reminder`, + }, + headers: { operation: `insert` }, + }) + + expect(results).toHaveLength(1) + expect(results[0]!.wakeMessage.changes[0]).toEqual({ + collection: `inbox`, + kind: `insert`, + key: `msg-1`, + from: `/principal/agent%3Aself`, + payload: { text: `wake up` }, + timestamp: `2026-01-01T00:00:00.000Z`, + message_type: `reminder`, + }) + }) + it(`ignores events for non-matching collections`, async () => { const registry = new WakeRegistry(createMockDb()) await registry.register({ From c94b65f55463c576a6f7d01392f4df03be6f2583 Mon Sep 17 00:00:00 2001 From: Kyle Mathews Date: Mon, 1 Jun 2026 15:58:01 -0600 Subject: [PATCH 2/2] Add changeset for self-send wake rendering --- .changeset/self-send-wake-rendering.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/self-send-wake-rendering.md diff --git a/.changeset/self-send-wake-rendering.md b/.changeset/self-send-wake-rendering.md new file mode 100644 index 0000000000..053f3bb157 --- /dev/null +++ b/.changeset/self-send-wake-rendering.md @@ -0,0 +1,7 @@ +--- +'@electric-ax/agents-runtime': patch +'@electric-ax/agents-server': patch +'@electric-ax/agents-server-ui': patch +--- + +Render self-send wake notifications with the sent message payload in the agent timeline.