@paradow/ledge 0.25.1 → 0.27.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 (32) hide show
  1. package/dist/cli/{action-WNQ3NJGD.js → action-7SJJTIEA.js} +4 -4
  2. package/dist/cli/{attach-UHM7QQ4W.js → attach-V7UPHVB2.js} +8 -8
  3. package/dist/cli/{bridge-R37AHVXS.js → bridge-JK3PMG7T.js} +1 -1
  4. package/dist/cli/{chunk-RKV5KYKL.js → chunk-2N7PSP7C.js} +3 -3
  5. package/dist/cli/{chunk-ARB4BKZJ.js → chunk-37G5F75H.js} +755 -557
  6. package/dist/cli/{chunk-TZBI2RVU.js → chunk-7GIUG73R.js} +1 -1
  7. package/dist/cli/{chunk-RYUDIFSI.js → chunk-7JRQCKBP.js} +6 -2
  8. package/dist/cli/{chunk-5VFFJ3ZC.js → chunk-7OGFH6KJ.js} +2 -2
  9. package/dist/cli/{chunk-ZDEEHFU3.js → chunk-ADAGKOFO.js} +1 -1
  10. package/dist/cli/{chunk-KRFXWD5S.js → chunk-CVHX7GUB.js} +685 -89
  11. package/dist/cli/chunk-HMTOPOJG.js +6 -0
  12. package/dist/cli/{chunk-O6FTIYJV.js → chunk-IGAGJVRZ.js} +3 -3
  13. package/dist/cli/{chunk-7XMGYJTN.js → chunk-ISNHG5SJ.js} +5 -5
  14. package/dist/cli/{chunk-TOFVC6IV.js → chunk-RA3OIXEQ.js} +2 -2
  15. package/dist/cli/{chunk-PUJLMKZC.js → chunk-TOSPL5H2.js} +3 -3
  16. package/dist/cli/{chunk-AVKFQSRP.js → chunk-UPKJO3BZ.js} +45 -17
  17. package/dist/cli/{chunk-JNLARCUC.js → chunk-YLN3VOGV.js} +49 -19
  18. package/dist/cli/{daemon-ESBBZW7O.js → daemon-YUPB5NUG.js} +34 -15
  19. package/dist/cli/{decide-UWJMKDR4.js → decide-HFI2WQXI.js} +3 -3
  20. package/dist/cli/{handover-5JHFA5EF.js → handover-GKORMXZ2.js} +4 -4
  21. package/dist/cli/{hook-XBSMUMZ7.js → hook-TJJEFV54.js} +10 -10
  22. package/dist/cli/index.js +16 -16
  23. package/dist/cli/{launch-OVB66BZJ.js → launch-QKQZZSIM.js} +8 -8
  24. package/dist/cli/{send-Y2C3BIGK.js → send-RI7JOO5K.js} +4 -4
  25. package/dist/cli/{status-5YEORNTH.js → status-RQRS26S2.js} +2 -2
  26. package/dist/cli/{task-R44VWZHR.js → task-U2XHBUKW.js} +4 -4
  27. package/dist/cli/{team-F7B3IG3I.js → team-NFC4XEIA.js} +6 -6
  28. package/dist/cli/{tui-YK6TXFYX.js → tui-UWR7SDYF.js} +8 -8
  29. package/dist/cli/{version-NFURQHXH.js → version-YYNMMWKJ.js} +1 -1
  30. package/dist/cli/{who-YMSQI64I.js → who-WW6IL4KD.js} +3 -3
  31. package/package.json +1 -1
  32. package/dist/cli/chunk-PA2JU476.js +0 -6
@@ -176,7 +176,7 @@ function isArchived(s) {
176
176
  }
177
177
 
178
178
  // ../protocol/src/teams.ts
179
- import { z as z4 } from "zod";
179
+ import { z as z7 } from "zod";
180
180
 
181
181
  // ../protocol/src/models.ts
182
182
  import { z as z3 } from "zod";
@@ -204,118 +204,257 @@ var ModelsListingSchema = z3.object({
204
204
  error: z3.string().optional()
205
205
  });
206
206
 
207
+ // ../protocol/src/projects.ts
208
+ import { z as z6 } from "zod";
209
+
210
+ // ../protocol/src/machines.ts
211
+ import { z as z5 } from "zod";
212
+
213
+ // ../protocol/src/ssh.ts
214
+ import { z as z4 } from "zod";
215
+ var SshAliasSchema = z4.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/);
216
+
217
+ // ../protocol/src/machines.ts
218
+ var MachineIdSchema = z5.string().regex(/^[a-zA-Z0-9_-]{1,64}$/);
219
+ var MachineSchema = z5.object({
220
+ id: MachineIdSchema,
221
+ label: z5.string().trim().min(1).max(80),
222
+ ssh: SshAliasSchema.optional()
223
+ });
224
+ var MachinesSchema = z5.array(MachineSchema).min(1).max(20).superRefine((list, ctx) => {
225
+ if (list[0]?.id !== "local" || list[0].ssh !== void 0) ctx.addIssue({ code: "custom", message: "the first machine is local, without ssh", path: [0] });
226
+ const ids = /* @__PURE__ */ new Set(), aliases = /* @__PURE__ */ new Set();
227
+ list.forEach((m, i) => {
228
+ if (i > 0 && !m.ssh) ctx.addIssue({ code: "custom", message: "a remote machine needs an ssh alias", path: [i, "ssh"] });
229
+ if (ids.has(m.id)) ctx.addIssue({ code: "custom", message: `duplicate id ${m.id}`, path: [i, "id"] });
230
+ ids.add(m.id);
231
+ if (m.ssh) {
232
+ if (aliases.has(m.ssh)) ctx.addIssue({ code: "custom", message: `duplicate ssh alias ${m.ssh}`, path: [i, "ssh"] });
233
+ aliases.add(m.ssh);
234
+ }
235
+ });
236
+ });
237
+
238
+ // ../protocol/src/projects.ts
239
+ var PROJECT_COLORS = { blue: "#3b82f6", green: "#10b981", amber: "#f59e0b", violet: "#8b5cf6", teal: "#14b8a6", pink: "#ec4899", red: "#ef4444", slate: "#64748b" };
240
+ var ProjectColorSchema = z6.enum(["blue", "green", "amber", "violet", "teal", "pink", "red", "slate"]);
241
+ var ProjectIdSchema = z6.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/);
242
+ function normalizePath(raw) {
243
+ const p = raw.trim().replace(/\/+/g, "/");
244
+ return p.length > 1 && p.endsWith("/") ? p.slice(0, -1) : p;
245
+ }
246
+ var PathSchema = z6.string().max(4096).refine((p) => p.startsWith("/") && p === normalizePath(p), "an absolute, normalized path");
247
+ var RepoSchema = z6.object({ machine: MachineIdSchema, path: PathSchema });
248
+ var ProjectSchema = z6.object({
249
+ id: ProjectIdSchema,
250
+ name: z6.string().trim().min(1).max(80),
251
+ color: ProjectColorSchema,
252
+ description: z6.string().max(500).default(""),
253
+ repos: z6.array(RepoSchema).max(50)
254
+ });
255
+ var RuleSchema = z6.object({ machine: MachineIdSchema, path: PathSchema, project: ProjectIdSchema });
256
+ function projectsProblems(p) {
257
+ const out = [];
258
+ const ids = /* @__PURE__ */ new Set(), names = /* @__PURE__ */ new Set(), repos = /* @__PURE__ */ new Set(), rules = /* @__PURE__ */ new Set();
259
+ p.projects.forEach((project, i) => {
260
+ if (ids.has(project.id)) out.push({ code: "duplicate_id", path: ["projects", i, "id"] });
261
+ ids.add(project.id);
262
+ const name = project.name.trim().toLocaleLowerCase();
263
+ if (names.has(name)) out.push({ code: "duplicate_name", path: ["projects", i, "name"] });
264
+ names.add(name);
265
+ project.repos.forEach((repo, j) => {
266
+ const key = `${repo.machine}
267
+ ${repo.path}`;
268
+ if (repos.has(key)) out.push({ code: "duplicate_repo", path: ["projects", i, "repos", j] });
269
+ repos.add(key);
270
+ });
271
+ });
272
+ p.rules.forEach((rule, i) => {
273
+ const key = `${rule.machine}
274
+ ${rule.path}`;
275
+ if (rules.has(key)) out.push({ code: "duplicate_rule", path: ["rules", i] });
276
+ rules.add(key);
277
+ if (!ids.has(rule.project)) out.push({ code: "unknown_project", path: ["rules", i, "project"] });
278
+ });
279
+ return out;
280
+ }
281
+ var ProjectsSchema = z6.object({ projects: z6.array(ProjectSchema).max(100), rules: z6.array(RuleSchema).max(1e3) }).superRefine((p, ctx) => {
282
+ for (const problem of projectsProblems(p)) ctx.addIssue({ code: "custom", message: problem.code, path: problem.path });
283
+ });
284
+ var DEFAULT_PROJECTS = { projects: [], rules: [] };
285
+ var under = (cwd, path2) => path2 === "/" || cwd === path2 || cwd.startsWith(`${path2}/`);
286
+ function projectOf(session, state) {
287
+ const machine = session.machineId ?? "local";
288
+ const cwd = normalizePath(session.cwd);
289
+ const known = new Set(state.projects.map((p) => p.id));
290
+ const candidates = [
291
+ ...state.projects.flatMap((p) => p.repos.filter((r) => r.machine === machine).map((r) => ({ project: p.id, path: r.path, rule: false }))),
292
+ ...state.rules.filter((r) => r.machine === machine && known.has(r.project)).map((r) => ({ project: r.project, path: r.path, rule: true }))
293
+ ].filter((c) => under(cwd, c.path));
294
+ candidates.sort((x, y) => y.path.length - x.path.length || Number(y.rule) - Number(x.rule));
295
+ return candidates[0]?.project ?? null;
296
+ }
297
+
207
298
  // ../protocol/src/teams.ts
208
- var RoleIdSchema = z4.string().regex(/^[a-z0-9][a-z0-9_-]{0,39}$/);
299
+ var RoleIdSchema = z7.string().regex(/^[a-z0-9][a-z0-9_-]{0,39}$/);
209
300
  var ROLE_LABEL_MAX = 40;
210
301
  var ROLE_PROMPT_MAX = 8e3;
