@llui/agent 0.0.32 → 0.0.35

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.
Files changed (145) hide show
  1. package/README.md +82 -1
  2. package/dist/client/agentConfirm.d.ts +48 -18
  3. package/dist/client/agentConfirm.d.ts.map +1 -1
  4. package/dist/client/agentConfirm.js +28 -25
  5. package/dist/client/agentConfirm.js.map +1 -1
  6. package/dist/client/agentConnect.d.ts +95 -34
  7. package/dist/client/agentConnect.d.ts.map +1 -1
  8. package/dist/client/agentConnect.js +85 -47
  9. package/dist/client/agentConnect.js.map +1 -1
  10. package/dist/client/agentLog.d.ts +31 -14
  11. package/dist/client/agentLog.d.ts.map +1 -1
  12. package/dist/client/agentLog.js +39 -20
  13. package/dist/client/agentLog.js.map +1 -1
  14. package/dist/client/effect-handler.d.ts +23 -0
  15. package/dist/client/effect-handler.d.ts.map +1 -1
  16. package/dist/client/effect-handler.js +185 -126
  17. package/dist/client/effect-handler.js.map +1 -1
  18. package/dist/client/effects.d.ts +13 -2
  19. package/dist/client/effects.d.ts.map +1 -1
  20. package/dist/client/effects.js.map +1 -1
  21. package/dist/client/factory.d.ts +55 -3
  22. package/dist/client/factory.d.ts.map +1 -1
  23. package/dist/client/factory.js +30 -5
  24. package/dist/client/factory.js.map +1 -1
  25. package/dist/client/rpc/describe-visible-content.d.ts +18 -5
  26. package/dist/client/rpc/describe-visible-content.d.ts.map +1 -1
  27. package/dist/client/rpc/describe-visible-content.js +112 -7
  28. package/dist/client/rpc/describe-visible-content.js.map +1 -1
  29. package/dist/client/rpc/list-actions.d.ts +52 -2
  30. package/dist/client/rpc/list-actions.d.ts.map +1 -1
  31. package/dist/client/rpc/list-actions.js +187 -5
  32. package/dist/client/rpc/list-actions.js.map +1 -1
  33. package/dist/client/rpc/query-state.d.ts +32 -0
  34. package/dist/client/rpc/query-state.d.ts.map +1 -0
  35. package/dist/client/rpc/query-state.js +82 -0
  36. package/dist/client/rpc/query-state.js.map +1 -0
  37. package/dist/client/rpc/send-message.d.ts +2 -0
  38. package/dist/client/rpc/send-message.d.ts.map +1 -1
  39. package/dist/client/rpc/send-message.js +119 -9
  40. package/dist/client/rpc/send-message.js.map +1 -1
  41. package/dist/client/rpc/would-dispatch.d.ts +66 -0
  42. package/dist/client/rpc/would-dispatch.d.ts.map +1 -0
  43. package/dist/client/rpc/would-dispatch.js +21 -0
  44. package/dist/client/rpc/would-dispatch.js.map +1 -0
  45. package/dist/client/ws-client.d.ts +3 -1
  46. package/dist/client/ws-client.d.ts.map +1 -1
  47. package/dist/client/ws-client.js +29 -0
  48. package/dist/client/ws-client.js.map +1 -1
  49. package/dist/codecs.d.ts +107 -0
  50. package/dist/codecs.d.ts.map +1 -0
  51. package/dist/codecs.js +166 -0
  52. package/dist/codecs.js.map +1 -0
  53. package/dist/protocol.d.ts +172 -12
  54. package/dist/protocol.d.ts.map +1 -1
  55. package/dist/protocol.js +7 -1
  56. package/dist/protocol.js.map +1 -1
  57. package/dist/server/cloudflare/durable-object.d.ts +11 -4
  58. package/dist/server/cloudflare/durable-object.d.ts.map +1 -1
  59. package/dist/server/cloudflare/durable-object.js.map +1 -1
  60. package/dist/server/cloudflare/index.d.ts +8 -4
  61. package/dist/server/cloudflare/index.d.ts.map +1 -1
  62. package/dist/server/cloudflare/index.js +8 -4
  63. package/dist/server/cloudflare/index.js.map +1 -1
  64. package/dist/server/cloudflare/worker.d.ts +10 -2
  65. package/dist/server/cloudflare/worker.d.ts.map +1 -1
  66. package/dist/server/cloudflare/worker.js +13 -6
  67. package/dist/server/cloudflare/worker.js.map +1 -1
  68. package/dist/server/core-entry.d.ts +2 -2
  69. package/dist/server/core-entry.d.ts.map +1 -1
  70. package/dist/server/core-entry.js +1 -1
  71. package/dist/server/core-entry.js.map +1 -1
  72. package/dist/server/core.d.ts +1 -3
  73. package/dist/server/core.d.ts.map +1 -1
  74. package/dist/server/core.js +13 -12
  75. package/dist/server/core.js.map +1 -1
  76. package/dist/server/factory.d.ts +1 -1
  77. package/dist/server/factory.d.ts.map +1 -1
  78. package/dist/server/factory.js +1 -2
  79. package/dist/server/factory.js.map +1 -1
  80. package/dist/server/http/mint.d.ts +6 -1
  81. package/dist/server/http/mint.d.ts.map +1 -1
  82. package/dist/server/http/mint.js +14 -6
  83. package/dist/server/http/mint.js.map +1 -1
  84. package/dist/server/http/resume.d.ts +3 -1
  85. package/dist/server/http/resume.d.ts.map +1 -1
  86. package/dist/server/http/resume.js +9 -7
  87. package/dist/server/http/resume.js.map +1 -1
  88. package/dist/server/index.d.ts +2 -2
  89. package/dist/server/index.d.ts.map +1 -1
  90. package/dist/server/index.js +1 -1
  91. package/dist/server/index.js.map +1 -1
  92. package/dist/server/lap/confirm-result.d.ts +0 -1
  93. package/dist/server/lap/confirm-result.d.ts.map +1 -1
  94. package/dist/server/lap/confirm-result.js +1 -1
  95. package/dist/server/lap/confirm-result.js.map +1 -1
  96. package/dist/server/lap/describe.d.ts +13 -2
  97. package/dist/server/lap/describe.d.ts.map +1 -1
  98. package/dist/server/lap/describe.js +23 -6
  99. package/dist/server/lap/describe.js.map +1 -1
  100. package/dist/server/lap/forward.d.ts +13 -1
  101. package/dist/server/lap/forward.d.ts.map +1 -1
  102. package/dist/server/lap/forward.js +75 -1
  103. package/dist/server/lap/forward.js.map +1 -1
  104. package/dist/server/lap/message.d.ts +0 -1
  105. package/dist/server/lap/message.d.ts.map +1 -1
  106. package/dist/server/lap/message.js +1 -1
  107. package/dist/server/lap/message.js.map +1 -1
  108. package/dist/server/lap/observe.d.ts +0 -1
  109. package/dist/server/lap/observe.d.ts.map +1 -1
  110. package/dist/server/lap/observe.js +1 -1
  111. package/dist/server/lap/observe.js.map +1 -1
  112. package/dist/server/lap/router.d.ts.map +1 -1
  113. package/dist/server/lap/router.js +7 -1
  114. package/dist/server/lap/router.js.map +1 -1
  115. package/dist/server/lap/wait.d.ts +0 -1
  116. package/dist/server/lap/wait.d.ts.map +1 -1
  117. package/dist/server/lap/wait.js +1 -1
  118. package/dist/server/lap/wait.js.map +1 -1
  119. package/dist/server/options.d.ts +7 -5
  120. package/dist/server/options.d.ts.map +1 -1
  121. package/dist/server/options.js.map +1 -1
  122. package/dist/server/token-store.d.ts +22 -0
  123. package/dist/server/token-store.d.ts.map +1 -1
  124. package/dist/server/token-store.js +24 -0
  125. package/dist/server/token-store.js.map +1 -1
  126. package/dist/server/token.d.ts +32 -17
  127. package/dist/server/token.d.ts.map +1 -1
  128. package/dist/server/token.js +40 -103
  129. package/dist/server/token.js.map +1 -1
  130. package/dist/server/web/upgrade.d.ts +1 -1
  131. package/dist/server/web/upgrade.js +1 -1
  132. package/dist/server/web/upgrade.js.map +1 -1
  133. package/dist/server/ws/pairing-registry.d.ts +22 -6
  134. package/dist/server/ws/pairing-registry.d.ts.map +1 -1
  135. package/dist/server/ws/pairing-registry.js +49 -0
  136. package/dist/server/ws/pairing-registry.js.map +1 -1
  137. package/dist/server/ws/upgrade.d.ts +0 -1
  138. package/dist/server/ws/upgrade.d.ts.map +1 -1
  139. package/dist/server/ws/upgrade.js +12 -4
  140. package/dist/server/ws/upgrade.js.map +1 -1
  141. package/dist/state-diff.d.ts +52 -0
  142. package/dist/state-diff.d.ts.map +1 -0
  143. package/dist/state-diff.js +119 -0
  144. package/dist/state-diff.js.map +1 -0
  145. package/package.json +7 -3
