@llui/agent 0.0.40 → 0.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/client/factory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/client/factory.ts"],"names":[],"mappings":"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"}
@@ -175,6 +175,18 @@ export function createAgentClient(opts) {
175
175
  });
176
176
  }
177
177
  installErrorListeners();
178
+ // Catch per-binding throws into drain.errors so a single bad
179
+ // binding doesn't blank the page AND the agent learns about it.
180
+ // Runtime contract: leaves the binding's `lastValue` unchanged
181
+ // (DOM stays at last-rendered value), continues with siblings,
182
+ // calls this hook once per binding throw.
183
+ opts.handle.setOnBindingError((info) => {
184
+ drainErrors.push({
185
+ kind: 'error',
186
+ message: `[binding ${info.kind}${info.key ? `:${info.key}` : ''}] ${info.message}`,
187
+ stack: info.stack,
188
+ });
189
+ });
178
190
  },
179
191
  stop() {
180
192
  if (confirmPollTimer)
@@ -185,6 +197,7 @@ export function createAgentClient(opts) {
185
197
  stateSubscription = null;
186
198
  }
187
199
  removeErrorListeners();
200
+ opts.handle.setOnBindingError(null);
188
201
  drainErrors.length = 0;
189
202
  wsClient?.close();
190
203
  },
