@parlor/chat 0.0.0-stage → 0.2.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 (83) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +23 -2
  3. package/dist/events.d.ts +4 -0
  4. package/dist/events.d.ts.map +1 -0
  5. package/dist/events.js +12 -0
  6. package/dist/events.js.map +1 -0
  7. package/dist/id-schemas.d.ts +5 -0
  8. package/dist/id-schemas.d.ts.map +1 -0
  9. package/dist/id-schemas.js +11 -0
  10. package/dist/id-schemas.js.map +1 -0
  11. package/dist/index.d.ts +9 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +7 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/items.d.ts +295 -0
  16. package/dist/items.d.ts.map +1 -0
  17. package/dist/items.js +113 -0
  18. package/dist/items.js.map +1 -0
  19. package/dist/limits.d.ts +4 -0
  20. package/dist/limits.d.ts.map +1 -0
  21. package/dist/limits.js +4 -0
  22. package/dist/limits.js.map +1 -0
  23. package/dist/model.d.ts +143 -0
  24. package/dist/model.d.ts.map +1 -0
  25. package/dist/model.js +2 -0
  26. package/dist/model.js.map +1 -0
  27. package/dist/open-turns.d.ts +19 -0
  28. package/dist/open-turns.d.ts.map +1 -0
  29. package/dist/open-turns.js +31 -0
  30. package/dist/open-turns.js.map +1 -0
  31. package/dist/protocol.d.ts +69 -0
  32. package/dist/protocol.d.ts.map +1 -0
  33. package/dist/protocol.js +80 -0
  34. package/dist/protocol.js.map +1 -0
  35. package/dist/server/actions.d.ts +561 -0
  36. package/dist/server/actions.d.ts.map +1 -0
  37. package/dist/server/actions.js +422 -0
  38. package/dist/server/actions.js.map +1 -0
  39. package/dist/server/context.d.ts +24 -0
  40. package/dist/server/context.d.ts.map +1 -0
  41. package/dist/server/context.js +77 -0
  42. package/dist/server/context.js.map +1 -0
  43. package/dist/server/index.d.ts +50 -0
  44. package/dist/server/index.d.ts.map +1 -0
  45. package/dist/server/index.js +145 -0
  46. package/dist/server/index.js.map +1 -0
  47. package/dist/server/live.d.ts +24 -0
  48. package/dist/server/live.d.ts.map +1 -0
  49. package/dist/server/live.js +130 -0
  50. package/dist/server/live.js.map +1 -0
  51. package/dist/server/migrations.d.ts +3 -0
  52. package/dist/server/migrations.d.ts.map +1 -0
  53. package/dist/server/migrations.js +96 -0
  54. package/dist/server/migrations.js.map +1 -0
  55. package/dist/server/party.d.ts +24 -0
  56. package/dist/server/party.d.ts.map +1 -0
  57. package/dist/server/party.js +38 -0
  58. package/dist/server/party.js.map +1 -0
  59. package/dist/server/routes.d.ts +17 -0
  60. package/dist/server/routes.d.ts.map +1 -0
  61. package/dist/server/routes.js +105 -0
  62. package/dist/server/routes.js.map +1 -0
  63. package/dist/server/rows.d.ts +49 -0
  64. package/dist/server/rows.d.ts.map +1 -0
  65. package/dist/server/rows.js +136 -0
  66. package/dist/server/rows.js.map +1 -0
  67. package/dist/server/store.d.ts +130 -0
  68. package/dist/server/store.d.ts.map +1 -0
  69. package/dist/server/store.js +539 -0
  70. package/dist/server/store.js.map +1 -0
  71. package/dist/tags.d.ts +7 -0
  72. package/dist/tags.d.ts.map +1 -0
  73. package/dist/tags.js +7 -0
  74. package/dist/tags.js.map +1 -0
  75. package/dist/testing/index.d.ts +46 -0
  76. package/dist/testing/index.d.ts.map +1 -0
  77. package/dist/testing/index.js +96 -0
  78. package/dist/testing/index.js.map +1 -0
  79. package/dist/view.d.ts +87 -0
  80. package/dist/view.d.ts.map +1 -0
  81. package/dist/view.js +236 -0
  82. package/dist/view.js.map +1 -0
  83. package/package.json +47 -3
