@parlor/agent-ui 0.0.0-stage → 0.1.0

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 (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +10 -2
  3. package/dist/client/agent-ui-client.d.ts +60 -0
  4. package/dist/client/agent-ui-client.d.ts.map +1 -0
  5. package/dist/client/agent-ui-client.js +407 -0
  6. package/dist/client/agent-ui-client.js.map +1 -0
  7. package/dist/client/confirmations.d.ts +34 -0
  8. package/dist/client/confirmations.d.ts.map +1 -0
  9. package/dist/client/confirmations.js +95 -0
  10. package/dist/client/confirmations.js.map +1 -0
  11. package/dist/client/environment.d.ts +37 -0
  12. package/dist/client/environment.d.ts.map +1 -0
  13. package/dist/client/environment.js +79 -0
  14. package/dist/client/environment.js.map +1 -0
  15. package/dist/client/highlight.d.ts +12 -0
  16. package/dist/client/highlight.d.ts.map +1 -0
  17. package/dist/client/highlight.js +98 -0
  18. package/dist/client/highlight.js.map +1 -0
  19. package/dist/client/index.d.ts +7 -0
  20. package/dist/client/index.d.ts.map +1 -0
  21. package/dist/client/index.js +7 -0
  22. package/dist/client/index.js.map +1 -0
  23. package/dist/client/json-equal.d.ts +2 -0
  24. package/dist/client/json-equal.d.ts.map +1 -0
  25. package/dist/client/json-equal.js +20 -0
  26. package/dist/client/json-equal.js.map +1 -0
  27. package/dist/client/registry.d.ts +54 -0
  28. package/dist/client/registry.d.ts.map +1 -0
  29. package/dist/client/registry.js +280 -0
  30. package/dist/client/registry.js.map +1 -0
  31. package/dist/client/screen.d.ts +20 -0
  32. package/dist/client/screen.d.ts.map +1 -0
  33. package/dist/client/screen.js +196 -0
  34. package/dist/client/screen.js.map +1 -0
  35. package/dist/client/write.d.ts +13 -0
  36. package/dist/client/write.d.ts.map +1 -0
  37. package/dist/client/write.js +101 -0
  38. package/dist/client/write.js.map +1 -0
  39. package/dist/index.d.ts +4 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +4 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/manifest.d.ts +44 -0
  44. package/dist/manifest.d.ts.map +1 -0
  45. package/dist/manifest.js +23 -0
  46. package/dist/manifest.js.map +1 -0
  47. package/dist/protocol.d.ts +206 -0
  48. package/dist/protocol.d.ts.map +1 -0
  49. package/dist/protocol.js +152 -0
  50. package/dist/protocol.js.map +1 -0
  51. package/dist/server/agent-ui.d.ts +36 -0
  52. package/dist/server/agent-ui.d.ts.map +1 -0
  53. package/dist/server/agent-ui.js +89 -0
  54. package/dist/server/agent-ui.js.map +1 -0
  55. package/dist/server/audience.d.ts +9 -0
  56. package/dist/server/audience.d.ts.map +1 -0
  57. package/dist/server/audience.js +15 -0
  58. package/dist/server/audience.js.map +1 -0
  59. package/dist/server/broker.d.ts +29 -0
  60. package/dist/server/broker.d.ts.map +1 -0
  61. package/dist/server/broker.js +152 -0
  62. package/dist/server/broker.js.map +1 -0
  63. package/dist/server/confirmations.d.ts +40 -0
  64. package/dist/server/confirmations.d.ts.map +1 -0
  65. package/dist/server/confirmations.js +230 -0
  66. package/dist/server/confirmations.js.map +1 -0
  67. package/dist/server/directory.d.ts +41 -0
  68. package/dist/server/directory.d.ts.map +1 -0
  69. package/dist/server/directory.js +193 -0
  70. package/dist/server/directory.js.map +1 -0
  71. package/dist/server/index.d.ts +10 -0
  72. package/dist/server/index.d.ts.map +1 -0
  73. package/dist/server/index.js +10 -0
  74. package/dist/server/index.js.map +1 -0
  75. package/dist/server/manifest-source.d.ts +10 -0
  76. package/dist/server/manifest-source.d.ts.map +1 -0
  77. package/dist/server/manifest-source.js +36 -0
  78. package/dist/server/manifest-source.js.map +1 -0
  79. package/dist/server/routes.d.ts +11 -0
  80. package/dist/server/routes.d.ts.map +1 -0
  81. package/dist/server/routes.js +38 -0
  82. package/dist/server/routes.js.map +1 -0
  83. package/dist/server/schemas.d.ts +69 -0
  84. package/dist/server/schemas.d.ts.map +1 -0
  85. package/dist/server/schemas.js +78 -0
  86. package/dist/server/schemas.js.map +1 -0
  87. package/dist/server/tools.d.ts +49 -0
  88. package/dist/server/tools.d.ts.map +1 -0
  89. package/dist/server/tools.js +312 -0
  90. package/dist/server/tools.js.map +1 -0
  91. package/dist/view.d.ts +54 -0
  92. package/dist/view.d.ts.map +1 -0
  93. package/dist/view.js +15 -0
  94. package/dist/view.js.map +1 -0
  95. package/dist/vite/index.d.ts +3 -0
  96. package/dist/vite/index.d.ts.map +1 -0
  97. package/dist/vite/index.js +3 -0
  98. package/dist/vite/index.js.map +1 -0
  99. package/dist/vite/manifest.d.ts +5 -0
  100. package/dist/vite/manifest.d.ts.map +1 -0
  101. package/dist/vite/manifest.js +107 -0
  102. package/dist/vite/manifest.js.map +1 -0
  103. package/dist/vite/plugin.d.ts +10 -0
  104. package/dist/vite/plugin.d.ts.map +1 -0
  105. package/dist/vite/plugin.js +143 -0
  106. package/dist/vite/plugin.js.map +1 -0
  107. package/package.json +65 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 cychien
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,11 @@
1
- # Temporary Holding Version
1
+ # @parlor/agent-ui
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ The agent's view of the app: route descriptions, views and the UI manifest an agent reads to know where the user is. Installed by `@parlor/client` and `@parlor/server`; you do not depend on it directly.
4
+
5
+ ```ts
6
+ import { UI_MANIFEST_FILE } from "@parlor/agent-ui";
7
+
8
+ console.log(UI_MANIFEST_FILE);
9
+ ```
10
+
11
+ Docs: https://cychien.github.io/parlor/guides/agent-sidebar/
@@ -0,0 +1,60 @@
1
+ import type { ClientChannel } from "@parlor/sync";
2
+ import type { AnyRouter } from "@tanstack/router-core";
3
+ import { type AgentOrigin, type ClientMessage, type QuerySnapshot, type RouteSnapshot, type ScreenSnapshot, type UiErrorCode, type UiOp } from "../protocol.js";
4
+ import { type ConfirmationStore } from "./confirmations.js";
5
+ import { type BrowserEnvironment } from "./environment.js";
6
+ import { type ViewRegistry } from "./registry.js";
7
+ import { type ScreenLimits } from "./screen.js";
8
+ export interface QuerySource {
9
+ active(): readonly QuerySnapshot[];
10
+ settled(timeoutMs: number): Promise<void>;
11
+ }
12
+ export interface AgentUiClientOptions {
13
+ readonly router?: AnyRouter | undefined;
14
+ readonly queries: QuerySource;
15
+ readonly send: (message: ClientMessage) => Promise<string | undefined>;
16
+ readonly platform: string;
17
+ readonly buildId?: string | undefined;
18
+ readonly environment?: BrowserEnvironment | undefined;
19
+ readonly limits?: Partial<ScreenLimits> | undefined;
20
+ readonly settleMs?: number | undefined;
21
+ readonly dev?: boolean | undefined;
22
+ }
23
+ /** What an agent is doing on this screen: a UI op, or waiting for the user to confirm. */
24
+ export type AgentActivityKind = UiOp | "confirm";
25
+ /** How the app answered an operation: it did it, or refused with the error code the agent got. */
26
+ export type AgentOutcome = {
27
+ readonly status: "done";
28
+ } | {
29
+ readonly status: "refused";
30
+ readonly code: UiErrorCode;
31
+ };
32
+ export interface AgentActivity {
33
+ /** A request is running, or a confirmation card is waiting for the user on this client. */
34
+ readonly busy: boolean;
35
+ readonly last: {
36
+ readonly op: AgentActivityKind;
37
+ readonly origin: AgentOrigin;
38
+ readonly at: number;
39
+ /** Undefined while the operation runs, and for `confirm`, which the user answers. */
40
+ readonly outcome?: AgentOutcome | undefined;
41
+ } | undefined;
42
+ }
43
+ export interface ActivityStore {
44
+ subscribe(listener: () => void): () => void;
45
+ get(): AgentActivity;
46
+ }
47
+ export interface AgentUiClient extends ClientChannel {
48
+ readonly views: ViewRegistry;
49
+ readonly activity: ActivityStore;
50
+ readonly confirmations: ConfirmationStore;
51
+ screen(): Promise<ScreenSnapshot>;
52
+ start(): () => void;
53
+ /** Forgets what belongs to the signed-in user: the pending confirmations. */
54
+ reset(): void;
55
+ /** Declares a chat thread shown here until the returned function runs (presence `watching`). */
56
+ watch(threadId: string): () => void;
57
+ }
58
+ export declare function routeSnapshot(router: AnyRouter): RouteSnapshot | null;
59
+ export declare function createAgentUiClient(options: AgentUiClientOptions): AgentUiClient;
60
+ //# sourceMappingURL=agent-ui-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-ui-client.d.ts","sourceRoot":"","sources":["../../src/client/agent-ui-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,407 @@
1
+ import { MAX_WATCHED_THREADS, parseUiFrame, UI_CHANNEL, UI_OPS, } from "../protocol.js";
2
+ import {} from "../view.js";
3
+ import { createConfirmationStore } from "./confirmations.js";
4
+ import { browserEnvironment } from "./environment.js";
5
+ import { createHighlightMarks, highlightView } from "./highlight.js";
6
+ import { createViewRegistry } from "./registry.js";
7
+ import { captureScreen, DEFAULT_SCREEN_LIMITS } from "./screen.js";
8
+ import { setView } from "./write.js";
9
+ const REPLY_CACHE_SIZE = 64;
10
+ const DEFAULT_SETTLE_MS = 1500;
11
+ const OBSERVER_WAIT_MS = 100;
12
+ export function routeSnapshot(router) {
13
+ const { matches, location } = router.state;
14
+ const leaf = matches.at(-1);
15
+ if (!leaf)
16
+ return null;
17
+ if (matches.some((match) => match._notFound)) {
18
+ return { notFound: true, url: location.href };
19
+ }
20
+ return {
21
+ notFound: false,
22
+ path: leaf.fullPath,
23
+ params: leaf.params,
24
+ search: location.search,
25
+ url: location.href,
26
+ };
27
+ }
28
+ function createActivityStore() {
29
+ const listeners = new Set();
30
+ let running = false;
31
+ let pending = 0;
32
+ let last;
33
+ let state = { busy: false, last: undefined };
34
+ const publish = () => {
35
+ state = { busy: running || pending > 0, last };
36
+ for (const listener of listeners)
37
+ listener();
38
+ };
39
+ return {
40
+ subscribe(listener) {
41
+ listeners.add(listener);
42
+ return () => listeners.delete(listener);
43
+ },
44
+ get: () => state,
45
+ begin(request, at) {
46
+ running = true;
47
+ last = { op: request.op, origin: request.origin, at, outcome: undefined };
48
+ publish();
49
+ },
50
+ end(reply) {
51
+ running = false;
52
+ if (last && last.op !== "confirm") {
53
+ last = {
54
+ ...last,
55
+ outcome: reply.ok
56
+ ? { status: "done" }
57
+ : { status: "refused", code: reply.error.code },
58
+ };
59
+ }
60
+ publish();
61
+ },
62
+ confirming(count, arrived) {
63
+ pending = count;
64
+ if (arrived)
65
+ last = { op: "confirm", origin: arrived.origin, at: arrived.at };
66
+ publish();
67
+ },
68
+ watched: () => listeners.size > 0,
69
+ };
70
+ }
71
+ export function createAgentUiClient(options) {
72
+ const env = options.environment ?? browserEnvironment();
73
+ const limits = { ...DEFAULT_SCREEN_LIMITS, ...options.limits };
74
+ const registry = createViewRegistry(env);
75
+ const unlistedWarned = new Set();
76
+ const warnIfUnlisted = (view) => {
77
+ const router = options.router;
78
+ if (!options.dev || !router || unlistedWarned.has(view.name))
79
+ return;
80
+ const matches = router.state.matches;
81
+ if (matches.some((match) => match.staticData?.views?.includes(view)))
82
+ return;
83
+ unlistedWarned.add(view.name);
84
+ console.warn(`[parlor] The agent view "${view.name}" mounted on ${router.state.location.pathname}, but no matched route lists it in staticData.views, so the manifest cannot tell agents where it lives.`);
85
+ };
86
+ const views = {
87
+ track(view, binding) {
88
+ const slot = registry.track(view, binding);
89
+ return {
90
+ ...slot,
91
+ mount(key) {
92
+ warnIfUnlisted(view);
93
+ return slot.mount(key);
94
+ },
95
+ };
96
+ },
97
+ };
98
+ const activity = createActivityStore();
99
+ const marks = createHighlightMarks(env);
100
+ const confirmations = createConfirmationStore({
101
+ env,
102
+ answer: (id, approve) => post({ type: "answer", id, approve }),
103
+ onWatchedChange: () => schedulePresence(),
104
+ onChange: () => {
105
+ const showing = confirmations.get();
106
+ const arrived = showing.filter((item) => !seenCards.has(item.id)).at(-1);
107
+ for (const item of showing)
108
+ seenCards.add(item.id);
109
+ activity.confirming(showing.length, arrived && { origin: arrived.origin, at: env.now() });
110
+ },
111
+ });
112
+ const seenCards = new Set();
113
+ const replies = new Map();
114
+ const queued = new Set();
115
+ const queue = [];
116
+ let draining = false;
117
+ let warnedUnwatched = false;
118
+ const deliver = (message) => options.send(message).then((next) => {
119
+ if (next !== undefined)
120
+ receive(next);
121
+ }, () => { });
122
+ const post = (message) => void deliver(message);
123
+ let lifecycleTail;
124
+ const postInOrder = (message) => {
125
+ const delivered = lifecycleTail === undefined
126
+ ? deliver(message)
127
+ : lifecycleTail.then(() => deliver(message));
128
+ const tail = delivered.finally(() => {
129
+ if (lifecycleTail === tail)
130
+ lifecycleTail = undefined;
131
+ });
132
+ lifecycleTail = tail;
133
+ };
134
+ const observed = async () => {
135
+ // A hidden page does not render, so its observer stays silent until it is shown.
136
+ if (!registry.awaitingObserver() || env.document?.visibilityState !== "visible") {
137
+ return;
138
+ }
139
+ let timer;
140
+ await Promise.race([
141
+ registry.observed(),
142
+ new Promise((resolve) => {
143
+ timer = env.setTimeout(resolve, OBSERVER_WAIT_MS);
144
+ }),
145
+ ]);
146
+ env.clearTimeout(timer);
147
+ };
148
+ const screen = async () => {
149
+ await observed();
150
+ return captureScreen(registry, {
151
+ route: () => (options.router ? routeSnapshot(options.router) : null),
152
+ queries: () => options.queries.active(),
153
+ }, env, limits);
154
+ };
155
+ const settleMs = options.settleMs ?? DEFAULT_SETTLE_MS;
156
+ const navigate = async (input) => {
157
+ const router = options.router;
158
+ if (!router) {
159
+ return {
160
+ code: "unknown_route",
161
+ message: "This app did not give FrameworkProvider a router, so it cannot navigate.",
162
+ };
163
+ }
164
+ if (!Object.hasOwn(router.routesByPath, input.to)) {
165
+ return { code: "unknown_route", message: `This app has no route ${input.to}.` };
166
+ }
167
+ const deadline = env.now() + settleMs;
168
+ let timer;
169
+ await Promise.race([
170
+ router.navigate({
171
+ to: input.to,
172
+ ...(input.params ? { params: input.params } : {}),
173
+ ...(input.search ? { search: input.search } : {}),
174
+ ...(input.replace === undefined ? {} : { replace: input.replace }),
175
+ }),
176
+ new Promise((resolve) => {
177
+ timer = env.setTimeout(resolve, settleMs);
178
+ }),
179
+ ]);
180
+ env.clearTimeout(timer);
181
+ await env.nextTask();
182
+ await options.queries.settled(Math.max(0, deadline - env.now()));
183
+ await env.nextTask();
184
+ return screen();
185
+ };
186
+ const execute = async (request) => {
187
+ const ok = (result) => ({
188
+ type: "reply",
189
+ id: request.id,
190
+ ok: true,
191
+ result,
192
+ });
193
+ const fail = (error) => ({
194
+ type: "reply",
195
+ id: request.id,
196
+ ok: false,
197
+ error,
198
+ });
199
+ try {
200
+ switch (request.op) {
201
+ case "screen":
202
+ return ok(await screen());
203
+ case "navigate": {
204
+ const outcome = await navigate(request.input);
205
+ return "code" in outcome ? fail(outcome) : ok({ screen: outcome });
206
+ }
207
+ case "set": {
208
+ const outcome = await setView(registry, request.input, env);
209
+ return "code" in outcome ? fail(outcome) : ok(outcome);
210
+ }
211
+ case "highlight": {
212
+ const outcome = await highlightView(registry, request.input, env, marks);
213
+ return "code" in outcome ? fail(outcome) : ok(outcome);
214
+ }
215
+ }
216
+ }
217
+ catch (error) {
218
+ return fail({
219
+ code: "internal",
220
+ message: error instanceof Error ? error.message : "The app failed to answer.",
221
+ });
222
+ }
223
+ };
224
+ const remember = (reply) => {
225
+ replies.set(reply.id, reply);
226
+ if (replies.size > REPLY_CACHE_SIZE)
227
+ replies.delete(replies.keys().next().value);
228
+ post(reply);
229
+ };
230
+ const drain = async () => {
231
+ if (draining)
232
+ return;
233
+ draining = true;
234
+ while (queue.length > 0) {
235
+ const request = queue.shift();
236
+ activity.begin(request, env.now());
237
+ const reply = await execute(request);
238
+ queued.delete(request.id);
239
+ remember(reply);
240
+ activity.end(reply);
241
+ }
242
+ draining = false;
243
+ };
244
+ const warnIfUnwatched = () => {
245
+ if (!options.dev || warnedUnwatched || activity.watched())
246
+ return;
247
+ warnedUnwatched = true;
248
+ console.warn("[parlor] An agent is reading or driving this screen, but nothing renders useAgentActivity(). Show users when an agent is at work by building an indicator on useAgentActivity().");
249
+ };
250
+ const watched = new Map();
251
+ let lastPresence;
252
+ let gone = false;
253
+ let connected = false;
254
+ let presenceTimer;
255
+ const presence = () => {
256
+ const visible = env.document?.visibilityState === "visible";
257
+ return {
258
+ type: "presence",
259
+ focused: visible && (env.document?.hasFocus() ?? false),
260
+ visible,
261
+ platform: options.platform,
262
+ ...(options.buildId === undefined ? {} : { buildId: options.buildId }),
263
+ ops: UI_OPS,
264
+ canConfirm: confirmations.watched(),
265
+ ...(watched.size > 0
266
+ ? { watching: [...watched.keys()].slice(0, MAX_WATCHED_THREADS) }
267
+ : {}),
268
+ };
269
+ };
270
+ const reportPresence = () => {
271
+ if (gone || !connected)
272
+ return;
273
+ const update = presence();
274
+ const serialized = JSON.stringify(update);
275
+ if (serialized === lastPresence)
276
+ return;
277
+ lastPresence = serialized;
278
+ postInOrder(update);
279
+ };
280
+ const schedulePresence = () => {
281
+ if (presenceTimer !== undefined)
282
+ return;
283
+ presenceTimer = env.setTimeout(() => {
284
+ presenceTimer = undefined;
285
+ reportPresence();
286
+ }, 0);
287
+ };
288
+ const leave = () => {
289
+ gone = true;
290
+ lastPresence = undefined;
291
+ if (presenceTimer !== undefined)
292
+ env.clearTimeout(presenceTimer);
293
+ presenceTimer = undefined;
294
+ postInOrder({ type: "leave" });
295
+ };
296
+ const resume = () => {
297
+ gone = false;
298
+ schedulePresence();
299
+ };
300
+ const presenceTargets = () => [
301
+ [env.window, "focus", schedulePresence],
302
+ [env.window, "blur", schedulePresence],
303
+ [env.window, "pageshow", resume],
304
+ [env.window, "pagehide", leave],
305
+ [env.document, "visibilitychange", schedulePresence],
306
+ ];
307
+ let presenceAttached = false;
308
+ const attachPresence = () => {
309
+ if (presenceAttached)
310
+ return;
311
+ presenceAttached = true;
312
+ for (const [target, event, listener] of presenceTargets()) {
313
+ target?.addEventListener(event, listener);
314
+ }
315
+ };
316
+ const detachPresence = () => {
317
+ presenceAttached = false;
318
+ for (const [target, event, listener] of presenceTargets()) {
319
+ target?.removeEventListener(event, listener);
320
+ }
321
+ if (presenceTimer !== undefined)
322
+ env.clearTimeout(presenceTimer);
323
+ presenceTimer = undefined;
324
+ lastPresence = undefined;
325
+ };
326
+ const receive = (data) => {
327
+ const parsed = parseUiFrame(data);
328
+ if (!parsed.ok) {
329
+ if (parsed.id !== undefined) {
330
+ remember({
331
+ type: "reply",
332
+ id: parsed.id,
333
+ ok: false,
334
+ error: {
335
+ code: "internal",
336
+ message: "The app could not read this UI request.",
337
+ },
338
+ });
339
+ }
340
+ return;
341
+ }
342
+ const { frame: request } = parsed;
343
+ if (!("op" in request)) {
344
+ confirmations.replace(request.items);
345
+ return;
346
+ }
347
+ const cached = replies.get(request.id);
348
+ if (cached) {
349
+ post(cached);
350
+ return;
351
+ }
352
+ if (queued.has(request.id))
353
+ return;
354
+ warnIfUnwatched();
355
+ queued.add(request.id);
356
+ queue.push(request);
357
+ void drain();
358
+ };
359
+ return {
360
+ event: UI_CHANNEL,
361
+ views,
362
+ activity,
363
+ confirmations,
364
+ screen,
365
+ opened() {
366
+ gone = false;
367
+ connected = true;
368
+ attachPresence();
369
+ lastPresence = undefined;
370
+ reportPresence();
371
+ },
372
+ closed() {
373
+ connected = false;
374
+ detachPresence();
375
+ },
376
+ receive,
377
+ watch(threadId) {
378
+ watched.set(threadId, (watched.get(threadId) ?? 0) + 1);
379
+ schedulePresence();
380
+ let released = false;
381
+ return () => {
382
+ if (released)
383
+ return;
384
+ released = true;
385
+ const remaining = (watched.get(threadId) ?? 1) - 1;
386
+ if (remaining > 0)
387
+ watched.set(threadId, remaining);
388
+ else
389
+ watched.delete(threadId);
390
+ schedulePresence();
391
+ };
392
+ },
393
+ reset() {
394
+ confirmations.replace([]);
395
+ },
396
+ start() {
397
+ registry.resume();
398
+ return () => {
399
+ registry.dispose();
400
+ marks.dispose();
401
+ confirmations.dispose();
402
+ detachPresence();
403
+ };
404
+ },
405
+ };
406
+ }
407
+ //# sourceMappingURL=agent-ui-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-ui-client.js","sourceRoot":"","sources":["../../src/client/agent-ui-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { AgentOrigin, ConfirmationPrompt } from "../protocol.js";
2
+ import type { BrowserEnvironment } from "./environment.js";
3
+ /** A pending agent request the user must approve, as an app renders it. */
4
+ export interface AgentConfirmation {
5
+ readonly id: string;
6
+ readonly action: string;
7
+ readonly description: string;
8
+ /** The validated input the action will run with, as JSON. */
9
+ readonly input: unknown;
10
+ readonly origin: AgentOrigin;
11
+ /** Local `Date.now()` time after which the server stops waiting. */
12
+ readonly expiresAt: number;
13
+ /** The chat thread an inline agent asked from; the chat shows the card inline there. */
14
+ readonly threadId?: string | undefined;
15
+ readonly approve: () => void;
16
+ readonly decline: () => void;
17
+ }
18
+ export interface ConfirmationStore {
19
+ subscribe(listener: () => void): () => void;
20
+ get(): readonly AgentConfirmation[];
21
+ }
22
+ export interface ConfirmationStoreRuntime extends ConfirmationStore {
23
+ replace(items: readonly ConfirmationPrompt[]): void;
24
+ watched(): boolean;
25
+ dispose(): void;
26
+ }
27
+ export interface ConfirmationStoreOptions {
28
+ readonly env: Pick<BrowserEnvironment, "now" | "setTimeout" | "clearTimeout">;
29
+ readonly answer: (id: string, approve: boolean) => void;
30
+ readonly onWatchedChange: () => void;
31
+ readonly onChange: () => void;
32
+ }
33
+ export declare function createConfirmationStore(options: ConfirmationStoreOptions): ConfirmationStoreRuntime;
34
+ //# sourceMappingURL=confirmations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"confirmations.d.ts","sourceRoot":"","sources":["../../src/client/confirmations.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,2EAA2E;AAC3E,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,6DAA6D;IAC7D,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,oEAAoE;IACpE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wFAAwF;IACxF,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC5C,GAAG,IAAI,SAAS,iBAAiB,EAAE,CAAC;CACrC;AAED,MAAM,WAAW,wBAAyB,SAAQ,iBAAiB;IACjE,OAAO,CAAC,KAAK,EAAE,SAAS,kBAAkB,EAAE,GAAG,IAAI,CAAC;IACpD,OAAO,IAAI,OAAO,CAAC;IACnB,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,kBAAkB,EAAE,KAAK,GAAG,YAAY,GAAG,cAAc,CAAC,CAAC;IAC9E,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACxD,QAAQ,CAAC,eAAe,EAAE,MAAM,IAAI,CAAC;IACrC,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC/B;AAoBD,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,GAChC,wBAAwB,CAoF1B"}
@@ -0,0 +1,95 @@
1
+ const signatureOf = (prompt) => JSON.stringify([
2
+ prompt.action,
3
+ prompt.description,
4
+ prompt.input,
5
+ prompt.origin.via,
6
+ prompt.origin.name,
7
+ prompt.threadId,
8
+ ]);
9
+ const sameItems = (a, b) => a.length === b.length && a.every((item, index) => item === b[index]);
10
+ export function createConfirmationStore(options) {
11
+ const { env } = options;
12
+ const listeners = new Set();
13
+ let entries = new Map();
14
+ const answered = new Set();
15
+ let visible = [];
16
+ let expiry;
17
+ const scheduleExpiry = () => {
18
+ env.clearTimeout(expiry);
19
+ expiry = undefined;
20
+ if (visible.length === 0)
21
+ return;
22
+ const next = Math.min(...visible.map((item) => item.expiresAt));
23
+ expiry = env.setTimeout(expire, Math.max(0, next - env.now()));
24
+ };
25
+ const commit = () => {
26
+ const next = [...entries.values()]
27
+ .map((entry) => entry.item)
28
+ .filter((item) => !answered.has(item.id));
29
+ if (sameItems(next, visible))
30
+ return;
31
+ visible = next;
32
+ scheduleExpiry();
33
+ for (const listener of listeners)
34
+ listener();
35
+ options.onChange();
36
+ };
37
+ function expire() {
38
+ const now = env.now();
39
+ entries = new Map([...entries].filter(([, entry]) => entry.item.expiresAt > now));
40
+ commit();
41
+ scheduleExpiry();
42
+ }
43
+ const respond = (id, approve) => {
44
+ if (answered.has(id))
45
+ return;
46
+ answered.add(id);
47
+ options.answer(id, approve);
48
+ commit();
49
+ };
50
+ const itemOf = (prompt) => ({
51
+ id: prompt.id,
52
+ action: prompt.action,
53
+ description: prompt.description,
54
+ input: prompt.input,
55
+ origin: prompt.origin,
56
+ expiresAt: env.now() + prompt.expiresInMs,
57
+ threadId: prompt.threadId,
58
+ approve: () => respond(prompt.id, true),
59
+ decline: () => respond(prompt.id, false),
60
+ });
61
+ return {
62
+ subscribe(listener) {
63
+ listeners.add(listener);
64
+ if (listeners.size === 1)
65
+ options.onWatchedChange();
66
+ return () => {
67
+ if (!listeners.delete(listener))
68
+ return;
69
+ if (listeners.size === 0)
70
+ options.onWatchedChange();
71
+ };
72
+ },
73
+ get: () => visible,
74
+ replace(prompts) {
75
+ const next = new Map();
76
+ for (const prompt of prompts) {
77
+ const signature = signatureOf(prompt);
78
+ const known = entries.get(prompt.id);
79
+ next.set(prompt.id, known?.signature === signature ? known : { signature, item: itemOf(prompt) });
80
+ }
81
+ entries = next;
82
+ for (const id of answered)
83
+ if (!next.has(id))
84
+ answered.delete(id);
85
+ commit();
86
+ },
87
+ watched: () => listeners.size > 0,
88
+ dispose() {
89
+ env.clearTimeout(expiry);
90
+ expiry = undefined;
91
+ listeners.clear();
92
+ },
93
+ };
94
+ }
95
+ //# sourceMappingURL=confirmations.js.map