@@ -1 +1 @@
1
- {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/client/factory.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AppHandle } from '@llui/dom'\nimport type { AgentEffect } from './effects.js'\nimport type { AgentConfirmState } from './agentConfirm.js'\nimport type {\n AgentDocs,\n AgentContext,\n LapDrainMeta,\n MessageAnnotations,\n MessageSchemaEntry,\n} from '../protocol.js'\nimport { attachWsClient, type WsLike, type RpcHosts } from './ws-client.js'\nimport { createEffectHandler } from './effect-handler.js'\nimport { makeDefaultCodecs, encodeForWire, decodeFromWire, type CodecRegistry } from '../codecs.js'\n\n/**\n * The shape the compiler emits as `__msgSchema`. Mirrors `MsgField`\n * from `@llui/vite-plugin/src/msg-schema.ts`. Three coexisting forms:\n *\n * 1. Bare primitive: `'string' | 'number' | 'boolean' | 'unknown'`\n * and bare enum: `{enum: [...]}` (values may be string, number,\n * or boolean — the compiler preserves the literal kind so JSON\n * round-trips don't lose type info).\n * 2. Bare nested types: `{kind: 'object', shape}` for inline /\n * followed-via-typeIndex shapes; `{kind: 'array', element}` for\n * `T[]` / `readonly T[]` / `Array<T>`; `{kind: 'discriminated-\n * union', discriminant, variants}` for tagged unions of objects\n * (e.g. `Format = {kind:'exact'} | {kind:'range', min, max}`).\n * The synthesizer recurses to build copy-paste-ready nested\n * examples; the validator walks the same tree.\n * 3. Rich descriptor: wraps any of the above with `{optional?,\n * priority?, hint?}` carrying TS optionality and `@should` hints.\n */\nexport type MsgSchemaBareType =\n | string\n | { enum: ReadonlyArray<string | number | boolean> }\n | { kind: 'object'; shape: Record<string, MsgSchemaField> }\n | { kind: 'array'; element: MsgSchemaBareType }\n | {\n kind: 'discriminated-union'\n discriminant: string\n variants: Record<string, Record<string, MsgSchemaField>>\n }\n\nexport type MsgSchemaField =\n | MsgSchemaBareType\n | {\n type: MsgSchemaBareType\n optional?: boolean\n priority?: 'should'\n hint?: string\n /**\n * Boolean JS expression authored with `@validates(\"expr\")` JSDoc.\n * Has `v` bound to the field value at runtime; the validator\n * compiles it lazily with `new Function('v', 'return (' + src +\n * ')')` and caches the function across calls. Use for invariants\n * the type system can't express — numeric ranges, format\n * predicates, length bounds.\n */\n validates?: string\n }\n\nexport type MsgSchemaShape = {\n discriminant: string\n variants: Record<string, Record<string, MsgSchemaField>>\n}\n\ntype ComponentMetadata = {\n __msgSchema?: unknown\n __stateSchema?: unknown\n __msgAnnotations?: Record<string, MessageAnnotations>\n __schemaHash?: string\n name: string\n agentAffordances?: (state: unknown) => Array<{ type: string; [k: string]: unknown }>\n agentDocs?: AgentDocs\n agentContext?: (state: unknown) => AgentContext\n}\n\nexport type CreateAgentClientOpts<State, Msg> = {\n handle: AppHandle\n def: ComponentMetadata\n appVersion?: string\n rootElement: Element | null\n slices: {\n getConnect: (s: State) => unknown\n getConfirm: (s: State) => AgentConfirmState\n wrapConnectMsg: (m: unknown) => Msg\n wrapConfirmMsg: (m: unknown) => Msg\n /**\n * Optional: wrap an agentLog msg so the client-side activity feed\n * mirrors what Claude is doing. If omitted, outbound log-append\n * frames still go to the server, but the local agent.log slice\n * stays empty (the UI won't show activity).\n */\n wrapLogMsg?: (m: unknown) => Msg\n }\n /**\n * Codec registry for non-JSON-safe values (Date, Blob, Map, …)\n * crossing the LAP boundary. Defaults to `makeDefaultCodecs()`\n * which ships `iso-date` and `epoch-millis`. Provide a custom\n * registry to register additional codecs (e.g. `base64-blob` for\n * file uploads). See `@llui/agent/codecs` for the convention.\n */\n codecs?: CodecRegistry\n /**\n * Base path for agent HTTP endpoints. Default: `'/agent'` (matches\n * the canonical paths in `@llui/vite-plugin`'s dev middleware and\n * `@llui/agent/server`). The mint URL, resume URLs, and revoke URL\n * derive from this so consumers don't have to keep them in sync.\n *\n * Override when:\n * - **Cross-origin agent server**: pass the full base, e.g.\n * `'https://api.example.com/agent'` or `'http://localhost:8787/agent'`.\n * - **`@cloudflare/vite-plugin` in dev**: pass `'/cdn-cgi/agent'`\n * because cloudflare-vite shadows non-`/cdn-cgi/*` routes.\n */\n agentBasePath?: string\n}\n\nexport type AgentClient = {\n effectHandler: (effect: AgentEffect) => Promise<void>\n start(): void\n stop(): void\n}\n\nexport function createAgentClient<State, Msg>(\n opts: CreateAgentClientOpts<State, Msg>,\n): AgentClient {\n let ws: WebSocket | null = null\n let wsClient: ReturnType<typeof attachWsClient> | null = null\n let confirmPollTimer: ReturnType<typeof setInterval> | null = null\n let stateSubscription: (() => void) | null = null\n const resolvedConfirms = new Set<string>()\n\n // Drain-error buffer: populated by persistent `window.error` and\n // `window.unhandledrejection` listeners installed on `start()`. The\n // send-message drain loop consumes and clears it per call so the\n // envelope surfaces only errors that fired during that window.\n const drainErrors: LapDrainMeta['errors'] = []\n let errorListenersInstalled = false\n let onErrorEvt: ((e: ErrorEvent) => void) | null = null\n let onRejectionEvt: ((e: PromiseRejectionEvent) => void) | null = null\n\n function installErrorListeners(): void {\n if (errorListenersInstalled) return\n if (typeof window === 'undefined') return\n onErrorEvt = (e: ErrorEvent) => {\n drainErrors.push({\n kind: 'error',\n message: e.message ?? String(e.error ?? 'unknown error'),\n stack: e.error instanceof Error ? e.error.stack : undefined,\n })\n }\n onRejectionEvt = (e: PromiseRejectionEvent) => {\n const r = e.reason\n const message = r instanceof Error ? r.message : typeof r === 'string' ? r : safeStringify(r)\n drainErrors.push({\n kind: 'unhandledrejection',\n message,\n stack: r instanceof Error ? r.stack : undefined,\n })\n }\n window.addEventListener('error', onErrorEvt)\n window.addEventListener('unhandledrejection', onRejectionEvt)\n errorListenersInstalled = true\n }\n\n function removeErrorListeners(): void {\n if (!errorListenersInstalled) return\n if (typeof window === 'undefined') return\n if (onErrorEvt) window.removeEventListener('error', onErrorEvt)\n if (onRejectionEvt) window.removeEventListener('unhandledrejection', onRejectionEvt)\n onErrorEvt = null\n onRejectionEvt = null\n errorListenersInstalled = false\n }\n\n // Codec registry handles non-JSON-safe values (Date, etc.) crossing\n // the LAP boundary. `getState` encodes outgoing snapshots; `send`\n // decodes incoming agent messages before they hit the reducer. The\n // tagged-value convention is documented in `@llui/agent/codecs`.\n const codecs = opts.codecs ?? makeDefaultCodecs()\n\n // Track the most recent send_message outcome so `describe_context`\n // can prepend a synthetic hint about it. Apps used to roll their\n // own `lastDispatchError` state field; the framework now owns it.\n let lastDispatchOutcome: import('./rpc/describe-context.js').LastDispatchOutcome | null = null\n\n const rpcHost: RpcHosts = {\n getState: () => encodeForWire(opts.handle.getState(), codecs),\n send: (m) => opts.handle.send(decodeFromWire(m, codecs)),\n flush: () => opts.handle.flush(),\n subscribe: (listener) => opts.handle.subscribe(() => listener()),\n getAndClearDrainErrors: () => drainErrors.splice(0, drainErrors.length),\n getMsgAnnotations: () => opts.def.__msgAnnotations ?? null,\n // The compiler-injected message schema. Used by `list_actions` to\n // synthesize payload examples for `@agentOnly` variants that have\n // no live UI binding — the agent should still see them as\n // affordances even though no human can click them.\n getMsgSchema: () => (opts.def.__msgSchema as MsgSchemaShape | undefined) ?? null,\n // Run the reducer in isolation for `would_dispatch`. Wraps the\n // AppHandle's same-named method so the host doesn't need a direct\n // reference to the live ComponentInstance.\n runReducer: (msg) => opts.handle.runReducer(msg),\n // Live binding descriptors: read from the runtime registry that\n // tracks which Msg variants are dispatchable from currently-mounted\n // event handlers. Empty array when the app wasn't compiled with\n // agent metadata (no tagger pass) or has no view bindings yet —\n // both produce the same \"no live affordances\" signal at the agent\n // layer.\n getBindingDescriptors: () => opts.handle.getBindingDescriptors(),\n getAgentAffordances: () => opts.def.agentAffordances ?? null,\n getAgentContext: () => opts.def.agentContext ?? null,\n getLastDispatchOutcome: () => lastDispatchOutcome,\n getRootElement: () => opts.rootElement,\n proposeConfirm: (entry) => {\n opts.handle.send(opts.slices.wrapConfirmMsg({ type: 'Propose', entry }))\n },\n }\n\n // Exposed so the WS client can update on each send_message reply.\n // Closure scope keeps the field write-protected — only the WS layer\n // mutates it; everyone else reads through the getter above.\n const recordDispatchOutcome = (outcome: typeof lastDispatchOutcome): void => {\n lastDispatchOutcome = outcome\n }\n\n const helloBuilder = () => ({\n t: 'hello' as const,\n appName: opts.def.name,\n appVersion: opts.appVersion ?? '0.0.0',\n msgSchema: (opts.def.__msgSchema ?? {}) as Record<string, MessageSchemaEntry>,\n stateSchema: (opts.def.__stateSchema ?? {}) as object,\n affordancesSample: opts.def.agentAffordances\n ? opts.def.agentAffordances(opts.handle.getState())\n : [],\n docs: opts.def.agentDocs ?? null,\n schemaHash: opts.def.__schemaHash ?? '',\n })\n\n const effectHandler = createEffectHandler({\n send: (m) => opts.handle.send(m),\n wrapAgentConnect: (m) => opts.slices.wrapConnectMsg(m),\n forward: (payload) => opts.handle.send(payload),\n agentBasePath: opts.agentBasePath,\n openWs: (token, wsUrl) => {\n if (ws) ws.close()\n ws = new WebSocket(`${wsUrl}?token=${encodeURIComponent(token)}`)\n wsClient = attachWsClient(ws as unknown as WsLike, rpcHost, helloBuilder, {\n onActivated: () => {\n opts.handle.send(opts.slices.wrapConnectMsg({ type: 'ActivatedByClaude' }))\n },\n onLogEntry: opts.slices.wrapLogMsg\n ? (entry) => {\n opts.handle.send(opts.slices.wrapLogMsg!({ type: 'Append', entry }))\n }\n : undefined,\n onDispatchOutcome: recordDispatchOutcome,\n })\n ws.addEventListener('open', () => {\n opts.handle.send(opts.slices.wrapConnectMsg({ type: 'WsOpened' }))\n })\n ws.addEventListener('close', () => {\n opts.handle.send(opts.slices.wrapConnectMsg({ type: 'WsClosed' }))\n })\n },\n closeWs: () => {\n wsClient?.close()\n ws = null\n wsClient = null\n },\n })\n\n const pollConfirms = () => {\n const state = opts.handle.getState() as State\n const confirm = opts.slices.getConfirm(state)\n for (const entry of confirm.pending) {\n if (entry.status === 'pending') continue\n if (resolvedConfirms.has(entry.id)) continue\n resolvedConfirms.add(entry.id)\n if (entry.status === 'approved') {\n wsClient?.resolveConfirm(\n entry.id,\n 'confirmed',\n encodeForWire(opts.handle.getState(), codecs),\n )\n } else if (entry.status === 'rejected') {\n wsClient?.resolveConfirm(entry.id, 'user-cancelled')\n }\n }\n }\n\n return {\n effectHandler,\n start() {\n if (!confirmPollTimer) confirmPollTimer = setInterval(pollConfirms, 200)\n if (!stateSubscription) {\n stateSubscription = opts.handle.subscribe((state) => {\n // Same codec convention as `getState`: outgoing snapshots\n // pass through the encoder so non-JSON-safe values (Date,\n // etc.) become tagged-wire form.\n wsClient?.emitStateUpdate('/', encodeForWire(state, codecs))\n })\n }\n installErrorListeners()\n },\n stop() {\n if (confirmPollTimer) clearInterval(confirmPollTimer)\n confirmPollTimer = null\n if (stateSubscription) {\n stateSubscription()\n stateSubscription = null\n }\n removeErrorListeners()\n drainErrors.length = 0\n wsClient?.close()\n },\n }\n}\n\nfunction safeStringify(v: unknown): string {\n try {\n return JSON.stringify(v)\n } catch {\n return String(v)\n }\n}\n"]}
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/client/factory.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AppHandle } from '@llui/dom'\nimport type { AgentEffect } from './effects.js'\nimport type { AgentConfirmState } from './agentConfirm.js'\nimport type {\n AgentDocs,\n AgentContext,\n LapDrainMeta,\n MessageAnnotations,\n MessageSchemaEntry,\n} from '../protocol.js'\nimport { attachWsClient, type WsLike, type RpcHosts } from './ws-client.js'\nimport { createEffectHandler } from './effect-handler.js'\nimport { makeDefaultCodecs, encodeForWire, decodeFromWire, type CodecRegistry } from '../codecs.js'\n\n/**\n * The shape the compiler emits as `__msgSchema`. Mirrors `MsgField`\n * from `@llui/vite-plugin/src/msg-schema.ts`. Three coexisting forms:\n *\n * 1. Bare primitive: `'string' | 'number' | 'boolean' | 'unknown'`\n * and bare enum: `{enum: [...]}` (values may be string, number,\n * or boolean — the compiler preserves the literal kind so JSON\n * round-trips don't lose type info).\n * 2. Bare nested types: `{kind: 'object', shape}` for inline /\n * followed-via-typeIndex shapes; `{kind: 'array', element}` for\n * `T[]` / `readonly T[]` / `Array<T>`; `{kind: 'discriminated-\n * union', discriminant, variants}` for tagged unions of objects\n * (e.g. `Format = {kind:'exact'} | {kind:'range', min, max}`).\n * The synthesizer recurses to build copy-paste-ready nested\n * examples; the validator walks the same tree.\n * 3. Rich descriptor: wraps any of the above with `{optional?,\n * priority?, hint?}` carrying TS optionality and `@should` hints.\n */\nexport type MsgSchemaBareType =\n | string\n | { enum: ReadonlyArray<string | number | boolean> }\n | { kind: 'object'; shape: Record<string, MsgSchemaField> }\n | { kind: 'array'; element: MsgSchemaBareType }\n | {\n kind: 'discriminated-union'\n discriminant: string\n variants: Record<string, Record<string, MsgSchemaField>>\n }\n\nexport type MsgSchemaField =\n | MsgSchemaBareType\n | {\n type: MsgSchemaBareType\n optional?: boolean\n priority?: 'should'\n hint?: string\n /**\n * Boolean JS expression authored with `@validates(\"expr\")` JSDoc.\n * Has `v` bound to the field value at runtime; the validator\n * compiles it lazily with `new Function('v', 'return (' + src +\n * ')')` and caches the function across calls. Use for invariants\n * the type system can't express — numeric ranges, format\n * predicates, length bounds.\n */\n validates?: string\n }\n\nexport type MsgSchemaShape = {\n discriminant: string\n variants: Record<string, Record<string, MsgSchemaField>>\n}\n\ntype ComponentMetadata = {\n __msgSchema?: unknown\n __stateSchema?: unknown\n __msgAnnotations?: Record<string, MessageAnnotations>\n __schemaHash?: string\n name: string\n agentAffordances?: (state: unknown) => Array<{ type: string; [k: string]: unknown }>\n agentDocs?: AgentDocs\n agentContext?: (state: unknown) => AgentContext\n}\n\nexport type CreateAgentClientOpts<State, Msg> = {\n handle: AppHandle\n def: ComponentMetadata\n appVersion?: string\n rootElement: Element | null\n slices: {\n getConnect: (s: State) => unknown\n getConfirm: (s: State) => AgentConfirmState\n wrapConnectMsg: (m: unknown) => Msg\n wrapConfirmMsg: (m: unknown) => Msg\n /**\n * Optional: wrap an agentLog msg so the client-side activity feed\n * mirrors what Claude is doing. If omitted, outbound log-append\n * frames still go to the server, but the local agent.log slice\n * stays empty (the UI won't show activity).\n */\n wrapLogMsg?: (m: unknown) => Msg\n }\n /**\n * Codec registry for non-JSON-safe values (Date, Blob, Map, …)\n * crossing the LAP boundary. Defaults to `makeDefaultCodecs()`\n * which ships `iso-date` and `epoch-millis`. Provide a custom\n * registry to register additional codecs (e.g. `base64-blob` for\n * file uploads). See `@llui/agent/codecs` for the convention.\n */\n codecs?: CodecRegistry\n /**\n * Base path for agent HTTP endpoints. Default: `'/agent'` (matches\n * the canonical paths in `@llui/vite-plugin`'s dev middleware and\n * `@llui/agent/server`). The mint URL, resume URLs, and revoke URL\n * derive from this so consumers don't have to keep them in sync.\n *\n * Override when:\n * - **Cross-origin agent server**: pass the full base, e.g.\n * `'https://api.example.com/agent'` or `'http://localhost:8787/agent'`.\n * - **`@cloudflare/vite-plugin` in dev**: pass `'/cdn-cgi/agent'`\n * because cloudflare-vite shadows non-`/cdn-cgi/*` routes.\n */\n agentBasePath?: string\n}\n\nexport type AgentClient = {\n effectHandler: (effect: AgentEffect) => Promise<void>\n start(): void\n stop(): void\n}\n\nexport function createAgentClient<State, Msg>(\n opts: CreateAgentClientOpts<State, Msg>,\n): AgentClient {\n let ws: WebSocket | null = null\n let wsClient: ReturnType<typeof attachWsClient> | null = null\n let confirmPollTimer: ReturnType<typeof setInterval> | null = null\n let stateSubscription: (() => void) | null = null\n const resolvedConfirms = new Set<string>()\n\n // Drain-error buffer: populated by persistent `window.error` and\n // `window.unhandledrejection` listeners installed on `start()`. The\n // send-message drain loop consumes and clears it per call so the\n // envelope surfaces only errors that fired during that window.\n const drainErrors: LapDrainMeta['errors'] = []\n let errorListenersInstalled = false\n let onErrorEvt: ((e: ErrorEvent) => void) | null = null\n let onRejectionEvt: ((e: PromiseRejectionEvent) => void) | null = null\n\n function installErrorListeners(): void {\n if (errorListenersInstalled) return\n if (typeof window === 'undefined') return\n onErrorEvt = (e: ErrorEvent) => {\n drainErrors.push({\n kind: 'error',\n message: e.message ?? String(e.error ?? 'unknown error'),\n stack: e.error instanceof Error ? e.error.stack : undefined,\n })\n }\n onRejectionEvt = (e: PromiseRejectionEvent) => {\n const r = e.reason\n const message = r instanceof Error ? r.message : typeof r === 'string' ? r : safeStringify(r)\n drainErrors.push({\n kind: 'unhandledrejection',\n message,\n stack: r instanceof Error ? r.stack : undefined,\n })\n }\n window.addEventListener('error', onErrorEvt)\n window.addEventListener('unhandledrejection', onRejectionEvt)\n errorListenersInstalled = true\n }\n\n function removeErrorListeners(): void {\n if (!errorListenersInstalled) return\n if (typeof window === 'undefined') return\n if (onErrorEvt) window.removeEventListener('error', onErrorEvt)\n if (onRejectionEvt) window.removeEventListener('unhandledrejection', onRejectionEvt)\n onErrorEvt = null\n onRejectionEvt = null\n errorListenersInstalled = false\n }\n\n // Codec registry handles non-JSON-safe values (Date, etc.) crossing\n // the LAP boundary. `getState` encodes outgoing snapshots; `send`\n // decodes incoming agent messages before they hit the reducer. The\n // tagged-value convention is documented in `@llui/agent/codecs`.\n const codecs = opts.codecs ?? makeDefaultCodecs()\n\n // Track the most recent send_message outcome so `describe_context`\n // can prepend a synthetic hint about it. Apps used to roll their\n // own `lastDispatchError` state field; the framework now owns it.\n let lastDispatchOutcome: import('./rpc/describe-context.js').LastDispatchOutcome | null = null\n\n const rpcHost: RpcHosts = {\n getState: () => encodeForWire(opts.handle.getState(), codecs),\n send: (m) => opts.handle.send(decodeFromWire(m, codecs)),\n flush: () => opts.handle.flush(),\n subscribe: (listener) => opts.handle.subscribe(() => listener()),\n getAndClearDrainErrors: () => drainErrors.splice(0, drainErrors.length),\n getMsgAnnotations: () => opts.def.__msgAnnotations ?? null,\n // The compiler-injected message schema. Used by `list_actions` to\n // synthesize payload examples for `@agentOnly` variants that have\n // no live UI binding — the agent should still see them as\n // affordances even though no human can click them.\n getMsgSchema: () => (opts.def.__msgSchema as MsgSchemaShape | undefined) ?? null,\n // Run the reducer in isolation for `would_dispatch`. Wraps the\n // AppHandle's same-named method so the host doesn't need a direct\n // reference to the live ComponentInstance.\n runReducer: (msg) => opts.handle.runReducer(msg),\n // Live binding descriptors: read from the runtime registry that\n // tracks which Msg variants are dispatchable from currently-mounted\n // event handlers. Empty array when the app wasn't compiled with\n // agent metadata (no tagger pass) or has no view bindings yet —\n // both produce the same \"no live affordances\" signal at the agent\n // layer.\n getBindingDescriptors: () => opts.handle.getBindingDescriptors(),\n getAgentAffordances: () => opts.def.agentAffordances ?? null,\n getAgentContext: () => opts.def.agentContext ?? null,\n getLastDispatchOutcome: () => lastDispatchOutcome,\n getRootElement: () => opts.rootElement,\n proposeConfirm: (entry) => {\n opts.handle.send(opts.slices.wrapConfirmMsg({ type: 'Propose', entry }))\n },\n }\n\n // Exposed so the WS client can update on each send_message reply.\n // Closure scope keeps the field write-protected — only the WS layer\n // mutates it; everyone else reads through the getter above.\n const recordDispatchOutcome = (outcome: typeof lastDispatchOutcome): void => {\n lastDispatchOutcome = outcome\n }\n\n const helloBuilder = () => ({\n t: 'hello' as const,\n appName: opts.def.name,\n appVersion: opts.appVersion ?? '0.0.0',\n msgSchema: (opts.def.__msgSchema ?? {}) as Record<string, MessageSchemaEntry>,\n stateSchema: (opts.def.__stateSchema ?? {}) as object,\n affordancesSample: opts.def.agentAffordances\n ? opts.def.agentAffordances(opts.handle.getState())\n : [],\n docs: opts.def.agentDocs ?? null,\n schemaHash: opts.def.__schemaHash ?? '',\n })\n\n const effectHandler = createEffectHandler({\n send: (m) => opts.handle.send(m),\n wrapAgentConnect: (m) => opts.slices.wrapConnectMsg(m),\n forward: (payload) => opts.handle.send(payload),\n agentBasePath: opts.agentBasePath,\n openWs: (token, wsUrl) => {\n if (ws) ws.close()\n ws = new WebSocket(`${wsUrl}?token=${encodeURIComponent(token)}`)\n wsClient = attachWsClient(ws as unknown as WsLike, rpcHost, helloBuilder, {\n onActivated: () => {\n opts.handle.send(opts.slices.wrapConnectMsg({ type: 'ActivatedByClaude' }))\n },\n onLogEntry: opts.slices.wrapLogMsg\n ? (entry) => {\n opts.handle.send(opts.slices.wrapLogMsg!({ type: 'Append', entry }))\n }\n : undefined,\n onDispatchOutcome: recordDispatchOutcome,\n })\n ws.addEventListener('open', () => {\n opts.handle.send(opts.slices.wrapConnectMsg({ type: 'WsOpened' }))\n })\n ws.addEventListener('close', () => {\n opts.handle.send(opts.slices.wrapConnectMsg({ type: 'WsClosed' }))\n })\n },\n closeWs: () => {\n wsClient?.close()\n ws = null\n wsClient = null\n },\n })\n\n const pollConfirms = () => {\n const state = opts.handle.getState() as State\n const confirm = opts.slices.getConfirm(state)\n for (const entry of confirm.pending) {\n if (entry.status === 'pending') continue\n if (resolvedConfirms.has(entry.id)) continue\n resolvedConfirms.add(entry.id)\n if (entry.status === 'approved') {\n wsClient?.resolveConfirm(\n entry.id,\n 'confirmed',\n encodeForWire(opts.handle.getState(), codecs),\n )\n } else if (entry.status === 'rejected') {\n wsClient?.resolveConfirm(entry.id, 'user-cancelled')\n }\n }\n }\n\n return {\n effectHandler,\n start() {\n if (!confirmPollTimer) confirmPollTimer = setInterval(pollConfirms, 200)\n if (!stateSubscription) {\n stateSubscription = opts.handle.subscribe((state) => {\n // Same codec convention as `getState`: outgoing snapshots\n // pass through the encoder so non-JSON-safe values (Date,\n // etc.) become tagged-wire form.\n wsClient?.emitStateUpdate('/', encodeForWire(state, codecs))\n })\n }\n installErrorListeners()\n // Catch per-binding throws into drain.errors so a single bad\n // binding doesn't blank the page AND the agent learns about it.\n // Runtime contract: leaves the binding's `lastValue` unchanged\n // (DOM stays at last-rendered value), continues with siblings,\n // calls this hook once per binding throw.\n opts.handle.setOnBindingError((info) => {\n drainErrors.push({\n kind: 'error',\n message: `[binding ${info.kind}${info.key ? `:${info.key}` : ''}] ${info.message}`,\n stack: info.stack,\n })\n })\n },\n stop() {\n if (confirmPollTimer) clearInterval(confirmPollTimer)\n confirmPollTimer = null\n if (stateSubscription) {\n stateSubscription()\n stateSubscription = null\n }\n removeErrorListeners()\n opts.handle.setOnBindingError(null)\n drainErrors.length = 0\n wsClient?.close()\n },\n }\n}\n\nfunction safeStringify(v: unknown): string {\n try {\n return JSON.stringify(v)\n } catch {\n return String(v)\n }\n}\n"]}
@@ -1,6 +1,20 @@
1
1
  import type { MessageAnnotations, OutlineNode } from '../../protocol.js';
2
2
  export type DescribeVisibleArgs = Record<string, never>;
3
3
  export type DescribeVisibleResult = {
4
+ /**
5
+ * The user's current URL — `window.location.href`, or `null` when
6
+ * running outside a browser (SSR / Node test harness).
7
+ *
8
+ * Why this is on the visible-content tool: the agent has no other
9
+ * way to verify "did my dispatch actually navigate the user?" Apps
10
+ * that bundle navigation into a Msg's effect chain (the canonical
11
+ * pattern) update the URL on commit; the agent reads it back here
12
+ * to confirm the user's view tracked the state change. When the URL
13
+ * doesn't move after a state-creating dispatch, the agent learns
14
+ * the dispatch landed but the navigation didn't — common when the
15
+ * Msg returned partial effects.
16
+ */
17
+ url: string | null;
4
18
  outline: OutlineNode[];
5
19
  /**
6
20
  * `'data-agent'` when the outline was scoped to author-tagged zones.
@@ -1 +1 @@
1
- {"version":3,"file":"describe-visible-content.d.ts","sourceRoot":"","sources":["../../../src/client/rpc/describe-visible-content.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAExE,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AACvD,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB;;;;;;;OAOG;IACH,MAAM,EAAE,YAAY,GAAG,UAAU,GAAG,WAAW,CAAA;CAChD,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,IAAI,OAAO,GAAG,IAAI,CAAA;IAChC,qBAAqB,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAA;IAC1D,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,IAAI,CAAA;CAC/D,CAAA;AAcD;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,mBAAmB,GAAG,qBAAqB,CAqB7F"}
1
+ {"version":3,"file":"describe-visible-content.d.ts","sourceRoot":"","sources":["../../../src/client/rpc/describe-visible-content.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAExE,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AACvD,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;;;;;;;;;OAYG;IACH,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;IAClB,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB;;;;;;;OAOG;IACH,MAAM,EAAE,YAAY,GAAG,UAAU,GAAG,WAAW,CAAA;CAChD,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,cAAc,IAAI,OAAO,GAAG,IAAI,CAAA;IAChC,qBAAqB,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAA;IAC1D,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,GAAG,IAAI,CAAA;CAC/D,CAAA;AAcD;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,mBAAmB,GAAG,qBAAqB,CAsB7F"}
@@ -22,9 +22,10 @@ const FALLBACK_MAX_DEPTH = 8;
22
22
  * can tell the outline is best-effort.
23
23
  */
24
24
  export function handleDescribeVisibleContent(host) {
25
+ const url = readCurrentUrl();
25
26
  const root = host.getRootElement();
26
27
  if (!root)
27
- return { outline: [], source: 'data-agent' };
28
+ return { url, outline: [], source: 'data-agent' };
28
29
  const allZones = Array.from(root.querySelectorAll('[data-agent]'));
29
30
  if (allZones.length > 0) {
30
31
  const out = [];
@@ -33,14 +34,27 @@ export function handleDescribeVisibleContent(host) {
33
34
  for (const zone of topLevel) {
34
35
  walk(zone, out);
35
36
  }
36
- return { outline: out, source: 'data-agent' };
37
+ return { url, outline: out, source: 'data-agent' };
37
38
  }
38
39
  // Fallback: walk the entire root with caps. Useful for apps without
39
40
  // any data-agent annotations — at minimum the agent gets headings,
40
41
  // buttons, links, lists, and visible text it can use to orient.
41
42
  const out = [];
42
43
  const truncated = walkFallback(root, out, 0);
43
- return { outline: out, source: truncated ? 'truncated' : 'fallback' };
44
+ return { url, outline: out, source: truncated ? 'truncated' : 'fallback' };
45
+ }
46
+ /**
47
+ * Read `window.location.href` defensively. Returns null when running
48
+ * outside a browser (SSR, Node test harness) — same contract as
49
+ * `getRootElement` returning null. Callers don't have to special-case
50
+ * non-browser environments.
51
+ */
52
+ function readCurrentUrl() {
53
+ if (typeof window === 'undefined')
54
+ return null;
55
+ if (typeof window.location === 'undefined')
56
+ return null;
57
+ return window.location.href;
44
58
  }
45
59
  function walk(el, out) {
46
60
  const tag = el.tagName.toLowerCase();
@@ -1 +1 @@
1
- {"version":3,"file":"describe-visible-content.js","sourceRoot":"","sources":["../../../src/client/rpc/describe-visible-content.ts"],"names":[],"mappings":"AAsBA;;;;;;;;GAQG;AACH,MAAM,kBAAkB,GAAG,GAAG,CAAA;AAC9B,MAAM,kBAAkB,GAAG,CAAC,CAAA;AAE5B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,4BAA4B,CAAC,IAAyB;IACpE,MAAM,IAAI,GAAG,IAAI,CAAC,cAAc,EAAE,CAAA;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,CAAA;IACvD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC,CAAA;IAClE,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,GAAG,GAAkB,EAAE,CAAA;QAC7B,4EAA4E;QAC5E,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAC9B,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAC5E,CAAA;QACD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QACjB,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAA;IAC/C,CAAC;IACD,oEAAoE;IACpE,mEAAmE;IACnE,gEAAgE;IAChE,MAAM,GAAG,GAAkB,EAAE,CAAA;IAC7B,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;IAC5C,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,EAAE,CAAA;AACvE,CAAC;AAED,SAAS,IAAI,CAAC,EAAW,EAAE,GAAkB;IAC3C,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAA;IACpC,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC1C,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;QAC1D,OAAM;IACR,CAAC;IACD,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QACrB,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,QAAQ;YACd,IAAI;YACJ,QAAQ,EAAG,EAAwB,CAAC,QAAQ;YAC5C,aAAa,EAAE,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,IAAI;SACrD,CAAC,CAAA;QACF,OAAM;IACR,CAAC;IACD,IAAI,GAAG,KAAK,GAAG,IAAI,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3C,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QACrE,OAAM;IACR,CAAC;IACD,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACpB,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,IAAI;YACvE,KAAK,EAAG,EAAuB,CAAC,KAAK,IAAI,IAAI;YAC7C,IAAI,EAAG,EAAuB,CAAC,IAAI,IAAI,MAAM;SAC9C,CAAC,CAAA;QACF,OAAM;IACR,CAAC;IACD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjC,MAAM,KAAK,GAAkB,EAAE,CAAA;QAC/B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC;gBACzC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;YACtE,CAAC;QACH,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;QACjC,OAAM;IACR,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;QAChC,OAAM;IACR,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;IAClB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,YAAY,CAAC,EAAW,EAAE,GAAkB,EAAE,KAAa;IAClE,IAAI,GAAG,CAAC,MAAM,IAAI,kBAAkB;QAAE,OAAO,IAAI,CAAA;IACjD,IAAI,KAAK,GAAG,kBAAkB;QAAE,OAAO,KAAK,CAAA;IAC5C,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,CAAA;IACpC,mEAAmE;IACnE,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,UAAU,IAAI,GAAG,KAAK,UAAU;QAAE,OAAO,KAAK,CAAA;IACjG,MAAM,IAAI,GAAG,CAAC,EAAE,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;IAC1C,IAAI,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACzB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAA;QAC1D,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,GAAG,KAAK,QAAQ,EAAE,CAAC;QACrB,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,CAAC;YACrD,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,EAAE;gBACjD,QAAQ,EAAG,EAAwB,CAAC,QAAQ;gBAC5C,aAAa,EAAE,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,IAAI;aACrD,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,GAAG,CAAC,MAAM,IAAI,kBAAkB,CAAA;IACzC,CAAC;IACD,IAAI,GAAG,KAAK,GAAG,IAAI,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3C,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QACrE,OAAO,GAAG,CAAC,MAAM,IAAI,kBAAkB,CAAA;IACzC,CAAC;IACD,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;QACpB,MAAM,SAAS,GAAI,EAAuB,CAAC,IAAI,IAAI,MAAM,CAAA;QACzD,oEAAoE;QACpE,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC3B,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI,EAAE,OAAO;gBACb,KAAK,EAAE,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,IAAI;gBACvE,KAAK,EAAG,EAAuB,CAAC,KAAK,IAAI,IAAI;gBAC7C,IAAI,EAAE,SAAS;aAChB,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,GAAG,CAAC,MAAM,IAAI,kBAAkB,CAAA;IACzC,CAAC;IACD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;QACjC,MAAM,KAAK,GAAkB,EAAE,CAAA;QAC/B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC5C,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,IAAI,EAAE,CAAC;gBACzC,MAAM,QAAQ,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;gBACjD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;oBAAE,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAA;YACvE,CAAC;QACH,CAAC;QACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;QACvD,OAAO,GAAG,CAAC,MAAM,IAAI,kBAAkB,CAAA;IACzC,CAAC;IACD,oEAAoE;IACpE,uDAAuD;IACvD,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChD,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAA;QAChC,OAAO,GAAG,CAAC,MAAM,IAAI,kBAAkB,CAAA;IACzC,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC5C,IAAI,YAAY,CAAC,KAAK,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC;YAAE,OAAO,IAAI,CAAA;IACtD,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC","sourcesContent":["import type { MessageAnnotations, OutlineNode } from '../../protocol.js'\n\nexport type DescribeVisibleArgs = Record<string, never>\nexport type DescribeVisibleResult = {\n outline: OutlineNode[]\n /**\n * `'data-agent'` when the outline was scoped to author-tagged zones.\n * `'fallback'` when the app has no `data-agent` attributes and the\n * walker fell back to a generic semantic-element pass over the root.\n * `'truncated'` when the fallback outline hit the node-count cap and\n * stopped early; the caller can ask follow-up questions through\n * `query_dom` or by inspecting state directly.\n */\n source: 'data-agent' | 'fallback' | 'truncated'\n}\n\nexport type DescribeVisibleHost = {\n getRootElement(): Element | null\n getBindingDescriptors(): Array<{ variant: string }> | null\n getMsgAnnotations(): Record<string, MessageAnnotations> | null\n}\n\n/**\n * Hard caps for the fallback walk. The author-tagged path doesn't need\n * caps — by definition the author chose what to expose. The fallback is\n * walking arbitrary DOM, so it has to bound the work.\n *\n * 200 nodes covers ~3–5 visible screens of typical app UI; depth 8 is\n * deep enough for nested content trees but stops us from descending\n * into giant virtualised lists or syntax-highlighted code blocks.\n */\nconst FALLBACK_MAX_NODES = 200\nconst FALLBACK_MAX_DEPTH = 8\n\n/**\n * Walk data-agent-tagged subtrees and produce a structured outline.\n * Buttons cross-reference __bindingDescriptors so Claude can tie\n * visible text to variant names.\n *\n * If the app has no `data-agent` tags, fall back to a depth-limited\n * walk of the entire root element. This makes the tool useful for apps\n * that haven't (yet) tagged their views — typical first-pass dogfood\n * targets — instead of returning an empty outline that conveys\n * nothing. The fallback path sets `source: 'fallback'` so the caller\n * can tell the outline is best-effort.\n */\nexport function handleDescribeVisibleContent(host: DescribeVisibleHost): DescribeVisibleResult {\n const root = host.getRootElement()\n if (!root) return { outline: [], source: 'data-agent' }\n const allZones = Array.from(root.querySelectorAll('[data-agent]'))\n if (allZones.length > 0) {\n const out: OutlineNode[] = []\n // Only walk top-level zones; skip zones that are descendants of other zones\n const topLevel = allZones.filter(\n (zone) => !allZones.some((other) => other !== zone && other.contains(zone)),\n )\n for (const zone of topLevel) {\n walk(zone, out)\n }\n return { outline: out, source: 'data-agent' }\n }\n // Fallback: walk the entire root with caps. Useful for apps without\n // any data-agent annotations — at minimum the agent gets headings,\n // buttons, links, lists, and visible text it can use to orient.\n const out: OutlineNode[] = []\n const truncated = walkFallback(root, out, 0)\n return { outline: out, source: truncated ? 'truncated' : 'fallback' }\n}\n\nfunction walk(el: Element, out: OutlineNode[]): void {\n const tag = el.tagName.toLowerCase()\n const text = (el.textContent ?? '').trim()\n if (/^h[1-6]$/.test(tag)) {\n out.push({ kind: 'heading', level: Number(tag[1]), text })\n return\n }\n if (tag === 'button') {\n out.push({\n kind: 'button',\n text,\n disabled: (el as HTMLButtonElement).disabled,\n actionVariant: el.getAttribute('data-agent') ?? null,\n })\n return\n }\n if (tag === 'a' && el.getAttribute('href')) {\n out.push({ kind: 'link', text, href: el.getAttribute('href') ?? '' })\n return\n }\n if (tag === 'input') {\n out.push({\n kind: 'input',\n label: el.getAttribute('aria-label') ?? el.getAttribute('name') ?? null,\n value: (el as HTMLInputElement).value ?? null,\n type: (el as HTMLInputElement).type ?? 'text',\n })\n return\n }\n if (tag === 'ul' || tag === 'ol') {\n const items: OutlineNode[] = []\n for (const child of Array.from(el.children)) {\n if (child.tagName.toLowerCase() === 'li') {\n items.push({ kind: 'item', text: (child.textContent ?? '').trim() })\n }\n }\n out.push({ kind: 'list', items })\n return\n }\n if (text.length > 0 && el.children.length === 0) {\n out.push({ kind: 'text', text })\n return\n }\n for (const child of Array.from(el.children)) {\n walk(child, out)\n }\n}\n\n/**\n * Depth- and count-limited walk for the fallback path. Returns true\n * iff the cap was hit (at least one element was skipped). Same node\n * vocabulary as `walk` but prunes more aggressively:\n *\n * - `<a>` without `href`, `<button>` without text — skipped (often\n * icon-only chrome that adds noise without helping the agent).\n * - Nested wrapper divs without semantic content — descended into\n * but not emitted.\n * - Standalone text nodes — only emitted when the parent has no\n * semantic children (preserves the existing `walk` heuristic).\n */\nfunction walkFallback(el: Element, out: OutlineNode[], depth: number): boolean {\n if (out.length >= FALLBACK_MAX_NODES) return true\n if (depth > FALLBACK_MAX_DEPTH) return false\n const tag = el.tagName.toLowerCase()\n // Skip script/style/noscript subtrees — never user-facing content.\n if (tag === 'script' || tag === 'style' || tag === 'noscript' || tag === 'template') return false\n const text = (el.textContent ?? '').trim()\n if (/^h[1-6]$/.test(tag)) {\n out.push({ kind: 'heading', level: Number(tag[1]), text })\n return false\n }\n if (tag === 'button') {\n if (text.length > 0 || el.getAttribute('aria-label')) {\n out.push({\n kind: 'button',\n text: text || el.getAttribute('aria-label') || '',\n disabled: (el as HTMLButtonElement).disabled,\n actionVariant: el.getAttribute('data-agent') ?? null,\n })\n }\n return out.length >= FALLBACK_MAX_NODES\n }\n if (tag === 'a' && el.getAttribute('href')) {\n out.push({ kind: 'link', text, href: el.getAttribute('href') ?? '' })\n return out.length >= FALLBACK_MAX_NODES\n }\n if (tag === 'input') {\n const inputType = (el as HTMLInputElement).type ?? 'text'\n // `hidden` inputs are almost always form-state plumbing; skip them.\n if (inputType !== 'hidden') {\n out.push({\n kind: 'input',\n label: el.getAttribute('aria-label') ?? el.getAttribute('name') ?? null,\n value: (el as HTMLInputElement).value ?? null,\n type: inputType,\n })\n }\n return out.length >= FALLBACK_MAX_NODES\n }\n if (tag === 'ul' || tag === 'ol') {\n const items: OutlineNode[] = []\n for (const child of Array.from(el.children)) {\n if (child.tagName.toLowerCase() === 'li') {\n const itemText = (child.textContent ?? '').trim()\n if (itemText.length > 0) items.push({ kind: 'item', text: itemText })\n }\n }\n if (items.length > 0) out.push({ kind: 'list', items })\n return out.length >= FALLBACK_MAX_NODES\n }\n // Bare text leaf: only emit if the element has a non-empty text and\n // no element children. Same rule as the tagged walker.\n if (text.length > 0 && el.children.length === 0) {\n out.push({ kind: 'text', text })\n return out.length >= FALLBACK_MAX_NODES\n }\n for (const child of Array.from(el.children)) {\n if (walkFallback(child, out, depth + 1)) return true\n }\n return false\n}\n"]}
1
+ {"version":3,"file":"describe-visible-content.js","sourceRoot":"","sources":["../../../src/client/rpc/describe-visible-content.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MessageAnnotations, OutlineNode } from '../../protocol.js'\n\nexport type DescribeVisibleArgs = Record<string, never>\nexport type DescribeVisibleResult = {\n /**\n * The user's current URL — `window.location.href`, or `null` when\n * running outside a browser (SSR / Node test harness).\n *\n * Why this is on the visible-content tool: the agent has no other\n * way to verify \"did my dispatch actually navigate the user?\" Apps\n * that bundle navigation into a Msg's effect chain (the canonical\n * pattern) update the URL on commit; the agent reads it back here\n * to confirm the user's view tracked the state change. When the URL\n * doesn't move after a state-creating dispatch, the agent learns\n * the dispatch landed but the navigation didn't — common when the\n * Msg returned partial effects.\n */\n url: string | null\n outline: OutlineNode[]\n /**\n * `'data-agent'` when the outline was scoped to author-tagged zones.\n * `'fallback'` when the app has no `data-agent` attributes and the\n * walker fell back to a generic semantic-element pass over the root.\n * `'truncated'` when the fallback outline hit the node-count cap and\n * stopped early; the caller can ask follow-up questions through\n * `query_dom` or by inspecting state directly.\n */\n source: 'data-agent' | 'fallback' | 'truncated'\n}\n\nexport type DescribeVisibleHost = {\n getRootElement(): Element | null\n getBindingDescriptors(): Array<{ variant: string }> | null\n getMsgAnnotations(): Record<string, MessageAnnotations> | null\n}\n\n/**\n * Hard caps for the fallback walk. The author-tagged path doesn't need\n * caps — by definition the author chose what to expose. The fallback is\n * walking arbitrary DOM, so it has to bound the work.\n *\n * 200 nodes covers ~3–5 visible screens of typical app UI; depth 8 is\n * deep enough for nested content trees but stops us from descending\n * into giant virtualised lists or syntax-highlighted code blocks.\n */\nconst FALLBACK_MAX_NODES = 200\nconst FALLBACK_MAX_DEPTH = 8\n\n/**\n * Walk data-agent-tagged subtrees and produce a structured outline.\n * Buttons cross-reference __bindingDescriptors so Claude can tie\n * visible text to variant names.\n *\n * If the app has no `data-agent` tags, fall back to a depth-limited\n * walk of the entire root element. This makes the tool useful for apps\n * that haven't (yet) tagged their views — typical first-pass dogfood\n * targets — instead of returning an empty outline that conveys\n * nothing. The fallback path sets `source: 'fallback'` so the caller\n * can tell the outline is best-effort.\n */\nexport function handleDescribeVisibleContent(host: DescribeVisibleHost): DescribeVisibleResult {\n const url = readCurrentUrl()\n const root = host.getRootElement()\n if (!root) return { url, outline: [], source: 'data-agent' }\n const allZones = Array.from(root.querySelectorAll('[data-agent]'))\n if (allZones.length > 0) {\n const out: OutlineNode[] = []\n // Only walk top-level zones; skip zones that are descendants of other zones\n const topLevel = allZones.filter(\n (zone) => !allZones.some((other) => other !== zone && other.contains(zone)),\n )\n for (const zone of topLevel) {\n walk(zone, out)\n }\n return { url, outline: out, source: 'data-agent' }\n }\n // Fallback: walk the entire root with caps. Useful for apps without\n // any data-agent annotations — at minimum the agent gets headings,\n // buttons, links, lists, and visible text it can use to orient.\n const out: OutlineNode[] = []\n const truncated = walkFallback(root, out, 0)\n return { url, outline: out, source: truncated ? 'truncated' : 'fallback' }\n}\n\n/**\n * Read `window.location.href` defensively. Returns null when running\n * outside a browser (SSR, Node test harness) — same contract as\n * `getRootElement` returning null. Callers don't have to special-case\n * non-browser environments.\n */\nfunction readCurrentUrl(): string | null {\n if (typeof window === 'undefined') return null\n if (typeof window.location === 'undefined') return null\n return window.location.href\n}\n\nfunction walk(el: Element, out: OutlineNode[]): void {\n const tag = el.tagName.toLowerCase()\n const text = (el.textContent ?? '').trim()\n if (/^h[1-6]$/.test(tag)) {\n out.push({ kind: 'heading', level: Number(tag[1]), text })\n return\n }\n if (tag === 'button') {\n out.push({\n kind: 'button',\n text,\n disabled: (el as HTMLButtonElement).disabled,\n actionVariant: el.getAttribute('data-agent') ?? null,\n })\n return\n }\n if (tag === 'a' && el.getAttribute('href')) {\n out.push({ kind: 'link', text, href: el.getAttribute('href') ?? '' })\n return\n }\n if (tag === 'input') {\n out.push({\n kind: 'input',\n label: el.getAttribute('aria-label') ?? el.getAttribute('name') ?? null,\n value: (el as HTMLInputElement).value ?? null,\n type: (el as HTMLInputElement).type ?? 'text',\n })\n return\n }\n if (tag === 'ul' || tag === 'ol') {\n const items: OutlineNode[] = []\n for (const child of Array.from(el.children)) {\n if (child.tagName.toLowerCase() === 'li') {\n items.push({ kind: 'item', text: (child.textContent ?? '').trim() })\n }\n }\n out.push({ kind: 'list', items })\n return\n }\n if (text.length > 0 && el.children.length === 0) {\n out.push({ kind: 'text', text })\n return\n }\n for (const child of Array.from(el.children)) {\n walk(child, out)\n }\n}\n\n/**\n * Depth- and count-limited walk for the fallback path. Returns true\n * iff the cap was hit (at least one element was skipped). Same node\n * vocabulary as `walk` but prunes more aggressively:\n *\n * - `<a>` without `href`, `<button>` without text — skipped (often\n * icon-only chrome that adds noise without helping the agent).\n * - Nested wrapper divs without semantic content — descended into\n * but not emitted.\n * - Standalone text nodes — only emitted when the parent has no\n * semantic children (preserves the existing `walk` heuristic).\n */\nfunction walkFallback(el: Element, out: OutlineNode[], depth: number): boolean {\n if (out.length >= FALLBACK_MAX_NODES) return true\n if (depth > FALLBACK_MAX_DEPTH) return false\n const tag = el.tagName.toLowerCase()\n // Skip script/style/noscript subtrees — never user-facing content.\n if (tag === 'script' || tag === 'style' || tag === 'noscript' || tag === 'template') return false\n const text = (el.textContent ?? '').trim()\n if (/^h[1-6]$/.test(tag)) {\n out.push({ kind: 'heading', level: Number(tag[1]), text })\n return false\n }\n if (tag === 'button') {\n if (text.length > 0 || el.getAttribute('aria-label')) {\n out.push({\n kind: 'button',\n text: text || el.getAttribute('aria-label') || '',\n disabled: (el as HTMLButtonElement).disabled,\n actionVariant: el.getAttribute('data-agent') ?? null,\n })\n }\n return out.length >= FALLBACK_MAX_NODES\n }\n if (tag === 'a' && el.getAttribute('href')) {\n out.push({ kind: 'link', text, href: el.getAttribute('href') ?? '' })\n return out.length >= FALLBACK_MAX_NODES\n }\n if (tag === 'input') {\n const inputType = (el as HTMLInputElement).type ?? 'text'\n // `hidden` inputs are almost always form-state plumbing; skip them.\n if (inputType !== 'hidden') {\n out.push({\n kind: 'input',\n label: el.getAttribute('aria-label') ?? el.getAttribute('name') ?? null,\n value: (el as HTMLInputElement).value ?? null,\n type: inputType,\n })\n }\n return out.length >= FALLBACK_MAX_NODES\n }\n if (tag === 'ul' || tag === 'ol') {\n const items: OutlineNode[] = []\n for (const child of Array.from(el.children)) {\n if (child.tagName.toLowerCase() === 'li') {\n const itemText = (child.textContent ?? '').trim()\n if (itemText.length > 0) items.push({ kind: 'item', text: itemText })\n }\n }\n if (items.length > 0) out.push({ kind: 'list', items })\n return out.length >= FALLBACK_MAX_NODES\n }\n // Bare text leaf: only emit if the element has a non-empty text and\n // no element children. Same rule as the tagged walker.\n if (text.length > 0 && el.children.length === 0) {\n out.push({ kind: 'text', text })\n return out.length >= FALLBACK_MAX_NODES\n }\n for (const child of Array.from(el.children)) {\n if (walkFallback(child, out, depth + 1)) return true\n }\n return false\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"list-actions.d.ts","sourceRoot":"","sources":["../../../src/client/rpc/list-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,eAAe,CAAA;AAEnE,KAAK,OAAO,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAClC,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;AAErD,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,IAAI,OAAO,CAAA;IACnB,qBAAqB,IAAI,OAAO,EAAE,GAAG,IAAI,CAAA;IACzC,iBAAiB,IAAI,WAAW,GAAG,IAAI,CAAA;IACvC,YAAY,IAAI,cAAc,GAAG,IAAI,CAAA;IACrC,mBAAmB,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC,GAAG,IAAI,CAAA;CAClG,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,KAAK,CAAC;QACb,OAAO,EAAE,MAAM,CAAA;QACf;;;;;WAKG;QACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;QACrB,eAAe,EAAE,OAAO,CAAA;QACxB,YAAY,EAAE,QAAQ,GAAG,YAAY,CAAA;QACrC,MAAM,EAAE,SAAS,GAAG,mBAAmB,GAAG,QAAQ,CAAA;QAClD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;QAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;QAC1B,sDAAsD;QACtD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,gEAAgE;QAChE,QAAQ,EAAE,MAAM,EAAE,CAAA;QAClB;;;;;WAKG;QACH,KAAK,EAAE,MAAM,EAAE,CAAA;QACf;;;;;;;;;;WAUG;QACH,UAAU,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAClD,CAAC,CAAA;CACH,CAAA;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,iBAAiB,CAgI1E"}
1
+ {"version":3,"file":"list-actions.d.ts","sourceRoot":"","sources":["../../../src/client/rpc/list-actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAkB,MAAM,eAAe,CAAA;AAEnE,KAAK,OAAO,GAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAA;AAClC,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAA;AAErD,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,IAAI,OAAO,CAAA;IACnB,qBAAqB,IAAI,OAAO,EAAE,GAAG,IAAI,CAAA;IACzC,iBAAiB,IAAI,WAAW,GAAG,IAAI,CAAA;IACvC,YAAY,IAAI,cAAc,GAAG,IAAI,CAAA;IACrC,mBAAmB,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC,CAAC,GAAG,IAAI,CAAA;CAClG,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,KAAK,CAAC;QACb,OAAO,EAAE,MAAM,CAAA;QACf;;;;;WAKG;QACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;QACrB,eAAe,EAAE,OAAO,CAAA;QACxB,YAAY,EAAE,QAAQ,GAAG,YAAY,CAAA;QACrC,MAAM,EAAE,SAAS,GAAG,mBAAmB,GAAG,QAAQ,CAAA;QAClD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;QAC3B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;QAC1B,sDAAsD;QACtD,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,gEAAgE;QAChE,QAAQ,EAAE,MAAM,EAAE,CAAA;QAClB;;;;;WAKG;QACH,KAAK,EAAE,MAAM,EAAE,CAAA;QACf;;;;;;;;;;WAUG;QACH,UAAU,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAClD,CAAC,CAAA;CACH,CAAA;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,iBAAiB,CA0J1E"}
@@ -2,7 +2,20 @@ export function handleListActions(host) {
2
2
  const annotations = host.getMsgAnnotations() ?? {};
3
3
  const state = host.getState();
4
4
  const descriptors = host.getBindingDescriptors() ?? [];
5
- const affordances = host.getAgentAffordances()?.(state) ?? [];
5
+ const affordancesFn = host.getAgentAffordances();
6
+ const affordances = affordancesFn ? affordancesFn(state) : [];
7
+ // When the app provides `agentAffordances(state)`, it's opted into
8
+ // explicit affordance control: only state-relevant Msgs are listed.
9
+ // `@agentOnly` schema-source variants are then filtered to those the
10
+ // hook returned — so a bulk-edit Msg like `Matrix/AddCriteria`
11
+ // doesn't surface on the home page just because it's tagged
12
+ // `@agentOnly`. Apps without `agentAffordances` keep the previous
13
+ // permissive default ("everything's available unless you say
14
+ // otherwise") since flipping that without explicit opt-in would
15
+ // break consumers who rely on schema-source surfacing of
16
+ // bulk Msgs.
17
+ const explicitAffordances = affordancesFn !== null;
18
+ const affordanceVariants = new Set(affordances.map((m) => m.type));
6
19
  const schema = host.getMsgSchema();
7
20
  const out = [];
8
21
  const seen = new Set();
@@ -26,6 +39,8 @@ export function handleListActions(host) {
26
39
  const ann = annotations[d.variant];
27
40
  if (ann?.dispatchMode === 'human-only')
28
41
  continue;
42
+ if (!passesRouteGate(ann, state))
43
+ continue;
29
44
  seen.add(d.variant);
30
45
  const variantSchema = schema?.variants[d.variant];
31
46
  out.push({
@@ -48,6 +63,8 @@ export function handleListActions(host) {
48
63
  const ann = annotations[msg.type];
49
64
  if (ann?.dispatchMode === 'human-only')
50
65
  continue;
66
+ if (!passesRouteGate(ann, state))
67
+ continue;
51
68
  seen.add(msg.type);
52
69
  const { type, ...rest } = msg;
53
70
  const variantSchema = schema?.variants[type];
@@ -79,6 +96,8 @@ export function handleListActions(host) {
79
96
  continue;
80
97
  if (!ann.alwaysAffordable)
81
98
  continue;
99
+ if (!passesRouteGate(ann, state))
100
+ continue;
82
101
  seen.add(variant);
83
102
  const fields = schema?.variants[variant];
84
103
  out.push({
@@ -105,6 +124,14 @@ export function handleListActions(host) {
105
124
  // their UI subtree is unmounted would pop hidden state in places the
106
125
  // user didn't navigate to. The explicit knobs are `@alwaysAffordable`
107
126
  // (handled above) or `agentAffordances(state)`.
127
+ //
128
+ // When the app provides `agentAffordances`, this pass is filtered:
129
+ // an `@agentOnly` variant only surfaces if the hook returned it.
130
+ // That makes route-gated bulk Msgs (`Matrix/AddCriteria` available
131
+ // only when a matrix is loaded) work as expected — they stop
132
+ // appearing on the home page just because they're tagged
133
+ // `@agentOnly`. Apps without `agentAffordances` keep the previous
134
+ // permissive default.
108
135
  if (schema) {
109
136
  for (const [variant, fields] of Object.entries(schema.variants)) {
110
137
  if (seen.has(variant))
@@ -112,6 +139,10 @@ export function handleListActions(host) {
112
139
  const ann = annotations[variant];
113
140
  if (ann?.dispatchMode !== 'agent-only')
114
141
  continue;
142
+ if (explicitAffordances && !affordanceVariants.has(variant))
143
+ continue;
144
+ if (!passesRouteGate(ann, state))
145
+ continue;
115
146
  out.push({
116
147
  variant,
117
148
  intent: ann.intent,
@@ -139,6 +170,46 @@ export function handleListActions(host) {
139
170
  * The first key is `type` so the payload reads as a complete Msg
140
171
  * shape — copy-paste-ready into `send_message`.
141
172
  */
173
+ /**
174
+ * Evaluate `@routeGated("predicate")` against the current state.
175
+ * Returns true (variant passes) when:
176
+ * - the variant has no `@routeGated` annotation, OR
177
+ * - the predicate evaluates truthy with `state` bound.
178
+ *
179
+ * Predicate is compiled lazily via `new Function('state', 'return (' +
180
+ * src + ')')` and cached in a module-level Map. Compile failures
181
+ * (syntactically broken predicates) degrade to "true" so a single
182
+ * malformed annotation doesn't paralyze the affordance pass — the
183
+ * build-time linter is the right place to catch syntactic issues.
184
+ * Evaluation throws fail-closed (return false) since a predicate that
185
+ * crashes on the current state shouldn't surface the variant.
186
+ */
187
+ function passesRouteGate(ann, state) {
188
+ const src = ann?.routeGate;
189
+ if (!src)
190
+ return true;
191
+ const predicate = compileRouteGate(src);
192
+ try {
193
+ return Boolean(predicate(state));
194
+ }
195
+ catch {
196
+ return false;
197
+ }
198
+ }
199
+ const routeGateCache = new Map();
200
+ function compileRouteGate(src) {
201
+ let fn = routeGateCache.get(src);
202
+ if (fn)
203
+ return fn;
204
+ try {
205
+ fn = new Function('state', `return (${src})`);
206
+ }
207
+ catch {
208
+ fn = () => true;
209
+ }
210
+ routeGateCache.set(src, fn);
211
+ return fn;
212
+ }
142
213
  function synthesizePayload(variant, fields) {
143
214
  const out = { type: variant };
144
215
  for (const [name, descriptor] of Object.entries(fields)) {
@@ -1 +1 @@
1
- {"version":3,"file":"list-actions.js","sourceRoot":"","sources":["../../../src/client/rpc/list-actions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MessageAnnotations } from '../../protocol.js'\nimport type { MsgSchemaShape, MsgSchemaField } from '../factory.js'\n\ntype Binding = { variant: string }\ntype Annotations = Record<string, MessageAnnotations>\n\nexport type ListActionsHost = {\n getState(): unknown\n getBindingDescriptors(): Binding[] | null\n getMsgAnnotations(): Annotations | null\n getMsgSchema(): MsgSchemaShape | null\n getAgentAffordances(): ((state: unknown) => Array<{ type: string; [k: string]: unknown }>) | null\n}\n\n/**\n * `dispatchMode` on each action is `'shared'` (human can also click via\n * a UI affordance) or `'agent-only'` (no UI binding — agent is the only\n * dispatcher). `'human-only'` variants are filtered out before this\n * point — they never reach the LLM.\n *\n * `source` distinguishes WHERE the affordance came from:\n * - `'binding'` — a tagged event handler is currently mounted in a\n * live scope (refcount > 0). Variants inside dead branches —\n * `show({when: false})`, unmounted `branch()` cases, removed `each`\n * items — auto-vanish from this set as their lifetimes dispose.\n * This is the framework's \"what can the user click right now\"\n * answer, and it's the default surface for the agent.\n * - `'always-affordable'` — either the app's `agentAffordances(state)`\n * hook listed the variant, or the variant carries the\n * `@alwaysAffordable` JSDoc tag. Both are the explicit \"agent can\n * reach this even when no live UI binding maps to it\" knob — bulk\n * seed ops (`Matrix/AddAlternatives`) and similar agent-driven\n * paths typically land here.\n * - `'schema'` — variant is annotated `@agentOnly` (the canonical\n * \"no UI button maps to this; the agent is the only dispatcher\")\n * and isn't already covered above. The payload is schema-synthesized\n * and the agent fills it in.\n *\n * `'shared'` variants WITHOUT a live binding, without\n * `agentAffordances` mention, and without `@alwaysAffordable` are\n * **deliberately hidden**. They're reachable through UI navigation —\n * the human user can't click them right now, and dispatching them\n * blindly would mutate state that drives `show()`/`branch()` gates,\n * popping hidden UI subtrees into view in places the user didn't\n * navigate to.\n */\nexport type ListActionsResult = {\n actions: Array<{\n variant: string\n /**\n * Human-readable phrase from `@intent(\"…\")`, or `null` when the\n * variant is unannotated. Mirror of LapActionsResponse.intent —\n * callers should treat `null` as a documentation gap and not as\n * \"missing label, fall back to variant name\".\n */\n intent: string | null\n requiresConfirm: boolean\n dispatchMode: 'shared' | 'agent-only'\n source: 'binding' | 'always-affordable' | 'schema'\n selectorHint: string | null\n payloadHint: object | null\n /** Cautionary text from `@warning` JSDoc, or null. */\n warning: string | null\n /** Concrete examples from `@example` JSDoc, in source order. */\n examples: string[]\n /**\n * Effect kinds this variant emits, from `@emits(\"k1\", \"k2\")`.\n * Empty when not annotated. Lets the agent know what side\n * effects fire — useful for batching (\"100 dispatches × cloud-\n * save = bad\") and for confirming destructive flows.\n */\n emits: string[]\n /**\n * Per-field guidance lifted from `@should(\"…\")` JSDoc on payload\n * fields. Path is dot/bracket notation rooted at the payload\n * (e.g. `\"cells\"` for a top-level field, `\"cells[].meta\"` for an\n * array element's nested field). Useful when the field is typed\n * as `unknown` or as a polymorphic shape — the hint says \"type\n * matches the criterion's kind: number for quantity, …\" so the\n * agent doesn't have to guess from the bare schema.\n *\n * Empty when no field on this variant carries an `@should` hint.\n */\n fieldHints: Array<{ path: string; hint: string }>\n }>\n}\n\nexport function handleListActions(host: ListActionsHost): ListActionsResult {\n const annotations = host.getMsgAnnotations() ?? {}\n const state = host.getState()\n const descriptors = host.getBindingDescriptors() ?? []\n const affordances = host.getAgentAffordances()?.(state) ?? []\n const schema = host.getMsgSchema()\n\n const out: ListActionsResult['actions'] = []\n const seen = new Set<string>()\n\n // From bindings — these have UI affordances by definition, so they're\n // either 'shared' (default) or, in the malformed case where someone\n // bound an `@agentOnly` Msg in a view, 'agent-only'. Either way the\n // agent can dispatch them.\n //\n // Filtered against the Msg schema: a binding whose variant isn't in\n // the user's Msg union is a library-internal Msg leaking through\n // `tagSend` translator wiring (the sortable component's `move`,\n // `drop`, `cancel`, etc. — they're routed into the user's update.ts\n // via a different shape but their lib names slip into the binding\n // registry). The agent has no use for those names — `would_dispatch`\n // / `send_message` would reject them as `unknown-variant` anyway —\n // so they pollute the affordance list. When a schema is available,\n // the schema's variant set is the source of truth.\n for (const d of descriptors) {\n if (schema && !(d.variant in schema.variants)) continue\n const ann = annotations[d.variant]\n if (ann?.dispatchMode === 'human-only') continue\n seen.add(d.variant)\n const variantSchema = schema?.variants[d.variant]\n out.push({\n variant: d.variant,\n intent: ann?.intent ?? null,\n requiresConfirm: ann?.requiresConfirm ?? false,\n dispatchMode: ann?.dispatchMode === 'agent-only' ? 'agent-only' : 'shared',\n source: 'binding',\n selectorHint: null,\n payloadHint: null,\n warning: ann?.warning ?? null,\n examples: ann?.examples ?? [],\n emits: ann?.emits ?? [],\n fieldHints: variantSchema ? collectFieldHints(variantSchema) : [],\n })\n }\n\n // From `agentAffordances(state)` — the integrator's explicit list of\n // currently-reachable Msgs, with concrete payloads they author.\n for (const msg of affordances) {\n const ann = annotations[msg.type]\n if (ann?.dispatchMode === 'human-only') continue\n seen.add(msg.type)\n const { type, ...rest } = msg\n const variantSchema = schema?.variants[type]\n out.push({\n variant: type,\n intent: ann?.intent ?? null,\n requiresConfirm: ann?.requiresConfirm ?? false,\n dispatchMode: ann?.dispatchMode === 'agent-only' ? 'agent-only' : 'shared',\n source: 'always-affordable',\n selectorHint: null,\n payloadHint: Object.keys(rest).length > 0 ? rest : null,\n warning: ann?.warning ?? null,\n examples: ann?.examples ?? [],\n emits: ann?.emits ?? [],\n fieldHints: variantSchema ? collectFieldHints(variantSchema) : [],\n })\n }\n\n // From `@alwaysAffordable` annotations — the per-variant equivalent\n // of `agentAffordances`. Variants tagged this way surface regardless\n // of whether a live binding maps to them, so bulk seed ops\n // (`Matrix/AddAlternatives`) and similar agent-driven paths are\n // available even when their UI counterparts (if any) aren't mounted.\n // The payload is schema-synthesized — `agentAffordances` is the way\n // to ship a concrete pre-filled payload alongside the affordance.\n for (const [variant, ann] of Object.entries(annotations)) {\n if (seen.has(variant)) continue\n if (ann.dispatchMode === 'human-only') continue\n if (!ann.alwaysAffordable) continue\n seen.add(variant)\n const fields = schema?.variants[variant]\n out.push({\n variant,\n intent: ann.intent,\n requiresConfirm: ann.requiresConfirm,\n dispatchMode: ann.dispatchMode === 'agent-only' ? 'agent-only' : 'shared',\n source: 'always-affordable',\n selectorHint: null,\n payloadHint: fields ? synthesizePayload(variant, fields) : null,\n warning: ann.warning,\n examples: ann.examples,\n emits: ann.emits,\n fieldHints: fields ? collectFieldHints(fields) : [],\n })\n }\n\n // From schema — variants that aren't already surfaced above and that\n // the author marked `@agentOnly`. The canonical \"no UI button maps\n // to this; the agent is the only dispatcher.\" Bulk edits, imports,\n // admin operations that have no human-facing affordance at all.\n //\n // `'shared'` variants WITHOUT a live binding stay hidden here — they\n // are reachable through UI navigation, and dispatching them while\n // their UI subtree is unmounted would pop hidden state in places the\n // user didn't navigate to. The explicit knobs are `@alwaysAffordable`\n // (handled above) or `agentAffordances(state)`.\n if (schema) {\n for (const [variant, fields] of Object.entries(schema.variants)) {\n if (seen.has(variant)) continue\n const ann = annotations[variant]\n if (ann?.dispatchMode !== 'agent-only') continue\n out.push({\n variant,\n intent: ann.intent,\n requiresConfirm: ann.requiresConfirm,\n dispatchMode: 'agent-only',\n source: 'schema',\n selectorHint: null,\n payloadHint: synthesizePayload(variant, fields),\n warning: ann.warning,\n examples: ann.examples,\n emits: ann.emits,\n fieldHints: collectFieldHints(fields),\n })\n }\n }\n\n return { actions: out }\n}\n\n/**\n * Build an example payload object the LLM can fill in. Required\n * fields always appear; optional fields appear only when annotated\n * `@should` (LLM is encouraged to fill them in). Fields without a\n * concrete primitive type (`'unknown'`) emit `null` placeholders the\n * LLM is expected to replace.\n *\n * The first key is `type` so the payload reads as a complete Msg\n * shape — copy-paste-ready into `send_message`.\n */\nfunction synthesizePayload(variant: string, fields: Record<string, MsgSchemaField>): object {\n const out: Record<string, unknown> = { type: variant }\n for (const [name, descriptor] of Object.entries(fields)) {\n const optional = isOptional(descriptor)\n const priority = isShould(descriptor)\n // Skip optional fields unless they're @should-flagged. Required\n // fields always appear.\n if (optional && priority !== 'should') continue\n out[name] = exampleValue(descriptor)\n }\n return out\n}\n\n/**\n * Walk a variant's field tree and collect every `@should` hint into a\n * flat list keyed by field path. Path conventions:\n * - top-level field: `\"cells\"`\n * - nested object property: `\"cells.value\"`\n * - array element: `\"cells[]\"` for the element itself; descendants\n * use `\"cells[].meta\"` and so on.\n *\n * Surfaces the same hints that show up nested inside\n * `description.messages.variants[X].field.hint` so callers don't have\n * to dig through the schema tree to find them.\n */\nfunction collectFieldHints(\n fields: Record<string, MsgSchemaField>,\n): Array<{ path: string; hint: string }> {\n const out: Array<{ path: string; hint: string }> = []\n for (const [name, descriptor] of Object.entries(fields)) {\n walkHint(name, descriptor, out)\n }\n return out\n}\n\nfunction walkHint(\n path: string,\n d: MsgSchemaField,\n out: Array<{ path: string; hint: string }>,\n): void {\n // Rich descriptor with a hint at this position.\n if (typeof d === 'object' && d !== null && 'type' in d) {\n if (typeof d.hint === 'string' && d.hint.length > 0) {\n out.push({ path, hint: d.hint })\n }\n // `@validates(...)` predicates surface alongside `@should` hints\n // so the agent sees the constraint at affordance time rather than\n // only as a post-dispatch rejection. The verbatim predicate text\n // is what the runtime evaluates; agents trained on JS read it\n // directly. Prefix `validates: ` to disambiguate from freeform\n // `@should` text.\n if (typeof d.validates === 'string' && d.validates.length > 0) {\n out.push({ path, hint: `validates: ${d.validates}` })\n }\n walkHintBare(path, d.type, out)\n return\n }\n walkHintBare(path, d, out)\n}\n\nfunction walkHintBare(path: string, t: unknown, out: Array<{ path: string; hint: string }>): void {\n if (t === null || typeof t !== 'object') return\n const obj = t as Record<string, unknown>\n if (obj.kind === 'object' && obj.shape !== null && typeof obj.shape === 'object') {\n for (const [name, descriptor] of Object.entries(obj.shape as Record<string, MsgSchemaField>)) {\n walkHint(`${path}.${name}`, descriptor, out)\n }\n return\n }\n if (obj.kind === 'array') {\n walkHint(`${path}[]`, obj.element as MsgSchemaField, out)\n }\n if (obj.kind === 'discriminated-union') {\n // Synthetic hint at the union's path summarizing the legal\n // discriminant values. Lets the agent see \"format expects one of:\n // exact, range, compound\" without walking the full schema. Then\n // walk each branch's per-field hints with a path-suffix that\n // disambiguates which branch the hint applies to.\n const variants = obj.variants as Record<string, Record<string, MsgSchemaField>>\n const discriminant = String(obj.discriminant)\n const legalValues = Object.keys(variants)\n if (legalValues.length > 0) {\n out.push({\n path,\n hint: `Discriminated union — set \\`${discriminant}\\` to one of: ${legalValues\n .map((v) => `'${v}'`)\n .join(', ')}.`,\n })\n }\n for (const [discValue, fields] of Object.entries(variants)) {\n for (const [fieldName, fieldDesc] of Object.entries(fields)) {\n walkHint(`${path}(${discriminant}=${discValue}).${fieldName}`, fieldDesc, out)\n }\n }\n }\n}\n\nfunction isOptional(d: MsgSchemaField): boolean {\n return typeof d === 'object' && 'type' in d && d.optional === true\n}\n\nfunction isShould(d: MsgSchemaField): 'should' | undefined {\n return typeof d === 'object' && 'type' in d ? d.priority : undefined\n}\n\nfunction exampleValue(d: MsgSchemaField): unknown {\n // Unwrap rich descriptor to get the bare type for synthesis.\n const t =\n typeof d === 'object' && 'type' in d\n ? d.type\n : (d as\n | Exclude<MsgSchemaField, object>\n | Extract<MsgSchemaField, { kind?: string; enum?: string[] }>)\n return synthesizeBare(t as never)\n}\n\nfunction synthesizeBare(t: unknown): unknown {\n if (typeof t === 'string') {\n if (t === 'string') return ''\n if (t === 'number') return 0\n if (t === 'boolean') return false\n return null // 'unknown' or unrecognized keyword → placeholder\n }\n if (t === null || typeof t !== 'object') return null\n const obj = t as Record<string, unknown>\n if ('enum' in obj && Array.isArray(obj.enum)) {\n // First option doubles as the canonical example. Native value type\n // round-trips (string/number/boolean) since the compiler preserved\n // the literal kind on emit.\n return obj.enum[0] ?? null\n }\n if (obj.kind === 'object' && obj.shape !== null && typeof obj.shape === 'object') {\n // Recurse into the nested shape. Same optional-skip rule as the\n // top-level synthesizer: required fields appear, optional ones\n // appear only when @should-flagged.\n const out: Record<string, unknown> = {}\n for (const [name, descriptor] of Object.entries(obj.shape as Record<string, MsgSchemaField>)) {\n const isOpt = isOptional(descriptor)\n const pri = isShould(descriptor)\n if (isOpt && pri !== 'should') continue\n out[name] = exampleValue(descriptor)\n }\n return out\n }\n if (obj.kind === 'array') {\n // Wrap the synthesized element in a one-item array. Lets the LLM\n // see the per-entry shape without us guessing at array length.\n return [synthesizeBare(obj.element)]\n }\n if (obj.kind === 'discriminated-union') {\n // Synthesize the FIRST branch as the concrete example. The full\n // shape (every legal branch + its payload) is preserved in\n // `description.messages.variants[X]` from `describe_app`, so the\n // agent that needs another branch reads the schema directly.\n // `collectFieldHints` adds a synthetic enumeration of the legal\n // `<discriminant>` values onto the hint surface so the agent\n // doesn't have to dig into the schema for the simple case.\n const variants = obj.variants as Record<string, Record<string, MsgSchemaField>>\n const discriminant = String(obj.discriminant)\n const firstEntry = Object.entries(variants).at(0)\n if (!firstEntry) return null\n const [firstValue, firstFields] = firstEntry\n const branch: Record<string, unknown> = { [discriminant]: firstValue }\n for (const [name, descriptor] of Object.entries(firstFields)) {\n const isOpt = isOptional(descriptor)\n const pri = isShould(descriptor)\n if (isOpt && pri !== 'should') continue\n branch[name] = exampleValue(descriptor)\n }\n return branch\n }\n return null\n}\n"]}
1
+ {"version":3,"file":"list-actions.js","sourceRoot":"","sources":["../../../src/client/rpc/list-actions.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MessageAnnotations } from '../../protocol.js'\nimport type { MsgSchemaShape, MsgSchemaField } from '../factory.js'\n\ntype Binding = { variant: string }\ntype Annotations = Record<string, MessageAnnotations>\n\nexport type ListActionsHost = {\n getState(): unknown\n getBindingDescriptors(): Binding[] | null\n getMsgAnnotations(): Annotations | null\n getMsgSchema(): MsgSchemaShape | null\n getAgentAffordances(): ((state: unknown) => Array<{ type: string; [k: string]: unknown }>) | null\n}\n\n/**\n * `dispatchMode` on each action is `'shared'` (human can also click via\n * a UI affordance) or `'agent-only'` (no UI binding — agent is the only\n * dispatcher). `'human-only'` variants are filtered out before this\n * point — they never reach the LLM.\n *\n * `source` distinguishes WHERE the affordance came from:\n * - `'binding'` — a tagged event handler is currently mounted in a\n * live scope (refcount > 0). Variants inside dead branches —\n * `show({when: false})`, unmounted `branch()` cases, removed `each`\n * items — auto-vanish from this set as their lifetimes dispose.\n * This is the framework's \"what can the user click right now\"\n * answer, and it's the default surface for the agent.\n * - `'always-affordable'` — either the app's `agentAffordances(state)`\n * hook listed the variant, or the variant carries the\n * `@alwaysAffordable` JSDoc tag. Both are the explicit \"agent can\n * reach this even when no live UI binding maps to it\" knob — bulk\n * seed ops (`Matrix/AddAlternatives`) and similar agent-driven\n * paths typically land here.\n * - `'schema'` — variant is annotated `@agentOnly` (the canonical\n * \"no UI button maps to this; the agent is the only dispatcher\")\n * and isn't already covered above. The payload is schema-synthesized\n * and the agent fills it in.\n *\n * `'shared'` variants WITHOUT a live binding, without\n * `agentAffordances` mention, and without `@alwaysAffordable` are\n * **deliberately hidden**. They're reachable through UI navigation —\n * the human user can't click them right now, and dispatching them\n * blindly would mutate state that drives `show()`/`branch()` gates,\n * popping hidden UI subtrees into view in places the user didn't\n * navigate to.\n */\nexport type ListActionsResult = {\n actions: Array<{\n variant: string\n /**\n * Human-readable phrase from `@intent(\"…\")`, or `null` when the\n * variant is unannotated. Mirror of LapActionsResponse.intent —\n * callers should treat `null` as a documentation gap and not as\n * \"missing label, fall back to variant name\".\n */\n intent: string | null\n requiresConfirm: boolean\n dispatchMode: 'shared' | 'agent-only'\n source: 'binding' | 'always-affordable' | 'schema'\n selectorHint: string | null\n payloadHint: object | null\n /** Cautionary text from `@warning` JSDoc, or null. */\n warning: string | null\n /** Concrete examples from `@example` JSDoc, in source order. */\n examples: string[]\n /**\n * Effect kinds this variant emits, from `@emits(\"k1\", \"k2\")`.\n * Empty when not annotated. Lets the agent know what side\n * effects fire — useful for batching (\"100 dispatches × cloud-\n * save = bad\") and for confirming destructive flows.\n */\n emits: string[]\n /**\n * Per-field guidance lifted from `@should(\"…\")` JSDoc on payload\n * fields. Path is dot/bracket notation rooted at the payload\n * (e.g. `\"cells\"` for a top-level field, `\"cells[].meta\"` for an\n * array element's nested field). Useful when the field is typed\n * as `unknown` or as a polymorphic shape — the hint says \"type\n * matches the criterion's kind: number for quantity, …\" so the\n * agent doesn't have to guess from the bare schema.\n *\n * Empty when no field on this variant carries an `@should` hint.\n */\n fieldHints: Array<{ path: string; hint: string }>\n }>\n}\n\nexport function handleListActions(host: ListActionsHost): ListActionsResult {\n const annotations = host.getMsgAnnotations() ?? {}\n const state = host.getState()\n const descriptors = host.getBindingDescriptors() ?? []\n const affordancesFn = host.getAgentAffordances()\n const affordances = affordancesFn ? affordancesFn(state) : []\n // When the app provides `agentAffordances(state)`, it's opted into\n // explicit affordance control: only state-relevant Msgs are listed.\n // `@agentOnly` schema-source variants are then filtered to those the\n // hook returned — so a bulk-edit Msg like `Matrix/AddCriteria`\n // doesn't surface on the home page just because it's tagged\n // `@agentOnly`. Apps without `agentAffordances` keep the previous\n // permissive default (\"everything's available unless you say\n // otherwise\") since flipping that without explicit opt-in would\n // break consumers who rely on schema-source surfacing of\n // bulk Msgs.\n const explicitAffordances = affordancesFn !== null\n const affordanceVariants = new Set(affordances.map((m) => m.type))\n const schema = host.getMsgSchema()\n\n const out: ListActionsResult['actions'] = []\n const seen = new Set<string>()\n\n // From bindings — these have UI affordances by definition, so they're\n // either 'shared' (default) or, in the malformed case where someone\n // bound an `@agentOnly` Msg in a view, 'agent-only'. Either way the\n // agent can dispatch them.\n //\n // Filtered against the Msg schema: a binding whose variant isn't in\n // the user's Msg union is a library-internal Msg leaking through\n // `tagSend` translator wiring (the sortable component's `move`,\n // `drop`, `cancel`, etc. — they're routed into the user's update.ts\n // via a different shape but their lib names slip into the binding\n // registry). The agent has no use for those names — `would_dispatch`\n // / `send_message` would reject them as `unknown-variant` anyway —\n // so they pollute the affordance list. When a schema is available,\n // the schema's variant set is the source of truth.\n for (const d of descriptors) {\n if (schema && !(d.variant in schema.variants)) continue\n const ann = annotations[d.variant]\n if (ann?.dispatchMode === 'human-only') continue\n if (!passesRouteGate(ann, state)) continue\n seen.add(d.variant)\n const variantSchema = schema?.variants[d.variant]\n out.push({\n variant: d.variant,\n intent: ann?.intent ?? null,\n requiresConfirm: ann?.requiresConfirm ?? false,\n dispatchMode: ann?.dispatchMode === 'agent-only' ? 'agent-only' : 'shared',\n source: 'binding',\n selectorHint: null,\n payloadHint: null,\n warning: ann?.warning ?? null,\n examples: ann?.examples ?? [],\n emits: ann?.emits ?? [],\n fieldHints: variantSchema ? collectFieldHints(variantSchema) : [],\n })\n }\n\n // From `agentAffordances(state)` — the integrator's explicit list of\n // currently-reachable Msgs, with concrete payloads they author.\n for (const msg of affordances) {\n const ann = annotations[msg.type]\n if (ann?.dispatchMode === 'human-only') continue\n if (!passesRouteGate(ann, state)) continue\n seen.add(msg.type)\n const { type, ...rest } = msg\n const variantSchema = schema?.variants[type]\n out.push({\n variant: type,\n intent: ann?.intent ?? null,\n requiresConfirm: ann?.requiresConfirm ?? false,\n dispatchMode: ann?.dispatchMode === 'agent-only' ? 'agent-only' : 'shared',\n source: 'always-affordable',\n selectorHint: null,\n payloadHint: Object.keys(rest).length > 0 ? rest : null,\n warning: ann?.warning ?? null,\n examples: ann?.examples ?? [],\n emits: ann?.emits ?? [],\n fieldHints: variantSchema ? collectFieldHints(variantSchema) : [],\n })\n }\n\n // From `@alwaysAffordable` annotations — the per-variant equivalent\n // of `agentAffordances`. Variants tagged this way surface regardless\n // of whether a live binding maps to them, so bulk seed ops\n // (`Matrix/AddAlternatives`) and similar agent-driven paths are\n // available even when their UI counterparts (if any) aren't mounted.\n // The payload is schema-synthesized — `agentAffordances` is the way\n // to ship a concrete pre-filled payload alongside the affordance.\n for (const [variant, ann] of Object.entries(annotations)) {\n if (seen.has(variant)) continue\n if (ann.dispatchMode === 'human-only') continue\n if (!ann.alwaysAffordable) continue\n if (!passesRouteGate(ann, state)) continue\n seen.add(variant)\n const fields = schema?.variants[variant]\n out.push({\n variant,\n intent: ann.intent,\n requiresConfirm: ann.requiresConfirm,\n dispatchMode: ann.dispatchMode === 'agent-only' ? 'agent-only' : 'shared',\n source: 'always-affordable',\n selectorHint: null,\n payloadHint: fields ? synthesizePayload(variant, fields) : null,\n warning: ann.warning,\n examples: ann.examples,\n emits: ann.emits,\n fieldHints: fields ? collectFieldHints(fields) : [],\n })\n }\n\n // From schema — variants that aren't already surfaced above and that\n // the author marked `@agentOnly`. The canonical \"no UI button maps\n // to this; the agent is the only dispatcher.\" Bulk edits, imports,\n // admin operations that have no human-facing affordance at all.\n //\n // `'shared'` variants WITHOUT a live binding stay hidden here — they\n // are reachable through UI navigation, and dispatching them while\n // their UI subtree is unmounted would pop hidden state in places the\n // user didn't navigate to. The explicit knobs are `@alwaysAffordable`\n // (handled above) or `agentAffordances(state)`.\n //\n // When the app provides `agentAffordances`, this pass is filtered:\n // an `@agentOnly` variant only surfaces if the hook returned it.\n // That makes route-gated bulk Msgs (`Matrix/AddCriteria` available\n // only when a matrix is loaded) work as expected — they stop\n // appearing on the home page just because they're tagged\n // `@agentOnly`. Apps without `agentAffordances` keep the previous\n // permissive default.\n if (schema) {\n for (const [variant, fields] of Object.entries(schema.variants)) {\n if (seen.has(variant)) continue\n const ann = annotations[variant]\n if (ann?.dispatchMode !== 'agent-only') continue\n if (explicitAffordances && !affordanceVariants.has(variant)) continue\n if (!passesRouteGate(ann, state)) continue\n out.push({\n variant,\n intent: ann.intent,\n requiresConfirm: ann.requiresConfirm,\n dispatchMode: 'agent-only',\n source: 'schema',\n selectorHint: null,\n payloadHint: synthesizePayload(variant, fields),\n warning: ann.warning,\n examples: ann.examples,\n emits: ann.emits,\n fieldHints: collectFieldHints(fields),\n })\n }\n }\n\n return { actions: out }\n}\n\n/**\n * Build an example payload object the LLM can fill in. Required\n * fields always appear; optional fields appear only when annotated\n * `@should` (LLM is encouraged to fill them in). Fields without a\n * concrete primitive type (`'unknown'`) emit `null` placeholders the\n * LLM is expected to replace.\n *\n * The first key is `type` so the payload reads as a complete Msg\n * shape — copy-paste-ready into `send_message`.\n */\n/**\n * Evaluate `@routeGated(\"predicate\")` against the current state.\n * Returns true (variant passes) when:\n * - the variant has no `@routeGated` annotation, OR\n * - the predicate evaluates truthy with `state` bound.\n *\n * Predicate is compiled lazily via `new Function('state', 'return (' +\n * src + ')')` and cached in a module-level Map. Compile failures\n * (syntactically broken predicates) degrade to \"true\" so a single\n * malformed annotation doesn't paralyze the affordance pass — the\n * build-time linter is the right place to catch syntactic issues.\n * Evaluation throws fail-closed (return false) since a predicate that\n * crashes on the current state shouldn't surface the variant.\n */\nfunction passesRouteGate(ann: MessageAnnotations | undefined, state: unknown): boolean {\n const src = ann?.routeGate\n if (!src) return true\n const predicate = compileRouteGate(src)\n try {\n return Boolean(predicate(state))\n } catch {\n return false\n }\n}\n\nconst routeGateCache = new Map<string, (state: unknown) => boolean>()\nfunction compileRouteGate(src: string): (state: unknown) => boolean {\n let fn = routeGateCache.get(src)\n if (fn) return fn\n try {\n fn = new Function('state', `return (${src})`) as (state: unknown) => boolean\n } catch {\n fn = () => true\n }\n routeGateCache.set(src, fn)\n return fn\n}\n\nfunction synthesizePayload(variant: string, fields: Record<string, MsgSchemaField>): object {\n const out: Record<string, unknown> = { type: variant }\n for (const [name, descriptor] of Object.entries(fields)) {\n const optional = isOptional(descriptor)\n const priority = isShould(descriptor)\n // Skip optional fields unless they're @should-flagged. Required\n // fields always appear.\n if (optional && priority !== 'should') continue\n out[name] = exampleValue(descriptor)\n }\n return out\n}\n\n/**\n * Walk a variant's field tree and collect every `@should` hint into a\n * flat list keyed by field path. Path conventions:\n * - top-level field: `\"cells\"`\n * - nested object property: `\"cells.value\"`\n * - array element: `\"cells[]\"` for the element itself; descendants\n * use `\"cells[].meta\"` and so on.\n *\n * Surfaces the same hints that show up nested inside\n * `description.messages.variants[X].field.hint` so callers don't have\n * to dig through the schema tree to find them.\n */\nfunction collectFieldHints(\n fields: Record<string, MsgSchemaField>,\n): Array<{ path: string; hint: string }> {\n const out: Array<{ path: string; hint: string }> = []\n for (const [name, descriptor] of Object.entries(fields)) {\n walkHint(name, descriptor, out)\n }\n return out\n}\n\nfunction walkHint(\n path: string,\n d: MsgSchemaField,\n out: Array<{ path: string; hint: string }>,\n): void {\n // Rich descriptor with a hint at this position.\n if (typeof d === 'object' && d !== null && 'type' in d) {\n if (typeof d.hint === 'string' && d.hint.length > 0) {\n out.push({ path, hint: d.hint })\n }\n // `@validates(...)` predicates surface alongside `@should` hints\n // so the agent sees the constraint at affordance time rather than\n // only as a post-dispatch rejection. The verbatim predicate text\n // is what the runtime evaluates; agents trained on JS read it\n // directly. Prefix `validates: ` to disambiguate from freeform\n // `@should` text.\n if (typeof d.validates === 'string' && d.validates.length > 0) {\n out.push({ path, hint: `validates: ${d.validates}` })\n }\n walkHintBare(path, d.type, out)\n return\n }\n walkHintBare(path, d, out)\n}\n\nfunction walkHintBare(path: string, t: unknown, out: Array<{ path: string; hint: string }>): void {\n if (t === null || typeof t !== 'object') return\n const obj = t as Record<string, unknown>\n if (obj.kind === 'object' && obj.shape !== null && typeof obj.shape === 'object') {\n for (const [name, descriptor] of Object.entries(obj.shape as Record<string, MsgSchemaField>)) {\n walkHint(`${path}.${name}`, descriptor, out)\n }\n return\n }\n if (obj.kind === 'array') {\n walkHint(`${path}[]`, obj.element as MsgSchemaField, out)\n }\n if (obj.kind === 'discriminated-union') {\n // Synthetic hint at the union's path summarizing the legal\n // discriminant values. Lets the agent see \"format expects one of:\n // exact, range, compound\" without walking the full schema. Then\n // walk each branch's per-field hints with a path-suffix that\n // disambiguates which branch the hint applies to.\n const variants = obj.variants as Record<string, Record<string, MsgSchemaField>>\n const discriminant = String(obj.discriminant)\n const legalValues = Object.keys(variants)\n if (legalValues.length > 0) {\n out.push({\n path,\n hint: `Discriminated union — set \\`${discriminant}\\` to one of: ${legalValues\n .map((v) => `'${v}'`)\n .join(', ')}.`,\n })\n }\n for (const [discValue, fields] of Object.entries(variants)) {\n for (const [fieldName, fieldDesc] of Object.entries(fields)) {\n walkHint(`${path}(${discriminant}=${discValue}).${fieldName}`, fieldDesc, out)\n }\n }\n }\n}\n\nfunction isOptional(d: MsgSchemaField): boolean {\n return typeof d === 'object' && 'type' in d && d.optional === true\n}\n\nfunction isShould(d: MsgSchemaField): 'should' | undefined {\n return typeof d === 'object' && 'type' in d ? d.priority : undefined\n}\n\nfunction exampleValue(d: MsgSchemaField): unknown {\n // Unwrap rich descriptor to get the bare type for synthesis.\n const t =\n typeof d === 'object' && 'type' in d\n ? d.type\n : (d as\n | Exclude<MsgSchemaField, object>\n | Extract<MsgSchemaField, { kind?: string; enum?: string[] }>)\n return synthesizeBare(t as never)\n}\n\nfunction synthesizeBare(t: unknown): unknown {\n if (typeof t === 'string') {\n if (t === 'string') return ''\n if (t === 'number') return 0\n if (t === 'boolean') return false\n return null // 'unknown' or unrecognized keyword → placeholder\n }\n if (t === null || typeof t !== 'object') return null\n const obj = t as Record<string, unknown>\n if ('enum' in obj && Array.isArray(obj.enum)) {\n // First option doubles as the canonical example. Native value type\n // round-trips (string/number/boolean) since the compiler preserved\n // the literal kind on emit.\n return obj.enum[0] ?? null\n }\n if (obj.kind === 'object' && obj.shape !== null && typeof obj.shape === 'object') {\n // Recurse into the nested shape. Same optional-skip rule as the\n // top-level synthesizer: required fields appear, optional ones\n // appear only when @should-flagged.\n const out: Record<string, unknown> = {}\n for (const [name, descriptor] of Object.entries(obj.shape as Record<string, MsgSchemaField>)) {\n const isOpt = isOptional(descriptor)\n const pri = isShould(descriptor)\n if (isOpt && pri !== 'should') continue\n out[name] = exampleValue(descriptor)\n }\n return out\n }\n if (obj.kind === 'array') {\n // Wrap the synthesized element in a one-item array. Lets the LLM\n // see the per-entry shape without us guessing at array length.\n return [synthesizeBare(obj.element)]\n }\n if (obj.kind === 'discriminated-union') {\n // Synthesize the FIRST branch as the concrete example. The full\n // shape (every legal branch + its payload) is preserved in\n // `description.messages.variants[X]` from `describe_app`, so the\n // agent that needs another branch reads the schema directly.\n // `collectFieldHints` adds a synthetic enumeration of the legal\n // `<discriminant>` values onto the hint surface so the agent\n // doesn't have to dig into the schema for the simple case.\n const variants = obj.variants as Record<string, Record<string, MsgSchemaField>>\n const discriminant = String(obj.discriminant)\n const firstEntry = Object.entries(variants).at(0)\n if (!firstEntry) return null\n const [firstValue, firstFields] = firstEntry\n const branch: Record<string, unknown> = { [discriminant]: firstValue }\n for (const [name, descriptor] of Object.entries(firstFields)) {\n const isOpt = isOptional(descriptor)\n const pri = isShould(descriptor)\n if (isOpt && pri !== 'should') continue\n branch[name] = exampleValue(descriptor)\n }\n return branch\n }\n return null\n}\n"]}
@@ -60,7 +60,17 @@ function validateObjectShape(value, shape, pathPrefix, errors, warnings, policy)
60
60
  const optional = isOptional(descriptor);
61
61
  const fieldValue = present ? value[name] : undefined;
62
62
  if (!present || fieldValue === undefined) {
63
- if (!optional) {
63
+ // Treat `unknown`-typed fields as implicitly optional. The
64
+ // schema extractor emits `field: string | undefined` as a
65
+ // required field of type 'unknown' (the union isn't a branded
66
+ // primitive), but semantically the field accepts undefined —
67
+ // and the validator's stated philosophy is "treat 'unknown' as
68
+ // any goes; don't report errors against fields whose schema we
69
+ // don't know." Without this, agents are forced to spell out
70
+ // `details: undefined`, `url: undefined`, … on every Criterion
71
+ // they author, which is exactly the kind of fumble we built the
72
+ // payload hints to prevent.
73
+ if (!optional && fieldType(descriptor) !== 'unknown') {
64
74
  errors.push({
65
75
  path: fieldPath,
66
76
  code: 'missing',
@@ -257,7 +267,6 @@ function compilePredicate(src) {
257
267
  if (fn)
258
268
  return fn;
259
269
  try {
260
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
261
270
  fn = new Function('v', `return (${src})`);
262
271
  }
263
272
  catch {
@@ -1 +1 @@
1
- {"version":3,"file":"validate-payload.js","sourceRoot":"","sources":["../../../src/client/rpc/validate-payload.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MsgSchemaShape, MsgSchemaField, MsgSchemaBareType } from '../factory.js'\n\n/**\n * Schema-driven payload validation for agent-dispatched Msgs. Walks\n * the compiler-emitted schema against a candidate Msg and reports\n * structural errors with a path-keyed list — the kind of feedback an\n * LLM can act on in a single round trip (\"set kind to one of: 'exact',\n * 'range', 'compound'\") instead of probing one field at a time.\n *\n * **What this is not.** This is not a TS type-checker. The schema is\n * best-effort: cross-file types, generics, complex unions, and\n * conditional types still surface as `'unknown'` and the validator\n * accepts anything for those. The validator's job is to catch the\n * mistakes a schema-aware LLM makes — wrong enum values, missing\n * discriminants, primitive type mismatches — not to mirror the entire\n * TypeScript surface area.\n *\n * **Tolerance for `'unknown'`.** Treat `'unknown'` as \"any goes.\" Don't\n * report errors against fields whose schema we don't know — those are\n * the schema's gaps, not the agent's.\n */\n\nexport type ValidationError = {\n /**\n * Dot-bracket path rooted at the Msg payload (NOT including `type`).\n * - top-level field: `'cells'`\n * - nested object property: `'cells.value'`\n * - array element: `'cells[0]'` (concrete index from the input)\n * - discriminated-union branch: `'format(kind=range).max'` — the\n * parenthesised `<discriminant>=<value>` segment names which branch\n * the error applies to, distinguishing the same field name across\n * branches.\n */\n path: string\n code:\n | 'unknown-variant'\n | 'missing'\n | 'wrong-type'\n | 'not-in-enum'\n | 'not-array'\n | 'not-object'\n | 'missing-discriminant'\n | 'unknown-discriminant-value'\n | 'unexpected-field'\n | 'validates-failed'\n message: string\n}\n\nexport type ValidationWarning = {\n path: string\n code: 'untyped-field'\n message: string\n}\n\nexport type ValidationResult =\n | { ok: true; warnings?: ValidationWarning[] }\n | { ok: false; errors: ValidationError[]; warnings?: ValidationWarning[] }\n\nexport type ValidationOptions = {\n /**\n * `'strict'` rejects fields that aren't declared in the schema (typos,\n * extra keys, fields the LLM hallucinated). Also emits warnings when\n * the agent provides a value for a field whose schema is `'unknown'`\n * — the validator can't structurally check the value, so the warning\n * surfaces the gap to the LLM (\"we accepted this but didn't validate\n * it\"). `'lenient'` (default) accepts extras silently and treats\n * `'unknown'` as a passthrough.\n *\n * Strict mode pairs with the cross-file schema fidelity in\n * `@llui/vite-plugin`@0.0.36+: with most fields fully resolved, strict\n * is rarely surprising. Apps that haven't migrated yet may find\n * strict overzealous and should stay on lenient.\n */\n policy?: 'strict' | 'lenient'\n}\n\nexport function validatePayload(\n msg: unknown,\n schema: MsgSchemaShape | null,\n opts: ValidationOptions = {},\n): ValidationResult {\n if (msg === null || typeof msg !== 'object' || Array.isArray(msg)) {\n return {\n ok: false,\n errors: [{ path: '', code: 'not-object', message: 'msg must be a plain object' }],\n }\n }\n const m = msg as Record<string, unknown>\n const variantKey = m[schema?.discriminant ?? 'type']\n if (typeof variantKey !== 'string') {\n return {\n ok: false,\n errors: [\n {\n path: schema?.discriminant ?? 'type',\n code: 'missing',\n message: `msg.${schema?.discriminant ?? 'type'} must be a string variant tag`,\n },\n ],\n }\n }\n\n // No schema available — the compiler didn't emit one, or the LLM is\n // talking to a build that predates schema emission. Accept the msg\n // structurally; the reducer will validate semantically.\n if (!schema) return { ok: true }\n\n const variantSchema = schema.variants[variantKey]\n if (!variantSchema) {\n return {\n ok: false,\n errors: [\n {\n path: schema.discriminant,\n code: 'unknown-variant',\n message: `'${variantKey}' is not a known variant. Legal values: ${Object.keys(\n schema.variants,\n )\n .map((v) => `'${v}'`)\n .join(', ')}.`,\n },\n ],\n }\n }\n\n const errors: ValidationError[] = []\n const warnings: ValidationWarning[] = []\n const policy = opts.policy ?? 'lenient'\n const payload: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(m)) {\n if (k !== schema.discriminant) payload[k] = v\n }\n validateObjectShape(payload, variantSchema, '', errors, warnings, policy)\n if (errors.length === 0) {\n return warnings.length === 0 ? { ok: true } : { ok: true, warnings }\n }\n return warnings.length === 0 ? { ok: false, errors } : { ok: false, errors, warnings }\n}\n\nfunction validateObjectShape(\n value: Record<string, unknown>,\n shape: Record<string, MsgSchemaField>,\n pathPrefix: string,\n errors: ValidationError[],\n warnings: ValidationWarning[],\n policy: 'strict' | 'lenient',\n): void {\n for (const [name, descriptor] of Object.entries(shape)) {\n const fieldPath = pathPrefix === '' ? name : `${pathPrefix}.${name}`\n const present = Object.prototype.hasOwnProperty.call(value, name)\n const optional = isOptional(descriptor)\n const fieldValue = present ? value[name] : undefined\n\n if (!present || fieldValue === undefined) {\n if (!optional) {\n errors.push({\n path: fieldPath,\n code: 'missing',\n message: `required field is missing`,\n })\n }\n continue\n }\n\n const ft = fieldType(descriptor)\n if (ft === 'unknown' && policy === 'strict') {\n warnings.push({\n path: fieldPath,\n code: 'untyped-field',\n message: `value accepted but field schema is 'unknown' — the validator could not structurally check it. If this field is reachable across file boundaries, consider whether @llui/vite-plugin can resolve it.`,\n })\n }\n\n const errCountBefore = errors.length\n validateField(fieldValue, ft, fieldPath, errors, warnings, policy)\n const structurallyValid = errors.length === errCountBefore\n\n // Domain-invariant predicate (`@validates(\"expr\")`). Runs only\n // when structural validation passed for this field — without the\n // right shape, the predicate would either throw (and we'd have to\n // double-report) or accidentally pass (e.g. `v.length` on a string\n // when we expected a number array). Predicate failures are errors\n // regardless of policy — the author opted into the constraint\n // deliberately.\n if (structurallyValid) {\n const validates = fieldValidatesPredicate(descriptor)\n if (validates !== null) {\n const predicate = compilePredicate(validates)\n let passed: boolean\n try {\n passed = Boolean(predicate(fieldValue))\n } catch {\n passed = false\n }\n if (!passed) {\n errors.push({\n path: fieldPath,\n code: 'validates-failed',\n message: `value violates \\`@validates(\"${validates}\")\\``,\n })\n }\n }\n }\n }\n\n // Strict mode: reject fields the schema doesn't declare. Catches\n // typos (`{tile: 'X'}` instead of `{title: 'X'}`), hallucinated\n // fields, and stale field names from before a refactor. Lenient\n // mode accepts extras silently — same shape TypeScript's structural\n // subtyping accepts at the call site.\n if (policy === 'strict') {\n for (const key of Object.keys(value)) {\n if (key in shape) continue\n const fieldPath = pathPrefix === '' ? key : `${pathPrefix}.${key}`\n errors.push({\n path: fieldPath,\n code: 'unexpected-field',\n message: `field '${key}' is not in the schema. Legal fields: ${Object.keys(shape)\n .map((k) => `'${k}'`)\n .join(', ')}.`,\n })\n }\n }\n}\n\nfunction validateField(\n value: unknown,\n type: MsgSchemaBareType,\n path: string,\n errors: ValidationError[],\n warnings: ValidationWarning[],\n policy: 'strict' | 'lenient',\n): void {\n if (type === 'unknown') return // schema gap; accept anything\n if (typeof type === 'string') {\n // Primitive keyword: 'string', 'number', 'boolean'.\n if (typeof value !== type) {\n errors.push({\n path,\n code: 'wrong-type',\n message: `expected ${type}, got ${describeType(value)}`,\n })\n }\n return\n }\n if ('enum' in type) {\n // Use Object.is so NaN and -0 match correctly; falls back to ===\n // semantics for ordinary values.\n const ok = type.enum.some((legal) => Object.is(legal, value) || legal === value)\n if (!ok) {\n errors.push({\n path,\n code: 'not-in-enum',\n message: `'${String(value)}' is not in the enum. Legal values: ${type.enum\n .map((v) => formatEnumValue(v))\n .join(', ')}.`,\n })\n }\n return\n }\n if (type.kind === 'object') {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n errors.push({\n path,\n code: 'not-object',\n message: `expected object, got ${describeType(value)}`,\n })\n return\n }\n validateObjectShape(\n value as Record<string, unknown>,\n type.shape,\n path,\n errors,\n warnings,\n policy,\n )\n return\n }\n if (type.kind === 'array') {\n if (!Array.isArray(value)) {\n errors.push({\n path,\n code: 'not-array',\n message: `expected array, got ${describeType(value)}`,\n })\n return\n }\n for (let i = 0; i < value.length; i++) {\n validateField(value[i], type.element, `${path}[${i}]`, errors, warnings, policy)\n }\n return\n }\n if (type.kind === 'discriminated-union') {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n errors.push({\n path,\n code: 'not-object',\n message: `expected discriminated-union object, got ${describeType(value)}`,\n })\n return\n }\n const obj = value as Record<string, unknown>\n const discValue = obj[type.discriminant]\n if (typeof discValue !== 'string') {\n errors.push({\n path: `${path}.${type.discriminant}`,\n code: 'missing-discriminant',\n message: `discriminant '${type.discriminant}' must be one of: ${Object.keys(type.variants)\n .map((v) => `'${v}'`)\n .join(', ')}`,\n })\n return\n }\n const branchSchema = type.variants[discValue]\n if (!branchSchema) {\n errors.push({\n path: `${path}.${type.discriminant}`,\n code: 'unknown-discriminant-value',\n message: `'${discValue}' is not a legal '${type.discriminant}'. Legal values: ${Object.keys(\n type.variants,\n )\n .map((v) => `'${v}'`)\n .join(', ')}.`,\n })\n return\n }\n // Recurse into the matched branch's payload (excluding the\n // discriminant itself, which is already validated above).\n const branchPayload: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(obj)) {\n if (k !== type.discriminant) branchPayload[k] = v\n }\n const branchPath = `${path}(${type.discriminant}=${discValue})`\n validateObjectShape(branchPayload, branchSchema, branchPath, errors, warnings, policy)\n }\n}\n\nfunction isOptional(d: MsgSchemaField): boolean {\n return typeof d === 'object' && d !== null && 'type' in d && d.optional === true\n}\n\nfunction fieldType(d: MsgSchemaField): MsgSchemaBareType {\n if (typeof d === 'object' && d !== null && 'type' in d) return d.type\n return d\n}\n\nfunction fieldValidatesPredicate(d: MsgSchemaField): string | null {\n if (typeof d === 'object' && d !== null && 'type' in d && typeof d.validates === 'string') {\n return d.validates\n }\n return null\n}\n\nconst predicateCache = new Map<string, (v: unknown) => boolean>()\n\n/**\n * Compile a `@validates(...)` predicate string into a runtime function.\n * Caches across calls — the schema is static at runtime, so each\n * predicate is compiled at most once.\n *\n * The predicate sees `v` as the field's value and inherits the host\n * environment's globals (Math, JSON, RegExp, etc.). On any compile\n * error, returns a no-op `() => true` so a malformed predicate doesn't\n * break dispatch — the build-time linter (`agent-validates-syntax`,\n * future) is the right place to catch syntactic issues.\n */\nfunction compilePredicate(src: string): (v: unknown) => boolean {\n let fn = predicateCache.get(src)\n if (fn) return fn\n try {\n // eslint-disable-next-line @typescript-eslint/no-implied-eval\n fn = new Function('v', `return (${src})`) as (v: unknown) => boolean\n } catch {\n fn = () => true\n }\n predicateCache.set(src, fn)\n return fn\n}\n\nfunction describeType(v: unknown): string {\n if (v === null) return 'null'\n if (Array.isArray(v)) return 'array'\n return typeof v\n}\n\nfunction formatEnumValue(v: string | number | boolean): string {\n return typeof v === 'string' ? `'${v}'` : String(v)\n}\n"]}
1
+ {"version":3,"file":"validate-payload.js","sourceRoot":"","sources":["../../../src/client/rpc/validate-payload.ts"],"names":[],"mappings":"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","sourcesContent":["import type { MsgSchemaShape, MsgSchemaField, MsgSchemaBareType } from '../factory.js'\n\n/**\n * Schema-driven payload validation for agent-dispatched Msgs. Walks\n * the compiler-emitted schema against a candidate Msg and reports\n * structural errors with a path-keyed list — the kind of feedback an\n * LLM can act on in a single round trip (\"set kind to one of: 'exact',\n * 'range', 'compound'\") instead of probing one field at a time.\n *\n * **What this is not.** This is not a TS type-checker. The schema is\n * best-effort: cross-file types, generics, complex unions, and\n * conditional types still surface as `'unknown'` and the validator\n * accepts anything for those. The validator's job is to catch the\n * mistakes a schema-aware LLM makes — wrong enum values, missing\n * discriminants, primitive type mismatches — not to mirror the entire\n * TypeScript surface area.\n *\n * **Tolerance for `'unknown'`.** Treat `'unknown'` as \"any goes.\" Don't\n * report errors against fields whose schema we don't know — those are\n * the schema's gaps, not the agent's.\n */\n\nexport type ValidationError = {\n /**\n * Dot-bracket path rooted at the Msg payload (NOT including `type`).\n * - top-level field: `'cells'`\n * - nested object property: `'cells.value'`\n * - array element: `'cells[0]'` (concrete index from the input)\n * - discriminated-union branch: `'format(kind=range).max'` — the\n * parenthesised `<discriminant>=<value>` segment names which branch\n * the error applies to, distinguishing the same field name across\n * branches.\n */\n path: string\n code:\n | 'unknown-variant'\n | 'missing'\n | 'wrong-type'\n | 'not-in-enum'\n | 'not-array'\n | 'not-object'\n | 'missing-discriminant'\n | 'unknown-discriminant-value'\n | 'unexpected-field'\n | 'validates-failed'\n message: string\n}\n\nexport type ValidationWarning = {\n path: string\n code: 'untyped-field'\n message: string\n}\n\nexport type ValidationResult =\n | { ok: true; warnings?: ValidationWarning[] }\n | { ok: false; errors: ValidationError[]; warnings?: ValidationWarning[] }\n\nexport type ValidationOptions = {\n /**\n * `'strict'` rejects fields that aren't declared in the schema (typos,\n * extra keys, fields the LLM hallucinated). Also emits warnings when\n * the agent provides a value for a field whose schema is `'unknown'`\n * — the validator can't structurally check the value, so the warning\n * surfaces the gap to the LLM (\"we accepted this but didn't validate\n * it\"). `'lenient'` (default) accepts extras silently and treats\n * `'unknown'` as a passthrough.\n *\n * Strict mode pairs with the cross-file schema fidelity in\n * `@llui/vite-plugin`@0.0.36+: with most fields fully resolved, strict\n * is rarely surprising. Apps that haven't migrated yet may find\n * strict overzealous and should stay on lenient.\n */\n policy?: 'strict' | 'lenient'\n}\n\nexport function validatePayload(\n msg: unknown,\n schema: MsgSchemaShape | null,\n opts: ValidationOptions = {},\n): ValidationResult {\n if (msg === null || typeof msg !== 'object' || Array.isArray(msg)) {\n return {\n ok: false,\n errors: [{ path: '', code: 'not-object', message: 'msg must be a plain object' }],\n }\n }\n const m = msg as Record<string, unknown>\n const variantKey = m[schema?.discriminant ?? 'type']\n if (typeof variantKey !== 'string') {\n return {\n ok: false,\n errors: [\n {\n path: schema?.discriminant ?? 'type',\n code: 'missing',\n message: `msg.${schema?.discriminant ?? 'type'} must be a string variant tag`,\n },\n ],\n }\n }\n\n // No schema available — the compiler didn't emit one, or the LLM is\n // talking to a build that predates schema emission. Accept the msg\n // structurally; the reducer will validate semantically.\n if (!schema) return { ok: true }\n\n const variantSchema = schema.variants[variantKey]\n if (!variantSchema) {\n return {\n ok: false,\n errors: [\n {\n path: schema.discriminant,\n code: 'unknown-variant',\n message: `'${variantKey}' is not a known variant. Legal values: ${Object.keys(\n schema.variants,\n )\n .map((v) => `'${v}'`)\n .join(', ')}.`,\n },\n ],\n }\n }\n\n const errors: ValidationError[] = []\n const warnings: ValidationWarning[] = []\n const policy = opts.policy ?? 'lenient'\n const payload: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(m)) {\n if (k !== schema.discriminant) payload[k] = v\n }\n validateObjectShape(payload, variantSchema, '', errors, warnings, policy)\n if (errors.length === 0) {\n return warnings.length === 0 ? { ok: true } : { ok: true, warnings }\n }\n return warnings.length === 0 ? { ok: false, errors } : { ok: false, errors, warnings }\n}\n\nfunction validateObjectShape(\n value: Record<string, unknown>,\n shape: Record<string, MsgSchemaField>,\n pathPrefix: string,\n errors: ValidationError[],\n warnings: ValidationWarning[],\n policy: 'strict' | 'lenient',\n): void {\n for (const [name, descriptor] of Object.entries(shape)) {\n const fieldPath = pathPrefix === '' ? name : `${pathPrefix}.${name}`\n const present = Object.prototype.hasOwnProperty.call(value, name)\n const optional = isOptional(descriptor)\n const fieldValue = present ? value[name] : undefined\n\n if (!present || fieldValue === undefined) {\n // Treat `unknown`-typed fields as implicitly optional. The\n // schema extractor emits `field: string | undefined` as a\n // required field of type 'unknown' (the union isn't a branded\n // primitive), but semantically the field accepts undefined —\n // and the validator's stated philosophy is \"treat 'unknown' as\n // any goes; don't report errors against fields whose schema we\n // don't know.\" Without this, agents are forced to spell out\n // `details: undefined`, `url: undefined`, … on every Criterion\n // they author, which is exactly the kind of fumble we built the\n // payload hints to prevent.\n if (!optional && fieldType(descriptor) !== 'unknown') {\n errors.push({\n path: fieldPath,\n code: 'missing',\n message: `required field is missing`,\n })\n }\n continue\n }\n\n const ft = fieldType(descriptor)\n if (ft === 'unknown' && policy === 'strict') {\n warnings.push({\n path: fieldPath,\n code: 'untyped-field',\n message: `value accepted but field schema is 'unknown' — the validator could not structurally check it. If this field is reachable across file boundaries, consider whether @llui/vite-plugin can resolve it.`,\n })\n }\n\n const errCountBefore = errors.length\n validateField(fieldValue, ft, fieldPath, errors, warnings, policy)\n const structurallyValid = errors.length === errCountBefore\n\n // Domain-invariant predicate (`@validates(\"expr\")`). Runs only\n // when structural validation passed for this field — without the\n // right shape, the predicate would either throw (and we'd have to\n // double-report) or accidentally pass (e.g. `v.length` on a string\n // when we expected a number array). Predicate failures are errors\n // regardless of policy — the author opted into the constraint\n // deliberately.\n if (structurallyValid) {\n const validates = fieldValidatesPredicate(descriptor)\n if (validates !== null) {\n const predicate = compilePredicate(validates)\n let passed: boolean\n try {\n passed = Boolean(predicate(fieldValue))\n } catch {\n passed = false\n }\n if (!passed) {\n errors.push({\n path: fieldPath,\n code: 'validates-failed',\n message: `value violates \\`@validates(\"${validates}\")\\``,\n })\n }\n }\n }\n }\n\n // Strict mode: reject fields the schema doesn't declare. Catches\n // typos (`{tile: 'X'}` instead of `{title: 'X'}`), hallucinated\n // fields, and stale field names from before a refactor. Lenient\n // mode accepts extras silently — same shape TypeScript's structural\n // subtyping accepts at the call site.\n if (policy === 'strict') {\n for (const key of Object.keys(value)) {\n if (key in shape) continue\n const fieldPath = pathPrefix === '' ? key : `${pathPrefix}.${key}`\n errors.push({\n path: fieldPath,\n code: 'unexpected-field',\n message: `field '${key}' is not in the schema. Legal fields: ${Object.keys(shape)\n .map((k) => `'${k}'`)\n .join(', ')}.`,\n })\n }\n }\n}\n\nfunction validateField(\n value: unknown,\n type: MsgSchemaBareType,\n path: string,\n errors: ValidationError[],\n warnings: ValidationWarning[],\n policy: 'strict' | 'lenient',\n): void {\n if (type === 'unknown') return // schema gap; accept anything\n if (typeof type === 'string') {\n // Primitive keyword: 'string', 'number', 'boolean'.\n if (typeof value !== type) {\n errors.push({\n path,\n code: 'wrong-type',\n message: `expected ${type}, got ${describeType(value)}`,\n })\n }\n return\n }\n if ('enum' in type) {\n // Use Object.is so NaN and -0 match correctly; falls back to ===\n // semantics for ordinary values.\n const ok = type.enum.some((legal) => Object.is(legal, value) || legal === value)\n if (!ok) {\n errors.push({\n path,\n code: 'not-in-enum',\n message: `'${String(value)}' is not in the enum. Legal values: ${type.enum\n .map((v) => formatEnumValue(v))\n .join(', ')}.`,\n })\n }\n return\n }\n if (type.kind === 'object') {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n errors.push({\n path,\n code: 'not-object',\n message: `expected object, got ${describeType(value)}`,\n })\n return\n }\n validateObjectShape(\n value as Record<string, unknown>,\n type.shape,\n path,\n errors,\n warnings,\n policy,\n )\n return\n }\n if (type.kind === 'array') {\n if (!Array.isArray(value)) {\n errors.push({\n path,\n code: 'not-array',\n message: `expected array, got ${describeType(value)}`,\n })\n return\n }\n for (let i = 0; i < value.length; i++) {\n validateField(value[i], type.element, `${path}[${i}]`, errors, warnings, policy)\n }\n return\n }\n if (type.kind === 'discriminated-union') {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n errors.push({\n path,\n code: 'not-object',\n message: `expected discriminated-union object, got ${describeType(value)}`,\n })\n return\n }\n const obj = value as Record<string, unknown>\n const discValue = obj[type.discriminant]\n if (typeof discValue !== 'string') {\n errors.push({\n path: `${path}.${type.discriminant}`,\n code: 'missing-discriminant',\n message: `discriminant '${type.discriminant}' must be one of: ${Object.keys(type.variants)\n .map((v) => `'${v}'`)\n .join(', ')}`,\n })\n return\n }\n const branchSchema = type.variants[discValue]\n if (!branchSchema) {\n errors.push({\n path: `${path}.${type.discriminant}`,\n code: 'unknown-discriminant-value',\n message: `'${discValue}' is not a legal '${type.discriminant}'. Legal values: ${Object.keys(\n type.variants,\n )\n .map((v) => `'${v}'`)\n .join(', ')}.`,\n })\n return\n }\n // Recurse into the matched branch's payload (excluding the\n // discriminant itself, which is already validated above).\n const branchPayload: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(obj)) {\n if (k !== type.discriminant) branchPayload[k] = v\n }\n const branchPath = `${path}(${type.discriminant}=${discValue})`\n validateObjectShape(branchPayload, branchSchema, branchPath, errors, warnings, policy)\n }\n}\n\nfunction isOptional(d: MsgSchemaField): boolean {\n return typeof d === 'object' && d !== null && 'type' in d && d.optional === true\n}\n\nfunction fieldType(d: MsgSchemaField): MsgSchemaBareType {\n if (typeof d === 'object' && d !== null && 'type' in d) return d.type\n return d\n}\n\nfunction fieldValidatesPredicate(d: MsgSchemaField): string | null {\n if (typeof d === 'object' && d !== null && 'type' in d && typeof d.validates === 'string') {\n return d.validates\n }\n return null\n}\n\nconst predicateCache = new Map<string, (v: unknown) => boolean>()\n\n/**\n * Compile a `@validates(...)` predicate string into a runtime function.\n * Caches across calls — the schema is static at runtime, so each\n * predicate is compiled at most once.\n *\n * The predicate sees `v` as the field's value and inherits the host\n * environment's globals (Math, JSON, RegExp, etc.). On any compile\n * error, returns a no-op `() => true` so a malformed predicate doesn't\n * break dispatch — the build-time linter (`agent-validates-syntax`,\n * future) is the right place to catch syntactic issues.\n */\nfunction compilePredicate(src: string): (v: unknown) => boolean {\n let fn = predicateCache.get(src)\n if (fn) return fn\n try {\n fn = new Function('v', `return (${src})`) as (v: unknown) => boolean\n } catch {\n fn = () => true\n }\n predicateCache.set(src, fn)\n return fn\n}\n\nfunction describeType(v: unknown): string {\n if (v === null) return 'null'\n if (Array.isArray(v)) return 'array'\n return typeof v\n}\n\nfunction formatEnumValue(v: string | number | boolean): string {\n return typeof v === 'string' ? `'${v}'` : String(v)\n}\n"]}
@@ -51,6 +51,16 @@ export type MessageAnnotations = {
51
51
  * annotated it yet.
52
52
  */
53
53
  emits: string[];
54
+ /**
55
+ * Boolean predicate authored as `@routeGated("expr")` JSDoc, with
56
+ * `state` bound at evaluation time. The variant only surfaces in
57
+ * `list_actions` when the predicate returns true. Compile-time
58
+ * alternative to `agentAffordances(state) => Msg[]` for the common
59
+ * case of "this Msg is reachable when state.X looks like Y." Null
60
+ * when the variant has no `@routeGated` tag (default affordance
61
+ * behavior applies).
62
+ */
63
+ routeGate?: string | null;
54
64
  };
55
65
  export type MessageSchemaEntry = {
56
66
  payloadSchema: object;
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,mEAAmE;AACnE,iEAAiE;AACjE,iEAAiE;AAshBjE,qEAAqE;AACrE,EAAE;AACF,qEAAqE;AACrE,4DAA4D;AAC5D,mEAAmE;AACnE,qCAAqC;AAErC,OAAO,EACL,QAAQ,EACR,UAAU,EACV,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,cAAc,GAEf,MAAM,aAAa,CAAA","sourcesContent":["// ── LAP — LLui Agent Protocol ────────────────────────────────────\n// JSON over HTTPS between the llui-agent bridge (MCP side) and the\n// @llui/agent server library mounted in the developer's backend.\n// See docs/superpowers/specs/2026-04-19-llui-agent-design.md §7.\n\nexport type LapErrorCode =\n | 'auth-failed'\n | 'revoked'\n | 'paused'\n | 'rate-limited'\n | 'invalid'\n | 'schema-error'\n | 'timeout'\n | 'internal'\n\nexport type LapError = {\n error: {\n code: LapErrorCode\n detail?: string\n retryAfterMs?: number\n }\n}\n\n/**\n * Who can dispatch a Msg variant.\n *\n * - `'shared'` (default) — both UI bindings and the agent can dispatch.\n * - `'human-only'` — UI-only. Agent calls to `/message` for these variants\n * are rejected with `LapMessageRejectReason: 'human-only'`. Use for\n * internal UI events (focus/blur, scroll, hover) the LLM has no business\n * triggering.\n * - `'agent-only'` — no UI binding exists. Reserved for LLM-driven flows\n * like batch operations or \"explain this state\" introspection variants.\n * Lint warns if a view references one via `send({ type: 'X' })`.\n *\n * JSDoc sugar: `@humanOnly` → `'human-only'`, `@agentOnly` → `'agent-only'`.\n * Absence of either tag → `'shared'`. The two tags are mutually exclusive\n * (enforced by `llui/agent-exclusive-annotations` ESLint rule).\n */\nexport type DispatchMode = 'shared' | 'human-only' | 'agent-only'\n\nexport type MessageAnnotations = {\n intent: string | null\n alwaysAffordable: boolean\n requiresConfirm: boolean\n dispatchMode: DispatchMode\n /**\n * Concrete copy-paste example dispatches authored as `@example`\n * JSDoc tags. Multiple tags on one variant become multiple\n * entries (mix typical / edge cases without nesting strings).\n */\n examples: string[]\n /**\n * Non-blocking caution authored as `@warning`. Distinct from\n * `requiresConfirm` (runtime user gate); this informs the LLM at\n * affordance time so it can decide whether the dispatch's\n * downstream is acceptable.\n */\n warning: string | null\n /**\n * Effect kinds this variant emits when dispatched, declared via\n * `@emits(\"kind1\", \"kind2\")`. Lets the agent reason about side\n * effects (cloud writes, analytics, persistent state changes)\n * before dispatching, and chunk multi-step flows accordingly\n * (\"don't dispatch X 100 times — each one fires cloud/save\").\n * Empty when the variant doesn't emit effects or the author hasn't\n * annotated it yet.\n */\n emits: string[]\n}\n\nexport type MessageSchemaEntry = {\n payloadSchema: object\n annotations: MessageAnnotations\n}\n\nexport type LapDescribeResponse = {\n name: string\n version: string\n stateSchema: object\n messages: Record<string, MessageSchemaEntry>\n docs: AgentDocs | null\n conventions: {\n dispatchModel: 'TEA'\n confirmationModel: 'runtime-mediated'\n readSurfaces: readonly (\n | 'state'\n | 'query_dom'\n | 'describe_visible_content'\n | 'describe_context'\n )[]\n }\n schemaHash: string\n}\n\nexport type LapStateRequest = { path?: string }\nexport type LapStateResponse = { state: unknown }\n\nexport type LapActionsResponse = {\n actions: Array<{\n variant: string\n /**\n * Human-readable phrase from `@intent(\"…\")`, or `null` when the\n * variant has no `@intent` annotation. Callers that surface\n * affordances to an LLM should treat `null` as \"this action is\n * undocumented\" — neither synthesise a label from the variant name\n * nor invent one. Pre-`@intent` variants would previously surface\n * as `intent: \"<variant>\"` here, which made unannotated actions\n * indistinguishable from properly-labelled ones; emitting `null`\n * keeps the gap visible.\n */\n intent: string | null\n requiresConfirm: boolean\n /**\n * `'shared'` — both UI and agent can dispatch. `'agent-only'` — no UI\n * binding exists; the agent is the sole dispatcher. `'human-only'`\n * variants never appear here (filtered before serialization).\n */\n dispatchMode: 'shared' | 'agent-only'\n /**\n * Where this affordance came from:\n * - `'binding'` — a tagged event handler is currently\n * mounted in the rendered DOM.\n * - `'always-affordable'` — the app's `agentAffordances(state)`\n * hook listed it as available right now.\n * - `'schema'` — neither of the above; the variant\n * is in the Msg union and annotated `@agentOnly`. The\n * `payloadHint` carries a synthesized example from the\n * compiler-derived field types — copy-paste-ready for\n * `send_message`. Bulk-edit operations land here.\n */\n source: 'binding' | 'always-affordable' | 'schema'\n selectorHint: string | null\n payloadHint: object | null\n /** Cautionary text from `@warning` JSDoc, or null. */\n warning: string | null\n /** Concrete examples from `@example` JSDoc, in source order. */\n examples: string[]\n /**\n * Effect kinds this variant emits, from `@emits(\"k1\", \"k2\")`.\n * Empty when not annotated.\n */\n emits: string[]\n /**\n * Per-field guidance lifted from `@should(\"…\")` JSDoc on payload\n * fields. Path is dot/bracket notation rooted at the payload (e.g.\n * `\"cells[].meta\"`). Surfaces hints that would otherwise be buried\n * inside the schema tree, so callers can read them alongside\n * `examples` without diving into `description.messages.variants`.\n */\n fieldHints: Array<{ path: string; hint: string }>\n }>\n}\n\nexport type LapMessageRequest = {\n msg: { type: string; [k: string]: unknown }\n reason?: string\n /**\n * Backpressure contract for how long `/message` waits before returning:\n * - `drained` (default): dispatch, then loop until the message queue is\n * idle for `drainQuietMs` ms or the 5s hard cap trips. Captures any\n * effect round-trips (http/delay/debounce) that feed back as messages.\n * - `idle`: dispatch + flush + one microtask yield. Captures the\n * synchronous update cycle but not async effects.\n * - `none`: dispatch and return without flushing. For high-throughput\n * fire-and-forget dispatch.\n */\n waitFor?: 'drained' | 'idle' | 'none'\n /**\n * Quiescence window when `waitFor === 'drained'`. Drain completes when\n * no new update cycle fires for this many ms. Default 100ms — long\n * enough for a localhost HTTP round-trip, short enough to be\n * imperceptible. Ignored for `idle` / `none`.\n */\n drainQuietMs?: number\n /**\n * Hard cap on total wait time. When `waitFor === 'drained'`, this is\n * the upper bound on how long the drain loop can run; if reached, the\n * response carries `drain.timedOut: true` with partial results. For\n * `pending-confirmation` messages, this is how long to wait for\n * the user's confirm/reject. Default 5_000ms.\n */\n timeoutMs?: number\n /**\n * Include the full post-drain `stateAfter` snapshot in the response.\n * Default `false` — the response carries `stateDiff` only and the\n * caller applies it to the prior snapshot (from connect/observe). For\n * apps with non-trivial state, the diff is orders of magnitude\n * smaller than the full state, and resending the snapshot on every\n * dispatch wastes bandwidth and (for LLM callers) context budget.\n *\n * Set `true` when the caller doesn't track state incrementally and\n * wants the snapshot back. The legacy `confirmed` and `wait` paths\n * always carry `stateAfter` because their flow is asynchronous and\n * a diff would be ambiguous.\n */\n includeState?: boolean\n}\n\nexport type LapMessageRejectReason =\n | 'human-only'\n | 'user-cancelled'\n | 'timeout'\n | 'invalid'\n | 'schema-error'\n | 'revoked'\n | 'paused'\n\n/**\n * Drain metadata attached to `dispatched` / `confirmed` responses.\n * `effectsObserved` counts update-cycle commits (not individual effects) —\n * it's a proxy for \"how much activity happened during the drain window.\"\n * `errors` surfaces sync throws from `onEffect` and unhandled rejections\n * from effect handlers that fired during the drain window, so the LLM\n * can see when an HTTP handler crashed silently.\n *\n * `warnings` surfaces non-blocking observations from the schema\n * validator — typically `untyped-field` flags raised in strict mode\n * when the agent provided a value for an `'unknown'`-typed field. The\n * dispatch landed (we accepted the value) but the validator couldn't\n * structurally check it, so the agent learns of the gap and can\n * tighten the next try if needed. Lenient mode never emits warnings;\n * the field is omitted in that case.\n */\nexport type LapDrainMeta = {\n effectsObserved: number\n durationMs: number\n timedOut: boolean\n errors: Array<{ kind: 'error' | 'unhandledrejection'; message: string; stack?: string }>\n warnings?: Array<{ path: string; code: string; message: string }>\n}\n\nexport type LapMessageResponse =\n | {\n status: 'dispatched'\n /**\n * Full post-drain state snapshot. Present only when the caller\n * passed `includeState: true` in the request — by default,\n * `stateDiff` is the only state-shaped field on the response\n * because callers can apply the diff to the prior snapshot from\n * `connect` / `observe`. See `LapMessageRequest.includeState`.\n */\n stateAfter?: unknown\n /**\n * Structural diff from pre-dispatch state to post-drain state,\n * in JSON-Patch shape (RFC 6902 subset: `add`, `remove`,\n * `replace`). Empty when the dispatch produced no observable\n * state change. The default state surface for callers — apply\n * incrementally to the snapshot from `connect`/`observe`.\n */\n stateDiff: import('./state-diff.js').StateDiff\n actions: LapActionsResponse['actions']\n drain: LapDrainMeta\n }\n | { status: 'pending-confirmation'; confirmId: string }\n | {\n /**\n * The user approved a `pending-confirmation` message. `stateAfter`\n * is the state snapshot captured when the approve was resolved;\n * effects produced by the approved dispatch may still be in\n * flight. The LLM should follow up with an `observe` call to\n * pick up a drained view and fresh actions — by design the\n * confirm path doesn't carry drain semantics because approval\n * can arrive arbitrarily later than the original request.\n */\n status: 'confirmed'\n stateAfter: unknown\n }\n | { status: 'rejected'; reason: LapMessageRejectReason; detail?: string }\n\nexport type LapConfirmResultRequest = { confirmId: string; timeoutMs?: number }\nexport type LapConfirmResultResponse =\n | { status: 'confirmed'; stateAfter: unknown }\n | { status: 'rejected'; reason: 'user-cancelled' | 'timeout' }\n | { status: 'still-pending' }\n\nexport type LapWaitRequest = { path?: string; timeoutMs?: number }\nexport type LapWaitResponse =\n | { status: 'changed'; stateAfter: unknown }\n | { status: 'timeout'; stateAfter: unknown }\n\nexport type LapQueryDomRequest = { name: string; multiple?: boolean }\nexport type LapQueryDomResponse = {\n elements: Array<{ text: string; attrs: Record<string, string>; path: number[] }>\n}\n\nexport type OutlineNode =\n | { kind: 'heading'; level: number; text: string }\n | { kind: 'text'; text: string }\n | { kind: 'list'; items: OutlineNode[] }\n | { kind: 'item'; text: string; children?: OutlineNode[] }\n | { kind: 'button'; text: string; disabled: boolean; actionVariant: string | null }\n | { kind: 'input'; label: string | null; value: string | null; type: string }\n | { kind: 'link'; text: string; href: string }\n\nexport type LapDescribeVisibleResponse = {\n outline: OutlineNode[]\n /**\n * Where the outline came from:\n * - `'data-agent'`: the app has `data-agent`-tagged zones and the\n * walker scoped the outline to them. The author chose what to\n * surface; trust the result.\n * - `'fallback'`: no `data-agent` tags exist; the walker fell back\n * to a depth- and count-limited semantic walk of the entire\n * root element. Useful for first-pass dogfood targets that\n * haven't tagged their views.\n * - `'truncated'`: same as `'fallback'` but the cap (200 nodes)\n * was hit before the walk finished. The visible content beyond\n * that point is not represented; reach for `query_dom` or state\n * reads if you need more.\n */\n source: 'data-agent' | 'fallback' | 'truncated'\n}\n\n// ── App + context documentation ──────────────────────────────────\n// Static app-level docs (authored once on the component record) and\n// dynamic per-state context docs (pure function of state, served by\n// `/lap/v1/context`). See spec §5.4.\n\nexport type AgentDocs = {\n purpose: string\n overview?: string\n cautions?: string[]\n /**\n * Free-form idiomatic-usage examples authored by the app: typical\n * sequences of dispatches the LLM should know about, like \"to\n * delete a saved matrix: dispatch Confirm/Ask first, then on\n * approve dispatch Cloud/Delete.\" Each entry is one example;\n * order is up to the author.\n */\n examples?: string[]\n}\n\nexport type AgentContext = {\n summary: string\n hints?: string[]\n cautions?: string[]\n}\n\nexport type LapContextResponse = { context: AgentContext }\n\n// ── Unified observe ──────────────────────────────────────────────\n// Single-call bootstrap. Replaces the get_state + list_actions +\n// describe_app trio for the common \"what can I see, what can I do\"\n// question. Returns the dynamic state + actions slice alongside the\n// static description (name/version/messages/docs) and any\n// state-derived context so one round-trip gives the LLM everything it\n// needs to decide its next action.\n\nexport type LapObserveResponse = {\n state: unknown\n actions: LapActionsResponse['actions']\n description: LapDescribeResponse\n context: AgentContext | null\n}\n\n// LAP endpoint catalog — a compile-time map binding each path to its\n// request/response shape. Useful for the bridge's dispatcher and for\n// typed test helpers.\nexport type LapEndpointMap = {\n '/lap/v1/describe': { req: null; res: LapDescribeResponse }\n '/lap/v1/state': { req: LapStateRequest; res: LapStateResponse }\n '/lap/v1/actions': { req: null; res: LapActionsResponse }\n '/lap/v1/message': { req: LapMessageRequest; res: LapMessageResponse }\n '/lap/v1/confirm-result': { req: LapConfirmResultRequest; res: LapConfirmResultResponse }\n '/lap/v1/wait': { req: LapWaitRequest; res: LapWaitResponse }\n '/lap/v1/query-dom': { req: LapQueryDomRequest; res: LapQueryDomResponse }\n '/lap/v1/describe-visible': { req: null; res: LapDescribeVisibleResponse }\n '/lap/v1/context': { req: null; res: LapContextResponse }\n '/lap/v1/observe': { req: null; res: LapObserveResponse }\n}\n\nexport type LapPath = keyof LapEndpointMap\nexport type LapRequest<P extends LapPath> = LapEndpointMap[P]['req']\nexport type LapResponse<P extends LapPath> = LapEndpointMap[P]['res']\n\n// ── Relay WS frames ──────────────────────────────────────────────\n// Bidirectional framing between the LLui runtime in the browser and\n// the @llui/agent server over /agent/ws. See spec §10.5.\n\nexport type LogKind =\n | 'proposed'\n | 'dispatched'\n | 'confirmed'\n | 'rejected'\n | 'blocked'\n | 'read'\n | 'error'\n\nexport type LogEntry = {\n id: string\n at: number\n kind: LogKind\n variant?: string\n intent?: string\n detail?: string\n /**\n * Structural diff from pre-dispatch state to post-drain state, in\n * JSON-Patch shape. Populated only for `kind: 'dispatched'` entries\n * — read entries (get_state / list_actions / observe / …) don't\n * mutate state, and an empty diff would just be noise. Lets the\n * agent reconstruct what each past action did without re-fetching\n * state snapshots.\n */\n stateDiff?: import('./state-diff.js').StateDiff\n}\n\nexport type HelloFrame = {\n t: 'hello'\n appName: string\n appVersion: string\n msgSchema: Record<string, MessageSchemaEntry>\n stateSchema: object\n affordancesSample: object[]\n docs: AgentDocs | null\n schemaHash: string\n}\n\nexport type RpcReplyFrame = { t: 'rpc-reply'; id: string; result: unknown }\nexport type RpcErrorFrame = { t: 'rpc-error'; id: string; code: string; detail?: string }\nexport type ConfirmResolvedFrame = {\n t: 'confirm-resolved'\n confirmId: string\n outcome: 'confirmed' | 'user-cancelled'\n stateAfter?: unknown\n}\nexport type StateUpdateFrame = { t: 'state-update'; path: string; stateAfter: unknown }\nexport type LogAppendFrame = { t: 'log-append'; entry: LogEntry }\n\nexport type ClientFrame =\n | HelloFrame\n | RpcReplyFrame\n | RpcErrorFrame\n | ConfirmResolvedFrame\n | StateUpdateFrame\n | LogAppendFrame\n\nexport type RpcFrame = { t: 'rpc'; id: string; tool: string; args: unknown }\nexport type RevokedFrame = { t: 'revoked' }\nexport type ActiveFrame = { t: 'active' }\n\nexport type ServerFrame = RpcFrame | RevokedFrame | ActiveFrame\n\n// ── Tokens + pairing ─────────────────────────────────────────────\n\ndeclare const TokenBrand: unique symbol\nexport type AgentToken = string & { readonly [TokenBrand]: 'AgentToken' }\n\nexport type TokenStatus =\n | 'awaiting-ws'\n | 'awaiting-claude'\n | 'active'\n | 'pending-resume'\n | 'revoked'\n\nexport type TokenRecord = {\n tid: string\n /**\n * SHA-256 hex of the bearer token. The plaintext token is never\n * stored — incoming requests hash their `Authorization: Bearer …`\n * value and look up by this field. Hash-only storage keeps a leaked\n * store from being a live-token leak. Mirrors the standard session-\n * cookie / API-key pattern.\n */\n tokenHash: string\n uid: string | null\n status: TokenStatus\n createdAt: number\n /**\n * Hard-expiry in milliseconds since epoch. The mint endpoint sets\n * this to `now + hardExpiryMs`; the verify path rejects requests\n * presenting tokens whose record has `expiresAt <= now`. Pre-0.0.35\n * the equivalent value lived inside the JWT payload as `exp` (in\n * seconds); the new opaque-token flow keeps it server-side so the\n * record is the single source of truth.\n */\n expiresAt: number\n lastSeenAt: number\n pendingResumeUntil: number | null\n origin: string\n label: string | null\n}\n\nexport type AgentSession = {\n tid: string\n label: string\n status: 'active' | 'pending-resume' | 'revoked'\n createdAt: number\n lastSeenAt: number\n}\n\n// HTTP envelopes for the mint/resume/revoke/sessions endpoints (non-LAP).\n\nexport type MintRequest = Record<string, never>\nexport type MintResponse = {\n token: AgentToken\n tid: string\n wsUrl: string\n lapUrl: string\n expiresAt: number\n}\n\nexport type ResumeListRequest = { tids: string[] }\nexport type ResumeListResponse = { sessions: AgentSession[] }\n\nexport type ResumeClaimRequest = { tid: string }\nexport type ResumeClaimResponse = { token: AgentToken; wsUrl: string }\n\nexport type RevokeRequest = { tid: string }\nexport type RevokeResponse = { status: 'revoked' }\n\nexport type SessionsResponse = { sessions: AgentSession[] }\n\n// ── Audit ────────────────────────────────────────────────────────\n\nexport type AuditEvent =\n | 'mint'\n | 'claim'\n | 'resume'\n | 'revoke'\n | 'lap-call'\n | 'msg-dispatched'\n | 'msg-blocked'\n | 'confirm-proposed'\n | 'confirm-approved'\n | 'confirm-rejected'\n | 'rate-limited'\n | 'auth-failed'\n\nexport type AuditEntry = {\n at: number\n tid: string | null\n uid: string | null\n event: AuditEvent\n detail: object\n}\n\n// ── Codec exports ─────────────────────────────────────────────────\n//\n// Re-exported here so consumers can `import { ..., type AgentCodec }\n// from '@llui/agent/protocol'`. The implementation lives in\n// `./codecs.ts` to keep the protocol type surface together but the\n// runtime registry/walkers separate.\n\nexport {\n WIRE_TAG,\n WIRE_VALUE,\n CodecRegistry,\n isoDateCodec,\n epochMillisCodec,\n makeDefaultCodecs,\n encodeForWire,\n decodeFromWire,\n type AgentCodec,\n} from './codecs.js'\n"]}
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,mEAAmE;AACnE,iEAAiE;AACjE,iEAAiE;AAgiBjE,qEAAqE;AACrE,EAAE;AACF,qEAAqE;AACrE,4DAA4D;AAC5D,mEAAmE;AACnE,qCAAqC;AAErC,OAAO,EACL,QAAQ,EACR,UAAU,EACV,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,iBAAiB,EACjB,aAAa,EACb,cAAc,GAEf,MAAM,aAAa,CAAA","sourcesContent":["// ── LAP — LLui Agent Protocol ────────────────────────────────────\n// JSON over HTTPS between the llui-agent bridge (MCP side) and the\n// @llui/agent server library mounted in the developer's backend.\n// See docs/superpowers/specs/2026-04-19-llui-agent-design.md §7.\n\nexport type LapErrorCode =\n | 'auth-failed'\n | 'revoked'\n | 'paused'\n | 'rate-limited'\n | 'invalid'\n | 'schema-error'\n | 'timeout'\n | 'internal'\n\nexport type LapError = {\n error: {\n code: LapErrorCode\n detail?: string\n retryAfterMs?: number\n }\n}\n\n/**\n * Who can dispatch a Msg variant.\n *\n * - `'shared'` (default) — both UI bindings and the agent can dispatch.\n * - `'human-only'` — UI-only. Agent calls to `/message` for these variants\n * are rejected with `LapMessageRejectReason: 'human-only'`. Use for\n * internal UI events (focus/blur, scroll, hover) the LLM has no business\n * triggering.\n * - `'agent-only'` — no UI binding exists. Reserved for LLM-driven flows\n * like batch operations or \"explain this state\" introspection variants.\n * Lint warns if a view references one via `send({ type: 'X' })`.\n *\n * JSDoc sugar: `@humanOnly` → `'human-only'`, `@agentOnly` → `'agent-only'`.\n * Absence of either tag → `'shared'`. The two tags are mutually exclusive\n * (enforced by `llui/agent-exclusive-annotations` ESLint rule).\n */\nexport type DispatchMode = 'shared' | 'human-only' | 'agent-only'\n\nexport type MessageAnnotations = {\n intent: string | null\n alwaysAffordable: boolean\n requiresConfirm: boolean\n dispatchMode: DispatchMode\n /**\n * Concrete copy-paste example dispatches authored as `@example`\n * JSDoc tags. Multiple tags on one variant become multiple\n * entries (mix typical / edge cases without nesting strings).\n */\n examples: string[]\n /**\n * Non-blocking caution authored as `@warning`. Distinct from\n * `requiresConfirm` (runtime user gate); this informs the LLM at\n * affordance time so it can decide whether the dispatch's\n * downstream is acceptable.\n */\n warning: string | null\n /**\n * Effect kinds this variant emits when dispatched, declared via\n * `@emits(\"kind1\", \"kind2\")`. Lets the agent reason about side\n * effects (cloud writes, analytics, persistent state changes)\n * before dispatching, and chunk multi-step flows accordingly\n * (\"don't dispatch X 100 times — each one fires cloud/save\").\n * Empty when the variant doesn't emit effects or the author hasn't\n * annotated it yet.\n */\n emits: string[]\n /**\n * Boolean predicate authored as `@routeGated(\"expr\")` JSDoc, with\n * `state` bound at evaluation time. The variant only surfaces in\n * `list_actions` when the predicate returns true. Compile-time\n * alternative to `agentAffordances(state) => Msg[]` for the common\n * case of \"this Msg is reachable when state.X looks like Y.\" Null\n * when the variant has no `@routeGated` tag (default affordance\n * behavior applies).\n */\n routeGate?: string | null\n}\n\nexport type MessageSchemaEntry = {\n payloadSchema: object\n annotations: MessageAnnotations\n}\n\nexport type LapDescribeResponse = {\n name: string\n version: string\n stateSchema: object\n messages: Record<string, MessageSchemaEntry>\n docs: AgentDocs | null\n conventions: {\n dispatchModel: 'TEA'\n confirmationModel: 'runtime-mediated'\n readSurfaces: readonly (\n | 'state'\n | 'query_dom'\n | 'describe_visible_content'\n | 'describe_context'\n )[]\n }\n schemaHash: string\n}\n\nexport type LapStateRequest = { path?: string }\nexport type LapStateResponse = { state: unknown }\n\nexport type LapActionsResponse = {\n actions: Array<{\n variant: string\n /**\n * Human-readable phrase from `@intent(\"…\")`, or `null` when the\n * variant has no `@intent` annotation. Callers that surface\n * affordances to an LLM should treat `null` as \"this action is\n * undocumented\" — neither synthesise a label from the variant name\n * nor invent one. Pre-`@intent` variants would previously surface\n * as `intent: \"<variant>\"` here, which made unannotated actions\n * indistinguishable from properly-labelled ones; emitting `null`\n * keeps the gap visible.\n */\n intent: string | null\n requiresConfirm: boolean\n /**\n * `'shared'` — both UI and agent can dispatch. `'agent-only'` — no UI\n * binding exists; the agent is the sole dispatcher. `'human-only'`\n * variants never appear here (filtered before serialization).\n */\n dispatchMode: 'shared' | 'agent-only'\n /**\n * Where this affordance came from:\n * - `'binding'` — a tagged event handler is currently\n * mounted in the rendered DOM.\n * - `'always-affordable'` — the app's `agentAffordances(state)`\n * hook listed it as available right now.\n * - `'schema'` — neither of the above; the variant\n * is in the Msg union and annotated `@agentOnly`. The\n * `payloadHint` carries a synthesized example from the\n * compiler-derived field types — copy-paste-ready for\n * `send_message`. Bulk-edit operations land here.\n */\n source: 'binding' | 'always-affordable' | 'schema'\n selectorHint: string | null\n payloadHint: object | null\n /** Cautionary text from `@warning` JSDoc, or null. */\n warning: string | null\n /** Concrete examples from `@example` JSDoc, in source order. */\n examples: string[]\n /**\n * Effect kinds this variant emits, from `@emits(\"k1\", \"k2\")`.\n * Empty when not annotated.\n */\n emits: string[]\n /**\n * Per-field guidance lifted from `@should(\"…\")` JSDoc on payload\n * fields. Path is dot/bracket notation rooted at the payload (e.g.\n * `\"cells[].meta\"`). Surfaces hints that would otherwise be buried\n * inside the schema tree, so callers can read them alongside\n * `examples` without diving into `description.messages.variants`.\n */\n fieldHints: Array<{ path: string; hint: string }>\n }>\n}\n\nexport type LapMessageRequest = {\n msg: { type: string; [k: string]: unknown }\n reason?: string\n /**\n * Backpressure contract for how long `/message` waits before returning:\n * - `drained` (default): dispatch, then loop until the message queue is\n * idle for `drainQuietMs` ms or the 5s hard cap trips. Captures any\n * effect round-trips (http/delay/debounce) that feed back as messages.\n * - `idle`: dispatch + flush + one microtask yield. Captures the\n * synchronous update cycle but not async effects.\n * - `none`: dispatch and return without flushing. For high-throughput\n * fire-and-forget dispatch.\n */\n waitFor?: 'drained' | 'idle' | 'none'\n /**\n * Quiescence window when `waitFor === 'drained'`. Drain completes when\n * no new update cycle fires for this many ms. Default 100ms — long\n * enough for a localhost HTTP round-trip, short enough to be\n * imperceptible. Ignored for `idle` / `none`.\n */\n drainQuietMs?: number\n /**\n * Hard cap on total wait time. When `waitFor === 'drained'`, this is\n * the upper bound on how long the drain loop can run; if reached, the\n * response carries `drain.timedOut: true` with partial results. For\n * `pending-confirmation` messages, this is how long to wait for\n * the user's confirm/reject. Default 5_000ms.\n */\n timeoutMs?: number\n /**\n * Include the full post-drain `stateAfter` snapshot in the response.\n * Default `false` — the response carries `stateDiff` only and the\n * caller applies it to the prior snapshot (from connect/observe). For\n * apps with non-trivial state, the diff is orders of magnitude\n * smaller than the full state, and resending the snapshot on every\n * dispatch wastes bandwidth and (for LLM callers) context budget.\n *\n * Set `true` when the caller doesn't track state incrementally and\n * wants the snapshot back. The legacy `confirmed` and `wait` paths\n * always carry `stateAfter` because their flow is asynchronous and\n * a diff would be ambiguous.\n */\n includeState?: boolean\n}\n\nexport type LapMessageRejectReason =\n | 'human-only'\n | 'user-cancelled'\n | 'timeout'\n | 'invalid'\n | 'schema-error'\n | 'revoked'\n | 'paused'\n\n/**\n * Drain metadata attached to `dispatched` / `confirmed` responses.\n * `effectsObserved` counts update-cycle commits (not individual effects) —\n * it's a proxy for \"how much activity happened during the drain window.\"\n * `errors` surfaces sync throws from `onEffect` and unhandled rejections\n * from effect handlers that fired during the drain window, so the LLM\n * can see when an HTTP handler crashed silently.\n *\n * `warnings` surfaces non-blocking observations from the schema\n * validator — typically `untyped-field` flags raised in strict mode\n * when the agent provided a value for an `'unknown'`-typed field. The\n * dispatch landed (we accepted the value) but the validator couldn't\n * structurally check it, so the agent learns of the gap and can\n * tighten the next try if needed. Lenient mode never emits warnings;\n * the field is omitted in that case.\n */\nexport type LapDrainMeta = {\n effectsObserved: number\n durationMs: number\n timedOut: boolean\n errors: Array<{ kind: 'error' | 'unhandledrejection'; message: string; stack?: string }>\n warnings?: Array<{ path: string; code: string; message: string }>\n}\n\nexport type LapMessageResponse =\n | {\n status: 'dispatched'\n /**\n * Full post-drain state snapshot. Present only when the caller\n * passed `includeState: true` in the request — by default,\n * `stateDiff` is the only state-shaped field on the response\n * because callers can apply the diff to the prior snapshot from\n * `connect` / `observe`. See `LapMessageRequest.includeState`.\n */\n stateAfter?: unknown\n /**\n * Structural diff from pre-dispatch state to post-drain state,\n * in JSON-Patch shape (RFC 6902 subset: `add`, `remove`,\n * `replace`). Empty when the dispatch produced no observable\n * state change. The default state surface for callers — apply\n * incrementally to the snapshot from `connect`/`observe`.\n */\n stateDiff: import('./state-diff.js').StateDiff\n actions: LapActionsResponse['actions']\n drain: LapDrainMeta\n }\n | { status: 'pending-confirmation'; confirmId: string }\n | {\n /**\n * The user approved a `pending-confirmation` message. `stateAfter`\n * is the state snapshot captured when the approve was resolved;\n * effects produced by the approved dispatch may still be in\n * flight. The LLM should follow up with an `observe` call to\n * pick up a drained view and fresh actions — by design the\n * confirm path doesn't carry drain semantics because approval\n * can arrive arbitrarily later than the original request.\n */\n status: 'confirmed'\n stateAfter: unknown\n }\n | { status: 'rejected'; reason: LapMessageRejectReason; detail?: string }\n\nexport type LapConfirmResultRequest = { confirmId: string; timeoutMs?: number }\nexport type LapConfirmResultResponse =\n | { status: 'confirmed'; stateAfter: unknown }\n | { status: 'rejected'; reason: 'user-cancelled' | 'timeout' }\n | { status: 'still-pending' }\n\nexport type LapWaitRequest = { path?: string; timeoutMs?: number }\nexport type LapWaitResponse =\n | { status: 'changed'; stateAfter: unknown }\n | { status: 'timeout'; stateAfter: unknown }\n\nexport type LapQueryDomRequest = { name: string; multiple?: boolean }\nexport type LapQueryDomResponse = {\n elements: Array<{ text: string; attrs: Record<string, string>; path: number[] }>\n}\n\nexport type OutlineNode =\n | { kind: 'heading'; level: number; text: string }\n | { kind: 'text'; text: string }\n | { kind: 'list'; items: OutlineNode[] }\n | { kind: 'item'; text: string; children?: OutlineNode[] }\n | { kind: 'button'; text: string; disabled: boolean; actionVariant: string | null }\n | { kind: 'input'; label: string | null; value: string | null; type: string }\n | { kind: 'link'; text: string; href: string }\n\nexport type LapDescribeVisibleResponse = {\n outline: OutlineNode[]\n /**\n * Where the outline came from:\n * - `'data-agent'`: the app has `data-agent`-tagged zones and the\n * walker scoped the outline to them. The author chose what to\n * surface; trust the result.\n * - `'fallback'`: no `data-agent` tags exist; the walker fell back\n * to a depth- and count-limited semantic walk of the entire\n * root element. Useful for first-pass dogfood targets that\n * haven't tagged their views.\n * - `'truncated'`: same as `'fallback'` but the cap (200 nodes)\n * was hit before the walk finished. The visible content beyond\n * that point is not represented; reach for `query_dom` or state\n * reads if you need more.\n */\n source: 'data-agent' | 'fallback' | 'truncated'\n}\n\n// ── App + context documentation ──────────────────────────────────\n// Static app-level docs (authored once on the component record) and\n// dynamic per-state context docs (pure function of state, served by\n// `/lap/v1/context`). See spec §5.4.\n\nexport type AgentDocs = {\n purpose: string\n overview?: string\n cautions?: string[]\n /**\n * Free-form idiomatic-usage examples authored by the app: typical\n * sequences of dispatches the LLM should know about, like \"to\n * delete a saved matrix: dispatch Confirm/Ask first, then on\n * approve dispatch Cloud/Delete.\" Each entry is one example;\n * order is up to the author.\n */\n examples?: string[]\n}\n\nexport type AgentContext = {\n summary: string\n hints?: string[]\n cautions?: string[]\n}\n\nexport type LapContextResponse = { context: AgentContext }\n\n// ── Unified observe ──────────────────────────────────────────────\n// Single-call bootstrap. Replaces the get_state + list_actions +\n// describe_app trio for the common \"what can I see, what can I do\"\n// question. Returns the dynamic state + actions slice alongside the\n// static description (name/version/messages/docs) and any\n// state-derived context so one round-trip gives the LLM everything it\n// needs to decide its next action.\n\nexport type LapObserveResponse = {\n state: unknown\n actions: LapActionsResponse['actions']\n description: LapDescribeResponse\n context: AgentContext | null\n}\n\n// LAP endpoint catalog — a compile-time map binding each path to its\n// request/response shape. Useful for the bridge's dispatcher and for\n// typed test helpers.\nexport type LapEndpointMap = {\n '/lap/v1/describe': { req: null; res: LapDescribeResponse }\n '/lap/v1/state': { req: LapStateRequest; res: LapStateResponse }\n '/lap/v1/actions': { req: null; res: LapActionsResponse }\n '/lap/v1/message': { req: LapMessageRequest; res: LapMessageResponse }\n '/lap/v1/confirm-result': { req: LapConfirmResultRequest; res: LapConfirmResultResponse }\n '/lap/v1/wait': { req: LapWaitRequest; res: LapWaitResponse }\n '/lap/v1/query-dom': { req: LapQueryDomRequest; res: LapQueryDomResponse }\n '/lap/v1/describe-visible': { req: null; res: LapDescribeVisibleResponse }\n '/lap/v1/context': { req: null; res: LapContextResponse }\n '/lap/v1/observe': { req: null; res: LapObserveResponse }\n}\n\nexport type LapPath = keyof LapEndpointMap\nexport type LapRequest<P extends LapPath> = LapEndpointMap[P]['req']\nexport type LapResponse<P extends LapPath> = LapEndpointMap[P]['res']\n\n// ── Relay WS frames ──────────────────────────────────────────────\n// Bidirectional framing between the LLui runtime in the browser and\n// the @llui/agent server over /agent/ws. See spec §10.5.\n\nexport type LogKind =\n | 'proposed'\n | 'dispatched'\n | 'confirmed'\n | 'rejected'\n | 'blocked'\n | 'read'\n | 'error'\n\nexport type LogEntry = {\n id: string\n at: number\n kind: LogKind\n variant?: string\n intent?: string\n detail?: string\n /**\n * Structural diff from pre-dispatch state to post-drain state, in\n * JSON-Patch shape. Populated only for `kind: 'dispatched'` entries\n * — read entries (get_state / list_actions / observe / …) don't\n * mutate state, and an empty diff would just be noise. Lets the\n * agent reconstruct what each past action did without re-fetching\n * state snapshots.\n */\n stateDiff?: import('./state-diff.js').StateDiff\n}\n\nexport type HelloFrame = {\n t: 'hello'\n appName: string\n appVersion: string\n msgSchema: Record<string, MessageSchemaEntry>\n stateSchema: object\n affordancesSample: object[]\n docs: AgentDocs | null\n schemaHash: string\n}\n\nexport type RpcReplyFrame = { t: 'rpc-reply'; id: string; result: unknown }\nexport type RpcErrorFrame = { t: 'rpc-error'; id: string; code: string; detail?: string }\nexport type ConfirmResolvedFrame = {\n t: 'confirm-resolved'\n confirmId: string\n outcome: 'confirmed' | 'user-cancelled'\n stateAfter?: unknown\n}\nexport type StateUpdateFrame = { t: 'state-update'; path: string; stateAfter: unknown }\nexport type LogAppendFrame = { t: 'log-append'; entry: LogEntry }\n\nexport type ClientFrame =\n | HelloFrame\n | RpcReplyFrame\n | RpcErrorFrame\n | ConfirmResolvedFrame\n | StateUpdateFrame\n | LogAppendFrame\n\nexport type RpcFrame = { t: 'rpc'; id: string; tool: string; args: unknown }\nexport type RevokedFrame = { t: 'revoked' }\nexport type ActiveFrame = { t: 'active' }\n\nexport type ServerFrame = RpcFrame | RevokedFrame | ActiveFrame\n\n// ── Tokens + pairing ─────────────────────────────────────────────\n\ndeclare const TokenBrand: unique symbol\nexport type AgentToken = string & { readonly [TokenBrand]: 'AgentToken' }\n\nexport type TokenStatus =\n | 'awaiting-ws'\n | 'awaiting-claude'\n | 'active'\n | 'pending-resume'\n | 'revoked'\n\nexport type TokenRecord = {\n tid: string\n /**\n * SHA-256 hex of the bearer token. The plaintext token is never\n * stored — incoming requests hash their `Authorization: Bearer …`\n * value and look up by this field. Hash-only storage keeps a leaked\n * store from being a live-token leak. Mirrors the standard session-\n * cookie / API-key pattern.\n */\n tokenHash: string\n uid: string | null\n status: TokenStatus\n createdAt: number\n /**\n * Hard-expiry in milliseconds since epoch. The mint endpoint sets\n * this to `now + hardExpiryMs`; the verify path rejects requests\n * presenting tokens whose record has `expiresAt <= now`. Pre-0.0.35\n * the equivalent value lived inside the JWT payload as `exp` (in\n * seconds); the new opaque-token flow keeps it server-side so the\n * record is the single source of truth.\n */\n expiresAt: number\n lastSeenAt: number\n pendingResumeUntil: number | null\n origin: string\n label: string | null\n}\n\nexport type AgentSession = {\n tid: string\n label: string\n status: 'active' | 'pending-resume' | 'revoked'\n createdAt: number\n lastSeenAt: number\n}\n\n// HTTP envelopes for the mint/resume/revoke/sessions endpoints (non-LAP).\n\nexport type MintRequest = Record<string, never>\nexport type MintResponse = {\n token: AgentToken\n tid: string\n wsUrl: string\n lapUrl: string\n expiresAt: number\n}\n\nexport type ResumeListRequest = { tids: string[] }\nexport type ResumeListResponse = { sessions: AgentSession[] }\n\nexport type ResumeClaimRequest = { tid: string }\nexport type ResumeClaimResponse = { token: AgentToken; wsUrl: string }\n\nexport type RevokeRequest = { tid: string }\nexport type RevokeResponse = { status: 'revoked' }\n\nexport type SessionsResponse = { sessions: AgentSession[] }\n\n// ── Audit ────────────────────────────────────────────────────────\n\nexport type AuditEvent =\n | 'mint'\n | 'claim'\n | 'resume'\n | 'revoke'\n | 'lap-call'\n | 'msg-dispatched'\n | 'msg-blocked'\n | 'confirm-proposed'\n | 'confirm-approved'\n | 'confirm-rejected'\n | 'rate-limited'\n | 'auth-failed'\n\nexport type AuditEntry = {\n at: number\n tid: string | null\n uid: string | null\n event: AuditEvent\n detail: object\n}\n\n// ── Codec exports ─────────────────────────────────────────────────\n//\n// Re-exported here so consumers can `import { ..., type AgentCodec }\n// from '@llui/agent/protocol'`. The implementation lives in\n// `./codecs.ts` to keep the protocol type surface together but the\n// runtime registry/walkers separate.\n\nexport {\n WIRE_TAG,\n WIRE_VALUE,\n CodecRegistry,\n isoDateCodec,\n epochMillisCodec,\n makeDefaultCodecs,\n encodeForWire,\n decodeFromWire,\n type AgentCodec,\n} from './codecs.js'\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llui/agent",
3
- "version": "0.0.40",
3
+ "version": "0.0.42",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "exports": {
@@ -40,12 +40,12 @@
40
40
  "ws": "^8.18.0"
41
41
  },
42
42
  "peerDependencies": {
43
- "@llui/dom": "^0.0.33"
43
+ "@llui/dom": "^0.0.34"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/node": "^22.0.0",
47
47
  "@types/ws": "^8.5.13",
48
- "@llui/dom": "0.0.33"
48
+ "@llui/dom": "0.0.34"
49
49
  },
50
50
  "description": "LLui Agent — LAP server + browser client runtime for driving LLui apps from LLM clients",
51
51
  "keywords": [