package/README.md CHANGED
@@ -51,6 +51,7 @@ server.on('upgrade', agent.wsUpgrade)
51
51
  ## Client
52
52
 
53
53
  ```ts
54
+ // @doc-skip — illustration uses `...` placeholders for handlers
54
55
  import { mountApp } from '@llui/dom'
55
56
  import { createAgentClient, agentConnect, agentConfirm, agentLog } from '@llui/agent/client'
56
57
  import { handleEffects } from '@llui/effects'
@@ -81,6 +82,7 @@ const onEffect = handleEffects<MyEffect | AgentEffect>()
81
82
  ## App-side annotations
82
83
 
83
84
  ```ts
85
+ // @doc-skip — illustration uses `...` placeholders for init/update/view
84
86
  type Msg =
85
87
  /** @intent("Increment the counter") */
86
88
  | { type: 'inc' }
@@ -175,8 +177,10 @@ view: ({ send, branch, show }) => {
175
177
  const connectParts = agentConnect.connect(
176
178
  (s) => s.agent.connect,
177
179
  (m) => send({ type: 'agent', sub: 'connect', msg: m }),
178
- { mintUrl: '/agent/mint' },
179
180
  )
181
+ // `mintUrl` is optional — the agent effect handler derives it from
182
+ // `EffectHandlerHost.agentBasePath` (default `/agent`). Pass an
183
+ // explicit `{ mintUrl }` only when minting from a non-default path.
180
184
 
181
185
  const confirmParts = agentConfirm.connect(
182
186
  (s) => s.agent.confirm,
@@ -208,3 +212,80 @@ view: ({ send, branch, show }) => {
208
212
  - `@llui/agent/client` — `createAgentClient`, `agentConnect`, `agentConfirm`, `agentLog`, `AgentEffect`.
209
213
 
210
214
  See the [Agent Protocol doc](../../docs/designs/10%20Agent%20Protocol.md) for the full wire protocol and security model.
215
+
216
+ ## Custom serialization (codecs)
217
+
218
+ JSON natively supports `string | number | boolean | null | array | object`. Component messages and state often carry values that don't round-trip through JSON: `Date`, `Blob`, `File`, `Map`, `Set`, `BigInt`. The agent ships a codec convention that lets these values cross the LAP boundary cleanly without forcing every component to invent its own envelope.
219
+
220
+ **Wire format.** A non-JSON-safe runtime value travels as a tagged object:
221
+
222
+ ```json
223
+ { "__codec": "iso-date", "wire": "2026-04-25T12:00:00.000Z" }
224
+ ```
225
+
226
+ The runtime walks every value crossing the LAP boundary symmetrically:
227
+
228
+ - **Outgoing** (`stateAfter` snapshots, action arguments): the encoder looks up a codec whose `matchesRuntime` claims the value and replaces it with the tagged shape.
229
+ - **Incoming** (`msg` payloads dispatched by the agent): the decoder detects the tagged shape and substitutes the runtime value before `update()` runs.
230
+
231
+ Reducers never see the tagged form. By the time `update()` is called, real `Date` / `Blob` / etc. are in place.
232
+
233
+ **Default codecs.** `makeDefaultCodecs()` ships with:
234
+
235
+ | Codec name | Encodes | Wire form |
236
+ | -------------- | ------- | ------------------ |
237
+ | `iso-date` | `Date` | ISO 8601 string |
238
+ | `epoch-millis` | `Date` | epoch milliseconds |
239
+
240
+ By default `iso-date` claims `Date` values. `epoch-millis` is registered but its `matchesRuntime` returns `false` so it doesn't shadow `iso-date` on encode — it's still available for explicit decode and for consumers who register a millis-first registry.
241
+
242
+ **Authoring.** Tag the variant's JSDoc with both `@intent` and `@codec("<name>")`:
243
+
244
+ ```ts
245
+ type DateInputMsg = {
246
+ /**
247
+ * @intent("Set the parsed date directly")
248
+ * @codec("iso-date")
249
+ */
250
+ type: 'setValue'
251
+ value: Date | null
252
+ }
253
+ ```
254
+
255
+ The `@codec` tag is documentation for human readers and the (eventual) schema generator. The runtime encode/decode is registry-driven and doesn't need per-field metadata at runtime.
256
+
257
+ **Custom codecs.** Pass a registry to `createAgentClient`:
258
+
259
+ ```ts
260
+ // @doc-skip — illustration uses placeholder encode/decode bodies
261
+ import { CodecRegistry, isoDateCodec } from '@llui/agent/codecs'
262
+
263
+ const codecs = new CodecRegistry()
264
+ codecs.register(isoDateCodec)
265
+ codecs.register({
266
+ name: 'base64-blob',
267
+ matchesRuntime: (v) => v instanceof Blob,
268
+ encode: async (b) => ({ name: b.name, type: b.type, base64: '...' }),
269
+ decode: (wire) => new Blob([], { type: wire.type }),
270
+ })
271
+
272
+ createAgentClient({ ..., codecs })
273
+ ```
274
+
275
+ `File`/`Blob` codecs are not in the default registry — handling is environment-specific (browser File API vs. Node Buffer vs. workers) and the encoded form is large enough that consumers should opt in deliberately.
276
+
277
+ ## Cloudflare-vite dual paths (dev only)
278
+
279
+ When a project ships `@cloudflare/vite-plugin`, that plugin proxies every
280
+ non-`/cdn-cgi/*` request to the worker — which shadows the canonical
281
+ `/agent/*` LAP routes. To keep agent flows working in dev, `@llui/vite-plugin`
282
+ registers the LAP middleware at **both** `/agent/*` and `/cdn-cgi/agent/*`,
283
+ and the client opts in by passing `agentBasePath: '/cdn-cgi/agent'`.
284
+
285
+ **This dual-path lives in the dev middleware only.** Production deployments
286
+ serve LAP routes from your own server (Express, Hono, the Cloudflare Worker
287
+ in `@llui/agent/server/cloudflare`, etc.); whichever base path you mount
288
+ there is what the client should target. The `/cdn-cgi/*` shim does not
289
+ exist in production and you do not need it — pick one canonical path
290
+ (`/agent` or whatever you mount), point `agentBasePath` at it, and you're
291
+ done.
@@ -11,16 +11,33 @@ export type ConfirmEntry = {
11
11
  export type AgentConfirmState = {
12
12
  pending: ConfirmEntry[];
13
13
  };
14
- export type AgentConfirmMsg = {
14
+ export type AgentConfirmMsg =
15
+ /**
16
+ * @humanOnly — internal: dispatched by `handleSendMessage` on the
17
+ * @llui/dom side when an agent message is gated by @requiresConfirm.
18
+ * Adds a pending entry to state; the user (not the agent) decides
19
+ * with Approve / Reject.
20
+ */
21
+ {
15
22
  type: 'Propose';
16
23
  entry: ConfirmEntry;
17
- } | {
24
+ }
25
+ /** @intent("Approve a pending agent action") */
26
+ | {
18
27
  type: 'Approve';
19
28
  id: string;
20
- } | {
29
+ }
30
+ /** @intent("Reject a pending agent action") */
31
+ | {
21
32
  type: 'Reject';
22
33
  id: string;
23
- } | {
34
+ }
35
+ /**
36
+ * @humanOnly — internal: the host app dispatches this on a timer to
37
+ * garbage-collect entries that have been pending past `maxAgeMs`.
38
+ * Agents have no business poking at the timer wheel directly.
39
+ */
40
+ | {
24
41
  type: 'ExpireStale';
25
42
  now: number;
26
43
  maxAgeMs: number;
@@ -28,33 +45,46 @@ export type AgentConfirmMsg = {
28
45
  export declare function init(): [AgentConfirmState, AgentEffect[]];
29
46
  export declare function update(state: AgentConfirmState, msg: AgentConfirmMsg): [AgentConfirmState, AgentEffect[]];
30
47
  import { type Send } from '@llui/dom';
31
- type ConnectBag = {
48
+ /**
49
+ * Static prop bag with reactive accessors. See agentConnect.ts for
50
+ * the rationale; spread directly into element helpers and the LLui
51
+ * runtime re-evaluates function-valued props on dirty bits.
52
+ *
53
+ * Per-entry props are exposed as a function `entry(id)` that returns
54
+ * a sub-bag whose values are themselves reactive — caller passes the
55
+ * id once, gets back a bag they can spread.
56
+ */
57
+ export type ConnectBag<S> = {
32
58
  root: {
33
- 'data-scope': string;
59
+ 'data-scope': 'agent-confirm';
34
60
  };
61
+ /**
62
+ * Resolves a per-entry sub-bag. The returned bag's accessors look
63
+ * up the entry by `id` lazily, so the bag stays valid even after
64
+ * approve/reject mutates the entry's status.
65
+ */
35
66
  entry: (id: string) => {
36
67
  card: {
37
- 'data-part': string;
38
- 'data-status': string;
68
+ 'data-part': 'entry';
69
+ 'data-status': (s: S) => 'pending' | 'approved' | 'rejected' | 'missing';
39
70
  'data-id': string;
40
71
  };
41
72
  approveButton: {
42
73
  onClick: () => void;
43
- disabled: boolean;
74
+ disabled: (s: S) => boolean;
44
75
  };
45
76
  rejectButton: {
46
77
  onClick: () => void;
47
- disabled: boolean;
78
+ disabled: (s: S) => boolean;
48
79
  };
49
- intentText: string;
50
- reasonText: string | null;
51
- payloadText: string;
52
- } | null;
80
+ intentText: (s: S) => string;
81
+ reasonText: (s: S) => string | null;
82
+ payloadText: (s: S) => string;
83
+ };
53
84
  empty: {
54
- 'data-part': string;
55
- 'data-visible': boolean;
85
+ 'data-part': 'empty';
86
+ 'data-visible': (s: S) => boolean;
56
87
  };
57
88
  };
58
- export declare function connect<S>(get: (s: S) => AgentConfirmState, send: Send<AgentConfirmMsg>): (state: S) => ConnectBag;
59
- export {};
89
+ export declare function connect<S>(get: (s: S) => AgentConfirmState, send: Send<AgentConfirmMsg>): ConnectBag<S>;
60
90
  //# sourceMappingURL=agentConfirm.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agentConfirm.d.ts","sourceRoot":"","sources":["../../src/client/agentConfirm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAA;CAC5C,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,OAAO,EAAE,YAAY,EAAE,CAAA;CAAE,CAAA;AAE3D,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1D,wBAAgB,IAAI,IAAI,CAAC,iBAAiB,EAAE,WAAW,EAAE,CAAC,CAEzD;AAED,wBAAgB,MAAM,CACpB,KAAK,EAAE,iBAAiB,EACxB,GAAG,EAAE,eAAe,GACnB,CAAC,iBAAiB,EAAE,WAAW,EAAE,CAAC,CAgCpC;AAGD,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AAErC,KAAK,UAAU,GAAG;IAChB,IAAI,EAAE;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAA;IAC9B,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK;QACrB,IAAI,EAAE;YAAE,WAAW,EAAE,MAAM,CAAC;YAAC,aAAa,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAA;SAAE,CAAA;QACvE,aAAa,EAAE;YAAE,OAAO,EAAE,MAAM,IAAI,CAAC;YAAC,QAAQ,EAAE,OAAO,CAAA;SAAE,CAAA;QACzD,YAAY,EAAE;YAAE,OAAO,EAAE,MAAM,IAAI,CAAC;YAAC,QAAQ,EAAE,OAAO,CAAA;SAAE,CAAA;QACxD,UAAU,EAAE,MAAM,CAAA;QAClB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;QACzB,WAAW,EAAE,MAAM,CAAA;KACpB,GAAG,IAAI,CAAA;IACR,KAAK,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,CAAA;CACxD,CAAA;AAED,wBAAgB,OAAO,CAAC,CAAC,EACvB,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,iBAAiB,EAChC,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,GAC1B,CAAC,KAAK,EAAE,CAAC,KAAK,UAAU,CA0B1B"}
1
+ {"version":3,"file":"agentConfirm.d.ts","sourceRoot":"","sources":["../../src/client/agentConfirm.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAA;CAC5C,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,OAAO,EAAE,YAAY,EAAE,CAAA;CAAE,CAAA;AAE3D,MAAM,MAAM,eAAe;AACzB;;;;;GAKG;AACD;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE;AAC1C,gDAAgD;GAC9C;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE;AACjC,+CAA+C;GAC7C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE;AAChC;;;;GAIG;GACD;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1D,wBAAgB,IAAI,IAAI,CAAC,iBAAiB,EAAE,WAAW,EAAE,CAAC,CAEzD;AAED,wBAAgB,MAAM,CACpB,KAAK,EAAE,iBAAiB,EACxB,GAAG,EAAE,eAAe,GACnB,CAAC,iBAAiB,EAAE,WAAW,EAAE,CAAC,CAgCpC;AAGD,OAAO,EAAW,KAAK,IAAI,EAAE,MAAM,WAAW,CAAA;AAE9C;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI;IAC1B,IAAI,EAAE;QAAE,YAAY,EAAE,eAAe,CAAA;KAAE,CAAA;IACvC;;;;OAIG;IACH,KAAK,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK;QACrB,IAAI,EAAE;YACJ,WAAW,EAAE,OAAO,CAAA;YACpB,aAAa,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;YACxE,SAAS,EAAE,MAAM,CAAA;SAClB,CAAA;QACD,aAAa,EAAE;YAAE,OAAO,EAAE,MAAM,IAAI,CAAC;YAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;SAAE,CAAA;QACnE,YAAY,EAAE;YAAE,OAAO,EAAE,MAAM,IAAI,CAAC;YAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;SAAE,CAAA;QAClE,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;QAC5B,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,GAAG,IAAI,CAAA;QACnC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,MAAM,CAAA;KAC9B,CAAA;IACD,KAAK,EAAE;QAAE,WAAW,EAAE,OAAO,CAAC;QAAC,cAAc,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,OAAO,CAAA;KAAE,CAAA;CACnE,CAAA;AAED,wBAAgB,OAAO,CAAC,CAAC,EACvB,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,iBAAiB,EAChC,IAAI,EAAE,IAAI,CAAC,eAAe,CAAC,GAC1B,UAAU,CAAC,CAAC,CAAC,CAgCf"}
@@ -34,33 +34,36 @@ export function update(state, msg) {
34
34
  }
35
35
  }
36
36
  // Connect bag:
37
- import {} from '@llui/dom';
37
+ import { tagSend } from '@llui/dom';
38
38
  export function connect(get, send) {
39
- return (state) => {
40
- const s = get(state);
41
- return {
42
- root: { 'data-scope': 'agent-confirm' },
43
- entry: (id) => {
44
- const e = s.pending.find((x) => x.id === id);
45
- if (!e)
46
- return null;
47
- return {
48
- card: { 'data-part': 'entry', 'data-status': e.status, 'data-id': e.id },
49
- approveButton: {
50
- onClick: () => send({ type: 'Approve', id }),
51
- disabled: e.status !== 'pending',
52
- },
53
- rejectButton: {
54
- onClick: () => send({ type: 'Reject', id }),
55
- disabled: e.status !== 'pending',
56
- },
57
- intentText: e.intent,
58
- reasonText: e.reason,
59
- payloadText: JSON.stringify(e.payload, null, 2),
60
- };
39
+ const findEntry = (state, id) => get(state).pending.find((e) => e.id === id);
40
+ return {
41
+ root: { 'data-scope': 'agent-confirm' },
42
+ entry: (id) => ({
43
+ card: {
44
+ 'data-part': 'entry',
45
+ 'data-status': (s) => findEntry(s, id)?.status ?? 'missing',
46
+ 'data-id': id,
47
+ },
48
+ approveButton: {
49
+ onClick: tagSend(send, ['Approve'], () => send({ type: 'Approve', id })),
50
+ disabled: (s) => findEntry(s, id)?.status !== 'pending',
51
+ },
52
+ rejectButton: {
53
+ onClick: tagSend(send, ['Reject'], () => send({ type: 'Reject', id })),
54
+ disabled: (s) => findEntry(s, id)?.status !== 'pending',
55
+ },
56
+ intentText: (s) => findEntry(s, id)?.intent ?? '',
57
+ reasonText: (s) => findEntry(s, id)?.reason ?? null,
58
+ payloadText: (s) => {
59
+ const e = findEntry(s, id);
60
+ return e ? JSON.stringify(e.payload, null, 2) : '';
61
61
  },
62
- empty: { 'data-part': 'empty', 'data-visible': s.pending.length === 0 },
63
- };
62
+ }),
63
+ empty: {
64
+ 'data-part': 'empty',
65
+ 'data-visible': (s) => get(s).pending.length === 0,
66
+ },
64
67
  };
65
68
  }
66
69
  //# sourceMappingURL=agentConfirm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agentConfirm.js","sourceRoot":"","sources":["../../src/client/agentConfirm.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentEffect } from './effects.js'\n\nexport type ConfirmEntry = {\n id: string\n variant: string\n payload: unknown\n intent: string\n reason: string | null\n proposedAt: number\n status: 'pending' | 'approved' | 'rejected'\n}\n\nexport type AgentConfirmState = { pending: ConfirmEntry[] }\n\nexport type AgentConfirmMsg =\n | { type: 'Propose'; entry: ConfirmEntry }\n | { type: 'Approve'; id: string }\n | { type: 'Reject'; id: string }\n | { type: 'ExpireStale'; now: number; maxAgeMs: number }\n\nexport function init(): [AgentConfirmState, AgentEffect[]] {\n return [{ pending: [] }, []]\n}\n\nexport function update(\n state: AgentConfirmState,\n msg: AgentConfirmMsg,\n): [AgentConfirmState, AgentEffect[]] {\n switch (msg.type) {\n case 'Propose':\n return [{ pending: [...state.pending, msg.entry] }, []]\n case 'Approve': {\n const entry = state.pending.find((e) => e.id === msg.id)\n if (!entry || entry.status !== 'pending') return [state, []]\n return [\n { pending: state.pending.map((e) => (e.id === msg.id ? { ...e, status: 'approved' } : e)) },\n [\n {\n type: 'AgentForwardMsg',\n payload: { type: entry.variant, ...(entry.payload as object) },\n },\n ],\n ]\n }\n case 'Reject':\n return [\n { pending: state.pending.map((e) => (e.id === msg.id ? { ...e, status: 'rejected' } : e)) },\n [],\n ]\n case 'ExpireStale':\n return [\n {\n pending: state.pending.filter(\n (e) => msg.now - e.proposedAt <= msg.maxAgeMs || e.status !== 'pending',\n ),\n },\n [],\n ]\n }\n}\n\n// Connect bag:\nimport { type Send } from '@llui/dom'\n\ntype ConnectBag = {\n root: { 'data-scope': string }\n entry: (id: string) => {\n card: { 'data-part': string; 'data-status': string; 'data-id': string }\n approveButton: { onClick: () => void; disabled: boolean }\n rejectButton: { onClick: () => void; disabled: boolean }\n intentText: string\n reasonText: string | null\n payloadText: string\n } | null\n empty: { 'data-part': string; 'data-visible': boolean }\n}\n\nexport function connect<S>(\n get: (s: S) => AgentConfirmState,\n send: Send<AgentConfirmMsg>,\n): (state: S) => ConnectBag {\n return (state) => {\n const s = get(state)\n return {\n root: { 'data-scope': 'agent-confirm' },\n entry: (id) => {\n const e = s.pending.find((x) => x.id === id)\n if (!e) return null\n return {\n card: { 'data-part': 'entry', 'data-status': e.status, 'data-id': e.id },\n approveButton: {\n onClick: () => send({ type: 'Approve', id }),\n disabled: e.status !== 'pending',\n },\n rejectButton: {\n onClick: () => send({ type: 'Reject', id }),\n disabled: e.status !== 'pending',\n },\n intentText: e.intent,\n reasonText: e.reason,\n payloadText: JSON.stringify(e.payload, null, 2),\n }\n },\n empty: { 'data-part': 'empty', 'data-visible': s.pending.length === 0 },\n }\n }\n}\n"]}
1
+ {"version":3,"file":"agentConfirm.js","sourceRoot":"","sources":["../../src/client/agentConfirm.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentEffect } from './effects.js'\n\nexport type ConfirmEntry = {\n id: string\n variant: string\n payload: unknown\n intent: string\n reason: string | null\n proposedAt: number\n status: 'pending' | 'approved' | 'rejected'\n}\n\nexport type AgentConfirmState = { pending: ConfirmEntry[] }\n\nexport type AgentConfirmMsg =\n /**\n * @humanOnly — internal: dispatched by `handleSendMessage` on the\n * @llui/dom side when an agent message is gated by @requiresConfirm.\n * Adds a pending entry to state; the user (not the agent) decides\n * with Approve / Reject.\n */\n | { type: 'Propose'; entry: ConfirmEntry }\n /** @intent(\"Approve a pending agent action\") */\n | { type: 'Approve'; id: string }\n /** @intent(\"Reject a pending agent action\") */\n | { type: 'Reject'; id: string }\n /**\n * @humanOnly — internal: the host app dispatches this on a timer to\n * garbage-collect entries that have been pending past `maxAgeMs`.\n * Agents have no business poking at the timer wheel directly.\n */\n | { type: 'ExpireStale'; now: number; maxAgeMs: number }\n\nexport function init(): [AgentConfirmState, AgentEffect[]] {\n return [{ pending: [] }, []]\n}\n\nexport function update(\n state: AgentConfirmState,\n msg: AgentConfirmMsg,\n): [AgentConfirmState, AgentEffect[]] {\n switch (msg.type) {\n case 'Propose':\n return [{ pending: [...state.pending, msg.entry] }, []]\n case 'Approve': {\n const entry = state.pending.find((e) => e.id === msg.id)\n if (!entry || entry.status !== 'pending') return [state, []]\n return [\n { pending: state.pending.map((e) => (e.id === msg.id ? { ...e, status: 'approved' } : e)) },\n [\n {\n type: 'AgentForwardMsg',\n payload: { type: entry.variant, ...(entry.payload as object) },\n },\n ],\n ]\n }\n case 'Reject':\n return [\n { pending: state.pending.map((e) => (e.id === msg.id ? { ...e, status: 'rejected' } : e)) },\n [],\n ]\n case 'ExpireStale':\n return [\n {\n pending: state.pending.filter(\n (e) => msg.now - e.proposedAt <= msg.maxAgeMs || e.status !== 'pending',\n ),\n },\n [],\n ]\n }\n}\n\n// Connect bag:\nimport { tagSend, type Send } from '@llui/dom'\n\n/**\n * Static prop bag with reactive accessors. See agentConnect.ts for\n * the rationale; spread directly into element helpers and the LLui\n * runtime re-evaluates function-valued props on dirty bits.\n *\n * Per-entry props are exposed as a function `entry(id)` that returns\n * a sub-bag whose values are themselves reactive — caller passes the\n * id once, gets back a bag they can spread.\n */\nexport type ConnectBag<S> = {\n root: { 'data-scope': 'agent-confirm' }\n /**\n * Resolves a per-entry sub-bag. The returned bag's accessors look\n * up the entry by `id` lazily, so the bag stays valid even after\n * approve/reject mutates the entry's status.\n */\n entry: (id: string) => {\n card: {\n 'data-part': 'entry'\n 'data-status': (s: S) => 'pending' | 'approved' | 'rejected' | 'missing'\n 'data-id': string\n }\n approveButton: { onClick: () => void; disabled: (s: S) => boolean }\n rejectButton: { onClick: () => void; disabled: (s: S) => boolean }\n intentText: (s: S) => string\n reasonText: (s: S) => string | null\n payloadText: (s: S) => string\n }\n empty: { 'data-part': 'empty'; 'data-visible': (s: S) => boolean }\n}\n\nexport function connect<S>(\n get: (s: S) => AgentConfirmState,\n send: Send<AgentConfirmMsg>,\n): ConnectBag<S> {\n const findEntry = (state: S, id: string): ConfirmEntry | undefined =>\n get(state).pending.find((e) => e.id === id)\n\n return {\n root: { 'data-scope': 'agent-confirm' },\n entry: (id) => ({\n card: {\n 'data-part': 'entry',\n 'data-status': (s) => findEntry(s, id)?.status ?? 'missing',\n 'data-id': id,\n },\n approveButton: {\n onClick: tagSend(send, ['Approve'], () => send({ type: 'Approve', id })),\n disabled: (s) => findEntry(s, id)?.status !== 'pending',\n },\n rejectButton: {\n onClick: tagSend(send, ['Reject'], () => send({ type: 'Reject', id })),\n disabled: (s) => findEntry(s, id)?.status !== 'pending',\n },\n intentText: (s) => findEntry(s, id)?.intent ?? '',\n reasonText: (s) => findEntry(s, id)?.reason ?? null,\n payloadText: (s) => {\n const e = findEntry(s, id)\n return e ? JSON.stringify(e.payload, null, 2) : ''\n },\n }),\n empty: {\n 'data-part': 'empty',\n 'data-visible': (s) => get(s).pending.length === 0,\n },\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import type { Send } from '@llui/dom';
1
+ import { type Send } from '@llui/dom';
2
2
  import type { AgentSession, AgentToken } from '../protocol.js';
3
3
  import type { AgentEffect } from './effects.js';
4
4
  export type AgentConnectStatus = 'idle' | 'minting' | 'pending-claude' | 'active' | 'error';
@@ -6,6 +6,13 @@ export type AgentConnectPendingToken = {
6
6
  token: AgentToken;
7
7
  tid: string;
8
8
  lapUrl: string;
9
+ /**
10
+ * Natural-language connect instruction the user copies into Claude.
11
+ * Includes URL, token, and the explicit `connect_session` tool
12
+ * call. Works in any Claude client (Desktop, CC CLI, etc.) — the
13
+ * Desktop-specific `/llui-connect` slash command is sugar over the
14
+ * same tool call.
15
+ */
9
16
  connectSnippet: string;
10
17
  expiresAt: number;
11
18
  };
@@ -19,89 +26,143 @@ export type AgentConnectState = {
19
26
  detail: string;
20
27
  } | null;
21
28
  };
22
- export type AgentConnectMsg = {
29
+ export type AgentConnectMsg =
30
+ /** @intent("Mint a new agent token and open the pairing WebSocket") */
31
+ {
23
32
  type: 'Mint';
24
- } | {
33
+ }
34
+ /**
35
+ * @humanOnly — internal: dispatched by the AgentMintRequest effect
36
+ * handler when the mint endpoint replies success. Carries the token
37
+ * and connection URLs into state.
38
+ */
39
+ | {
25
40
  type: 'MintSucceeded';
26
41
  token: AgentToken;
27
42
  tid: string;
28
43
  lapUrl: string;
29
44
  wsUrl: string;
30
45
  expiresAt: number;
31
- } | {
46
+ }
47
+ /** @humanOnly — internal: dispatched by the AgentMintRequest handler on failure. */
48
+ | {
32
49
  type: 'MintFailed';
33
50
  error: {
34
51
  code: string;
35
52
  detail: string;
36
53
  };
37
- } | {
54
+ }
55
+ /** @humanOnly — internal: WS adapter signalled the pairing socket is open. */
56
+ | {
38
57
  type: 'WsOpened';
39
- } | {
58
+ }
59
+ /** @humanOnly — internal: WS adapter signalled the pairing socket is closed. */
60
+ | {
40
61
  type: 'WsClosed';
41
- } | {
62
+ }
63
+ /** @humanOnly — internal: Claude bound the session via /agent/claim. */
64
+ | {
42
65
  type: 'ActivatedByClaude';
43
- } | {
66
+ }
67
+ /** @intent("Check which previously-issued agent sessions can be resumed") */
68
+ | {
44
69
  type: 'ResumeList';
45
70
  tids: string[];
46
- } | {
71
+ }
72
+ /** @humanOnly — internal: AgentResumeCheck effect handler returned the list. */
73
+ | {
47
74
  type: 'ResumeListLoaded';
48
75
  sessions: AgentSession[];
49
- } | {
76
+ }
77
+ /** @intent("Resume an existing agent session by tid") */
78
+ | {
50
79
  type: 'Resume';
51
80
  tid: string;
52
- } | {
81
+ }
82
+ /** @intent("Revoke an agent session by tid") */
83
+ | {
53
84
  type: 'Revoke';
54
85
  tid: string;
55
- } | {
86
+ }
87
+ /** @intent("Dismiss the current agent connect error") */
88
+ | {
56
89
  type: 'ClearError';
57
- } | {
90
+ }
91
+ /** @humanOnly — internal: AgentSessionsList effect handler returned the list. */
92
+ | {
58
93
  type: 'SessionsLoaded';
59
94
  sessions: AgentSession[];
60
- } | {
95
+ }
96
+ /** @intent("Refresh the list of active agent sessions") */
97
+ | {
61
98
  type: 'RefreshSessions';
99
+ }
100
+ /**
101
+ * @intent("Copy the agent connect snippet to the clipboard")
102
+ * Resolves the pendingToken's snippet in update() (state-reading is
103
+ * what update() is for) and dispatches a clipboard-write effect.
104
+ */
105
+ | {
106
+ type: 'CopyConnectSnippet';
62
107
  };
108
+ /**
109
+ * Options threaded through `init()` and `update()`. `mintUrl` is
110
+ * optional — when omitted the agent effect handler derives it from
111
+ * `EffectHandlerHost.agentBasePath` (default `/agent` → `/agent/mint`).
112
+ * Set explicitly only when the mint endpoint lives outside the
113
+ * configured base path.
114
+ */
63
115
  export type AgentConnectInitOpts = {
64
- mintUrl: string;
116
+ mintUrl?: string;
65
117
  };
66
118
  /** Component shape is [State, Effect[]] — consistent with @llui/components. */
67
119
  export declare function init(_opts: AgentConnectInitOpts): [AgentConnectState, AgentEffect[]];
68
- export declare function update(state: AgentConnectState, msg: AgentConnectMsg, opts: AgentConnectInitOpts): [AgentConnectState, AgentEffect[]];
120
+ export declare function update(state: AgentConnectState, msg: AgentConnectMsg, opts?: AgentConnectInitOpts): [AgentConnectState, AgentEffect[]];
69
121
  export type AgentConnectConnectOptions = {
70
122
  id?: string;
71
123
  };
72
- type ConnectBag = {
124
+ /**
125
+ * Static prop bag with reactive accessors. Mirrors the @llui/components
126
+ * pattern (e.g. `dialog.connect`): callers spread bag keys directly
127
+ * into element helpers, and function-valued props re-evaluate per
128
+ * binding-mask hit. The previous shape — `(state) => bag` — required
129
+ * callers to wrap every prop access in their own arrow, which the
130
+ * documented usage didn't do (and silently produced `undefined` props
131
+ * when spread).
132
+ */
133
+ export type ConnectBag<S> = {
73
134
  root: {
74
- 'data-scope': string;
75
- 'data-state': string;
135
+ 'data-scope': 'agent-connect';
136
+ 'data-state': (s: S) => AgentConnectStatus;
76
137
  };
77
138
  mintTrigger: {
78
139
  onClick: () => void;
79
- disabled: boolean;
140
+ disabled: (s: S) => boolean;
80
141
  };
81
142
  pendingTokenBox: {
82
- 'data-part': string;
83
- 'data-visible': boolean;
143
+ 'data-part': 'pending-token';
144
+ 'data-visible': (s: S) => boolean;
84
145
  };
85
146
  copyConnectSnippetButton: {
86
147
  onClick: () => void;
87
- disabled: boolean;
148
+ disabled: (s: S) => boolean;
88
149
  };
89
150
  sessionsList: {
90
- 'data-part': string;
151
+ 'data-part': 'sessions-list';
91
152
  };
92
153
  sessionItem: (tid: string) => {
93
- 'data-part': string;
154
+ 'data-part': 'session-item';
94
155
  'data-tid': string;
95
156
  };
96
157
  revokeButton: (tid: string) => {
97
158
  onClick: () => void;
98
159
  };
99
160
  resumeBanner: {
100
- 'data-part': string;
101
- 'data-visible': boolean;
161
+ 'data-part': 'resume-banner';
162
+ 'data-visible': (s: S) => boolean;
102
163
  };
103
164
  resumeItem: (tid: string) => {
104
- 'data-part': string;
165
+ 'data-part': 'resume-item';
105
166
  'data-tid': string;
106
167
  };
107
168
  resumeButton: (tid: string) => {
@@ -111,15 +172,15 @@ type ConnectBag = {
111
172
  onClick: () => void;
112
173
  };
113
174
  error: {
114
- 'data-part': string;
115
- 'data-visible': boolean;
175
+ 'data-part': 'error';
176
+ 'data-visible': (s: S) => boolean;
116
177
  onClick: () => void;
117
178
  };
118
179
  };
119
180
  /**
120
- * Builds prop bags for the view. See spec §9.1 and the @llui/components
121
- * dialog.ts pattern.
181
+ * Builds prop bags for the view. Static-bag-with-reactive-accessors
182
+ * shape (matches the @llui/components convention); spread directly
183
+ * into element helpers.
122
184
  */
123
- export declare function connect<S>(get: (s: S) => AgentConnectState, send: Send<AgentConnectMsg>, _opts?: AgentConnectConnectOptions): (state: S) => ConnectBag;
124
- export {};
185
+ export declare function connect<S>(get: (s: S) => AgentConnectState, send: Send<AgentConnectMsg>, _opts?: AgentConnectConnectOptions): ConnectBag<S>;
125
186
  //# sourceMappingURL=agentConnect.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agentConnect.d.ts","sourceRoot":"","sources":["../../src/client/agentConnect.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agentConnect.d.ts","sourceRoot":"","sources":["../../src/client/agentConnect.ts"],"names":[],"mappings":"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"}