211
- var RoleSchema = z4.object({
302
+ var DefinitionHashSchema = z7.string().regex(/^[0-9a-f]{16}$/);
303
+ var RoleSchema = z7.object({
212
304
  id: RoleIdSchema,
213
- label: z4.string().min(1).max(ROLE_LABEL_MAX),
214
- prompt: z4.string().max(ROLE_PROMPT_MAX),
305
+ label: z7.string().min(1).max(ROLE_LABEL_MAX),
306
+ prompt: z7.string().max(ROLE_PROMPT_MAX),
215
307
  tool: ToolSchema.optional(),
216
308
  model: ModelIdSchema.optional(),
217
309
  effort: EffortSchema.optional(),
218
310
  autonomy: AutonomySchema.optional(),
219
- source: z4.enum(["repo", "home"]),
220
- path: z4.string(),
221
- shadows: z4.string().optional()
311
+ source: z7.enum(["repo", "home"]),
312
+ path: z7.string(),
313
+ shadows: z7.string().optional(),
314
+ /** 16 hex chars of the file's text: what a write or delete must name as its base (absent from older daemons). */
315
+ hash: DefinitionHashSchema.optional()
222
316
  });
223
- var DefinitionProblemSchema = z4.object({ path: z4.string(), reason: z4.string() });
317
+ var DefinitionProblemSchema = z7.object({ path: z7.string(), reason: z7.string() });
224
318
  var TEAM_SEATS_MAX = 8;
225
- var SeatSchema = z4.object({
319
+ var SeatSchema = z7.object({
226
320
  role: RoleIdSchema,
227
321
  tool: ToolSchema.optional(),
228
322
  model: ModelIdSchema.optional(),
229
323
  effort: EffortSchema.optional(),
230
- name: z4.string().min(1).max(40).optional()
324
+ name: z7.string().min(1).max(40).optional()
231
325
  });
232
326
  var uniqueRoles = (seats) => new Set(seats.map((s) => s.role)).size === seats.length;
233
- var SeatsSchema = z4.array(SeatSchema).min(1).max(TEAM_SEATS_MAX).refine(uniqueRoles, "a role twice in one team");
234
- var TeamNameSchema = z4.string().trim().min(1).max(60);
235
- var TeamTemplateSchema = z4.object({ id: z4.string().min(1).max(64), name: TeamNameSchema, seats: SeatsSchema, source: z4.enum(["repo", "home"]), path: z4.string() });
236
- var TeamIdSchema = z4.string().regex(/^team-[0-9a-f]{4,8}$/);
237
- var TeamStateSchema = z4.enum(["active", "resting", "dissolved"]);
238
- var TeamSchema = z4.object({
327
+ var SeatsSchema = z7.array(SeatSchema).min(1).max(TEAM_SEATS_MAX).refine(uniqueRoles, "a role twice in one team");
328
+ var TeamNameSchema = z7.string().trim().min(1).max(60);
329
+ var TemplateIdSchema = z7.string().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/);
330
+ var TeamTemplateSchema = z7.object({ id: z7.string().min(1).max(64), name: TeamNameSchema, seats: SeatsSchema, source: z7.enum(["repo", "home"]), path: z7.string(), hash: DefinitionHashSchema.optional() });
331
+ var TeamIdSchema = z7.string().regex(/^team-[0-9a-f]{4,8}$/);
332
+ var TeamStateSchema = z7.enum(["active", "resting", "dissolved"]);
333
+ var TeamSchema = z7.object({
239
334
  id: TeamIdSchema,
240
335
  name: TeamNameSchema,
241
- template: z4.string().optional(),
242
- project: z4.string().nullable(),
243
- machine: z4.string(),
244
- cwd: z4.string(),
336
+ template: z7.string().optional(),
337
+ project: z7.string().nullable(),
338
+ machine: z7.string(),
339
+ cwd: z7.string(),
245
340
  state: TeamStateSchema,
246
- seats: z4.array(z4.object({ role: RoleIdSchema, sessionId: z4.string().nullable() })).max(TEAM_SEATS_MAX * 2),
247
- createdAt: z4.string(),
248
- updatedAt: z4.string(),
249
- restingAt: z4.string().optional(),
250
- dissolvedAt: z4.string().optional()
341
+ /** A live seat: `tool`, `model` and `effort` are what it was composed with over the role's defaults; `leaving` marks a seat removed
342
+ * from the composition that finishes its turn and then is closed. */
343
+ seats: z7.array(z7.object({
344
+ role: RoleIdSchema,
345
+ sessionId: z7.string().nullable(),
346
+ tool: ToolSchema.optional(),
347
+ model: ModelIdSchema.optional(),
348
+ effort: EffortSchema.optional(),
349
+ leaving: z7.literal(true).optional()
350
+ })).max(TEAM_SEATS_MAX * 2),
351
+ createdAt: z7.string(),
352
+ updatedAt: z7.string(),
353
+ restingAt: z7.string().optional(),
354
+ dissolvedAt: z7.string().optional()
251
355
  });
252
- var RolesListSchema = z4.object({ type: z4.literal("roles.list"), cwd: z4.string().min(1).optional(), requestId: z4.string().max(100).optional(), machineId: z4.string().optional() });
253
- var RolesListingSchema = z4.object({
254
- type: z4.literal("roles.listing"),
255
- requestId: z4.string().optional(),
256
- roles: z4.array(RoleSchema),
257
- templates: z4.array(TeamTemplateSchema).default([]),
258
- problems: z4.array(DefinitionProblemSchema),
356
+ var RolesListSchema = z7.object({ type: z7.literal("roles.list"), cwd: z7.string().min(1).optional(), requestId: z7.string().max(100).optional(), machineId: z7.string().optional() });
357
+ var RolesListingSchema = z7.object({
358
+ type: z7.literal("roles.listing"),
359
+ requestId: z7.string().optional(),
360
+ roles: z7.array(RoleSchema),
361
+ templates: z7.array(TeamTemplateSchema).default([]),
362
+ problems: z7.array(DefinitionProblemSchema),
259
363
  /** Set by the fleet when the project's machine could not answer (#99): 'offline', or 'outdated' for a daemon without roles.list. */
260
- error: z4.string().optional()
364
+ error: z7.string().optional()
261
365
  });
262
- var TeamLaunchSchema = z4.object({
263
- type: z4.literal("team.launch"),
264
- rid: z4.string().min(1).max(100),
265
- cwd: z4.string().min(1).optional(),
266
- template: z4.string().min(1).max(64).optional(),
366
+ var TeamLaunchSchema = z7.object({
367
+ type: z7.literal("team.launch"),
368
+ rid: z7.string().min(1).max(100),
369
+ cwd: z7.string().min(1).optional(),
370
+ template: z7.string().min(1).max(64).optional(),
267
371
  seats: SeatsSchema.optional(),
268
372
  name: TeamNameSchema.optional(),
269
- qid: z4.string().min(1).optional(),
270
- machineId: z4.string().optional()
373
+ qid: z7.string().min(1).optional(),
374
+ machineId: z7.string().optional(),
375
+ /** The project's name, for a client that holds no path (the phone): the daemon resolves its folder. */
376
+ project: ProjectIdSchema.optional()
377
+ });
378
+ var TeamJoinSchema = z7.object({ type: z7.literal("team.join"), team: TeamIdSchema, session: z7.string().min(1), role: RoleIdSchema });
379
+ var TeamLeaveSchema = z7.object({ type: z7.literal("team.leave"), team: TeamIdSchema, session: z7.string().min(1) });
380
+ var TeamResumeSchema = z7.object({ type: z7.literal("team.resume"), team: TeamIdSchema });
381
+ var TeamDissolveSchema = z7.object({ type: z7.literal("team.dissolve"), team: TeamIdSchema });
382
+ var TeamSaveSchema = z7.object({ type: z7.literal("team.save"), rid: z7.string().min(1).max(100), name: TeamNameSchema, seats: SeatsSchema, qid: z7.string().min(1).optional() });
383
+ var DefinitionScopeSchema = z7.enum(["home", "repo"]);
384
+ var RoleDraftSchema = RoleSchema.pick({ id: true, label: true, prompt: true, tool: true, model: true, effort: true, autonomy: true });
385
+ var DefinitionCodeSchema = z7.enum(["changed", "exists", "missing", "unknown_project", "invalid"]);
386
+ var scopeFields = { rid: z7.string().min(1).max(100), scope: DefinitionScopeSchema, project: ProjectIdSchema.optional() };
387
+ var scopeIssue = (m) => m.scope === void 0 || m.scope === "repo" === (m.project !== void 0) ? null : "a repo scope names a project, a home scope none";
388
+ var DefinitionBaseSchema = DefinitionHashSchema;
389
+ var DefinitionsListSchema = z7.object({ type: z7.literal("definitions.list"), requestId: z7.string().max(100).optional() });
390
+ var RoleWriteSchema = z7.object({ type: z7.literal("role.write"), ...scopeFields, role: RoleDraftSchema, base: DefinitionBaseSchema.nullable() });
391
+ var RoleDeleteSchema = z7.object({ type: z7.literal("role.delete"), ...scopeFields, id: RoleIdSchema, base: DefinitionBaseSchema });
392
+ var TemplateWriteSchema = z7.object({
393
+ type: z7.literal("template.write"),
394
+ ...scopeFields,
395
+ id: TemplateIdSchema.optional(),
396
+ name: TeamNameSchema,
397
+ seats: SeatsSchema,
398
+ base: DefinitionBaseSchema.nullable()
399
+ });
400
+ var TemplateDeleteSchema = z7.object({ type: z7.literal("template.delete"), ...scopeFields, id: TemplateIdSchema, base: DefinitionBaseSchema });
401
+ var TeamComposeSchema = z7.object({ type: z7.literal("team.compose"), rid: z7.string().min(1).max(100), team: TeamIdSchema, seats: SeatsSchema });
402
+ var TeamSeatSchema = z7.object({ type: z7.literal("team.seat"), rid: z7.string().min(1).max(100), team: TeamIdSchema, role: RoleIdSchema, action: z7.enum(["start", "restart"]) });
403
+ var DefinitionsListingSchema = z7.object({
404
+ type: z7.literal("definitions.listing"),
405
+ requestId: z7.string().optional(),
406
+ scopes: z7.array(z7.object({
407
+ scope: DefinitionScopeSchema,
408
+ project: z7.string().nullable(),
409
+ roles: z7.array(RoleSchema),
410
+ templates: z7.array(TeamTemplateSchema),
411
+ problems: z7.array(DefinitionProblemSchema)
412
+ }))
271
413
  });
272
- var TeamJoinSchema = z4.object({ type: z4.literal("team.join"), team: TeamIdSchema, session: z4.string().min(1), role: RoleIdSchema });
273
- var TeamLeaveSchema = z4.object({ type: z4.literal("team.leave"), team: TeamIdSchema, session: z4.string().min(1) });
274
- var TeamResumeSchema = z4.object({ type: z4.literal("team.resume"), team: TeamIdSchema });
275
- var TeamDissolveSchema = z4.object({ type: z4.literal("team.dissolve"), team: TeamIdSchema });
276
- var TeamSaveSchema = z4.object({ type: z4.literal("team.save"), rid: z4.string().min(1).max(100), name: TeamNameSchema, seats: SeatsSchema, qid: z4.string().min(1).optional() });
277
- var TeamsMessageSchema = z4.object({ type: z4.literal("teams"), teams: z4.array(TeamSchema) });
278
- var TeamUpdatedSchema = z4.object({ type: z4.literal("team.updated"), team: TeamSchema });
279
- var TeamLaunchedSchema = z4.object({ type: z4.literal("team.launched"), rid: z4.string(), team: TeamSchema });
280
- var TeamFailedSchema = z4.object({ type: z4.literal("team.failed"), rid: z4.string(), reason: z4.string(), team: TeamSchema.optional() });
281
- var TeamSavedSchema = z4.object({ type: z4.literal("team.saved"), rid: z4.string(), path: z4.string().optional(), reason: z4.string().optional() });
414
+ var DefinitionResultSchema = z7.object({ type: z7.literal("definition.result"), rid: z7.string(), id: z7.string().optional(), hash: DefinitionHashSchema.optional(), code: DefinitionCodeSchema.optional(), reason: z7.string().optional() });
415
+ var TeamChangedSchema = z7.object({ type: z7.literal("team.changed"), rid: z7.string(), team: TeamSchema.optional(), reason: z7.string().optional() });
416
+ var TeamsMessageSchema = z7.object({ type: z7.literal("teams"), teams: z7.array(TeamSchema) });
417
+ var TeamUpdatedSchema = z7.object({ type: z7.literal("team.updated"), team: TeamSchema });
418
+ var TeamLaunchedSchema = z7.object({ type: z7.literal("team.launched"), rid: z7.string(), team: TeamSchema });
419
+ var TeamFailedSchema = z7.object({ type: z7.literal("team.failed"), rid: z7.string(), reason: z7.string(), team: TeamSchema.optional() });
420
+ var TeamSavedSchema = z7.object({ type: z7.literal("team.saved"), rid: z7.string(), path: z7.string().optional(), reason: z7.string().optional() });
282
421
  var isTeamLive = (t) => t.state !== "dissolved";
283
422
 
284
423
  // ../protocol/src/tasks.ts
285
- import { z as z5 } from "zod";
424
+ import { z as z8 } from "zod";
286
425
  var TASK_TITLE_MAX = 200;
287
426
  var TASK_TEXT_MAX = 2e4;
288
427
  var LEDGE_GIVER = "ledge";
289
428
  var TASK_OPS = ["give", "take", "pass", "done", "refuse", "cancel", "drop"];
290
429
  var TRANSMISSION_OPS = ["give", "pass", "done", "refuse", "cancel"];
291
- var TaskLogEntrySchema = z5.object({
292
- at: z5.string(),
293
- by: z5.string(),
294
- what: z5.string(),
295
- op: z5.enum(TASK_OPS).optional(),
296
- from: z5.string().optional(),
297
- to: z5.string().optional(),
298
- fromName: z5.string().optional(),
299
- toName: z5.string().optional(),
300
- note: z5.string().optional()
430
+ var TaskLogEntrySchema = z8.object({
431
+ at: z8.string(),
432
+ by: z8.string(),
433
+ what: z8.string(),
434
+ op: z8.enum(TASK_OPS).optional(),
435
+ from: z8.string().optional(),
436
+ to: z8.string().optional(),
437
+ fromName: z8.string().optional(),
438
+ toName: z8.string().optional(),
439
+ note: z8.string().optional()
301
440
  });
302
- var TaskSchema = z5.object({
303
- id: z5.string(),
304
- title: z5.string(),
305
- text: z5.string().optional(),
306
- giver: z5.string(),
307
- giverName: z5.string(),
308
- owner: z5.string(),
309
- ownerName: z5.string(),
310
- state: z5.enum(["open", "taken", "done", "refused", "dropped"]),
311
- result: z5.string().optional(),
441
+ var TaskSchema = z8.object({
442
+ id: z8.string(),
443
+ title: z8.string(),
444
+ text: z8.string().optional(),
445
+ giver: z8.string(),
446
+ giverName: z8.string(),
447
+ owner: z8.string(),
448
+ ownerName: z8.string(),
449
+ state: z8.enum(["open", "taken", "done", "refused", "dropped"]),
450
+ result: z8.string().optional(),
312
451
  /** The live team its owner sat in when it was given (or passed), so a team's tasks can be listed. */
313
- team: z5.string().optional(),
452
+ team: z8.string().optional(),
314
453
  /** A task Ledge gave and the user put away from « À toi » once closed. */
315
- seen: z5.boolean().optional(),
316
- at: z5.string(),
317
- updatedAt: z5.string(),
318
- log: z5.array(TaskLogEntrySchema)
454
+ seen: z8.boolean().optional(),
455
+ at: z8.string(),
456
+ updatedAt: z8.string(),
457
+ log: z8.array(TaskLogEntrySchema)
319
458
  });
320
459
  var handOver = (op) => TRANSMISSION_OPS.includes(op ?? "");
321
460
  function transmissions(t) {
@@ -323,54 +462,54 @@ function transmissions(t) {
323
462
  }
324
463
  var givenByLedge = (t) => t.giver === LEDGE_GIVER;
325
464
  var taskClosed = (t) => t.state === "done" || t.state === "refused" || t.state === "dropped";
326
- var TaskCmdSchema = z5.object({
327
- type: z5.literal("task.cmd"),
328
- rid: z5.string().min(1),
329
- by: z5.string().min(1),
330
- op: z5.enum(["give", "take", "done", "refuse", "pass", "show", "list", "seen", "cancel"]),
331
- task: z5.string().min(1).max(40).optional(),
332
- to: z5.string().min(1).optional(),
333
- title: z5.string().min(1).max(TASK_TITLE_MAX).optional(),
334
- text: z5.string().max(TASK_TEXT_MAX).optional(),
335
- all: z5.boolean().optional(),
336
- team: z5.string().min(1).max(40).optional(),
337
- qid: z5.string().min(1).optional(),
338
- row: z5.number().int().min(0).max(7).optional()
465
+ var TaskCmdSchema = z8.object({
466
+ type: z8.literal("task.cmd"),
467
+ rid: z8.string().min(1),
468
+ by: z8.string().min(1),
469
+ op: z8.enum(["give", "take", "done", "refuse", "pass", "show", "list", "seen", "cancel"]),
470
+ task: z8.string().min(1).max(40).optional(),
471
+ to: z8.string().min(1).optional(),
472
+ title: z8.string().min(1).max(TASK_TITLE_MAX).optional(),
473
+ text: z8.string().max(TASK_TEXT_MAX).optional(),
474
+ all: z8.boolean().optional(),
475
+ team: z8.string().min(1).max(40).optional(),
476
+ qid: z8.string().min(1).optional(),
477
+ row: z8.number().int().min(0).max(7).optional()
339
478
  });
340
- var TaskUpdatedSchema = z5.object({ type: z5.literal("task.updated"), task: TaskSchema });
341
- var TaskResultSchema = z5.object({
342
- type: z5.literal("task.result"),
343
- rid: z5.string(),
479
+ var TaskUpdatedSchema = z8.object({ type: z8.literal("task.updated"), task: TaskSchema });
480
+ var TaskResultSchema = z8.object({
481
+ type: z8.literal("task.result"),
482
+ rid: z8.string(),
344
483
  task: TaskSchema.optional(),
345
- tasks: z5.array(TaskSchema).optional(),
346
- reason: z5.string().optional()
484
+ tasks: z8.array(TaskSchema).optional(),
485
+ reason: z8.string().optional()
347
486
  });
348
487
 
349
488
  // ../protocol/src/actions.ts
350
- import { z as z8 } from "zod";
489
+ import { z as z11 } from "zod";
351
490
 
352
491
  // ../protocol/src/proposal.ts
353
- import { z as z6 } from "zod";
354
- var ProposalBlockSchema = z6.object({ cwd: z6.string().trim().min(1), prompt: z6.string().optional() });
355
- var RelayBlockSchema = z6.object({ session: z6.string().trim().min(1), text: z6.string().trim().min(1) });
356
- var ProjectBlockSchema = z6.object({
357
- name: z6.string().trim().min(1).max(80),
358
- description: z6.string().max(500).optional(),
359
- repos: z6.array(z6.object({ path: z6.string().min(1).max(4096), why: z6.string().trim().min(1).max(200) })).min(1).max(50),
360
- addTo: z6.string().trim().max(80).optional()
492
+ import { z as z9 } from "zod";
493
+ var ProposalBlockSchema = z9.object({ cwd: z9.string().trim().min(1), prompt: z9.string().optional() });
494
+ var RelayBlockSchema = z9.object({ session: z9.string().trim().min(1), text: z9.string().trim().min(1) });
495
+ var ProjectBlockSchema = z9.object({
496
+ name: z9.string().trim().min(1).max(80),
497
+ description: z9.string().max(500).optional(),
498
+ repos: z9.array(z9.object({ path: z9.string().min(1).max(4096), why: z9.string().trim().min(1).max(200) })).min(1).max(50),
499
+ addTo: z9.string().trim().max(80).optional()
361
500
  });
362
- var CloseBlockSchema = z6.object({ session: z6.string().trim().min(1) });
363
- var TeamBlockSchema = z6.object({
364
- cwd: z6.string().trim().min(1),
365
- template: z6.string().trim().min(1).max(64).optional(),
366
- name: z6.string().trim().min(1).max(60).optional(),
367
- seats: z6.array(z6.object({ role: z6.string().trim().min(1).max(40), tool: z6.enum(["claude", "codex", "cursor", "omp"]).optional(), model: z6.string().max(200).optional(), effort: z6.string().max(20).optional(), name: z6.string().max(40).optional() })).min(1).max(8).optional()
501
+ var CloseBlockSchema = z9.object({ session: z9.string().trim().min(1) });
502
+ var TeamBlockSchema = z9.object({
503
+ cwd: z9.string().trim().min(1),
504
+ template: z9.string().trim().min(1).max(64).optional(),
505
+ name: z9.string().trim().min(1).max(60).optional(),
506
+ seats: z9.array(z9.object({ role: z9.string().trim().min(1).max(40), tool: z9.enum(["claude", "codex", "cursor", "omp"]).optional(), model: z9.string().max(200).optional(), effort: z9.string().max(20).optional(), name: z9.string().max(40).optional() })).min(1).max(8).optional()
368
507
  }).refine((b) => !!b.template || !!b.seats?.length, "a template or seats");
369
- var TaskBlockSchema = z6.object({
370
- to: z6.string().trim().min(1).max(80),
371
- team: z6.string().trim().max(40).optional(),
372
- title: z6.string().trim().min(1).max(200),
373
- text: z6.string().max(2e4).optional()
508
+ var TaskBlockSchema = z9.object({
509
+ to: z9.string().trim().min(1).max(80),
510
+ team: z9.string().trim().max(40).optional(),
511
+ title: z9.string().trim().min(1).max(200),
512
+ text: z9.string().max(2e4).optional()
374
513
  });
375
514
  var BLOCK = /```ledge-(session|relay|project|close|team|task|action)[ \t]*\n?([\s\S]*?)(?:```|$)/g;
376
515
  function extractProposal(answer) {
@@ -424,8 +563,8 @@ function parseProjectBlock(raw) {
424
563
  }
425
564
 
426
565
  // ../protocol/src/decisions.ts
427
- import { z as z7 } from "zod";
428
- var DecisionSchema = z7.enum(["accept", "deny", "always"]);
566
+ import { z as z10 } from "zod";
567
+ var DecisionSchema = z10.enum(["accept", "deny", "always"]);
429
568
  var NOTE_MAX = 4e3;
430
569
  var NOTE_NOT_TYPED = "note_not_typed";
431
570
  var DECISION_OFFERS = {
@@ -455,7 +594,7 @@ function pendingKey(p) {
455
594
  }
456
595
 
457
596
  // ../protocol/src/actions.ts
458
- var ActionRiskSchema = z8.enum(["read", "reversible", "destructive"]);
597
+ var ActionRiskSchema = z11.enum(["read", "reversible", "destructive"]);
459
598
  var ACTION_IDS = [
460
599
  "session.launch",
461
600
  "session.relay",
@@ -477,11 +616,11 @@ var ACTION_IDS = [
477
616
  "task.cancel",
478
617
  "task.pass"
479
618
  ];
480
- var ActionIdSchema = z8.enum(ACTION_IDS);
619
+ var ActionIdSchema = z11.enum(ACTION_IDS);
481
620
  var def = (d) => d;
482
- var SessionRef = z8.string().trim().min(1).max(80);
483
- var TeamRef = z8.string().trim().min(1).max(60);
484
- var TaskRef = z8.string().trim().min(1).max(40);
621
+ var SessionRef = z11.string().trim().min(1).max(80);
622
+ var TeamRef = z11.string().trim().min(1).max(60);
623
+ var TaskRef = z11.string().trim().min(1).max(40);
485
624
  var LaunchArgs = ProposalBlockSchema.extend({ model: ModelIdSchema.optional(), effort: EffortSchema.optional() });
486
625
  var ACTIONS = [
487
626
  def({
@@ -559,14 +698,14 @@ var ACTIONS = [
559
698
  phone: null,
560
699
  risk: "reversible",
561
700
  max: 8,
562
- args: z8.object({ session: SessionRef, model: ModelIdSchema.nullable(), effort: EffortSchema.nullable() }),
701
+ args: z11.object({ session: SessionRef, model: ModelIdSchema.nullable(), effort: EffortSchema.nullable() }),
563
702
  summary: "changer le mod\xE8le et l'effort d'une session en cours (null : le d\xE9faut de l'agent) ; elle red\xE9marre sur la m\xEAme conversation, \xE0 son prochain moment libre",
564
703
  when: "quand l'utilisateur demande de passer une session sur un autre mod\xE8le ou un autre effort",
565
704
  example: { session: "Nova", model: "claude-opus-5-5", effort: "high" }
566
705
  }),
567
706
  def({
568
707
  id: "session.interrupt",
569
- args: z8.object({ session: SessionRef }),
708
+ args: z11.object({ session: SessionRef }),
570
709
  card: "generic",
571
710
  phone: null,
572
711
  risk: "reversible",
@@ -577,7 +716,7 @@ var ACTIONS = [
577
716
  }),
578
717
  def({
579
718
  id: "session.archive",
580
- args: z8.object({ session: SessionRef }),
719
+ args: z11.object({ session: SessionRef }),
581
720
  card: "generic",
582
721
  phone: null,
583
722
  risk: "reversible",
@@ -588,7 +727,7 @@ var ACTIONS = [
588
727
  }),
589
728
  def({
590
729
  id: "session.restore",
591
- args: z8.object({ session: SessionRef }),
730
+ args: z11.object({ session: SessionRef }),
592
731
  card: "generic",
593
732
  phone: null,
594
733
  risk: "reversible",
@@ -599,7 +738,7 @@ var ACTIONS = [
599
738
  }),
600
739
  def({
601
740
  id: "session.resume",
602
- args: z8.object({ session: SessionRef }),
741
+ args: z11.object({ session: SessionRef }),
603
742
  card: "generic",
604
743
  phone: "act",
605
744
  risk: "reversible",
@@ -613,7 +752,7 @@ var ACTIONS = [
613
752
  card: "generic",
614
753
  phone: "act",
615
754
  max: 1,
616
- args: z8.object({ session: SessionRef, decision: z8.enum(["accept", "deny"]), note: z8.string().trim().min(1).max(NOTE_MAX).optional() }),
755
+ args: z11.object({ session: SessionRef, decision: z11.enum(["accept", "deny"]), note: z11.string().trim().min(1).max(NOTE_MAX).optional() }),
617
756
  risk: (a) => a.decision === "accept" ? "destructive" : "reversible",
618
757
  summary: "accepter ou refuser la demande en attente d'une session (permission, diff ou plan), note possible avec un refus ; jamais \xAB toujours \xBB",
619
758
  when: "seulement quand l'utilisateur demande explicitement d'accepter ou de refuser la demande d'une session pr\xE9cise, et que sessions.md montre une demande en attente pour elle ; cite la demande telle quelle dans ta r\xE9ponse",
@@ -621,7 +760,7 @@ var ACTIONS = [
621
760
  }),
622
761
  def({
623
762
  id: "team.join",
624
- args: z8.object({ team: TeamRef, session: SessionRef, role: RoleIdSchema }),
763
+ args: z11.object({ team: TeamRef, session: SessionRef, role: RoleIdSchema }),
625
764
  card: "generic",
626
765
  phone: null,
627
766
  risk: "reversible",
@@ -632,7 +771,7 @@ var ACTIONS = [
632
771
  }),
633
772
  def({
634
773
  id: "team.leave",
635
- args: z8.object({ team: TeamRef, session: SessionRef }),
774
+ args: z11.object({ team: TeamRef, session: SessionRef }),
636
775
  card: "generic",
637
776
  phone: null,
638
777
  risk: "reversible",
@@ -643,7 +782,7 @@ var ACTIONS = [
643
782
  }),
644
783
  def({
645
784
  id: "team.resume",
646
- args: z8.object({ team: TeamRef }),
785
+ args: z11.object({ team: TeamRef }),
647
786
  card: "generic",
648
787
  phone: "act",
649
788
  risk: "reversible",
@@ -654,7 +793,7 @@ var ACTIONS = [
654
793
  }),
655
794
  def({
656
795
  id: "team.dissolve",
657
- args: z8.object({ team: TeamRef }),
796
+ args: z11.object({ team: TeamRef }),
658
797
  card: "generic",
659
798
  phone: "act",
660
799
  risk: "destructive",
@@ -666,7 +805,7 @@ var ACTIONS = [
666
805
  }),
667
806
  def({
668
807
  id: "team.save",
669
- args: z8.object({ team: TeamRef, name: TeamNameSchema }),
808
+ args: z11.object({ team: TeamRef, name: TeamNameSchema }),
670
809
  card: "generic",
671
810
  phone: null,
672
811
  risk: "reversible",
@@ -677,7 +816,7 @@ var ACTIONS = [
677
816
  }),
678
817
  def({
679
818
  id: "task.cancel",
680
- args: z8.object({ task: TaskRef, reason: z8.string().trim().min(1).max(500).optional() }),
819
+ args: z11.object({ task: TaskRef, reason: z11.string().trim().min(1).max(500).optional() }),
681
820
  card: "generic",
682
821
  phone: "act",
683
822
  risk: "destructive",
@@ -688,7 +827,7 @@ var ACTIONS = [
688
827
  }),
689
828
  def({
690
829
  id: "task.pass",
691
- args: z8.object({ task: TaskRef, to: SessionRef, note: z8.string().trim().min(1).max(TASK_TEXT_MAX).optional() }),
830
+ args: z11.object({ task: TaskRef, to: SessionRef, note: z11.string().trim().min(1).max(TASK_TEXT_MAX).optional() }),
692
831
  card: "generic",
693
832
  phone: null,
694
833
  risk: "reversible",
@@ -701,7 +840,7 @@ var ACTIONS = [
701
840
  var byId = new Map(ACTIONS.map((a) => [a.id, a]));
702
841
  var actionById = (id) => byId.get(id);
703
842
  var riskOf = (a, args) => typeof a.risk === "function" ? a.risk(args) : a.risk;
704
- var ActionBlockSchema = z8.object({ action: z8.string().trim().min(1).max(40), args: z8.record(z8.unknown()).default({}) });
843
+ var ActionBlockSchema = z11.object({ action: z11.string().trim().min(1).max(40), args: z11.record(z11.unknown()).default({}) });
705
844
  var LEGACY_FENCE_ACTION = {
706
845
  session: "session.launch",
707
846
  relay: "session.relay",
@@ -747,119 +886,119 @@ var NEVER_PROPOSED = [
747
886
  import { z as z21 } from "zod";
748
887
 
749
888
  // ../protocol/src/chat.ts
750
- import { z as z10 } from "zod";
889
+ import { z as z13 } from "zod";
751
890
 
752
891
  // ../protocol/src/attachments.ts
753
- import { z as z9 } from "zod";
892
+ import { z as z12 } from "zod";
754
893
  var ATTACHMENT_ID = /^[0-9a-f]{64}$/;
755
- var AttachmentIdSchema = z9.string().regex(ATTACHMENT_ID);
894
+ var AttachmentIdSchema = z12.string().regex(ATTACHMENT_ID);
756
895
  var IMAGE_MIMES = ["image/webp", "image/jpeg", "image/png", "image/gif"];
757
- var ImageMimeSchema = z9.enum(IMAGE_MIMES);
896
+ var ImageMimeSchema = z12.enum(IMAGE_MIMES);
758
897
  var ATTACHMENT_MAX = 4e5;
759
898
  var ATTACHMENT_LOCAL_MAX = 2e6;
760
899
  var PREVIEW_MAX = 4e4;
761
900
  var ATTACHMENTS_MAX = 5;
762
901
  var b64Max = (bytes) => Math.ceil(bytes / 3) * 4;
763
- var AttachmentRefSchema = z9.object({
902
+ var AttachmentRefSchema = z12.object({
764
903
  id: AttachmentIdSchema,
765
904
  mime: ImageMimeSchema,
766
- width: z9.number().int().positive(),
767
- height: z9.number().int().positive(),
768
- bytes: z9.number().int().positive(),
769
- preview: z9.boolean()
905
+ width: z12.number().int().positive(),
906
+ height: z12.number().int().positive(),
907
+ bytes: z12.number().int().positive(),
908
+ preview: z12.boolean()
770
909
  });
771
- var ImageUploadSchema = z9.object({
910
+ var ImageUploadSchema = z12.object({
772
911
  mime: ImageMimeSchema,
773
- data: z9.string().min(1).max(b64Max(ATTACHMENT_LOCAL_MAX)),
774
- preview: z9.object({ mime: ImageMimeSchema, data: z9.string().min(1).max(b64Max(PREVIEW_MAX)) }).optional()
912
+ data: z12.string().min(1).max(b64Max(ATTACHMENT_LOCAL_MAX)),
913
+ preview: z12.object({ mime: ImageMimeSchema, data: z12.string().min(1).max(b64Max(PREVIEW_MAX)) }).optional()
775
914
  });
776
- var AttachmentErrorReasonSchema = z9.enum(["too_large", "not_image", "unreadable", "not_found", "offline"]);
777
- var requestId = z9.string().min(1).max(100);
778
- var AttachmentPutSchema = z9.object({ type: z9.literal("attachment.put"), requestId, id: z9.string().optional(), image: ImageUploadSchema });
779
- var AttachmentGetSchema = z9.object({ type: z9.literal("attachment.get"), requestId, attachment: AttachmentIdSchema, preview: z9.boolean().optional(), id: z9.string().optional(), machine: z9.string().optional() });
780
- var AttachmentStoredSchema = z9.object({ type: z9.literal("attachment.stored"), requestId, ref: AttachmentRefSchema });
781
- var AttachmentDataSchema = z9.object({ type: z9.literal("attachment.data"), requestId, attachment: AttachmentIdSchema, mime: ImageMimeSchema, data: z9.string() });
782
- var AttachmentErrorSchema = z9.object({ type: z9.literal("attachment.error"), requestId, reason: AttachmentErrorReasonSchema });
915
+ var AttachmentErrorReasonSchema = z12.enum(["too_large", "not_image", "unreadable", "not_found", "offline"]);
916
+ var requestId = z12.string().min(1).max(100);
917
+ var AttachmentPutSchema = z12.object({ type: z12.literal("attachment.put"), requestId, id: z12.string().optional(), image: ImageUploadSchema });
918
+ var AttachmentGetSchema = z12.object({ type: z12.literal("attachment.get"), requestId, attachment: AttachmentIdSchema, preview: z12.boolean().optional(), id: z12.string().optional(), machine: z12.string().optional() });
919
+ var AttachmentStoredSchema = z12.object({ type: z12.literal("attachment.stored"), requestId, ref: AttachmentRefSchema });
920
+ var AttachmentDataSchema = z12.object({ type: z12.literal("attachment.data"), requestId, attachment: AttachmentIdSchema, mime: ImageMimeSchema, data: z12.string() });
921
+ var AttachmentErrorSchema = z12.object({ type: z12.literal("attachment.error"), requestId, reason: AttachmentErrorReasonSchema });
783
922
 
784
923
  // ../protocol/src/chat.ts
785
- var ChatStepSchema = z10.object({
786
- kind: z10.enum(["sessions", "pane", "reply", "git", "repo"]),
787
- id: z10.string().optional(),
788
- name: z10.string().optional(),
789
- path: z10.string().optional()
924
+ var ChatStepSchema = z13.object({
925
+ kind: z13.enum(["sessions", "pane", "reply", "git", "repo"]),
926
+ id: z13.string().optional(),
927
+ name: z13.string().optional(),
928
+ path: z13.string().optional()
790
929
  });
791
- var ChatProposalSchema = z10.object({
792
- cwd: z10.string().min(1),
793
- project: z10.string(),
794
- prompt: z10.string().optional(),
930
+ var ChatProposalSchema = z13.object({
931
+ cwd: z13.string().min(1),
932
+ project: z13.string(),
933
+ prompt: z13.string().optional(),
795
934
  tool: ToolSchema,
796
935
  /** What Ledge proposed on the card's picker (spec 2026-10-26 action registry §4), the agent's own default when left out. */
797
936
  model: ModelIdSchema.optional(),
798
937
  effort: EffortSchema.optional(),
799
- launchedId: z10.string().optional(),
800
- error: z10.string().optional()
938
+ launchedId: z13.string().optional(),
939
+ error: z13.string().optional()
801
940
  });
802
941
  var MAX_PROPOSALS = 8;
803
- var ChatProposalsSchema = z10.array(ChatProposalSchema).min(1).max(MAX_PROPOSALS);
804
- var ChatRelaySchema = z10.object({
805
- id: z10.string().min(1),
806
- name: z10.string(),
942
+ var ChatProposalsSchema = z13.array(ChatProposalSchema).min(1).max(MAX_PROPOSALS);
943
+ var ChatRelaySchema = z13.object({
944
+ id: z13.string().min(1),
945
+ name: z13.string(),
807
946
  tool: ToolSchema,
808
- text: z10.string().min(1),
809
- status: z10.enum(["queued", "sent"]).optional(),
810
- sentAt: z10.string().datetime().optional(),
811
- error: z10.string().optional()
947
+ text: z13.string().min(1),
948
+ status: z13.enum(["queued", "sent"]).optional(),
949
+ sentAt: z13.string().datetime().optional(),
950
+ error: z13.string().optional()
812
951
  });
813
- var ChatCloseSchema = z10.object({
814
- id: z10.string().min(1),
815
- name: z10.string(),
952
+ var ChatCloseSchema = z13.object({
953
+ id: z13.string().min(1),
954
+ name: z13.string(),
816
955
  tool: ToolSchema,
817
- closedAt: z10.string().datetime().optional(),
818
- how: z10.enum(["exit", "killed"]).optional(),
819
- error: z10.string().optional()
956
+ closedAt: z13.string().datetime().optional(),
957
+ how: z13.enum(["exit", "killed"]).optional(),
958
+ error: z13.string().optional()
820
959
  });
821
- var ChatClosesSchema = z10.array(ChatCloseSchema).min(1).max(MAX_PROPOSALS);
822
- var ChatProjectProposalSchema = z10.object({
823
- name: z10.string().min(1).max(80),
824
- description: z10.string().max(500).optional(),
825
- repos: z10.array(z10.object({ path: z10.string().min(1).max(4096), why: z10.string().min(1).max(200) })).min(1).max(50),
826
- addTo: z10.string().min(1).max(80).optional()
960
+ var ChatClosesSchema = z13.array(ChatCloseSchema).min(1).max(MAX_PROPOSALS);
961
+ var ChatProjectProposalSchema = z13.object({
962
+ name: z13.string().min(1).max(80),
963
+ description: z13.string().max(500).optional(),
964
+ repos: z13.array(z13.object({ path: z13.string().min(1).max(4096), why: z13.string().min(1).max(200) })).min(1).max(50),
965
+ addTo: z13.string().min(1).max(80).optional()
827
966
  });
828
- var ChatTeamSeatSchema = z10.object({
829
- role: z10.string().min(1),
830
- label: z10.string(),
967
+ var ChatTeamSeatSchema = z13.object({
968
+ role: z13.string().min(1),
969
+ label: z13.string(),
831
970
  tool: ToolSchema,
832
- model: z10.string().optional(),
833
- effort: z10.string().optional(),
971
+ model: z13.string().optional(),
972
+ effort: z13.string().optional(),
834
973
  autonomy: AutonomySchema.optional(),
835
- name: z10.string().optional()
974
+ name: z13.string().optional()
836
975
  });
837
- var ChatTeamProposalSchema = z10.object({
838
- cwd: z10.string().min(1),
839
- project: z10.string(),
840
- projectName: z10.string().optional(),
841
- name: z10.string().min(1),
842
- template: z10.string().optional(),
843
- seats: z10.array(ChatTeamSeatSchema).min(1).max(8),
844
- teamId: z10.string().optional(),
845
- launchedAt: z10.string().datetime().optional(),
846
- error: z10.string().optional(),
847
- savedPath: z10.string().optional()
976
+ var ChatTeamProposalSchema = z13.object({
977
+ cwd: z13.string().min(1),
978
+ project: z13.string(),
979
+ projectName: z13.string().optional(),
980
+ name: z13.string().min(1),
981
+ template: z13.string().optional(),
982
+ seats: z13.array(ChatTeamSeatSchema).min(1).max(8),
983
+ teamId: z13.string().optional(),
984
+ launchedAt: z13.string().datetime().optional(),
985
+ error: z13.string().optional(),
986
+ savedPath: z13.string().optional()
848
987
  });
849
- var ChatTaskProposalSchema = z10.object({
850
- to: z10.string().min(1),
851
- toName: z10.string().optional(),
852
- team: z10.string().optional(),
853
- title: z10.string().min(1).max(200),
854
- text: z10.string().max(2e4).optional(),
855
- taskId: z10.string().optional(),
856
- ownerName: z10.string().optional(),
857
- state: z10.enum(["open", "taken", "done", "refused", "dropped"]).optional(),
858
- givenAt: z10.string().datetime().optional(),
859
- error: z10.string().optional()
988
+ var ChatTaskProposalSchema = z13.object({
989
+ to: z13.string().min(1),
990
+ toName: z13.string().optional(),
991
+ team: z13.string().optional(),
992
+ title: z13.string().min(1).max(200),
993
+ text: z13.string().max(2e4).optional(),
994
+ taskId: z13.string().optional(),
995
+ ownerName: z13.string().optional(),
996
+ state: z13.enum(["open", "taken", "done", "refused", "dropped"]).optional(),
997
+ givenAt: z13.string().datetime().optional(),
998
+ error: z13.string().optional()
860
999
  });
861
- var ChatTasksSchema = z10.array(ChatTaskProposalSchema).min(1).max(MAX_PROPOSALS);
862
- var ActionVarsSchema = z10.record(z10.string().max(40), z10.string().max(300));
1000
+ var ChatTasksSchema = z13.array(ChatTaskProposalSchema).min(1).max(MAX_PROPOSALS);
1001
+ var ActionVarsSchema = z13.record(z13.string().max(40), z13.string().max(300));
863
1002
  var DETAIL_MAX = 4e3;
864
1003
  var ACTION_ERROR_CODES = [
865
1004
  "unknown",
@@ -886,34 +1025,34 @@ var ACTION_ERROR_CODES = [
886
1025
  "cut",
887
1026
  "failed"
888
1027
  ];
889
- var ChatActionStateSchema = z10.enum(["running", "done", "denied", "failed", "refused"]);
890
- var ChatActionSchema = z10.object({
891
- action: z10.string().min(1).max(40),
892
- args: z10.record(z10.unknown()),
893
- summary: z10.string().min(1).max(300),
1028
+ var ChatActionStateSchema = z13.enum(["running", "done", "denied", "failed", "refused"]);
1029
+ var ChatActionSchema = z13.object({
1030
+ action: z13.string().min(1).max(40),
1031
+ args: z13.record(z13.unknown()),
1032
+ summary: z13.string().min(1).max(300),
894
1033
  vars: ActionVarsSchema.optional(),
895
- detail: z10.string().max(DETAIL_MAX).optional(),
896
- detailCut: z10.literal(true).optional(),
1034
+ detail: z13.string().max(DETAIL_MAX).optional(),
1035
+ detailCut: z13.literal(true).optional(),
897
1036
  risk: ActionRiskSchema,
898
- session: z10.string().optional(),
899
- team: z10.string().optional(),
1037
+ session: z13.string().optional(),
1038
+ team: z13.string().optional(),
900
1039
  state: ChatActionStateSchema.optional(),
901
- doneAt: z10.string().datetime().optional(),
902
- error: z10.string().optional(),
903
- code: z10.string().max(40).optional()
1040
+ doneAt: z13.string().datetime().optional(),
1041
+ error: z13.string().optional(),
1042
+ code: z13.string().max(40).optional()
904
1043
  });
905
- var ChatActionsSchema = z10.array(ChatActionSchema).min(1).max(MAX_PROPOSALS);
906
- var ChatTurnSchema = z10.object({
907
- machineId: z10.string().optional(),
908
- machineName: z10.string().optional(),
909
- choices: z10.array(z10.object({ id: z10.string(), label: z10.string() })).optional(),
910
- qid: z10.string().min(1),
911
- question: z10.string(),
912
- askedAt: z10.string().datetime(),
913
- steps: z10.array(ChatStepSchema),
914
- answer: z10.string().optional(),
915
- answeredAt: z10.string().datetime().optional(),
916
- error: z10.string().optional(),
1044
+ var ChatActionsSchema = z13.array(ChatActionSchema).min(1).max(MAX_PROPOSALS);
1045
+ var ChatTurnSchema = z13.object({
1046
+ machineId: z13.string().optional(),
1047
+ machineName: z13.string().optional(),
1048
+ choices: z13.array(z13.object({ id: z13.string(), label: z13.string() })).optional(),
1049
+ qid: z13.string().min(1),
1050
+ question: z13.string(),
1051
+ askedAt: z13.string().datetime(),
1052
+ steps: z13.array(ChatStepSchema),
1053
+ answer: z13.string().optional(),
1054
+ answeredAt: z13.string().datetime().optional(),
1055
+ error: z13.string().optional(),
917
1056
  proposal: ChatProposalSchema.optional(),
918
1057
  proposals: ChatProposalsSchema.optional(),
919
1058
  relay: ChatRelaySchema.optional(),
@@ -922,50 +1061,50 @@ var ChatTurnSchema = z10.object({
922
1061
  team: ChatTeamProposalSchema.optional(),
923
1062
  tasks: ChatTasksSchema.optional(),
924
1063
  actions: ChatActionsSchema.optional(),
925
- ignoredAt: z10.string().datetime().optional(),
926
- attachments: z10.array(AttachmentRefSchema).optional()
1064
+ ignoredAt: z13.string().datetime().optional(),
1065
+ attachments: z13.array(AttachmentRefSchema).optional()
927
1066
  });
928
1067
  var proposalRows = (t) => t?.proposals ?? (t?.proposal ? [t.proposal] : []);
929
1068
 
930
1069
  // ../protocol/src/repos.ts
931
- import { z as z11 } from "zod";
932
- var ReposInspectSchema = z11.object({
933
- type: z11.literal("repos.inspect"),
934
- requestId: z11.string().min(1).max(100),
935
- paths: z11.array(z11.string().min(1)).min(1).max(50),
936
- machineId: z11.string().optional()
1070
+ import { z as z14 } from "zod";
1071
+ var ReposInspectSchema = z14.object({
1072
+ type: z14.literal("repos.inspect"),
1073
+ requestId: z14.string().min(1).max(100),
1074
+ paths: z14.array(z14.string().min(1)).min(1).max(50),
1075
+ machineId: z14.string().optional()
937
1076
  });
938
- var RepoInfoSchema = z11.object({ path: z11.string(), exists: z11.boolean(), branch: z11.string().nullable() });
939
- var ReposInfoSchema = z11.object({ type: z11.literal("repos.info"), requestId: z11.string(), repos: z11.array(RepoInfoSchema) });
1077
+ var RepoInfoSchema = z14.object({ path: z14.string(), exists: z14.boolean(), branch: z14.string().nullable() });
1078
+ var ReposInfoSchema = z14.object({ type: z14.literal("repos.info"), requestId: z14.string(), repos: z14.array(RepoInfoSchema) });
940
1079
 
941
1080
  // ../protocol/src/scan.ts
942
- import { z as z12 } from "zod";
943
- var ReposScanSchema = z12.object({ type: z12.literal("repos.scan"), requestId: z12.string().min(1).max(100), machineId: z12.string().optional() });
944
- var FoundRepoSchema = z12.object({ path: z12.string(), branch: z12.string().nullable(), remote: z12.string().optional(), manifest: z12.string().max(200).optional() });
945
- var ReposFoundSchema = z12.object({ type: z12.literal("repos.found"), requestId: z12.string(), repos: z12.array(FoundRepoSchema).max(500), truncated: z12.boolean(), error: z12.string().optional() });
1081
+ import { z as z15 } from "zod";
1082
+ var ReposScanSchema = z15.object({ type: z15.literal("repos.scan"), requestId: z15.string().min(1).max(100), machineId: z15.string().optional() });
1083
+ var FoundRepoSchema = z15.object({ path: z15.string(), branch: z15.string().nullable(), remote: z15.string().optional(), manifest: z15.string().max(200).optional() });
1084
+ var ReposFoundSchema = z15.object({ type: z15.literal("repos.found"), requestId: z15.string(), repos: z15.array(FoundRepoSchema).max(500), truncated: z15.boolean(), error: z15.string().optional() });
946
1085
 
947
1086
  // ../protocol/src/documents.ts
948
- import { z as z13 } from "zod";
1087
+ import { z as z16 } from "zod";
949
1088
  var DOCUMENT_MAX_BYTES = 1048576;
950
- var path = z13.string().min(1).max(4096);
951
- var requestId2 = z13.string().min(1);
952
- var DocumentReadSchema = z13.object({
953
- type: z13.literal("document.read"),
1089
+ var path = z16.string().min(1).max(4096);
1090
+ var requestId2 = z16.string().min(1);
1091
+ var DocumentReadSchema = z16.object({
1092
+ type: z16.literal("document.read"),
954
1093
  requestId: requestId2,
955
1094
  path,
956
- machineId: z13.string().optional(),
957
- sessionId: z13.string().min(1).optional(),
1095
+ machineId: z16.string().optional(),
1096
+ sessionId: z16.string().min(1).optional(),
958
1097
  basePath: path.optional()
959
1098
  });
960
- var DocumentContentSchema = z13.object({
961
- type: z13.literal("document.content"),
1099
+ var DocumentContentSchema = z16.object({
1100
+ type: z16.literal("document.content"),
962
1101
  requestId: requestId2,
963
1102
  path,
964
- text: z13.string(),
965
- bytes: z13.number().int().nonnegative(),
966
- modifiedAt: z13.string().datetime()
1103
+ text: z16.string(),
1104
+ bytes: z16.number().int().nonnegative(),
1105
+ modifiedAt: z16.string().datetime()
967
1106
  });
968
- var DocumentErrorCodeSchema = z13.enum([
1107
+ var DocumentErrorCodeSchema = z16.enum([
969
1108
  "not_found",
970
1109
  "not_file",
971
1110
  "unsupported_path",
@@ -977,150 +1116,63 @@ var DocumentErrorCodeSchema = z13.enum([
977
1116
  "session_missing",
978
1117
  "read_failed"
979
1118
  ]);
980
- var DocumentErrorSchema = z13.object({
981
- type: z13.literal("document.error"),
1119
+ var DocumentErrorSchema = z16.object({
1120
+ type: z16.literal("document.error"),
982
1121
  requestId: requestId2,
983
1122
  path,
984
1123
  code: DocumentErrorCodeSchema
985
1124
  });
986
1125
 
987
1126
  // ../protocol/src/routing.ts
988
- import { z as z14 } from "zod";
989
- var MachineInventorySchema = z14.object({
990
- id: z14.string().min(1).max(80),
991
- label: z14.string().min(1).max(120),
992
- online: z14.boolean(),
993
- local: z14.boolean(),
994
- sessions: z14.array(z14.object({ id: z14.string(), name: z14.string(), project: z14.string(), cwd: z14.string(), topic: z14.string().optional(), state: z14.string(), readOnly: z14.boolean() })).max(500),
995
- folders: z14.array(z14.object({ project: z14.string(), cwd: z14.string() })).max(100)
1127
+ import { z as z17 } from "zod";
1128
+ var MachineInventorySchema = z17.object({
1129
+ id: z17.string().min(1).max(80),
1130
+ label: z17.string().min(1).max(120),
1131
+ online: z17.boolean(),
1132
+ local: z17.boolean(),
1133
+ sessions: z17.array(z17.object({ id: z17.string(), name: z17.string(), project: z17.string(), cwd: z17.string(), topic: z17.string().optional(), state: z17.string(), readOnly: z17.boolean() })).max(500),
1134
+ folders: z17.array(z17.object({ project: z17.string(), cwd: z17.string() })).max(100)
996
1135
  });
997
- var RoutingContextSchema = z14.object({
998
- machines: z14.array(MachineInventorySchema).min(1).max(20),
999
- history: z14.array(z14.object({ question: z14.string().max(2e4), answer: z14.string().max(2e4).optional(), machineId: z14.string().optional() })).max(50)
1136
+ var RoutingContextSchema = z17.object({
1137
+ machines: z17.array(MachineInventorySchema).min(1).max(20),
1138
+ history: z17.array(z17.object({ question: z17.string().max(2e4), answer: z17.string().max(2e4).optional(), machineId: z17.string().optional() })).max(50)
1000
1139
  });
1001
- var RouteResultSchema = z14.object({
1140
+ var RouteResultSchema = z17.object({
1002
1141
  /** Null means an answer or a clarification, never an implicit local destination. */
1003
- machineId: z14.string().nullable(),
1004
- text: z14.string().min(1).max(2e4),
1005
- choices: z14.array(z14.string()).max(20).optional()
1006
- });
1007
-
1008
- // ../protocol/src/ssh.ts
1009
- import { z as z15 } from "zod";
1010
- var SshAliasSchema = z15.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/);
1011
-
1012
- // ../protocol/src/machines.ts
1013
- import { z as z16 } from "zod";
1014
- var MachineIdSchema = z16.string().regex(/^[a-zA-Z0-9_-]{1,64}$/);
1015
- var MachineSchema = z16.object({
1016
- id: MachineIdSchema,
1017
- label: z16.string().trim().min(1).max(80),
1018
- ssh: SshAliasSchema.optional()
1019
- });
1020
- var MachinesSchema = z16.array(MachineSchema).min(1).max(20).superRefine((list, ctx) => {
1021
- if (list[0]?.id !== "local" || list[0].ssh !== void 0) ctx.addIssue({ code: "custom", message: "the first machine is local, without ssh", path: [0] });
1022
- const ids = /* @__PURE__ */ new Set(), aliases = /* @__PURE__ */ new Set();
1023
- list.forEach((m, i) => {
1024
- if (i > 0 && !m.ssh) ctx.addIssue({ code: "custom", message: "a remote machine needs an ssh alias", path: [i, "ssh"] });
1025
- if (ids.has(m.id)) ctx.addIssue({ code: "custom", message: `duplicate id ${m.id}`, path: [i, "id"] });
1026
- ids.add(m.id);
1027
- if (m.ssh) {
1028
- if (aliases.has(m.ssh)) ctx.addIssue({ code: "custom", message: `duplicate ssh alias ${m.ssh}`, path: [i, "ssh"] });
1029
- aliases.add(m.ssh);
1030
- }
1031
- });
1142
+ machineId: z17.string().nullable(),
1143
+ text: z17.string().min(1).max(2e4),
1144
+ choices: z17.array(z17.string()).max(20).optional()
1032
1145
  });
1033
1146
 
1034
1147
  // ../protocol/src/island.ts
1035
- import { z as z17 } from "zod";
1036
- var IslandScaleSchema = z17.union([z17.literal("auto"), z17.literal(1), z17.literal(1.25), z17.literal(1.5), z17.literal(2)]);
1037
- var IslandPrefsSchema = z17.object({
1148
+ import { z as z18 } from "zod";
1149
+ var IslandScaleSchema = z18.union([z18.literal("auto"), z18.literal(1), z18.literal(1.25), z18.literal(1.5), z18.literal(2)]);
1150
+ var IslandPrefsSchema = z18.object({
1038
1151
  /** Shown at the top of the screen; hidden, Desktop still notifies. */
1039
- visible: z17.boolean(),
1152
+ visible: z18.boolean(),
1040
1153
  /** `primary` (whichever it is after a reconfiguration), or a monitor's id as the shell lists it (`list_monitors`: the OS
1041
1154
  * name, `#index` without one). `second`, written by older fronts, is the first monitor that is not the primary. */
1042
- screen: z17.string().trim().min(1).max(200),
1043
- position: z17.enum(["center", "left", "right"]),
1155
+ screen: z18.string().trim().min(1).max(200),
1156
+ position: z18.enum(["center", "left", "right"]),
1044
1157
  /** A strip under a maximised window. */
1045
- discreet: z17.boolean(),
1158
+ discreet: z18.boolean(),
1046
1159
  islandScale: IslandScaleSchema,
1047
1160
  panelScale: IslandScaleSchema,
1048
1161
  /** What the island shows besides asks and questions, which it always shows. */
1049
- shows: z17.object({
1162
+ shows: z18.object({
1050
1163
  /** Allow, deny or answer in a line from the island; off, its cards only say « Open in Ledge ». */
1051
- quick: z17.boolean(),
1164
+ quick: z18.boolean(),
1052
1165
  /** The 6 s bubble when an agent finishes. */
1053
- finished: z17.boolean(),
1166
+ finished: z18.boolean(),
1054
1167
  /** An agent's sentence in a bubble. */
1055
- say: z17.boolean(),
1168
+ say: z18.boolean(),
1056
1169
  /** The sub-agents next to their main agent. */
1057
- helpers: z17.boolean()
1170
+ helpers: z18.boolean()
1058
1171
  }),
1059
1172
  /** The global shortcut that opens the island, as shown (`Ctrl Alt L`). */
1060
- shortcut: z17.string().trim().min(1).max(40)
1173
+ shortcut: z18.string().trim().min(1).max(40)
1061
1174
  });
1062
1175
 
1063
- // ../protocol/src/projects.ts
1064
- import { z as z18 } from "zod";
1065
- var PROJECT_COLORS = { blue: "#3b82f6", green: "#10b981", amber: "#f59e0b", violet: "#8b5cf6", teal: "#14b8a6", pink: "#ec4899", red: "#ef4444", slate: "#64748b" };
1066
- var ProjectColorSchema = z18.enum(["blue", "green", "amber", "violet", "teal", "pink", "red", "slate"]);
1067
- var ProjectIdSchema = z18.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/);
1068
- function normalizePath(raw) {
1069
- const p = raw.trim().replace(/\/+/g, "/");
1070
- return p.length > 1 && p.endsWith("/") ? p.slice(0, -1) : p;
1071
- }
1072
- var PathSchema = z18.string().max(4096).refine((p) => p.startsWith("/") && p === normalizePath(p), "an absolute, normalized path");
1073
- var RepoSchema = z18.object({ machine: MachineIdSchema, path: PathSchema });
1074
- var ProjectSchema = z18.object({
1075
- id: ProjectIdSchema,
1076
- name: z18.string().trim().min(1).max(80),
1077
- color: ProjectColorSchema,
1078
- description: z18.string().max(500).default(""),
1079
- repos: z18.array(RepoSchema).max(50)
1080
- });
1081
- var RuleSchema = z18.object({ machine: MachineIdSchema, path: PathSchema, project: ProjectIdSchema });
1082
- function projectsProblems(p) {
1083
- const out = [];
1084
- const ids = /* @__PURE__ */ new Set(), names = /* @__PURE__ */ new Set(), repos = /* @__PURE__ */ new Set(), rules = /* @__PURE__ */ new Set();
1085
- p.projects.forEach((project, i) => {
1086
- if (ids.has(project.id)) out.push({ code: "duplicate_id", path: ["projects", i, "id"] });
1087
- ids.add(project.id);
1088
- const name = project.name.trim().toLocaleLowerCase();
1089
- if (names.has(name)) out.push({ code: "duplicate_name", path: ["projects", i, "name"] });
1090
- names.add(name);
1091
- project.repos.forEach((repo, j) => {
1092
- const key = `${repo.machine}
1093
- ${repo.path}`;
1094
- if (repos.has(key)) out.push({ code: "duplicate_repo", path: ["projects", i, "repos", j] });
1095
- repos.add(key);
1096
- });
1097
- });
1098
- p.rules.forEach((rule, i) => {
1099
- const key = `${rule.machine}
1100
- ${rule.path}`;
1101
- if (rules.has(key)) out.push({ code: "duplicate_rule", path: ["rules", i] });
1102
- rules.add(key);
1103
- if (!ids.has(rule.project)) out.push({ code: "unknown_project", path: ["rules", i, "project"] });
1104
- });
1105
- return out;
1106
- }
1107
- var ProjectsSchema = z18.object({ projects: z18.array(ProjectSchema).max(100), rules: z18.array(RuleSchema).max(1e3) }).superRefine((p, ctx) => {
1108
- for (const problem of projectsProblems(p)) ctx.addIssue({ code: "custom", message: problem.code, path: problem.path });
1109
- });
1110
- var DEFAULT_PROJECTS = { projects: [], rules: [] };
1111
- var under = (cwd, path2) => path2 === "/" || cwd === path2 || cwd.startsWith(`${path2}/`);
1112
- function projectOf(session, state) {
1113
- const machine = session.machineId ?? "local";
1114
- const cwd = normalizePath(session.cwd);
1115
- const known = new Set(state.projects.map((p) => p.id));
1116
- const candidates = [
1117
- ...state.projects.flatMap((p) => p.repos.filter((r) => r.machine === machine).map((r) => ({ project: p.id, path: r.path, rule: false }))),
1118
- ...state.rules.filter((r) => r.machine === machine && known.has(r.project)).map((r) => ({ project: r.project, path: r.path, rule: true }))
1119
- ].filter((c) => under(cwd, c.path));
1120
- candidates.sort((x, y) => y.path.length - x.path.length || Number(y.rule) - Number(x.rule));
1121
- return candidates[0]?.project ?? null;
1122
- }
1123
-
1124
1176
  // ../protocol/src/thread.ts
1125
1177
  import { z as z19 } from "zod";
1126
1178
  var ToolStatusSchema = z19.enum(["running", "success", "failed", "unknown"]);
@@ -1382,6 +1434,9 @@ var ServerMessageSchema = z21.discriminatedUnion("type", [
1382
1434
  TeamLaunchedSchema,
1383
1435
  TeamFailedSchema,
1384
1436
  TeamSavedSchema,
1437
+ DefinitionsListingSchema,
1438
+ DefinitionResultSchema,
1439
+ TeamChangedSchema,
1385
1440
  z21.object({
1386
1441
  type: z21.literal("error"),
1387
1442
  message: z21.string(),
@@ -1559,8 +1614,18 @@ var ClientMessageSchema = z21.discriminatedUnion("type", [
1559
1614
  TeamLeaveSchema,
1560
1615
  TeamResumeSchema,
1561
1616
  TeamDissolveSchema,
1562
- TeamSaveSchema
1563
- ]);
1617
+ TeamSaveSchema,
1618
+ DefinitionsListSchema,
1619
+ RoleWriteSchema,
1620
+ RoleDeleteSchema,
1621
+ TemplateWriteSchema,
1622
+ TemplateDeleteSchema,
1623
+ TeamComposeSchema,
1624
+ TeamSeatSchema
1625
+ ]).superRefine((m, ctx) => {
1626
+ const issue = "scope" in m ? scopeIssue(m) : null;
1627
+ if (issue) ctx.addIssue({ code: z21.ZodIssueCode.custom, message: issue, path: ["project"] });
1628
+ });
1564
1629
  function parseClientMessage(raw) {
1565
1630
  return ClientMessageSchema.parse(raw);
1566
1631
  }
@@ -1731,7 +1796,7 @@ var MeResponseSchema = z23.object({
1731
1796
  });
1732
1797
 
1733
1798
  // ../protocol/src/phone.ts
1734
- import { z as z25 } from "zod";
1799
+ import { z as z26 } from "zod";
1735
1800
 
1736
1801
  // ../protocol/src/push.ts
1737
1802
  import { z as z24 } from "zod";
@@ -1777,6 +1842,51 @@ var PushPayloadSchema = z24.object({
1777
1842
  tag: z24.string().regex(/^[A-Za-z0-9_-]{1,32}$/)
1778
1843
  });
1779
1844
 
1845
+ // ../protocol/src/phoneTeams.ts
1846
+ import { z as z25 } from "zod";
1847
+ var scope = DefinitionScopeSchema;
1848
+ var PhoneSeatsSchema = z25.array(SeatSchema.strict()).min(1).max(TEAM_SEATS_MAX).refine(uniqueRoles, "a role twice in one team");
1849
+ var PhoneRoleDraftSchema = RoleDraftSchema.strict();
1850
+ var projectName = z25.string().max(80).nullable();
1851
+ var PhoneRoleSchema = z25.object({
1852
+ id: RoleIdSchema,
1853
+ label: z25.string().min(1).max(ROLE_LABEL_MAX),
1854
+ prompt: z25.string().max(ROLE_PROMPT_MAX),
1855
+ cut: z25.literal(true).optional(),
1856
+ tool: ToolSchema.optional(),
1857
+ model: ModelIdSchema.optional(),
1858
+ effort: EffortSchema.optional(),
1859
+ autonomy: AutonomySchema.optional(),
1860
+ scope,
1861
+ project: projectName,
1862
+ hash: DefinitionHashSchema,
1863
+ shadows: z25.literal(true).optional(),
1864
+ shadowed: z25.literal(true).optional(),
1865
+ shadowedIn: z25.array(z25.string().max(80)).min(1).max(8).optional()
1866
+ }).strict();
1867
+ var PhoneTemplateSchema = z25.object({ id: TemplateIdSchema, name: TeamNameSchema, seats: PhoneSeatsSchema, scope, project: projectName, hash: DefinitionHashSchema }).strict();
1868
+ var PhoneProblemSchema = z25.object({ file: z25.string().max(80), scope, project: projectName, reason: z25.string().max(200) }).strict();
1869
+ var PhoneCatalogSchema = z25.object({
1870
+ /** The names of the projects with a local repository: the ones a « Dépôt » scope or a « Lever » can name. */
1871
+ projects: z25.array(z25.string().max(80)).max(50),
1872
+ roles: z25.array(PhoneRoleSchema).max(200),
1873
+ templates: z25.array(PhoneTemplateSchema).max(100),
1874
+ problems: z25.array(PhoneProblemSchema).max(50)
1875
+ }).strict();
1876
+ var TEAMS_OPERATION_TYPES = ["role.write", "role.delete", "template.write", "template.delete", "team.launch", "team.compose", "team.seat", "team.dissolve"];
1877
+ var isTeamsOperation = (m) => TEAMS_OPERATION_TYPES.includes(m.type);
1878
+ function canonicalJson(v) {
1879
+ const sort = (x) => {
1880
+ if (Array.isArray(x)) return x.map(sort);
1881
+ if (x !== null && typeof x === "object") {
1882
+ const o = x;
1883
+ return Object.fromEntries(Object.keys(o).sort().filter((k) => o[k] !== void 0).map((k) => [k, sort(o[k])]));
1884
+ }
1885
+ return x;
1886
+ };
1887
+ return JSON.stringify(sort(v));
1888
+ }
1889
+
1780
1890
  // ../protocol/src/phone.ts
1781
1891
  var PHONE_PROTOCOL = 1;
1782
1892
  var PAD_TIERS = [1024, 4096, 16384, 65536, 262144, 655360];
@@ -1795,22 +1905,22 @@ var THREAD_TEXT_MAX = 8192;
1795
1905
  var TOOL_TEXT_MAX = 2048;
1796
1906
  var PENDING_BODY_MAX = 65536;
1797
1907
  var SNAPSHOT_BODY_MAX = 2048;
1798
- var RiskSchema = z25.enum(["low", "high"]);
1799
- var RiskReasonSchema = z25.enum(["question", "read_only_command", "edit_inside_folder", "pushes", "destroys", "deploys", "publishes", "pipes_to_shell", "network", "writes_outside_folder", "sensitive_path", "unsafe_flag", "shell_syntax", "script", "plan", "unknown"]);
1800
- var OperationIdSchema = z25.string().uuid();
1801
- var OperationStatusSchema = z25.enum(["received", "applied", "rejected", "failed"]);
1802
- var OperationReasonSchema = z25.enum([...RefusalCodeSchema.options, "untypable", "confirm_required", "conflict", "assertion_invalid", "assertion_expired"]);
1803
- var CapabilitiesSchema = z25.object({
1908
+ var RiskSchema = z26.enum(["low", "high"]);
1909
+ var RiskReasonSchema = z26.enum(["question", "read_only_command", "edit_inside_folder", "pushes", "destroys", "deploys", "publishes", "pipes_to_shell", "network", "writes_outside_folder", "sensitive_path", "unsafe_flag", "shell_syntax", "script", "plan", "unknown"]);
1910
+ var OperationIdSchema = z26.string().uuid();
1911
+ var OperationStatusSchema = z26.enum(["received", "applied", "rejected", "failed"]);
1912
+ var OperationReasonSchema = z26.enum([...RefusalCodeSchema.options, "untypable", "confirm_required", "conflict", "assertion_invalid", "assertion_expired", "changed", "exists", "unknown_project", "seat_failed"]);
1913
+ var CapabilitiesSchema = z26.object({
1804
1914
  /** A question can be answered in free text. */
1805
- freeTextAnswer: z25.boolean(),
1915
+ freeTextAnswer: z26.boolean(),
1806
1916
  /** The session's accept/deny can be typed; absent = true. */
1807
- decide: z25.boolean().optional(),
1917
+ decide: z26.boolean().optional(),
1808
1918
  /** OMP's dialog questions can be answered from the phone; absent = false. */
1809
- questions: z25.boolean().optional()
1919
+ questions: z26.boolean().optional()
1810
1920
  });
1811
1921
  var UNTYPABLE = /[\u0000-\u001f\u007f-\u009f\u200b\u200e\u200f\u2028-\u202e\u2066-\u2069\ufeff]/;
1812
- var CapabilitiesByToolSchema = z25.object({ claude: CapabilitiesSchema, codex: CapabilitiesSchema, cursor: CapabilitiesSchema, omp: CapabilitiesSchema });
1813
- var PhonePendingSchema = PendingSchema.extend({ key: z25.string().max(64), risk: RiskSchema, riskReason: RiskReasonSchema, cut: z25.literal(true).optional() });
1922
+ var CapabilitiesByToolSchema = z26.object({ claude: CapabilitiesSchema, codex: CapabilitiesSchema, cursor: CapabilitiesSchema, omp: CapabilitiesSchema });
1923
+ var PhonePendingSchema = PendingSchema.extend({ key: z26.string().max(64), risk: RiskSchema, riskReason: RiskReasonSchema, cut: z26.literal(true).optional() });
1814
1924
  var PhoneSessionSchema = SessionSchema.pick({
1815
1925
  id: true,
1816
1926
  name: true,
@@ -1833,240 +1943,318 @@ var PhoneSessionSchema = SessionSchema.pick({
1833
1943
  /** Its context and its relief (context handover spec §3.2): the phone shows the gauge; the relief is started from the PC. */
1834
1944
  context: true,
1835
1945
  relieves: true
1836
- }).extend({ pending: PhonePendingSchema.optional(), unread: z25.boolean(), handover: z25.object({ state: HandoverStateSchema, toName: z25.string().max(80).optional() }).strict().optional() });
1837
- var B64U2 = z25.string().regex(/^[A-Za-z0-9_-]*$/);
1838
- var CredentialSchema = z25.object({
1946
+ }).extend({ pending: PhonePendingSchema.optional(), unread: z26.boolean(), handover: z26.object({ state: HandoverStateSchema, toName: z26.string().max(80).optional() }).strict().optional() });
1947
+ var B64U2 = z26.string().regex(/^[A-Za-z0-9_-]*$/);
1948
+ var CredentialSchema = z26.object({
1839
1949
  id: B64U2.max(1366),
1840
1950
  publicKey: B64U2.max(2048),
1841
- alg: z25.union([z25.literal(-7), z25.literal(-257)]),
1951
+ alg: z26.union([z26.literal(-7), z26.literal(-257)]),
1842
1952
  clientDataJSON: B64U2.max(4096),
1843
1953
  authenticatorData: B64U2.max(4096),
1844
- transports: z25.array(z25.string().max(20)).max(8).optional()
1954
+ transports: z26.array(z26.string().max(20)).max(8).optional()
1845
1955
  });
1846
- var AssertionSchema = z25.object({
1956
+ var AssertionSchema = z26.object({
1847
1957
  id: B64U2.max(1366),
1848
1958
  clientDataJSON: B64U2.max(4096),
1849
1959
  authenticatorData: B64U2.max(4096),
1850
1960
  signature: B64U2.max(1024)
1851
1961
  });
1852
- var ConfirmPurposeSchema = z25.enum(["register", "decide", "launch", "close", "act"]);
1962
+ var TeamsDigestSchema = z26.string().regex(/^[0-9a-f]{64}$/);
1963
+ var ConfirmPurposeSchema = z26.enum(["register", "decide", "launch", "close", "act", "define", "team", "pc"]);
1853
1964
  var PhoneChatStepSchema = ChatStepSchema.pick({ kind: true, id: true, name: true }).strict();
1854
- var PhoneChatProposalSchema = z25.object({
1855
- project: z25.string().max(80),
1965
+ var PhoneChatProposalSchema = z26.object({
1966
+ project: z26.string().max(80),
1856
1967
  tool: ToolSchema,
1857
- prompt: z25.string().max(TOOL_TEXT_MAX).optional(),
1858
- launchedId: z25.string().optional(),
1859
- failed: z25.literal(true).optional()
1968
+ prompt: z26.string().max(TOOL_TEXT_MAX).optional(),
1969
+ launchedId: z26.string().optional(),
1970
+ failed: z26.literal(true).optional()
1860
1971
  }).strict();
1861
- var PhoneChatRelaySchema = z25.object({
1862
- id: z25.string().min(1),
1863
- name: z25.string(),
1972
+ var PhoneChatRelaySchema = z26.object({
1973
+ id: z26.string().min(1),
1974
+ name: z26.string(),
1864
1975
  tool: ToolSchema,
1865
- text: z25.string().max(TOOL_TEXT_MAX),
1866
- status: z25.enum(["queued", "sent"]).optional(),
1867
- sentAt: z25.string().datetime().optional(),
1868
- failed: z25.literal(true).optional()
1976
+ text: z26.string().max(TOOL_TEXT_MAX),
1977
+ status: z26.enum(["queued", "sent"]).optional(),
1978
+ sentAt: z26.string().datetime().optional(),
1979
+ failed: z26.literal(true).optional()
1869
1980
  }).strict();
1870
- var PhoneChatCloseSchema = z25.object({
1871
- id: z25.string().min(1),
1872
- name: z25.string(),
1981
+ var PhoneChatCloseSchema = z26.object({
1982
+ id: z26.string().min(1),
1983
+ name: z26.string(),
1873
1984
  tool: ToolSchema,
1874
- how: z25.enum(["exit", "killed"]).optional(),
1875
- closedAt: z25.string().datetime().optional(),
1876
- failed: z25.literal(true).optional()
1985
+ how: z26.enum(["exit", "killed"]).optional(),
1986
+ closedAt: z26.string().datetime().optional(),
1987
+ failed: z26.literal(true).optional()
1877
1988
  }).strict();
1878
- var PhoneChatTeamSchema = z25.object({
1879
- project: z25.string().max(80),
1880
- name: z25.string().max(60),
1881
- template: z25.string().max(64).optional(),
1882
- seats: z25.array(z25.object({ role: z25.string().max(40), label: z25.string().max(40), tool: ToolSchema, model: z25.string().max(200).optional(), effort: z25.string().max(20).optional(), autonomy: AutonomySchema.optional() }).strict()).min(1).max(8),
1883
- teamId: z25.string().max(40).optional(),
1884
- launchedAt: z25.string().datetime().optional(),
1885
- failed: z25.literal(true).optional()
1989
+ var PhoneChatTeamSchema = z26.object({
1990
+ project: z26.string().max(80),
1991
+ name: z26.string().max(60),
1992
+ template: z26.string().max(64).optional(),
1993
+ seats: z26.array(z26.object({ role: z26.string().max(40), label: z26.string().max(40), tool: ToolSchema, model: z26.string().max(200).optional(), effort: z26.string().max(20).optional(), autonomy: AutonomySchema.optional() }).strict()).min(1).max(8),
1994
+ teamId: z26.string().max(40).optional(),
1995
+ launchedAt: z26.string().datetime().optional(),
1996
+ failed: z26.literal(true).optional()
1886
1997
  }).strict();
1887
- var PhoneChatTaskSchema = z25.object({
1888
- to: z25.string().max(80),
1889
- toName: z25.string().max(80).optional(),
1890
- title: z25.string().max(200),
1891
- text: z25.string().max(TOOL_TEXT_MAX).optional(),
1892
- taskId: z25.string().max(40).optional(),
1893
- ownerName: z25.string().max(80).optional(),
1894
- state: z25.enum(["open", "taken", "done", "refused", "dropped"]).optional(),
1895
- failed: z25.literal(true).optional()
1998
+ var PhoneChatTaskSchema = z26.object({
1999
+ to: z26.string().max(80),
2000
+ toName: z26.string().max(80).optional(),
2001
+ title: z26.string().max(200),
2002
+ text: z26.string().max(TOOL_TEXT_MAX).optional(),
2003
+ taskId: z26.string().max(40).optional(),
2004
+ ownerName: z26.string().max(80).optional(),
2005
+ state: z26.enum(["open", "taken", "done", "refused", "dropped"]).optional(),
2006
+ failed: z26.literal(true).optional()
1896
2007
  }).strict();
1897
- var PhoneChatActionSchema = z25.object({
1898
- action: z25.string().min(1).max(40),
1899
- summary: z25.string().max(300),
2008
+ var PhoneChatActionSchema = z26.object({
2009
+ action: z26.string().min(1).max(40),
2010
+ summary: z26.string().max(300),
1900
2011
  vars: ActionVarsSchema.optional(),
1901
- detail: z25.string().max(TOOL_TEXT_MAX).optional(),
1902
- detailCut: z25.literal(true).optional(),
2012
+ detail: z26.string().max(TOOL_TEXT_MAX).optional(),
2013
+ detailCut: z26.literal(true).optional(),
1903
2014
  risk: ActionRiskSchema,
1904
- session: z25.string().max(100).optional(),
1905
- team: z25.string().max(40).optional(),
2015
+ session: z26.string().max(100).optional(),
2016
+ team: z26.string().max(40).optional(),
1906
2017
  state: ChatActionStateSchema.optional(),
1907
- doneAt: z25.string().datetime().optional(),
1908
- code: z25.string().max(40).optional()
2018
+ doneAt: z26.string().datetime().optional(),
2019
+ code: z26.string().max(40).optional()
1909
2020
  }).strict();
1910
- var PhoneTeamSchema = z25.object({
1911
- id: z25.string().max(40),
1912
- name: z25.string().max(60),
1913
- project: z25.string().max(80).nullable(),
1914
- state: z25.enum(["active", "resting"]),
1915
- seats: z25.array(z25.object({ role: z25.string().max(40), sessionId: z25.string().max(100).nullable() }).strict()).max(16),
1916
- done: z25.number().int().min(0),
1917
- given: z25.number().int().min(0)
2021
+ var PhoneTeamSchema = z26.object({
2022
+ id: z26.string().max(40),
2023
+ name: z26.string().max(60),
2024
+ project: z26.string().max(80).nullable(),
2025
+ state: z26.enum(["active", "resting"]),
2026
+ template: z26.string().max(64).optional(),
2027
+ /** Absent from a daemon older than the phone: the phone then says no start time. */
2028
+ createdAt: z26.string().optional(),
2029
+ /** `tool`, `model` and `effort` are what the seat was composed with; `leaving` is a seat that finishes its turn and is then closed. */
2030
+ seats: z26.array(z26.object({
2031
+ role: z26.string().max(40),
2032
+ sessionId: z26.string().max(100).nullable(),
2033
+ tool: ToolSchema.optional(),
2034
+ model: ModelIdSchema.optional(),
2035
+ effort: EffortSchema.optional(),
2036
+ leaving: z26.literal(true).optional()
2037
+ }).strict()).max(16),
2038
+ done: z26.number().int().min(0),
2039
+ given: z26.number().int().min(0)
1918
2040
  }).strict();
1919
- var PhoneTaskSchema = z25.object({
1920
- id: z25.string().max(40),
1921
- title: z25.string().max(200),
1922
- owner: z25.string().max(100),
1923
- ownerName: z25.string().max(80),
1924
- ownerRole: z25.string().max(40).optional(),
1925
- team: z25.string().max(40).optional(),
1926
- teamName: z25.string().max(60).optional(),
1927
- state: z25.enum(["open", "taken", "done", "refused", "dropped"]),
1928
- result: z25.string().max(TOOL_TEXT_MAX).optional(),
1929
- cut: z25.literal(true).optional(),
1930
- at: z25.string(),
1931
- updatedAt: z25.string(),
1932
- seen: z25.literal(true).optional()
2041
+ var PhoneTaskSchema = z26.object({
2042
+ id: z26.string().max(40),
2043
+ title: z26.string().max(200),
2044
+ owner: z26.string().max(100),
2045
+ ownerName: z26.string().max(80),
2046
+ ownerRole: z26.string().max(40).optional(),
2047
+ team: z26.string().max(40).optional(),
2048
+ teamName: z26.string().max(60).optional(),
2049
+ state: z26.enum(["open", "taken", "done", "refused", "dropped"]),
2050
+ result: z26.string().max(TOOL_TEXT_MAX).optional(),
2051
+ cut: z26.literal(true).optional(),
2052
+ at: z26.string(),
2053
+ updatedAt: z26.string(),
2054
+ seen: z26.literal(true).optional()
1933
2055
  }).strict();
1934
- var ChatErrorCodeSchema = z25.enum(["busy", "timeout", "cancelled", "failed"]);
1935
- var PhoneChatTurnSchema = z25.object({
2056
+ var ChatErrorCodeSchema = z26.enum(["busy", "timeout", "cancelled", "failed"]);
2057
+ var PhoneChatTurnSchema = z26.object({
1936
2058
  qid: OperationIdSchema,
1937
- question: z25.string().max(MESSAGE_MAX),
1938
- askedAt: z25.string().datetime(),
1939
- steps: z25.array(PhoneChatStepSchema).max(50),
1940
- answer: z25.string().max(THREAD_TEXT_MAX).optional(),
1941
- answeredAt: z25.string().datetime().optional(),
2059
+ question: z26.string().max(MESSAGE_MAX),
2060
+ askedAt: z26.string().datetime(),
2061
+ steps: z26.array(PhoneChatStepSchema).max(50),
2062
+ answer: z26.string().max(THREAD_TEXT_MAX).optional(),
2063
+ answeredAt: z26.string().datetime().optional(),
1942
2064
  error: ChatErrorCodeSchema.optional(),
1943
- proposals: z25.array(PhoneChatProposalSchema).max(MAX_PROPOSALS).optional(),
2065
+ proposals: z26.array(PhoneChatProposalSchema).max(MAX_PROPOSALS).optional(),
1944
2066
  relay: PhoneChatRelaySchema.optional(),
1945
- closes: z25.array(PhoneChatCloseSchema).min(1).max(MAX_PROPOSALS).optional(),
1946
- cut: z25.literal(true).optional(),
2067
+ closes: z26.array(PhoneChatCloseSchema).min(1).max(MAX_PROPOSALS).optional(),
2068
+ cut: z26.literal(true).optional(),
1947
2069
  team: PhoneChatTeamSchema.optional(),
1948
- tasks: z25.array(PhoneChatTaskSchema).min(1).max(MAX_PROPOSALS).optional(),
1949
- actions: z25.array(PhoneChatActionSchema).min(1).max(MAX_PROPOSALS).optional(),
1950
- ignoredAt: z25.string().datetime().optional(),
1951
- attachments: z25.array(AttachmentRefSchema).max(ATTACHMENTS_MAX).optional()
2070
+ tasks: z26.array(PhoneChatTaskSchema).min(1).max(MAX_PROPOSALS).optional(),
2071
+ actions: z26.array(PhoneChatActionSchema).min(1).max(MAX_PROPOSALS).optional(),
2072
+ ignoredAt: z26.string().datetime().optional(),
2073
+ attachments: z26.array(AttachmentRefSchema).max(ATTACHMENTS_MAX).optional()
1952
2074
  }).strict();
1953
2075
  var CHAT_HISTORY_BUDGET = 393216;
1954
- var sessionId = z25.string().min(1).max(100);
1955
- var PhoneExpectSchema = PendingSchema.pick({ kind: true, text: true }).extend({ key: z25.string().min(1).max(64) });
1956
- var CardRowsSchema = z25.array(z25.number().int().min(0).max(MAX_PROPOSALS - 1)).min(1).max(MAX_PROPOSALS).refine((r) => new Set(r).size === r.length, "a row twice");
1957
- var PhoneClientMessageSchema = z25.discriminatedUnion("type", [
1958
- z25.object({ type: z25.literal("snapshot.request") }),
1959
- z25.object({ type: z25.literal("session.thread"), id: sessionId }),
2076
+ var sessionId = z26.string().min(1).max(100);
2077
+ var PhoneExpectSchema = PendingSchema.pick({ kind: true, text: true }).extend({ key: z26.string().min(1).max(64) });
2078
+ var CardRowsSchema = z26.array(z26.number().int().min(0).max(MAX_PROPOSALS - 1)).min(1).max(MAX_PROPOSALS).refine((r) => new Set(r).size === r.length, "a row twice");
2079
+ var teamsOp = { op: OperationIdSchema, assertion: AssertionSchema.optional() };
2080
+ var PcActionSchema = z26.enum(["update", "restart"]);
2081
+ var pcSubject = (action, version) => action === "update" ? `update@${version ?? ""}` : "restart";
2082
+ var teamsScope = { scope: DefinitionScopeSchema, project: z26.string().min(1).max(80).optional() };
2083
+ var PhoneClientMessageSchema = z26.discriminatedUnion("type", [
2084
+ z26.object({ type: z26.literal("snapshot.request") }),
2085
+ z26.object({ type: z26.literal("session.thread"), id: sessionId }),
1960
2086
  /** The session's request with its whole body (up to `PENDING_BODY_MAX`). */
1961
- z25.object({ type: z25.literal("session.pending"), id: sessionId }),
2087
+ z26.object({ type: z26.literal("session.pending"), id: sessionId }),
1962
2088
  /** The session whose terminal the phone shows; null when it shows none. */
1963
- z25.object({ type: z25.literal("session.watch"), id: sessionId.nullable() }),
1964
- z25.object({ type: z25.literal("session.read"), id: sessionId, at: z25.string().datetime() }),
2089
+ z26.object({ type: z26.literal("session.watch"), id: sessionId.nullable() }),
2090
+ z26.object({ type: z26.literal("session.read"), id: sessionId, at: z26.string().datetime() }),
1965
2091
  /** Asks for a challenge. One object for both purposes: the gateway refuses a `decide` without `id` and `expect`. */
1966
- z25.object({ type: z25.literal("confirm.prepare"), purpose: ConfirmPurposeSchema, id: sessionId.optional(), expect: PhoneExpectSchema.optional(), qid: OperationIdSchema.optional() }),
1967
- z25.object({ type: z25.literal("credential.register"), op: OperationIdSchema, credential: CredentialSchema }),
1968
- z25.object({
1969
- type: z25.literal("session.decide"),
2092
+ z26.object({
2093
+ type: z26.literal("confirm.prepare"),
2094
+ purpose: ConfirmPurposeSchema,
2095
+ id: sessionId.optional(),
2096
+ expect: PhoneExpectSchema.optional(),
2097
+ qid: OperationIdSchema.optional(),
2098
+ /** sha256 of the `define` or `team` operation the challenge is for (`teamsDigest`). */
2099
+ digest: TeamsDigestSchema.optional(),
2100
+ /** A `pc` challenge: what it is for, and for an update the version it covers. */
2101
+ action: PcActionSchema.optional(),
2102
+ version: z26.string().regex(SEMVER).optional()
2103
+ }),
2104
+ z26.object({ type: z26.literal("credential.register"), op: OperationIdSchema, credential: CredentialSchema }),
2105
+ z26.object({
2106
+ type: z26.literal("session.decide"),
1970
2107
  op: OperationIdSchema,
1971
2108
  id: sessionId,
1972
2109
  decision: DecisionSchema,
1973
- note: z25.string().trim().min(1).max(NOTE_MAX).optional(),
2110
+ note: z26.string().trim().min(1).max(NOTE_MAX).optional(),
1974
2111
  /** The request the phone showed: refused unless it is still the pending one. */
1975
2112
  expect: PhoneExpectSchema,
1976
2113
  /** The device check over the challenge of `confirm.prepare`; required by the daemon for a high-risk accept. */
1977
2114
  assertion: AssertionSchema.optional()
1978
2115
  }),
1979
- z25.object({
1980
- type: z25.literal("session.reply"),
2116
+ z26.object({
2117
+ type: z26.literal("session.reply"),
1981
2118
  op: OperationIdSchema,
1982
2119
  id: sessionId,
1983
- text: z25.string().max(MESSAGE_MAX),
1984
- attachments: z25.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional(),
2120
+ text: z26.string().max(MESSAGE_MAX),
2121
+ attachments: z26.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional(),
1985
2122
  /** The request the reply answers, or null when the phone showed none: refused if the session's request is no longer that one. */
1986
2123
  expect: PhoneExpectSchema.nullable(),
1987
2124
  assertion: AssertionSchema.optional()
1988
2125
  }),
1989
2126
  /** OMP's `ask`: the answers to every question of the dialog `requestId`, in order; `cancel` declines it. Bounds as the local `session.answer`. */
1990
- z25.object({
1991
- type: z25.literal("session.answer"),
2127
+ z26.object({
2128
+ type: z26.literal("session.answer"),
1992
2129
  op: OperationIdSchema,
1993
2130
  id: sessionId,
1994
- requestId: z25.string().min(1).max(200),
1995
- answers: z25.array(z25.object({ id: z25.string().max(200), selected: z25.array(z25.string().max(2e3)).max(100), text: z25.string().max(2e4).optional() })).max(50),
1996
- cancel: z25.literal(true).optional(),
2131
+ requestId: z26.string().min(1).max(200),
2132
+ answers: z26.array(z26.object({ id: z26.string().max(200), selected: z26.array(z26.string().max(2e3)).max(100), text: z26.string().max(2e4).optional() })).max(50),
2133
+ cancel: z26.literal(true).optional(),
1997
2134
  expect: PhoneExpectSchema
1998
2135
  }),
1999
- z25.object({ type: z25.literal("session.interrupt"), op: OperationIdSchema, id: sessionId }),
2136
+ z26.object({ type: z26.literal("session.interrupt"), op: OperationIdSchema, id: sessionId }),
2000
2137
  /** The phone drops its passkey from the daemon. */
2001
- z25.object({ type: z25.literal("device.forget"), op: OperationIdSchema }),
2138
+ z26.object({ type: z26.literal("device.forget"), op: OperationIdSchema }),
2002
2139
  /** The phone's push subscription, with the VAPID key it was made with (so a key change is seen). */
2003
- z25.object({ type: z25.literal("push.subscribe"), op: OperationIdSchema, subscription: PushSubscriptionSchema, key: B64U2.length(87) }),
2004
- z25.object({ type: z25.literal("push.unsubscribe"), op: OperationIdSchema }),
2140
+ z26.object({ type: z26.literal("push.subscribe"), op: OperationIdSchema, subscription: PushSubscriptionSchema, key: B64U2.length(87) }),
2141
+ z26.object({ type: z26.literal("push.unsubscribe"), op: OperationIdSchema }),
2005
2142
  /** The phone's own chat with Ledge. */
2006
- z25.object({ type: z25.literal("chat.ask"), qid: OperationIdSchema, text: z25.string().trim().max(MESSAGE_MAX), attachments: z25.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional() }),
2007
- z25.object({ type: z25.literal("chat.cancel"), qid: OperationIdSchema }),
2008
- z25.object({ type: z25.literal("chat.reset") }),
2009
- z25.object({ type: z25.literal("chat.history") }),
2143
+ z26.object({ type: z26.literal("chat.ask"), qid: OperationIdSchema, text: z26.string().trim().max(MESSAGE_MAX), attachments: z26.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional() }),
2144
+ z26.object({ type: z26.literal("chat.cancel"), qid: OperationIdSchema }),
2145
+ z26.object({ type: z26.literal("chat.reset") }),
2146
+ z26.object({ type: z26.literal("chat.history") }),
2010
2147
  /** An image to store, sent alone before the message that names it; no `id`, and at most `ATTACHMENT_MAX` bytes. */
2011
- AttachmentPutSchema.pick({ type: true, requestId: true }).extend({ image: ImageUploadSchema.extend({ data: z25.string().min(1).max(b64Max(ATTACHMENT_MAX)) }) }),
2148
+ AttachmentPutSchema.pick({ type: true, requestId: true }).extend({ image: ImageUploadSchema.extend({ data: z26.string().min(1).max(b64Max(ATTACHMENT_MAX)) }) }),
2012
2149
  AttachmentGetSchema.pick({ type: true, requestId: true, attachment: true, preview: true }),
2013
- z25.object({ type: z25.literal("chat.relay"), op: OperationIdSchema, qid: OperationIdSchema }),
2014
- z25.object({ type: z25.literal("chat.launch"), op: OperationIdSchema, qid: OperationIdSchema, rows: CardRowsSchema.optional(), assertion: AssertionSchema.optional() }),
2015
- z25.object({ type: z25.literal("chat.close"), op: OperationIdSchema, qid: OperationIdSchema, rows: CardRowsSchema.optional(), assertion: AssertionSchema.optional() }),
2150
+ z26.object({ type: z26.literal("chat.relay"), op: OperationIdSchema, qid: OperationIdSchema }),
2151
+ z26.object({ type: z26.literal("chat.launch"), op: OperationIdSchema, qid: OperationIdSchema, rows: CardRowsSchema.optional(), assertion: AssertionSchema.optional() }),
2152
+ z26.object({ type: z26.literal("chat.close"), op: OperationIdSchema, qid: OperationIdSchema, rows: CardRowsSchema.optional(), assertion: AssertionSchema.optional() }),
2016
2153
  /** The turn's team card (roles spec §3.8): launched like a session card, with the device check (purpose `launch`, the turn). */
2017
- z25.object({ type: z25.literal("chat.team"), op: OperationIdSchema, qid: OperationIdSchema, assertion: AssertionSchema.optional() }),
2154
+ z26.object({ type: z26.literal("chat.team"), op: OperationIdSchema, qid: OperationIdSchema, assertion: AssertionSchema.optional() }),
2018
2155
  /** A row of the turn's task card: given by Ledge. */
2019
- z25.object({ type: z25.literal("chat.task"), op: OperationIdSchema, qid: OperationIdSchema, row: z25.number().int().min(0).max(MAX_PROPOSALS - 1) }),
2156
+ z26.object({ type: z26.literal("chat.task"), op: OperationIdSchema, qid: OperationIdSchema, row: z26.number().int().min(0).max(MAX_PROPOSALS - 1) }),
2020
2157
  /** Rows of the turn's generic card (action registry spec §5): `confirmed` as the local `chat.act`; a row whose action asks
2021
2158
  * for a device check (`phone`) needs one assertion, purpose `act`, over the turn. */
2022
- z25.object({
2023
- type: z25.literal("chat.act"),
2159
+ z26.object({
2160
+ type: z26.literal("chat.act"),
2024
2161
  op: OperationIdSchema,
2025
2162
  qid: OperationIdSchema,
2026
2163
  rows: CardRowsSchema.optional(),
2027
- confirmed: z25.literal(true).optional(),
2164
+ confirmed: z26.literal(true).optional(),
2028
2165
  assertion: AssertionSchema.optional(),
2029
2166
  /** « Refuser », as the local `chat.act`: no passkey, no confirmation. */
2030
- deny: z25.literal(true).optional()
2167
+ deny: z26.literal(true).optional()
2031
2168
  }),
2032
2169
  /** « Ignorer » the turn's cards, or `undo` (« Revoir »), as the local `chat.ignore`. */
2033
- z25.object({ type: z25.literal("chat.ignore"), op: OperationIdSchema, qid: OperationIdSchema, undo: z25.literal(true).optional() }),
2170
+ z26.object({ type: z26.literal("chat.ignore"), op: OperationIdSchema, qid: OperationIdSchema, undo: z26.literal(true).optional() }),
2034
2171
  /** « Reprendre » a resting team. */
2035
- z25.object({ type: z25.literal("team.resume"), op: OperationIdSchema, team: z25.string().min(1).max(40) }),
2172
+ z26.object({ type: z26.literal("team.resume"), op: OperationIdSchema, team: z26.string().min(1).max(40) }),
2036
2173
  /** Puts a closed task Ledge gave away from « À traiter ». */
2037
- z25.object({ type: z25.literal("task.seen"), op: OperationIdSchema, task: z25.string().min(1).max(40) }),
2174
+ z26.object({ type: z26.literal("task.seen"), op: OperationIdSchema, task: z26.string().min(1).max(40) }),
2038
2175
  /** Whether the phone's app is in front: a device that is visible gets no push. */
2039
- z25.object({ type: z25.literal("presence"), visible: z25.boolean() })
2040
- ]);
2041
- var PhoneServerMessageSchema = z25.discriminatedUnion("type", [
2042
- z25.object({ type: z25.literal("snapshot"), protocol: z25.literal(PHONE_PROTOCOL), sessions: z25.array(PhoneSessionSchema), capabilities: CapabilitiesByToolSchema, daemon: z25.object({ version: z25.string(), name: z25.string().max(40), boot: z25.string().uuid().optional() }), device: z25.object({ confirm: z25.boolean(), push: z25.enum(["on", "off", "stale", "unavailable"]).optional(), chat: z25.literal(true).optional(), contextNear: ContextPrefsSchema.shape.near.optional() }).optional() }),
2043
- z25.object({ type: z25.literal("confirm.challenge"), purpose: ConfirmPurposeSchema, challenge: B64U2.max(64), rpId: z25.string().max(253), credentialId: B64U2.max(1366).optional(), expiresInMs: z25.number().int().positive() }),
2044
- z25.object({ type: z25.literal("session.updated"), session: PhoneSessionSchema }),
2045
- z25.object({ type: z25.literal("session.removed"), id: z25.string() }),
2176
+ z26.object({ type: z26.literal("presence"), visible: z26.boolean() }),
2177
+ /** The roles, templates and problems of every scope the phone may name; then one role whole, when the catalog cut its prompt. */
2178
+ z26.object({ type: z26.literal("teams.catalog") }),
2179
+ z26.object({ type: z26.literal("teams.role"), ...teamsScope, id: RoleIdSchema }).strict(),
2180
+ /** `base` is the hash the phone was shown, null to create. */
2181
+ z26.object({ type: z26.literal("role.write"), ...teamsOp, ...teamsScope, role: PhoneRoleDraftSchema, base: DefinitionHashSchema.nullable() }).strict(),
2182
+ z26.object({ type: z26.literal("role.delete"), ...teamsOp, ...teamsScope, id: RoleIdSchema, base: DefinitionHashSchema }).strict(),
2183
+ /** No `id`: create, the id comes from the name. */
2184
+ z26.object({ type: z26.literal("template.write"), ...teamsOp, ...teamsScope, id: TemplateIdSchema.optional(), name: TeamNameSchema, seats: PhoneSeatsSchema, base: DefinitionHashSchema.nullable() }).strict(),
2185
+ z26.object({ type: z26.literal("template.delete"), ...teamsOp, ...teamsScope, id: TemplateIdSchema, base: DefinitionHashSchema }).strict(),
2186
+ z26.object({ type: z26.literal("team.launch"), ...teamsOp, project: z26.string().min(1).max(80), name: TeamNameSchema, seats: PhoneSeatsSchema, template: z26.string().min(1).max(64).optional() }).strict(),
2187
+ z26.object({ type: z26.literal("team.compose"), ...teamsOp, team: TeamIdSchema, seats: PhoneSeatsSchema }).strict(),
2188
+ z26.object({ type: z26.literal("team.seat"), ...teamsOp, team: TeamIdSchema, role: RoleIdSchema, action: z26.enum(["start", "restart"]) }).strict(),
2189
+ z26.object({ type: z26.literal("team.dissolve"), ...teamsOp, team: TeamIdSchema }).strict(),
2190
+ /** Installs `version` on the PC, then restarts its daemon; the phone asks for its own build's version. Passkey, purpose `pc`. */
2191
+ z26.object({ type: z26.literal("daemon.update"), ...teamsOp, version: z26.string().regex(SEMVER) }).strict(),
2192
+ /** Restarts the PC's daemon without installing anything. Passkey, purpose `pc`. */
2193
+ z26.object({ type: z26.literal("daemon.restart"), ...teamsOp }).strict()
2194
+ ]).superRefine((m, ctx) => {
2195
+ const issue = "scope" in m ? scopeIssue(m) : null;
2196
+ if (issue) ctx.addIssue({ code: z26.ZodIssueCode.custom, message: issue, path: ["project"] });
2197
+ });
2198
+ var PhoneServerMessageSchema = z26.discriminatedUnion("type", [
2199
+ z26.object({ type: z26.literal("snapshot"), protocol: z26.literal(PHONE_PROTOCOL), sessions: z26.array(PhoneSessionSchema), capabilities: CapabilitiesByToolSchema, daemon: z26.object({
2200
+ version: z26.string(),
2201
+ name: z26.string().max(40),
2202
+ boot: z26.string().uuid().optional(),
2203
+ teams: z26.literal(true).optional(),
2204
+ /** `update`: the daemon can install a version and restart (npm, systemd); `restart`: it can restart (systemd). */
2205
+ update: z26.literal(true).optional(),
2206
+ restart: z26.literal(true).optional()
2207
+ }), device: z26.object({ confirm: z26.boolean(), push: z26.enum(["on", "off", "stale", "unavailable"]).optional(), chat: z26.literal(true).optional(), contextNear: ContextPrefsSchema.shape.near.optional() }).optional() }),
2208
+ z26.object({
2209
+ type: z26.literal("confirm.challenge"),
2210
+ purpose: ConfirmPurposeSchema,
2211
+ challenge: B64U2.max(64),
2212
+ rpId: z26.string().max(253),
2213
+ credentialId: B64U2.max(1366).optional(),
2214
+ expiresInMs: z26.number().int().positive(),
2215
+ /** Echoed from the `confirm.prepare` of a `define` or `team` challenge, so the phone matches each challenge to its own call. Absent from an older gateway. */
2216
+ digest: TeamsDigestSchema.optional()
2217
+ }),
2218
+ z26.object({ type: z26.literal("session.updated"), session: PhoneSessionSchema }),
2219
+ z26.object({ type: z26.literal("session.removed"), id: z26.string() }),
2046
2220
  /** `pending.cut` is set when even this body was shortened. */
2047
- z25.object({ type: z25.literal("session.pending"), id: z25.string(), pending: PhonePendingSchema }),
2048
- z25.object({ type: z25.literal("session.preview"), id: z25.string(), lines: z25.array(z25.string()) }),
2221
+ z26.object({ type: z26.literal("session.pending"), id: z26.string(), pending: PhonePendingSchema }),
2222
+ z26.object({ type: z26.literal("session.preview"), id: z26.string(), lines: z26.array(z26.string()) }),
2049
2223
  /** `cut`: the ids of the items shortened; `more`: older items were left out. */
2050
- z25.object({ type: z25.literal("session.thread"), id: z25.string(), items: z25.array(ThreadItemSchema), cut: z25.array(z25.string()), more: z25.boolean() }),
2051
- z25.object({ type: z25.literal("session.thread.item"), id: z25.string(), item: ThreadItemSchema, cut: z25.literal(true).optional() }),
2052
- z25.object({ type: z25.literal("operation.result"), op: OperationIdSchema, status: OperationStatusSchema, reason: OperationReasonSchema.optional() }),
2053
- z25.object({ type: z25.literal("chat.history"), turns: z25.array(PhoneChatTurnSchema).max(50) }),
2054
- z25.object({ type: z25.literal("chat.step"), qid: OperationIdSchema, step: PhoneChatStepSchema }),
2224
+ z26.object({ type: z26.literal("session.thread"), id: z26.string(), items: z26.array(ThreadItemSchema), cut: z26.array(z26.string()), more: z26.boolean() }),
2225
+ z26.object({ type: z26.literal("session.thread.item"), id: z26.string(), item: ThreadItemSchema, cut: z26.literal(true).optional() }),
2226
+ z26.object({ type: z26.literal("operation.result"), op: OperationIdSchema, status: OperationStatusSchema, reason: OperationReasonSchema.optional() }),
2227
+ z26.object({ type: z26.literal("chat.history"), turns: z26.array(PhoneChatTurnSchema).max(50) }),
2228
+ z26.object({ type: z26.literal("chat.step"), qid: OperationIdSchema, step: PhoneChatStepSchema }),
2055
2229
  /** The whole text so far, not an increment. */
2056
- z25.object({ type: z25.literal("chat.delta"), qid: OperationIdSchema, text: z25.string().max(THREAD_TEXT_MAX) }),
2057
- z25.object({ type: z25.literal("chat.done"), qid: OperationIdSchema, turn: PhoneChatTurnSchema }),
2058
- z25.object({ type: z25.literal("chat.error"), qid: OperationIdSchema, code: ChatErrorCodeSchema }),
2230
+ z26.object({ type: z26.literal("chat.delta"), qid: OperationIdSchema, text: z26.string().max(THREAD_TEXT_MAX) }),
2231
+ z26.object({ type: z26.literal("chat.done"), qid: OperationIdSchema, turn: PhoneChatTurnSchema }),
2232
+ z26.object({ type: z26.literal("chat.error"), qid: OperationIdSchema, code: ChatErrorCodeSchema }),
2233
+ z26.object({ type: z26.literal("teams.catalog"), catalog: PhoneCatalogSchema }),
2234
+ /** The daemon updating or restarting itself, whoever asked: npm runs, then the service restarts (the link drops right after). */
2235
+ z26.object({ type: z26.literal("daemon.progress"), version: z26.string().max(40), step: z26.enum(["installing", "restarting"]) }),
2236
+ /** Nothing was changed. Never npm's output nor a command: both hold the PC's paths. */
2237
+ z26.object({ type: z26.literal("daemon.failed"), version: z26.string().max(40), reason: UpdateFailureSchema }),
2238
+ z26.object({ type: z26.literal("teams.role"), role: PhoneRoleSchema }),
2059
2239
  /** The live teams, after each snapshot and on every change. */
2060
- z25.object({ type: z25.literal("teams"), teams: z25.array(PhoneTeamSchema).max(50) }),
2240
+ z26.object({ type: z26.literal("teams"), teams: z26.array(PhoneTeamSchema).max(50) }),
2061
2241
  /** The tasks Ledge gave, open or closed lately, after each snapshot; then each change. */
2062
- z25.object({ type: z25.literal("tasks"), tasks: z25.array(PhoneTaskSchema).max(200) }),
2063
- z25.object({ type: z25.literal("task.updated"), task: PhoneTaskSchema }),
2242
+ z26.object({ type: z26.literal("tasks"), tasks: z26.array(PhoneTaskSchema).max(200) }),
2243
+ z26.object({ type: z26.literal("task.updated"), task: PhoneTaskSchema }),
2064
2244
  AttachmentStoredSchema,
2065
2245
  AttachmentDataSchema,
2066
2246
  AttachmentErrorSchema,
2067
2247
  /** Never carries free text. */
2068
- z25.object({ type: z25.literal("error"), code: z25.enum(["invalid", "unknown_session", "too_large"]), request: z25.string().max(40).optional() })
2248
+ z26.object({ type: z26.literal("error"), code: z26.enum(["invalid", "unknown_session", "too_large"]), request: z26.string().max(40).optional() })
2069
2249
  ]);
2250
+ var teamsPurpose = (type) => type.startsWith("team.") ? "team" : "define";
2251
+ var DIGEST_OP = "00000000-0000-4000-8000-000000000000";
2252
+ async function teamsDigest(m) {
2253
+ const { op: _op, assertion: _assertion, ...raw } = m;
2254
+ const { op: _parsedOp, assertion: _parsedAssertion, ...rest } = PhoneClientMessageSchema.parse({ ...raw, op: DIGEST_OP });
2255
+ const bytes = new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(canonicalJson(rest))));
2256
+ return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
2257
+ }
2070
2258
 
2071
2259
  // src/auth.ts
2072
2260
  import { createHash, createHmac, randomBytes, timingSafeEqual } from "crypto";
@@ -2218,12 +2406,19 @@ export {
2218
2406
  parseTeamBlock,
2219
2407
  parseTaskBlock,
2220
2408
  parseProjectBlock,
2409
+ SshAliasSchema,
2410
+ MachinesSchema,
2411
+ PROJECT_COLORS,
2412
+ ProjectsSchema,
2413
+ DEFAULT_PROJECTS,
2414
+ projectOf,
2221
2415
  RoleIdSchema,
2222
2416
  ROLE_LABEL_MAX,
2223
2417
  ROLE_PROMPT_MAX,
2224
2418
  RoleSchema,
2225
2419
  SeatsSchema,
2226
2420
  TeamNameSchema,
2421
+ TemplateIdSchema,
2227
2422
  TeamSchema,
2228
2423
  isTeamLive,
2229
2424
  NOTE_MAX,
@@ -2248,19 +2443,14 @@ export {
2248
2443
  ChatTurnSchema,
2249
2444
  proposalRows,
2250
2445
  DOCUMENT_MAX_BYTES,
2251
- SshAliasSchema,
2252
- MachinesSchema,
2253
2446
  IslandPrefsSchema,
2254
- PROJECT_COLORS,
2255
- ProjectsSchema,
2256
- DEFAULT_PROJECTS,
2257
- projectOf,
2258
2447
  RouteResultSchema,
2259
2448
  DEFAULT_RELAY_URL,
2260
2449
  MobileConfigSchema,
2261
2450
  PROTOCOL_PORT,
2262
2451
  RefusalCodeSchema,
2263
2452
  RecentSchema,
2453
+ SEMVER,
2264
2454
  MESSAGE_MAX,
2265
2455
  SUMMARY_MAX,
2266
2456
  parseClientMessage,
@@ -2279,6 +2469,11 @@ export {
2279
2469
  pushEndpointAllowed,
2280
2470
  PushSendResultSchema,
2281
2471
  PushPayloadSchema,
2472
+ PhoneRoleSchema,
2473
+ PhoneTemplateSchema,
2474
+ TEAMS_OPERATION_TYPES,
2475
+ isTeamsOperation,
2476
+ canonicalJson,
2282
2477
  PHONE_PROTOCOL,
2283
2478
  padPlain,
2284
2479
  THREAD_ITEMS_MAX,
@@ -2290,7 +2485,10 @@ export {
2290
2485
  OperationIdSchema,
2291
2486
  UNTYPABLE,
2292
2487
  CHAT_HISTORY_BUDGET,
2488
+ pcSubject,
2293
2489
  PhoneClientMessageSchema,
2490
+ teamsPurpose,
2491
+ teamsDigest,
2294
2492
  tokenEquals,
2295
2493
  hostAllowed,
2296
2494
  requestAuthorized,