@@ -0,0 +1,422 @@
1
+ import { ActionError, } from "@parlor/core";
2
+ import { createRegistry } from "@parlor/core/registry";
3
+ import { HOST_GRANTS_TAG } from "@parlor/server";
4
+ import { z } from "zod";
5
+ import { idSchema } from "../id-schemas.js";
6
+ import { chatItemBodies, hostItemDraft } from "../items.js";
7
+ import { HOST_PROTOCOL } from "../protocol.js";
8
+ import { CHAT_ACTIVITY_TAG, CHAT_TAG, HOSTS_TAG } from "../tags.js";
9
+ import { turnContext } from "./context.js";
10
+ import { chatAction } from "./party.js";
11
+ import { agentInfoSchema, TURN_FAILURES } from "./rows.js";
12
+ const presenceDueSchema = z
13
+ .record(z.string().min(1).max(64), z.number().int().nonnegative())
14
+ .refine((due) => Object.keys(due).length <= 256, "At most 256 devices.");
15
+ import { THREAD_LIST_LIMIT, } from "./store.js";
16
+ export { CHAT_ACTIVITY_TAG, CHAT_TAG, HOSTS_TAG, HOST_GRANTS_TAG };
17
+ const threadId = idSchema("thread");
18
+ const turnId = idSchema("turn");
19
+ const itemId = idSchema("item");
20
+ const afterSeq = z.number().int().min(0);
21
+ const MIN_HOST_PROTOCOL = 2;
22
+ const CONTEXT_HISTORY_ITEMS = 200;
23
+ const TERMINAL = new Set(["done", "failed", "cancelled"]);
24
+ const dbOf = (ctx) => ctx.db;
25
+ async function activeHosts(deps, db, owner) {
26
+ const hosts = await deps.store.listHosts(db, owner);
27
+ const { hostActive } = deps.auth;
28
+ if (!hostActive)
29
+ return hosts;
30
+ const holding = await Promise.all(hosts.map((host) => hostActive.call(deps.auth, host.grantId)));
31
+ const gone = hosts.filter((_host, at) => !holding[at]);
32
+ if (gone.length > 0) {
33
+ await deps.pruneHosts(owner, gone.map((host) => host.id));
34
+ }
35
+ return hosts.filter((_host, at) => holding[at]);
36
+ }
37
+ const summaryOf = ({ grantId: _grantId, protocol: _protocol, ...summary }) => summary;
38
+ export function userChatActions(deps) {
39
+ const { enforcing } = deps;
40
+ return {
41
+ open: chatAction("user", enforcing, {
42
+ description: "The sidebar's first paint in one round trip: threads, computers, and a thread's last page with what streams now.",
43
+ input: z.object({
44
+ threadId: threadId.optional(),
45
+ limit: z.number().int().min(1).max(500).default(200),
46
+ }),
47
+ reads: (input) => [
48
+ [CHAT_TAG, ...(input.threadId ? [input.threadId] : [])],
49
+ [HOSTS_TAG],
50
+ [HOST_GRANTS_TAG],
51
+ ],
52
+ run: async (input, user, ctx) => {
53
+ const db = dbOf(ctx);
54
+ const [threads, hosts, page] = await Promise.all([
55
+ deps.store.listThreads(db, user),
56
+ activeHosts(deps, db, user),
57
+ deps.store.readPage(db, user, input.threadId, input.limit),
58
+ ]);
59
+ const thread = page.thread;
60
+ const open = thread ? deps.relay.open(user, thread.id) : [];
61
+ const streaming = open.filter((turn) => {
62
+ const state = page.turns.find((status) => status.turnId === turn.turnId)?.state;
63
+ const ended = state !== undefined && TERMINAL.has(state);
64
+ if (ended)
65
+ deps.relay.settle(user, turn.threadId, turn.turnId);
66
+ return !ended;
67
+ });
68
+ return {
69
+ threads,
70
+ ...(threads.length >= THREAD_LIST_LIMIT ? { moreThreads: true } : {}),
71
+ hosts: hosts.map(summaryOf),
72
+ page: { ...page, open: streaming },
73
+ };
74
+ },
75
+ }),
76
+ items: chatAction("user", enforcing, {
77
+ description: "A thread's items after a sequence number.",
78
+ input: z.object({ threadId, afterSeq }),
79
+ reads: (input) => [[CHAT_TAG, input.threadId]],
80
+ run: (input, user, ctx) => deps.store.readItemsAfter(dbOf(ctx), user, input.threadId, input.afterSeq),
81
+ }),
82
+ history: chatAction("user", enforcing, {
83
+ description: "A thread's items before a sequence number, oldest first, with their turns; hasMore while older ones remain.",
84
+ input: z.object({
85
+ threadId,
86
+ beforeSeq: z.number().int().min(1),
87
+ limit: z.number().int().min(1).max(500).default(200),
88
+ }),
89
+ reads: (input) => [[CHAT_TAG, input.threadId]],
90
+ run: async (input, user, ctx) => {
91
+ const read = deps.store.readItemsBefore?.bind(deps.store);
92
+ if (!read)
93
+ throw new ActionError("not_found", "This chat store keeps no history.");
94
+ return read(dbOf(ctx), user, input.threadId, input.beforeSeq, input.limit);
95
+ },
96
+ }),
97
+ threadsBefore: chatAction("user", enforcing, {
98
+ description: "The user's threads updated before a thread, newest first, for the list past what open returned.",
99
+ input: z.object({
100
+ before: z.object({ updatedAt: z.number().int().min(0), id: threadId }),
101
+ limit: z.number().int().min(1).max(500).default(200),
102
+ }),
103
+ reads: [CHAT_TAG],
104
+ run: async (input, user, ctx) => {
105
+ const list = deps.store.listThreadsBefore?.bind(deps.store);
106
+ if (!list)
107
+ throw new ActionError("not_found", "This chat store keeps no history.");
108
+ return list(dbOf(ctx), user, input.before, input.limit);
109
+ },
110
+ }),
111
+ hosts: chatAction("user", enforcing, {
112
+ description: "The user's computers and the agents on them.",
113
+ input: z.object({}),
114
+ reads: [HOSTS_TAG, HOST_GRANTS_TAG],
115
+ run: async (_input, user, ctx) => (await activeHosts(deps, dbOf(ctx), user)).map(summaryOf),
116
+ }),
117
+ send: chatAction("user", enforcing, {
118
+ description: "Send a prompt to an agent on one of the user's computers.",
119
+ input: z.object({
120
+ threadId,
121
+ turnId,
122
+ itemId,
123
+ clientId: z.string().min(1).max(128),
124
+ prompt: chatItemBodies.prompt.body,
125
+ }),
126
+ run: async (input, user, ctx) => {
127
+ const hosts = await activeHosts(deps, dbOf(ctx), user);
128
+ const host = hosts.find((candidate) => candidate.id === input.prompt.agent.hostId);
129
+ if (!host)
130
+ throw new ActionError("not_found", "Computer not found");
131
+ return deps.transact(user, async (tx) => {
132
+ await deps.store.appendUserItems(tx, user, {
133
+ threadId: input.threadId,
134
+ turnId: input.turnId,
135
+ items: [{ id: input.itemId, kind: "prompt", body: input.prompt }],
136
+ turn: {
137
+ turnId: input.turnId,
138
+ agent: input.prompt.agent,
139
+ clientId: input.clientId,
140
+ deviceId: user.deviceId,
141
+ maxQueued: deps.maxQueued,
142
+ },
143
+ });
144
+ return {
145
+ result: { id: input.threadId, turnId: input.turnId },
146
+ threadId: input.threadId,
147
+ };
148
+ });
149
+ },
150
+ }),
151
+ answer: chatAction("user", enforcing, {
152
+ description: "Answer the agent's permission prompt or question.",
153
+ input: z.object({ threadId, turnId, itemId, answer: chatItemBodies.answer.body }),
154
+ run: async (input, user) => {
155
+ const { signed } = input.answer;
156
+ if (signed && deps.auth.device) {
157
+ const device = await deps.auth.device(user.userId, signed.deviceId);
158
+ if (!device) {
159
+ throw new ActionError("forbidden", "This device cannot answer.");
160
+ }
161
+ }
162
+ return deps.transact(user, async (tx) => {
163
+ await deps.store.appendUserItems(tx, user, {
164
+ threadId: input.threadId,
165
+ turnId: input.turnId,
166
+ items: [{ id: input.itemId, kind: "answer", body: input.answer }],
167
+ });
168
+ return { result: { id: input.threadId }, threadId: input.threadId };
169
+ });
170
+ },
171
+ }),
172
+ cancel: chatAction("user", enforcing, {
173
+ description: "Stop the running turn; what the agent already said is kept.",
174
+ input: z.object({ threadId, turnId, itemId }),
175
+ writes: [CHAT_TAG],
176
+ run: async (input, user, ctx) => {
177
+ await deps.store.appendUserItems(dbOf(ctx), user, {
178
+ threadId: input.threadId,
179
+ turnId: input.turnId,
180
+ items: [{ id: input.itemId, kind: "cancel", body: {} }],
181
+ });
182
+ return { id: input.threadId };
183
+ },
184
+ }),
185
+ userActive: chatAction("user", enforcing, {
186
+ description: "Tell the user's computers a tab is in use, so a polling computer speeds up; carries no content and writes no table.",
187
+ input: z.object({}),
188
+ writes: [CHAT_ACTIVITY_TAG],
189
+ run: () => ({ ok: true }),
190
+ }),
191
+ };
192
+ }
193
+ /** What the user's computers call; `hostHello` first on every link. */
194
+ export function hostChatActions(deps) {
195
+ const { enforcing } = deps;
196
+ const welcomed = new Set();
197
+ const welcome = async (host, db) => {
198
+ const hosts = await deps.store.listHosts(db, host);
199
+ const known = hosts.find((candidate) => candidate.id === host.host.hostId);
200
+ if (!known)
201
+ throw new ActionError("forbidden", "Say hello before anything else.");
202
+ if (known.protocol < MIN_HOST_PROTOCOL) {
203
+ await deps.pruneHosts(host, [known.id]);
204
+ throw new ActionError("forbidden", "Say hello before anything else.");
205
+ }
206
+ welcomed.add(known.id);
207
+ return known;
208
+ };
209
+ const requireWelcome = async (host, db) => {
210
+ if (!welcomed.has(host.host.hostId))
211
+ await welcome(host, db);
212
+ };
213
+ const agentNames = new Map();
214
+ const learnAgents = (hostId, agents) => {
215
+ agentNames.set(hostId, new Map(agents.map((agent) => [agent.id, agent.name])));
216
+ };
217
+ const agentNameOf = async (host, db, agentId) => {
218
+ if (!agentNames.has(host.host.hostId)) {
219
+ const known = (await deps.store.listHosts(db, host)).find((candidate) => candidate.id === host.host.hostId);
220
+ if (known)
221
+ learnAgents(known.id, known.agents);
222
+ }
223
+ return agentNames.get(host.host.hostId)?.get(agentId) ?? agentId;
224
+ };
225
+ const mint = async (host, db, turn) => {
226
+ if (!deps.auth.delegate) {
227
+ throw new ActionError("internal", "The auth provider cannot mint turn tokens.");
228
+ }
229
+ return deps.auth.delegate(host.host, {
230
+ threadId: turn.threadId,
231
+ turnId: turn.turnId,
232
+ clientId: turn.clientId,
233
+ agent: await agentNameOf(host, db, turn.agentId),
234
+ ttlMs: deps.leaseMs,
235
+ });
236
+ };
237
+ return {
238
+ hostHello: chatAction("host", enforcing, {
239
+ description: "A link's first call: agree on the host protocol and report this computer online with its agents.",
240
+ input: z.object({
241
+ protocols: z.object({
242
+ min: z.number().int().min(1),
243
+ max: z.number().int().min(1),
244
+ }),
245
+ hostVersion: z.string().min(1).max(32),
246
+ name: z.string().min(1).max(80),
247
+ platform: z.string().min(1).max(32),
248
+ agents: z.array(agentInfoSchema).max(32),
249
+ devices: z.array(z.string().min(1).max(64)).max(256).optional(),
250
+ presenceDue: presenceDueSchema.optional(),
251
+ }),
252
+ writes: [HOSTS_TAG],
253
+ run: async (input, host, ctx) => {
254
+ const id = host.host.hostId;
255
+ const protocols = { min: MIN_HOST_PROTOCOL, max: HOST_PROTOCOL };
256
+ const refuse = async (reason) => {
257
+ welcomed.delete(id);
258
+ await deps.store.pruneHosts(dbOf(ctx), host, [id]);
259
+ return { id, accepted: false, reason, protocols };
260
+ };
261
+ if (input.protocols.max < protocols.min)
262
+ return refuse("host_too_old");
263
+ const protocol = Math.min(input.protocols.max, protocols.max);
264
+ if (protocol < input.protocols.min)
265
+ return refuse("app_too_old");
266
+ await deps.store.reportHost(dbOf(ctx), host, host.host, {
267
+ protocol,
268
+ name: input.name,
269
+ platform: input.platform,
270
+ agents: input.agents,
271
+ devices: input.devices,
272
+ presenceDue: input.presenceDue,
273
+ online: true,
274
+ ttlMs: 2 * deps.heartbeatMs,
275
+ });
276
+ learnAgents(id, input.agents);
277
+ welcomed.add(id);
278
+ return {
279
+ id,
280
+ accepted: true,
281
+ protocol,
282
+ leaseMs: deps.leaseMs,
283
+ heartbeatMs: deps.heartbeatMs,
284
+ userActivity: true,
285
+ };
286
+ },
287
+ }),
288
+ hostReport: chatAction("host", enforcing, {
289
+ description: "This computer went offline or changed its agents.",
290
+ input: z.object({
291
+ online: z.boolean(),
292
+ agents: z.array(agentInfoSchema).max(32),
293
+ devices: z.array(z.string().min(1).max(64)).max(256).optional(),
294
+ presenceDue: presenceDueSchema.optional(),
295
+ }),
296
+ writes: [HOSTS_TAG],
297
+ run: async (input, host, ctx) => {
298
+ const db = dbOf(ctx);
299
+ const known = await welcome(host, db);
300
+ const { onlineUntil } = await deps.store.reportHost(db, host, host.host, {
301
+ protocol: known.protocol,
302
+ name: known.name,
303
+ platform: known.platform,
304
+ agents: input.agents,
305
+ devices: input.devices,
306
+ presenceDue: input.presenceDue,
307
+ online: input.online,
308
+ ttlMs: 2 * deps.heartbeatMs,
309
+ });
310
+ learnAgents(host.host.hostId, input.agents);
311
+ return { id: host.host.hostId, onlineUntil };
312
+ },
313
+ }),
314
+ hostClaim: chatAction("host", enforcing, {
315
+ description: "Take the next turn addressed to this computer with its turn token; not_found when none waits.",
316
+ input: z.object({}),
317
+ run: async (_input, host, ctx) => {
318
+ const db = dbOf(ctx);
319
+ await requireWelcome(host, db);
320
+ await deps.reconcile(host);
321
+ const claimed = await deps.transact(host, async (tx) => {
322
+ const taken = await deps.store.claimTurn(tx, host, host.host, deps.leaseMs);
323
+ if (!taken)
324
+ throw new ActionError("not_found", "No turn is waiting.");
325
+ return { result: taken, threadId: taken.id };
326
+ });
327
+ try {
328
+ const token = await mint(host, db, {
329
+ threadId: claimed.id,
330
+ turnId: claimed.turnId,
331
+ clientId: claimed.clientId,
332
+ agentId: claimed.agent.agentId,
333
+ });
334
+ const deviceId = claimed.prompt.body.signed?.deviceId;
335
+ const [device, account, page] = await Promise.all([
336
+ deviceId ? deps.auth.device?.(host.userId, deviceId) : undefined,
337
+ deps.auth.account?.(host.userId),
338
+ deps.store.readPage(db, host, claimed.id, CONTEXT_HISTORY_ITEMS),
339
+ ]);
340
+ const context = turnContext({
341
+ appName: deps.appName,
342
+ appOrigin: deps.appOrigin(ctx),
343
+ account,
344
+ device,
345
+ instructions: deps.instructions,
346
+ history: page.items.filter((item) => item.seq < claimed.prompt.seq),
347
+ });
348
+ return { ...claimed, device, context, token };
349
+ }
350
+ catch (error) {
351
+ await deps
352
+ .transact(host, async (tx) => {
353
+ const released = await deps.store.releaseClaim(tx, host, host.host, claimed.turnId);
354
+ return { result: released, threadId: claimed.id };
355
+ })
356
+ .catch(() => false);
357
+ throw error;
358
+ }
359
+ },
360
+ }),
361
+ hostSignals: chatAction("host", enforcing, {
362
+ description: "Answers and stop requests for the turns this computer runs.",
363
+ input: z.object({ turns: z.array(z.object({ turnId, afterSeq })).max(16) }),
364
+ run: async (input, host, ctx) => {
365
+ const db = dbOf(ctx);
366
+ await requireWelcome(host, db);
367
+ const signals = await deps.store.readSignals(db, host, host.host, input.turns);
368
+ return Promise.all(signals.map(async (batch) => {
369
+ const answering = new Set(batch.items.flatMap((item) => item.kind === "answer" && item.body.signed
370
+ ? [item.body.signed.deviceId]
371
+ : []));
372
+ const devices = (await Promise.all([...answering].map((deviceId) => deps.auth.device?.(host.userId, deviceId)))).filter((device) => device !== undefined);
373
+ return devices.length > 0 ? { ...batch, devices } : batch;
374
+ }));
375
+ },
376
+ }),
377
+ hostAppend: chatAction("host", enforcing, {
378
+ description: "Append finished items of a running turn and extend its lease; no items only renews it.",
379
+ input: z.object({ turnId, items: z.array(hostItemDraft).max(64) }),
380
+ run: async (input, host, ctx) => {
381
+ await requireWelcome(host, dbOf(ctx));
382
+ const appended = await deps.transact(host, async (tx) => {
383
+ const result = await deps.store.appendHostItems(tx, host, host.host, input.turnId, input.items, deps.leaseMs);
384
+ return {
385
+ result,
386
+ threadId: input.items.length > 0 ? result.threadId : undefined,
387
+ };
388
+ });
389
+ const token = await mint(host, dbOf(ctx), { ...appended, turnId: input.turnId });
390
+ return { id: appended.threadId, leaseUntil: appended.leaseUntil, token };
391
+ },
392
+ }),
393
+ hostFinish: chatAction("host", enforcing, {
394
+ description: "End a turn, once.",
395
+ input: z.object({
396
+ turnId,
397
+ outcome: z.discriminatedUnion("state", [
398
+ z.object({ state: z.literal("done"), stopReason: z.string() }),
399
+ z.object({ state: z.literal("cancelled") }),
400
+ z.object({ state: z.literal("failed"), reason: z.enum(TURN_FAILURES) }),
401
+ ]),
402
+ }),
403
+ run: async (input, host, ctx) => {
404
+ await requireWelcome(host, dbOf(ctx));
405
+ const finished = await deps.transact(host, async (tx) => {
406
+ const result = await deps.store.finishTurn(tx, host, host.host, input.turnId, input.outcome);
407
+ return { result, threadId: result.threadId };
408
+ });
409
+ deps.relay.settle(host, finished.threadId, input.turnId);
410
+ return { id: finished.threadId };
411
+ },
412
+ }),
413
+ };
414
+ }
415
+ /**
416
+ * The chat's actions at `/_parlor/chat/actions/<name>`: plugin actions, so never on MCP
417
+ * and never callable by an agent. Writes return the thread or host id as `id`.
418
+ */
419
+ export function chatActions(deps) {
420
+ return createRegistry({ ...userChatActions(deps), ...hostChatActions(deps) });
421
+ }
422
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../../src/server/actions.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type ActionContext,\n ActionError,\n type HostId,\n type ThreadId,\n type TurnId,\n} from \"@parlor/core\";\nimport { type ActionsOf, createRegistry } from \"@parlor/core/registry\";\nimport { type AuthProvider, HOST_GRANTS_TAG } from \"@parlor/server\";\nimport { z } from \"zod\";\n\nimport { idSchema } from \"../id-schemas.js\";\nimport { chatItemBodies, hostItemDraft, type LoggedItem } from \"../items.js\";\nimport type {\n AgentInfo,\n ChatOwner,\n ChatSnapshot,\n ThreadHistory,\n ThreadList,\n ClaimedTurn,\n HostSummary,\n TurnSignals,\n} from \"../model.js\";\nimport { HOST_PROTOCOL, type HostWelcome } from \"../protocol.js\";\nimport { CHAT_ACTIVITY_TAG, CHAT_TAG, HOSTS_TAG } from \"../tags.js\";\nimport { turnContext } from \"./context.js\";\nimport type { LiveRelay } from \"./live.js\";\nimport { type ChatHost, chatAction } from \"./party.js\";\nimport { agentInfoSchema, TURN_FAILURES } from \"./rows.js\";\n\nconst presenceDueSchema = z\n .record(z.string().min(1).max(64), z.number().int().nonnegative())\n .refine((due) => Object.keys(due).length <= 256, \"At most 256 devices.\");\nimport {\n type ChatDb,\n type ChatStore,\n type StoredHost,\n THREAD_LIST_LIMIT,\n} from \"./store.js\";\n\nexport { CHAT_ACTIVITY_TAG, CHAT_TAG, HOSTS_TAG, HOST_GRANTS_TAG };\n\nexport interface Written<T> {\n readonly result: T;\n readonly threadId: ThreadId | undefined;\n}\n\nexport interface ChatActionDeps {\n readonly enforcing: boolean;\n /**\n * Runs `work` in one transaction with the thread's sync event. Actions that call the auth\n * provider do so outside it, because a provider may read through another connection\n * (PGlite has one, and the transaction holds it).\n */\n /** Runs `work` in one transaction and wakes only `owner`'s tabs and computers. */\n readonly transact: <T>(\n owner: ChatOwner,\n work: (tx: ChatDb) => Promise<Written<T>>,\n ) => Promise<T>;\n /** Commits the lapsed leases and liveness of `owner`, with the sync events they owe. */\n readonly reconcile: (owner: ChatOwner) => Promise<void>;\n /** Drops the owner's computer rows whose grant is gone; best effort, never fails a read. */\n readonly pruneHosts: (owner: ChatOwner, hostIds: readonly HostId[]) => Promise<void>;\n readonly auth: AuthProvider;\n readonly store: ChatStore;\n readonly relay: LiveRelay;\n readonly leaseMs: number;\n readonly heartbeatMs: number;\n readonly maxQueued: number;\n readonly instructions: string | undefined;\n readonly appName: string;\n readonly appOrigin: (ctx: ActionContext) => string;\n}\n\nconst threadId = idSchema(\"thread\");\nconst turnId = idSchema(\"turn\");\nconst itemId = idSchema(\"item\");\nconst afterSeq = z.number().int().min(0);\n\nconst MIN_HOST_PROTOCOL = 2;\nconst CONTEXT_HISTORY_ITEMS = 200;\nconst TERMINAL: ReadonlySet<string> = new Set([\"done\", \"failed\", \"cancelled\"]);\n\nconst dbOf = (ctx: ActionContext) => ctx.db as ChatDb;\n\nasync function activeHosts(\n deps: ChatActionDeps,\n db: ChatDb,\n owner: ChatOwner,\n): Promise<StoredHost[]> {\n const hosts = await deps.store.listHosts(db, owner);\n const { hostActive } = deps.auth;\n if (!hostActive) return hosts;\n const holding = await Promise.all(\n hosts.map((host) => hostActive.call(deps.auth, host.grantId)),\n );\n const gone = hosts.filter((_host, at) => !holding[at]);\n if (gone.length > 0) {\n await deps.pruneHosts(\n owner,\n gone.map((host) => host.id),\n );\n }\n return hosts.filter((_host, at) => holding[at]);\n}\n\nconst summaryOf = ({\n grantId: _grantId,\n protocol: _protocol,\n ...summary\n}: StoredHost): HostSummary => summary;\n\nexport function userChatActions(deps: ChatActionDeps) {\n const { enforcing } = deps;\n return {\n open: chatAction(\"user\", enforcing, {\n description:\n \"The sidebar's first paint in one round trip: threads, computers, and a thread's last page with what streams now.\",\n input: z.object({\n threadId: threadId.optional(),\n limit: z.number().int().min(1).max(500).default(200),\n }),\n reads: (input) => [\n [CHAT_TAG, ...(input.threadId ? [input.threadId] : [])],\n [HOSTS_TAG],\n [HOST_GRANTS_TAG],\n ],\n run: async (input, user, ctx): Promise<ChatSnapshot> => {\n const db = dbOf(ctx);\n const [threads, hosts, page] = await Promise.all([\n deps.store.listThreads(db, user),\n activeHosts(deps, db, user),\n deps.store.readPage(db, user, input.threadId, input.limit),\n ]);\n const thread = page.thread;\n const open = thread ? deps.relay.open(user, thread.id) : [];\n const streaming = open.filter((turn) => {\n const state = page.turns.find((status) => status.turnId === turn.turnId)?.state;\n const ended = state !== undefined && TERMINAL.has(state);\n if (ended) deps.relay.settle(user, turn.threadId, turn.turnId);\n return !ended;\n });\n return {\n threads,\n ...(threads.length >= THREAD_LIST_LIMIT ? { moreThreads: true } : {}),\n hosts: hosts.map(summaryOf),\n page: { ...page, open: streaming },\n };\n },\n }),\n items: chatAction(\"user\", enforcing, {\n description: \"A thread's items after a sequence number.\",\n input: z.object({ threadId, afterSeq }),\n reads: (input) => [[CHAT_TAG, input.threadId]],\n run: (input, user, ctx): Promise<LoggedItem[]> =>\n deps.store.readItemsAfter(dbOf(ctx), user, input.threadId, input.afterSeq),\n }),\n history: chatAction(\"user\", enforcing, {\n description:\n \"A thread's items before a sequence number, oldest first, with their turns; hasMore while older ones remain.\",\n input: z.object({\n threadId,\n beforeSeq: z.number().int().min(1),\n limit: z.number().int().min(1).max(500).default(200),\n }),\n reads: (input) => [[CHAT_TAG, input.threadId]],\n run: async (input, user, ctx): Promise<ThreadHistory> => {\n const read = deps.store.readItemsBefore?.bind(deps.store);\n if (!read)\n throw new ActionError(\"not_found\", \"This chat store keeps no history.\");\n return read(dbOf(ctx), user, input.threadId, input.beforeSeq, input.limit);\n },\n }),\n threadsBefore: chatAction(\"user\", enforcing, {\n description:\n \"The user's threads updated before a thread, newest first, for the list past what open returned.\",\n input: z.object({\n before: z.object({ updatedAt: z.number().int().min(0), id: threadId }),\n limit: z.number().int().min(1).max(500).default(200),\n }),\n reads: [CHAT_TAG],\n run: async (input, user, ctx): Promise<ThreadList> => {\n const list = deps.store.listThreadsBefore?.bind(deps.store);\n if (!list)\n throw new ActionError(\"not_found\", \"This chat store keeps no history.\");\n return list(dbOf(ctx), user, input.before, input.limit);\n },\n }),\n hosts: chatAction(\"user\", enforcing, {\n description: \"The user's computers and the agents on them.\",\n input: z.object({}),\n reads: [HOSTS_TAG, HOST_GRANTS_TAG],\n run: async (_input, user, ctx): Promise<HostSummary[]> =>\n (await activeHosts(deps, dbOf(ctx), user)).map(summaryOf),\n }),\n send: chatAction(\"user\", enforcing, {\n description: \"Send a prompt to an agent on one of the user's computers.\",\n input: z.object({\n threadId,\n turnId,\n itemId,\n clientId: z.string().min(1).max(128),\n prompt: chatItemBodies.prompt.body,\n }),\n run: async (\n input,\n user,\n ctx,\n ): Promise<{ readonly id: string; readonly turnId: string }> => {\n const hosts = await activeHosts(deps, dbOf(ctx), user);\n const host = hosts.find(\n (candidate) => candidate.id === input.prompt.agent.hostId,\n );\n if (!host) throw new ActionError(\"not_found\", \"Computer not found\");\n return deps.transact(user, async (tx) => {\n await deps.store.appendUserItems(tx, user, {\n threadId: input.threadId,\n turnId: input.turnId,\n items: [{ id: input.itemId, kind: \"prompt\", body: input.prompt }],\n turn: {\n turnId: input.turnId,\n agent: input.prompt.agent,\n clientId: input.clientId,\n deviceId: user.deviceId,\n maxQueued: deps.maxQueued,\n },\n });\n return {\n result: { id: input.threadId, turnId: input.turnId },\n threadId: input.threadId,\n };\n });\n },\n }),\n answer: chatAction(\"user\", enforcing, {\n description: \"Answer the agent's permission prompt or question.\",\n input: z.object({ threadId, turnId, itemId, answer: chatItemBodies.answer.body }),\n run: async (input, user): Promise<{ readonly id: string }> => {\n const { signed } = input.answer;\n if (signed && deps.auth.device) {\n const device = await deps.auth.device(user.userId, signed.deviceId);\n if (!device) {\n throw new ActionError(\"forbidden\", \"This device cannot answer.\");\n }\n }\n return deps.transact(user, async (tx) => {\n await deps.store.appendUserItems(tx, user, {\n threadId: input.threadId,\n turnId: input.turnId,\n items: [{ id: input.itemId, kind: \"answer\", body: input.answer }],\n });\n return { result: { id: input.threadId }, threadId: input.threadId };\n });\n },\n }),\n cancel: chatAction(\"user\", enforcing, {\n description: \"Stop the running turn; what the agent already said is kept.\",\n input: z.object({ threadId, turnId, itemId }),\n writes: [CHAT_TAG],\n run: async (input, user, ctx): Promise<{ readonly id: string }> => {\n await deps.store.appendUserItems(dbOf(ctx), user, {\n threadId: input.threadId,\n turnId: input.turnId,\n items: [{ id: input.itemId, kind: \"cancel\", body: {} }],\n });\n return { id: input.threadId };\n },\n }),\n userActive: chatAction(\"user\", enforcing, {\n description:\n \"Tell the user's computers a tab is in use, so a polling computer speeds up; carries no content and writes no table.\",\n input: z.object({}),\n writes: [CHAT_ACTIVITY_TAG],\n run: (): { readonly ok: true } => ({ ok: true }),\n }),\n };\n}\n\n/** What the user's computers call; `hostHello` first on every link. */\nexport function hostChatActions(deps: ChatActionDeps) {\n const { enforcing } = deps;\n const welcomed = new Set<HostId>();\n const welcome = async (host: ChatHost, db: ChatDb) => {\n const hosts = await deps.store.listHosts(db, host);\n const known = hosts.find((candidate) => candidate.id === host.host.hostId);\n if (!known) throw new ActionError(\"forbidden\", \"Say hello before anything else.\");\n if (known.protocol < MIN_HOST_PROTOCOL) {\n await deps.pruneHosts(host, [known.id]);\n throw new ActionError(\"forbidden\", \"Say hello before anything else.\");\n }\n welcomed.add(known.id);\n return known;\n };\n const requireWelcome = async (host: ChatHost, db: ChatDb) => {\n if (!welcomed.has(host.host.hostId)) await welcome(host, db);\n };\n const agentNames = new Map<HostId, ReadonlyMap<string, string>>();\n const learnAgents = (hostId: HostId, agents: readonly AgentInfo[]) => {\n agentNames.set(hostId, new Map(agents.map((agent) => [agent.id, agent.name])));\n };\n const agentNameOf = async (host: ChatHost, db: ChatDb, agentId: string) => {\n if (!agentNames.has(host.host.hostId)) {\n const known = (await deps.store.listHosts(db, host)).find(\n (candidate) => candidate.id === host.host.hostId,\n );\n if (known) learnAgents(known.id, known.agents);\n }\n return agentNames.get(host.host.hostId)?.get(agentId) ?? agentId;\n };\n const mint = async (\n host: ChatHost,\n db: ChatDb,\n turn: { threadId: ThreadId; turnId: TurnId; clientId: string; agentId: string },\n ) => {\n if (!deps.auth.delegate) {\n throw new ActionError(\"internal\", \"The auth provider cannot mint turn tokens.\");\n }\n return deps.auth.delegate(host.host, {\n threadId: turn.threadId,\n turnId: turn.turnId,\n clientId: turn.clientId,\n agent: await agentNameOf(host, db, turn.agentId),\n ttlMs: deps.leaseMs,\n });\n };\n return {\n hostHello: chatAction(\"host\", enforcing, {\n description:\n \"A link's first call: agree on the host protocol and report this computer online with its agents.\",\n input: z.object({\n protocols: z.object({\n min: z.number().int().min(1),\n max: z.number().int().min(1),\n }),\n hostVersion: z.string().min(1).max(32),\n name: z.string().min(1).max(80),\n platform: z.string().min(1).max(32),\n agents: z.array(agentInfoSchema).max(32),\n devices: z.array(z.string().min(1).max(64)).max(256).optional(),\n presenceDue: presenceDueSchema.optional(),\n }),\n writes: [HOSTS_TAG],\n run: async (input, host, ctx): Promise<HostWelcome & { readonly id: string }> => {\n const id = host.host.hostId;\n const protocols = { min: MIN_HOST_PROTOCOL, max: HOST_PROTOCOL };\n const refuse = async (reason: \"host_too_old\" | \"app_too_old\") => {\n welcomed.delete(id);\n await deps.store.pruneHosts(dbOf(ctx), host, [id]);\n return { id, accepted: false as const, reason, protocols };\n };\n if (input.protocols.max < protocols.min) return refuse(\"host_too_old\");\n const protocol = Math.min(input.protocols.max, protocols.max);\n if (protocol < input.protocols.min) return refuse(\"app_too_old\");\n await deps.store.reportHost(dbOf(ctx), host, host.host, {\n protocol,\n name: input.name,\n platform: input.platform,\n agents: input.agents,\n devices: input.devices,\n presenceDue: input.presenceDue,\n online: true,\n ttlMs: 2 * deps.heartbeatMs,\n });\n learnAgents(id, input.agents);\n welcomed.add(id);\n return {\n id,\n accepted: true,\n protocol,\n leaseMs: deps.leaseMs,\n heartbeatMs: deps.heartbeatMs,\n userActivity: true,\n };\n },\n }),\n hostReport: chatAction(\"host\", enforcing, {\n description: \"This computer went offline or changed its agents.\",\n input: z.object({\n online: z.boolean(),\n agents: z.array(agentInfoSchema).max(32),\n devices: z.array(z.string().min(1).max(64)).max(256).optional(),\n presenceDue: presenceDueSchema.optional(),\n }),\n writes: [HOSTS_TAG],\n run: async (\n input,\n host,\n ctx,\n ): Promise<{ readonly id: string; readonly onlineUntil: number }> => {\n const db = dbOf(ctx);\n const known = await welcome(host, db);\n const { onlineUntil } = await deps.store.reportHost(db, host, host.host, {\n protocol: known.protocol,\n name: known.name,\n platform: known.platform,\n agents: input.agents,\n devices: input.devices,\n presenceDue: input.presenceDue,\n online: input.online,\n ttlMs: 2 * deps.heartbeatMs,\n });\n learnAgents(host.host.hostId, input.agents);\n return { id: host.host.hostId, onlineUntil };\n },\n }),\n hostClaim: chatAction(\"host\", enforcing, {\n description:\n \"Take the next turn addressed to this computer with its turn token; not_found when none waits.\",\n input: z.object({}),\n run: async (_input, host, ctx): Promise<ClaimedTurn> => {\n const db = dbOf(ctx);\n await requireWelcome(host, db);\n await deps.reconcile(host);\n const claimed = await deps.transact(host, async (tx) => {\n const taken = await deps.store.claimTurn(tx, host, host.host, deps.leaseMs);\n if (!taken) throw new ActionError(\"not_found\", \"No turn is waiting.\");\n return { result: taken, threadId: taken.id };\n });\n try {\n const token = await mint(host, db, {\n threadId: claimed.id,\n turnId: claimed.turnId,\n clientId: claimed.clientId,\n agentId: claimed.agent.agentId,\n });\n const deviceId = claimed.prompt.body.signed?.deviceId;\n const [device, account, page] = await Promise.all([\n deviceId ? deps.auth.device?.(host.userId, deviceId) : undefined,\n deps.auth.account?.(host.userId),\n deps.store.readPage(db, host, claimed.id, CONTEXT_HISTORY_ITEMS),\n ]);\n const context = turnContext({\n appName: deps.appName,\n appOrigin: deps.appOrigin(ctx),\n account,\n device,\n instructions: deps.instructions,\n history: page.items.filter((item) => item.seq < claimed.prompt.seq),\n });\n return { ...claimed, device, context, token };\n } catch (error) {\n await deps\n .transact(host, async (tx) => {\n const released = await deps.store.releaseClaim(\n tx,\n host,\n host.host,\n claimed.turnId,\n );\n return { result: released, threadId: claimed.id };\n })\n .catch(() => false);\n throw error;\n }\n },\n }),\n hostSignals: chatAction(\"host\", enforcing, {\n description: \"Answers and stop requests for the turns this computer runs.\",\n input: z.object({ turns: z.array(z.object({ turnId, afterSeq })).max(16) }),\n run: async (input, host, ctx): Promise<TurnSignals[]> => {\n const db = dbOf(ctx);\n await requireWelcome(host, db);\n const signals = await deps.store.readSignals(db, host, host.host, input.turns);\n return Promise.all(\n signals.map(async (batch): Promise<TurnSignals> => {\n const answering = new Set(\n batch.items.flatMap((item) =>\n item.kind === \"answer\" && item.body.signed\n ? [item.body.signed.deviceId]\n : [],\n ),\n );\n const devices = (\n await Promise.all(\n [...answering].map((deviceId) =>\n deps.auth.device?.(host.userId, deviceId),\n ),\n )\n ).filter((device) => device !== undefined);\n return devices.length > 0 ? { ...batch, devices } : batch;\n }),\n );\n },\n }),\n hostAppend: chatAction(\"host\", enforcing, {\n description:\n \"Append finished items of a running turn and extend its lease; no items only renews it.\",\n input: z.object({ turnId, items: z.array(hostItemDraft).max(64) }),\n run: async (\n input,\n host,\n ctx,\n ): Promise<{\n readonly id: string;\n readonly leaseUntil: number;\n readonly token: ClaimedTurn[\"token\"];\n }> => {\n await requireWelcome(host, dbOf(ctx));\n const appended = await deps.transact(host, async (tx) => {\n const result = await deps.store.appendHostItems(\n tx,\n host,\n host.host,\n input.turnId,\n input.items,\n deps.leaseMs,\n );\n return {\n result,\n threadId: input.items.length > 0 ? result.threadId : undefined,\n };\n });\n const token = await mint(host, dbOf(ctx), { ...appended, turnId: input.turnId });\n return { id: appended.threadId, leaseUntil: appended.leaseUntil, token };\n },\n }),\n hostFinish: chatAction(\"host\", enforcing, {\n description: \"End a turn, once.\",\n input: z.object({\n turnId,\n outcome: z.discriminatedUnion(\"state\", [\n z.object({ state: z.literal(\"done\"), stopReason: z.string() }),\n z.object({ state: z.literal(\"cancelled\") }),\n z.object({ state: z.literal(\"failed\"), reason: z.enum(TURN_FAILURES) }),\n ]),\n }),\n run: async (input, host, ctx): Promise<{ readonly id: string }> => {\n await requireWelcome(host, dbOf(ctx));\n const finished = await deps.transact(host, async (tx) => {\n const result = await deps.store.finishTurn(\n tx,\n host,\n host.host,\n input.turnId,\n input.outcome,\n );\n return { result, threadId: result.threadId };\n });\n deps.relay.settle(host, finished.threadId, input.turnId);\n return { id: finished.threadId };\n },\n }),\n };\n}\n\n/**\n * The chat's actions at `/_parlor/chat/actions/<name>`: plugin actions, so never on MCP\n * and never callable by an agent. Writes return the thread or host id as `id`.\n */\nexport function chatActions(deps: ChatActionDeps) {\n return createRegistry({ ...userChatActions(deps), ...hostChatActions(deps) });\n}\n\nexport type ChatActionRegistry = ReturnType<typeof chatActions>;\nexport type ChatActionMap = ActionsOf<ChatActionRegistry>;\nexport type ChatUserActionMap = ReturnType<typeof userChatActions>;\nexport type ChatHostActionMap = ReturnType<typeof hostChatActions>;\n"]}
@@ -0,0 +1,24 @@
1
+ import type { LoggedItem } from "../items.js";
2
+ export declare const TRANSCRIPT_BUDGET_BYTES: number;
3
+ export interface TurnContextInput {
4
+ readonly appName: string;
5
+ readonly appOrigin: string;
6
+ readonly account?: {
7
+ readonly name: string;
8
+ readonly email?: string | undefined;
9
+ } | undefined;
10
+ readonly device?: {
11
+ readonly name: string;
12
+ readonly platform: string;
13
+ } | undefined;
14
+ readonly instructions?: string | undefined;
15
+ /** The thread before this turn, trimmed from its oldest end to the budget. */
16
+ readonly history: readonly LoggedItem[];
17
+ }
18
+ /**
19
+ * The `<parlor-context>` block before a fresh agent session's first prompt. Built on the
20
+ * backend so every host and agent gets the same words; the transcript tail is what lets a
21
+ * switched or restarted agent continue the thread.
22
+ */
23
+ export declare function turnContext(input: TurnContextInput): string;
24
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/server/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,eAAO,MAAM,uBAAuB,QAAW,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EACb;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,GAC9D,SAAS,CAAC;IACd,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACnF,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,8EAA8E;IAC9E,QAAQ,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,CAAC;CACzC;AAMD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAoB3D"}
@@ -0,0 +1,77 @@
1
+ export const TRANSCRIPT_BUDGET_BYTES = 8 * 1024;
2
+ const encoder = new TextEncoder();
3
+ const byteLength = (text) => encoder.encode(text).length;
4
+ const ELLIPSIS = "...";
5
+ /**
6
+ * The `<parlor-context>` block before a fresh agent session's first prompt. Built on the
7
+ * backend so every host and agent gets the same words; the transcript tail is what lets a
8
+ * switched or restarted agent continue the thread.
9
+ */
10
+ export function turnContext(input) {
11
+ const app = input.appOrigin ? `${input.appName} (${input.appOrigin})` : input.appName;
12
+ const who = input.account
13
+ ? `${input.account.name}${input.account.email ? ` <${input.account.email}>` : ""}`
14
+ : "the signed-in user";
15
+ const from = input.device
16
+ ? ` They are writing from ${input.device.name} (${input.device.platform}).`
17
+ : "";
18
+ const lines = [
19
+ "<parlor-context>",
20
+ `You are working inside ${app} for ${who}.${from}`,
21
+ "The app's tools are its own actions plus ui_* tools that act on the screen of the chat you are in. Some actions wait for the user to approve them in the app before they run.",
22
+ ];
23
+ if (input.instructions)
24
+ lines.push("", input.instructions.trim());
25
+ const transcript = transcriptOf(input.history);
26
+ if (transcript.length > 0) {
27
+ lines.push("", "The conversation so far, oldest first:", ...transcript);
28
+ }
29
+ lines.push("</parlor-context>");
30
+ return lines.join("\n");
31
+ }
32
+ function lineOf(item) {
33
+ switch (item.kind) {
34
+ case "prompt":
35
+ return `user: ${item.body.text}`;
36
+ case "reply":
37
+ return `assistant: ${item.body.text}`;
38
+ case "tool":
39
+ return `tool: ${item.body.title} (${item.body.status})`;
40
+ default:
41
+ return undefined;
42
+ }
43
+ }
44
+ function transcriptOf(history) {
45
+ const kept = [];
46
+ let used = 0;
47
+ for (let at = history.length - 1; at >= 0; at -= 1) {
48
+ const item = history[at];
49
+ const line = item && lineOf(item);
50
+ if (line === undefined)
51
+ continue;
52
+ const size = byteLength(line) + 1;
53
+ if (used + size > TRANSCRIPT_BUDGET_BYTES) {
54
+ if (kept.length === 0)
55
+ kept.push(tailWithin(line, TRANSCRIPT_BUDGET_BYTES - 1));
56
+ break;
57
+ }
58
+ used += size;
59
+ kept.push(line);
60
+ }
61
+ return kept.reverse();
62
+ }
63
+ function tailWithin(line, budget) {
64
+ const room = budget - byteLength(ELLIPSIS);
65
+ const chars = [...line];
66
+ let size = 0;
67
+ let from = chars.length;
68
+ while (from > 0) {
69
+ const next = size + byteLength(chars[from - 1] ?? "");
70
+ if (next > room)
71
+ break;
72
+ size = next;
73
+ from -= 1;
74
+ }
75
+ return ELLIPSIS + chars.slice(from).join("");
76
+ }
77
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/server/context.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,GAAG,IAAI,CAAC;AAchD,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAClC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;AACjE,MAAM,QAAQ,GAAG,KAAK,CAAC;AAEvB;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,KAAuB;IACjD,MAAM,GAAG,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,KAAK,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC;IACtF,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO;QACvB,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAClF,CAAC,CAAC,oBAAoB,CAAC;IACzB,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM;QACvB,CAAC,CAAC,0BAA0B,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,CAAC,QAAQ,IAAI;QAC3E,CAAC,CAAC,EAAE,CAAC;IACP,MAAM,KAAK,GAAG;QACZ,kBAAkB;QAClB,0BAA0B,GAAG,QAAQ,GAAG,IAAI,IAAI,EAAE;QAClD,+KAA+K;KAChL,CAAC;IACF,IAAI,KAAK,CAAC,YAAY;QAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;IAClE,MAAM,UAAU,GAAG,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,wCAAwC,EAAE,GAAG,UAAU,CAAC,CAAC;IAC1E,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IAChC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,SAAS,MAAM,CAAC,IAAgB;IAC9B,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,QAAQ;YACX,OAAO,SAAS,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACnC,KAAK,OAAO;YACV,OAAO,cAAc,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACxC,KAAK,MAAM;YACT,OAAO,SAAS,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC;QAC1D;YACE,OAAO,SAAS,CAAC;IACrB,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CAAC,OAA8B;IAClD,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;QACzB,MAAM,IAAI,GAAG,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,IAAI,GAAG,IAAI,GAAG,uBAAuB,EAAE,CAAC;YAC1C,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,uBAAuB,GAAG,CAAC,CAAC,CAAC,CAAC;YAChF,MAAM;QACR,CAAC;QACD,IAAI,IAAI,IAAI,CAAC;QACb,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;AACxB,CAAC;AAED,SAAS,UAAU,CAAC,IAAY,EAAE,MAAc;IAC9C,MAAM,IAAI,GAAG,MAAM,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IACxB,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,IAAI,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC;IACxB,OAAO,IAAI,GAAG,CAAC,EAAE,CAAC;QAChB,MAAM,IAAI,GAAG,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACtD,IAAI,IAAI,GAAG,IAAI;YAAE,MAAM;QACvB,IAAI,GAAG,IAAI,CAAC;QACZ,IAAI,IAAI,CAAC,CAAC;IACZ,CAAC;IACD,OAAO,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC/C,CAAC","sourcesContent":["import type { LoggedItem } from \"../items.js\";\n\nexport const TRANSCRIPT_BUDGET_BYTES = 8 * 1024;\n\nexport interface TurnContextInput {\n readonly appName: string;\n readonly appOrigin: string;\n readonly account?:\n | { readonly name: string; readonly email?: string | undefined }\n | undefined;\n readonly device?: { readonly name: string; readonly platform: string } | undefined;\n readonly instructions?: string | undefined;\n /** The thread before this turn, trimmed from its oldest end to the budget. */\n readonly history: readonly LoggedItem[];\n}\n\nconst encoder = new TextEncoder();\nconst byteLength = (text: string) => encoder.encode(text).length;\nconst ELLIPSIS = \"...\";\n\n/**\n * The `<parlor-context>` block before a fresh agent session's first prompt. Built on the\n * backend so every host and agent gets the same words; the transcript tail is what lets a\n * switched or restarted agent continue the thread.\n */\nexport function turnContext(input: TurnContextInput): string {\n const app = input.appOrigin ? `${input.appName} (${input.appOrigin})` : input.appName;\n const who = input.account\n ? `${input.account.name}${input.account.email ? ` <${input.account.email}>` : \"\"}`\n : \"the signed-in user\";\n const from = input.device\n ? ` They are writing from ${input.device.name} (${input.device.platform}).`\n : \"\";\n const lines = [\n \"<parlor-context>\",\n `You are working inside ${app} for ${who}.${from}`,\n \"The app's tools are its own actions plus ui_* tools that act on the screen of the chat you are in. Some actions wait for the user to approve them in the app before they run.\",\n ];\n if (input.instructions) lines.push(\"\", input.instructions.trim());\n const transcript = transcriptOf(input.history);\n if (transcript.length > 0) {\n lines.push(\"\", \"The conversation so far, oldest first:\", ...transcript);\n }\n lines.push(\"</parlor-context>\");\n return lines.join(\"\\n\");\n}\n\nfunction lineOf(item: LoggedItem): string | undefined {\n switch (item.kind) {\n case \"prompt\":\n return `user: ${item.body.text}`;\n case \"reply\":\n return `assistant: ${item.body.text}`;\n case \"tool\":\n return `tool: ${item.body.title} (${item.body.status})`;\n default:\n return undefined;\n }\n}\n\nfunction transcriptOf(history: readonly LoggedItem[]): string[] {\n const kept: string[] = [];\n let used = 0;\n for (let at = history.length - 1; at >= 0; at -= 1) {\n const item = history[at];\n const line = item && lineOf(item);\n if (line === undefined) continue;\n const size = byteLength(line) + 1;\n if (used + size > TRANSCRIPT_BUDGET_BYTES) {\n if (kept.length === 0) kept.push(tailWithin(line, TRANSCRIPT_BUDGET_BYTES - 1));\n break;\n }\n used += size;\n kept.push(line);\n }\n return kept.reverse();\n}\n\nfunction tailWithin(line: string, budget: number): string {\n const room = budget - byteLength(ELLIPSIS);\n const chars = [...line];\n let size = 0;\n let from = chars.length;\n while (from > 0) {\n const next = size + byteLength(chars[from - 1] ?? \"\");\n if (next > room) break;\n size = next;\n from -= 1;\n }\n return ELLIPSIS + chars.slice(from).join(\"\");\n}\n"]}