|
|
@@ -1,6 +1,7 @@
|
|
|
# Agent Note: Web command business surfaces and assembly (ui-commands / ui-skill / ui-subagent)
|
|
|
|
|
|
Status: implemented
|
|
|
+Archived: 2026-09-04
|
|
|
|
|
|
English | [中文](2026-07-25-web-command-surfaces-and-assembly.zh.md)
|
|
|
|
|
|
@@ -21,7 +22,7 @@ The pipeline was ready but command knowledge had no landing spot: host-side `ctx
|
|
|
|
|
|
- The `ClientSessionContext { sessionId }` projection is self-held in the ui-input-trigger contract (types.ts): sessions are always agent-backed, so session identity is the entire projection of command capability; the wire addresses by `{sessionId}` (both `command.list` and `command.execute`; the host resolves the Agent from the session header).
|
|
|
- The directory is compartmented by `SessionId`, with per-key single-flight + an epoch guard (an old pull never overwrites newer state); `commands/changed` soft-invalidates every key (the old snapshot keeps serving while the repull runs in the background), `connection/reset` hard-invalidates every key and rewarms, Enter strong-waits on the current key, and a failure keeps the draft with no downgrade. Prewarming hangs on the source's `warm` hook — once over the full roster at scope birth, which covers the entire session lifecycle (session capability is constant from birth).
|
|
|
-- `register(contribution)` registers client commands (a localized description resolver + `available(projection)` + a popupSelect spec); candidate synthesis combines the host directory with available contributions, localizes the six first-party Host descriptions only when their command name and canonical English copy both match, then applies query/position filtering. Scoped or third-party Host descriptions remain verbatim, and a host/contribution name clash fails loud. A locale switch re-fetches every open trigger controller in place, while a source gate keeps each first-party Host registration aligned with the English dictionary and `HOST_DESCRIPTION_KEYS`.
|
|
|
+- `register(contribution)` registers client commands (a descriptor + `available(projection)` + a popupSelect spec); candidate synthesis = the host directory + contribution availability filtering, then the query/position pass, and a host/contribution name clash fails loud.
|
|
|
- The three command kinds derive from the registration surfaces; developers never declare positions: a host descriptor with `input` = **leadingInput** (backfill `/name ␣` + claim, keep typing arguments, leading position only); a client-registered popupSelect spec = **popupSelect** (the official select-box shell, business ships zero components); neither = **execute** (run on selection, zero UI).
|
|
|
- The dispatch decision table: the menu can trigger all three kinds; Space recognizes only leadingInput (the misfire defense: irreversible side effects keep explicit entry points only); Enter runs execute / opens the shell only on a bare token, while leadingInput tolerates trailing arguments.
|
|
|
- The popup from `popupFor(actx)`: search filters locally, select is single-flight, the projection is captured at open, onSelect consumes the token through the consume-token event only on success, a failure is retained for retry, and a session switch merely hides it. The popup shell is a transient layer (never in the state machine): the box holds focus, Enter/↑↓/Escape belong to it, and clicking outside the box dismisses (clicking the textarea also returns focus).
|
|
|
@@ -58,5 +59,5 @@ The pipeline was ready but command knowledge had no landing spot: host-side `ctx
|
|
|
|
|
|
- Shipping a business command = a host registration plus one client `command.register` (popupSelect) or zero registration (execute/leadingInput derive automatically), with zero skeleton changes; the cost is that the three-kind semantics concentrate in ui-commands, and a hypothetical fourth kind means changing it.
|
|
|
- The resident directory cache plus push invalidation buys zero-latency menus and reliable enter adjudication; the cost is three invalidation paths (the change frame, reconnect, the epoch guard) that all need tests pinning them.
|
|
|
-- sessionId addressing puts the host's per-agent effective directory (global + scoped shadows) straight on the wire. The client preserves command identity, input metadata, and noncanonical descriptions while resolving exact first-party description pairs through its current locale.
|
|
|
+- sessionId addressing puts the host's per-agent effective directory (global + scoped shadows) straight on the wire, with the client presenting it as-is.
|
|
|
- Known gaps: the popupSelect shell has no shipped business consumer yet (model selection and its kin arrive with the host `selectModel` work in live-mutation shape, serving as the onboarding template then); the queue's second cut (per-item Inbox operations), rich result cards, and roster configurability sit in the ledger awaiting their triggers.
|