@paradow/ledge 0.33.0 → 0.34.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 (42) hide show
  1. package/dist/cli/{action-QW2ZQQBN.js → action-K42H5BDA.js} +5 -5
  2. package/dist/cli/{attach-ULTYWCJ7.js → attach-KEE4A5YP.js} +28 -15
  3. package/dist/cli/{bridge-CSLF7EW6.js → bridge-X327AZY4.js} +2 -2
  4. package/dist/cli/{chunk-3DB3VOMM.js → chunk-25RVT5MR.js} +3 -103
  5. package/dist/cli/{chunk-GXL3X7M7.js → chunk-3OJCWJAA.js} +2 -2
  6. package/dist/cli/chunk-4OYVM4MT.js +49 -0
  7. package/dist/cli/{chunk-JEGPTNWV.js → chunk-4TCSADFR.js} +5 -23
  8. package/dist/cli/{chunk-HOOHS3MX.js → chunk-53ISXX2R.js} +1 -1
  9. package/dist/cli/{chunk-6IYPRUQG.js → chunk-54KF5RBY.js} +1 -1
  10. package/dist/cli/{chunk-ASYAWVFW.js → chunk-7NHQGP6J.js} +1 -1
  11. package/dist/cli/{chunk-4HXJQEUN.js → chunk-G7XPEVCG.js} +5 -5
  12. package/dist/cli/{chunk-WXE2NOE5.js → chunk-IWY7DSSO.js} +835 -1033
  13. package/dist/cli/{chunk-CSLVBADC.js → chunk-KPDTYX7F.js} +3 -3
  14. package/dist/cli/chunk-RPH773TY.js +6 -0
  15. package/dist/cli/{chunk-CCSUP5ZI.js → chunk-RX5CJ7YH.js} +3 -5
  16. package/dist/cli/{chunk-NLL2EQJ2.js → chunk-T547FLQN.js} +38 -4
  17. package/dist/cli/{chunk-K7UEKSB2.js → chunk-UJ2WBGLW.js} +2 -2
  18. package/dist/cli/{chunk-XOZD4BP5.js → chunk-ULOMKEB6.js} +4 -4
  19. package/dist/cli/{chunk-CPERVAPQ.js → chunk-V4XKKL6K.js} +13 -40
  20. package/dist/cli/{chunk-PZ3F4QH3.js → daemon-RO43S3S5.js} +4655 -2964
  21. package/dist/cli/{decide-PFHHOCFZ.js → decide-KZFYL3HY.js} +5 -5
  22. package/dist/cli/{handover-EMO6JT7O.js → handover-BWNMI2RA.js} +5 -5
  23. package/dist/cli/{hook-W2BU74H5.js → hook-ZLWXI5EQ.js} +21 -71
  24. package/dist/cli/index.js +18 -25
  25. package/dist/cli/launch-GCX7TXOH.js +28 -0
  26. package/dist/cli/{send-NEI4X33R.js → send-SXZAPVRH.js} +5 -5
  27. package/dist/cli/{setup-K42IVMHS.js → setup-TJ32FMVJ.js} +4 -4
  28. package/dist/cli/{status-U2HGGKHF.js → status-YDVRES4E.js} +3 -3
  29. package/dist/cli/{task-PDDCE23D.js → task-TUSOVJK7.js} +5 -5
  30. package/dist/cli/{tui-UPMRMCPC.js → tui-TCVIRZCQ.js} +1401 -1269
  31. package/dist/cli/{uninstall-4IMMR55T.js → uninstall-QO7YMSLA.js} +4 -4
  32. package/dist/cli/{version-LUMK3Z3T.js → version-BAYSYWFP.js} +1 -1
  33. package/dist/cli/who-6AZYSP7T.js +12 -0
  34. package/dist/ledge-guide.md +26 -49
  35. package/package.json +2 -1
  36. package/dist/cli/chunk-4VNKZOC2.js +0 -160
  37. package/dist/cli/chunk-E3LXONBI.js +0 -6
  38. package/dist/cli/chunk-NWIICISV.js +0 -290
  39. package/dist/cli/daemon-5GT545BB.js +0 -2322
  40. package/dist/cli/launch-LP7YJR5N.js +0 -36
  41. package/dist/cli/team-S3ASP22H.js +0 -205
  42. package/dist/cli/who-NM3GPAPJ.js +0 -12
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  paths
3
- } from "./chunk-HOOHS3MX.js";
3
+ } from "./chunk-53ISXX2R.js";
4
4
 
5
5
  // ../protocol/src/handover.ts
6
6
  import { z } from "zod";
@@ -19,7 +19,7 @@ var HandoverSchema = z.object({
19
19
  to: z.string().optional(),
20
20
  toName: z.string().optional(),
21
21
  reason: z.string().optional(),
22
- /** Started by Ledge itself (a seat working without asking), not by the user. */
22
+ /** Started by Ledge itself (a session working without asking), not by the user. */
23
23
  auto: z.literal(true).optional()
24
24
  });
25
25
  var RelievesSchema = z.object({ id: z.string(), name: z.string(), at: z.string().datetime() });
@@ -36,23 +36,6 @@ var HandoverResultSchema = z.object({ type: z.literal("handover.result"), rid: z
36
36
  import { z as z2 } from "zod";
37
37
  var ToolSchema = z2.enum(["claude", "codex", "cursor", "omp"]);
38
38
  var OmpApprovalSchema = z2.enum(["always-ask", "write", "yolo"]);
39
- var AutonomySchema = z2.enum(["ask", "edits", "auto"]);
40
- function autonomyArgs(tool, autonomy) {
41
- if (!autonomy || autonomy === "ask") return [];
42
- switch (tool) {
43
- case "claude":
44
- return ["--permission-mode", autonomy === "edits" ? "acceptEdits" : "auto"];
45
- case "codex":
46
- return autonomy === "edits" ? ["--ask-for-approval", "on-request"] : ["--ask-for-approval", "never", "--sandbox", "workspace-write"];
47
- case "cursor":
48
- return autonomy === "auto" ? ["--force"] : [];
49
- case "omp":
50
- return [];
51
- }
52
- }
53
- function ompApprovalFor(autonomy) {
54
- return autonomy === "auto" ? "yolo" : autonomy ? "always-ask" : void 0;
55
- }
56
39
  var BackendSchema = z2.enum(["tmux", "omp-rpc"]);
57
40
  var SessionStateSchema = z2.enum(["starting", "working", "waiting_input", "waiting_permission", "idle", "exited", "error"]);
58
41
  var AskQuestionSchema = z2.object({
@@ -119,6 +102,8 @@ var SessionSchema = z2.object({
119
102
  worktree: z2.boolean().optional(),
120
103
  /** The folder the agent works in now, as its last hook reported it: `cwd` stays where it started, this follows a worktree it entered. */
121
104
  workdir: z2.string().optional(),
105
+ /** The OpenRig seat this agent is: its session name (`dev-build@starter`), its rig, and its role (`dev.build`) once OpenRig named it. */
106
+ rig: z2.object({ seat: z2.string(), name: z2.string(), role: z2.string().optional() }).optional(),
122
107
  tmuxSession: z2.string().nullable(),
123
108
  /** Left out for a tmux session. `omp-rpc`: no pane, nothing to attach to; the daemon holds the process (see `agentSessionFile`). */
124
109
  backend: BackendSchema.optional(),
@@ -138,17 +123,6 @@ var SessionSchema = z2.object({
138
123
  effort: z2.string().optional(),
139
124
  /** OMP: the approval mode it was launched with, kept by a resume; left out, `always-ask`. */
140
125
  approval: OmpApprovalSchema.optional(),
141
- /** The role it was launched with or took in a team (spec 2026-10-25 roles §3.3): its id, its label as it was then. */
142
- role: z2.string().optional(),
143
- roleLabel: z2.string().optional(),
144
- /** The live team it sits in (`team-…`); left out, the project's common table. */
145
- team: z2.string().optional(),
146
- /** The name of the team it was last taken out of (a leave, a dissolution, a seat in another team): a refused `@role` says so. */
147
- teamLeft: z2.string().optional(),
148
- /** Its team as it was last told it (`seatKey`): its next turn is told again when the team has changed since. */
149
- teamSeen: z2.string().optional(),
150
- /** Its role's autonomy, as launched (kept by a resume); left out, `ask`. */
151
- autonomy: AutonomySchema.optional(),
152
126
  /** Its context as its agent last reported it, after a turn (context handover spec §3.1); left out, not measured. */
153
127
  context: ContextSchema.optional(),
154
128
  /** Its relief by a fresh session (§3.3): asked, launched, done or failed. */
@@ -166,7 +140,10 @@ var SessionSchema = z2.object({
166
140
  exitCode: z2.number().int().nullable().optional(),
167
141
  exitedAt: z2.string().datetime().optional(),
168
142
  lastError: z2.string().optional(),
169
- source: z2.enum(["launcher", "hook_only"]),
143
+ /** `launcher`: Ledge launched it; `hook_only`: only its hooks are known (read-only); `rig`: an OpenRig seat Ledge follows through
144
+ * its tmux pane on the user's default server, answered like its own, whose life stays OpenRig's (no close, kill, resume, model). */
145
+ // A kind a newer daemon adds reads as read-only here, never as a snapshot thrown away whole (« hors ligne »).
146
+ source: z2.enum(["launcher", "hook_only", "rig"]).catch("hook_only"),
170
147
  /** When the session was put in the archive (session management): set, it leaves the live list and waits to be restored, resumed or deleted. */
171
148
  archivedAt: z2.string().datetime().optional(),
172
149
  /** When the session was last taken out of the archive: the poller's retirement clock restarts from it, not from `exitedAt`. */
@@ -179,293 +156,39 @@ function isArchived(s) {
179
156
  return s.archivedAt !== void 0;
180
157
  }
181
158
 
182
- // ../protocol/src/teams.ts
183
- import { z as z7 } from "zod";
184
-
185
- // ../protocol/src/models.ts
186
- import { z as z3 } from "zod";
187
- var ModelIdSchema = z3.string().min(1).max(200).regex(/^[A-Za-z0-9][A-Za-z0-9._:/@[\]=,+-]*$/, "not a model id");
188
- var EffortSchema = z3.string().min(1).max(20).regex(/^[a-z]+$/, "not an effort");
189
- var ModelChoiceSchema = z3.object({
190
- id: ModelIdSchema,
191
- label: z3.string(),
192
- description: z3.string().optional(),
193
- efforts: z3.array(EffortSchema).optional(),
194
- defaultEffort: EffortSchema.optional(),
195
- isDefault: z3.boolean().optional()
196
- });
197
- var ModelsListSchema = z3.object({
198
- type: z3.literal("models.list"),
199
- requestId: z3.string().min(1).max(100),
200
- tool: ToolSchema,
201
- machineId: z3.string().optional()
202
- });
203
- var ModelsListingSchema = z3.object({
204
- type: z3.literal("models.listing"),
205
- requestId: z3.string(),
206
- tool: ToolSchema,
207
- models: z3.array(ModelChoiceSchema),
208
- error: z3.string().optional()
209
- });
210
- var ModelRefusalSchema = z3.enum(["not_launched", "ended", "no_conversation", "not_running", "effort_in_model", "restart_failed", "refused"]);
211
- var SessionModelAcceptedSchema = z3.object({ type: z3.literal("session.model.accepted"), id: z3.string(), when: z3.enum(["now", "turn", "none"]) });
212
-
213
- // ../protocol/src/projects.ts
214
- import { z as z6 } from "zod";
215
-
216
- // ../protocol/src/machines.ts
217
- import { z as z5 } from "zod";
218
-
219
- // ../protocol/src/ssh.ts
220
- import { z as z4 } from "zod";
221
- var SshAliasSchema = z4.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/);
222
-
223
- // ../protocol/src/machines.ts
224
- var MachineIdSchema = z5.string().regex(/^[a-zA-Z0-9_-]{1,64}$/);
225
- var MachineSchema = z5.object({
226
- id: MachineIdSchema,
227
- label: z5.string().trim().min(1).max(80),
228
- ssh: SshAliasSchema.optional(),
229
- /** Kept in the list but never connected to: no peer, no retry, no session shown until it is enabled again. */
230
- disabled: z5.boolean().optional()
231
- });
232
- var MachinesSchema = z5.array(MachineSchema).min(1).max(20).superRefine((list, ctx) => {
233
- if (list[0]?.id !== "local" || list[0].ssh !== void 0) ctx.addIssue({ code: "custom", message: "the first machine is local, without ssh", path: [0] });
234
- const ids = /* @__PURE__ */ new Set(), aliases = /* @__PURE__ */ new Set();
235
- list.forEach((m, i) => {
236
- if (i === 0 && m.disabled) ctx.addIssue({ code: "custom", message: "the local machine cannot be disabled", path: [0, "disabled"] });
237
- if (i > 0 && !m.ssh) ctx.addIssue({ code: "custom", message: "a remote machine needs an ssh alias", path: [i, "ssh"] });
238
- if (ids.has(m.id)) ctx.addIssue({ code: "custom", message: `duplicate id ${m.id}`, path: [i, "id"] });
239
- ids.add(m.id);
240
- if (m.ssh) {
241
- if (aliases.has(m.ssh)) ctx.addIssue({ code: "custom", message: `duplicate ssh alias ${m.ssh}`, path: [i, "ssh"] });
242
- aliases.add(m.ssh);
243
- }
244
- });
245
- });
246
-
247
- // ../protocol/src/projects.ts
248
- var PROJECT_COLORS = { blue: "#3b82f6", green: "#10b981", amber: "#f59e0b", violet: "#8b5cf6", teal: "#14b8a6", pink: "#ec4899", red: "#ef4444", slate: "#64748b" };
249
- var ProjectColorSchema = z6.enum(["blue", "green", "amber", "violet", "teal", "pink", "red", "slate"]);
250
- var ProjectIdSchema = z6.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/);
251
- function normalizePath(raw) {
252
- const p = raw.trim().replace(/\/+/g, "/");
253
- return p.length > 1 && p.endsWith("/") ? p.slice(0, -1) : p;
254
- }
255
- var PathSchema = z6.string().max(4096).refine((p) => p.startsWith("/") && p === normalizePath(p), "an absolute, normalized path");
256
- var RepoSchema = z6.object({ machine: MachineIdSchema, path: PathSchema });
257
- var ProjectSchema = z6.object({
258
- id: ProjectIdSchema,
259
- name: z6.string().trim().min(1).max(80),
260
- color: ProjectColorSchema,
261
- description: z6.string().max(500).default(""),
262
- repos: z6.array(RepoSchema).max(50)
263
- });
264
- var RuleSchema = z6.object({ machine: MachineIdSchema, path: PathSchema, project: ProjectIdSchema });
265
- function projectsProblems(p) {
266
- const out = [];
267
- const ids = /* @__PURE__ */ new Set(), names = /* @__PURE__ */ new Set(), repos = /* @__PURE__ */ new Set(), rules = /* @__PURE__ */ new Set();
268
- p.projects.forEach((project, i) => {
269
- if (ids.has(project.id)) out.push({ code: "duplicate_id", path: ["projects", i, "id"] });
270
- ids.add(project.id);
271
- const name = project.name.trim().toLocaleLowerCase();
272
- if (names.has(name)) out.push({ code: "duplicate_name", path: ["projects", i, "name"] });
273
- names.add(name);
274
- project.repos.forEach((repo, j) => {
275
- const key = `${repo.machine}
276
- ${repo.path}`;
277
- if (repos.has(key)) out.push({ code: "duplicate_repo", path: ["projects", i, "repos", j] });
278
- repos.add(key);
279
- });
280
- });
281
- p.rules.forEach((rule, i) => {
282
- const key = `${rule.machine}
283
- ${rule.path}`;
284
- if (rules.has(key)) out.push({ code: "duplicate_rule", path: ["rules", i] });
285
- rules.add(key);
286
- if (!ids.has(rule.project)) out.push({ code: "unknown_project", path: ["rules", i, "project"] });
287
- });
288
- return out;
289
- }
290
- var ProjectsSchema = z6.object({ projects: z6.array(ProjectSchema).max(100), rules: z6.array(RuleSchema).max(1e3) }).superRefine((p, ctx) => {
291
- for (const problem of projectsProblems(p)) ctx.addIssue({ code: "custom", message: problem.code, path: problem.path });
292
- });
293
- var DEFAULT_PROJECTS = { projects: [], rules: [] };
294
- var under = (cwd, path2) => path2 === "/" || cwd === path2 || cwd.startsWith(`${path2}/`);
295
- function projectOf(session, state) {
296
- const machine = session.machineId ?? "local";
297
- const cwd = normalizePath(session.cwd);
298
- const known = new Set(state.projects.map((p) => p.id));
299
- const candidates = [
300
- ...state.projects.flatMap((p) => p.repos.filter((r) => r.machine === machine).map((r) => ({ project: p.id, path: r.path, rule: false }))),
301
- ...state.rules.filter((r) => r.machine === machine && known.has(r.project)).map((r) => ({ project: r.project, path: r.path, rule: true }))
302
- ].filter((c) => under(cwd, c.path));
303
- candidates.sort((x, y) => y.path.length - x.path.length || Number(y.rule) - Number(x.rule));
304
- return candidates[0]?.project ?? null;
305
- }
306
-
307
- // ../protocol/src/teams.ts
308
- var RoleIdSchema = z7.string().regex(/^[a-z0-9][a-z0-9_-]{0,39}$/);
309
- var ROLE_LABEL_MAX = 40;
310
- var ROLE_PROMPT_MAX = 8e3;
311
- var DefinitionHashSchema = z7.string().regex(/^[0-9a-f]{16}$/);
312
- var RoleSchema = z7.object({
313
- id: RoleIdSchema,
314
- label: z7.string().min(1).max(ROLE_LABEL_MAX),
315
- prompt: z7.string().max(ROLE_PROMPT_MAX),
316
- tool: ToolSchema.optional(),
317
- model: ModelIdSchema.optional(),
318
- effort: EffortSchema.optional(),
319
- autonomy: AutonomySchema.optional(),
320
- source: z7.enum(["repo", "home"]),
321
- path: z7.string(),
322
- shadows: z7.string().optional(),
323
- /** 16 hex chars of the file's text: what a write or delete must name as its base (absent from older daemons). */
324
- hash: DefinitionHashSchema.optional()
325
- });
326
- var DefinitionProblemSchema = z7.object({ path: z7.string(), reason: z7.string() });
327
- var TEAM_SEATS_MAX = 8;
328
- var SeatSchema = z7.object({
329
- role: RoleIdSchema,
330
- tool: ToolSchema.optional(),
331
- model: ModelIdSchema.optional(),
332
- effort: EffortSchema.optional(),
333
- name: z7.string().min(1).max(40).optional()
334
- });
335
- var uniqueRoles = (seats) => new Set(seats.map((s) => s.role)).size === seats.length;
336
- var SeatsSchema = z7.array(SeatSchema).min(1).max(TEAM_SEATS_MAX).refine(uniqueRoles, "a role twice in one team");
337
- var TeamNameSchema = z7.string().trim().min(1).max(60);
338
- var TemplateIdSchema = z7.string().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/);
339
- 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() });
340
- var TeamIdSchema = z7.string().regex(/^team-[0-9a-f]{4,8}$/);
341
- var TeamStateSchema = z7.enum(["active", "resting", "dissolved"]);
342
- var TeamSchema = z7.object({
343
- id: TeamIdSchema,
344
- name: TeamNameSchema,
345
- template: z7.string().optional(),
346
- project: z7.string().nullable(),
347
- machine: z7.string(),
348
- cwd: z7.string(),
349
- state: TeamStateSchema,
350
- /** A live seat: `tool`, `model` and `effort` are what it was composed with over the role's defaults, `name` the bot name it asks
351
- * for (its template's or its composition's); `leaving` marks a seat removed from the composition that finishes its turn and then is closed. */
352
- seats: z7.array(z7.object({
353
- role: RoleIdSchema,
354
- sessionId: z7.string().nullable(),
355
- tool: ToolSchema.optional(),
356
- model: ModelIdSchema.optional(),
357
- effort: EffortSchema.optional(),
358
- name: SeatSchema.shape.name,
359
- leaving: z7.literal(true).optional()
360
- })).max(TEAM_SEATS_MAX * 2),
361
- createdAt: z7.string(),
362
- updatedAt: z7.string(),
363
- restingAt: z7.string().optional(),
364
- dissolvedAt: z7.string().optional()
365
- });
366
- 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() });
367
- var RolesListingSchema = z7.object({
368
- type: z7.literal("roles.listing"),
369
- requestId: z7.string().optional(),
370
- roles: z7.array(RoleSchema),
371
- templates: z7.array(TeamTemplateSchema).default([]),
372
- problems: z7.array(DefinitionProblemSchema),
373
- /** Set by the fleet when the project's machine could not answer (#99): 'offline', or 'outdated' for a daemon without roles.list. */
374
- error: z7.string().optional()
375
- });
376
- var TeamLaunchSchema = z7.object({
377
- type: z7.literal("team.launch"),
378
- rid: z7.string().min(1).max(100),
379
- cwd: z7.string().min(1).optional(),
380
- template: z7.string().min(1).max(64).optional(),
381
- seats: SeatsSchema.optional(),
382
- name: TeamNameSchema.optional(),
383
- qid: z7.string().min(1).optional(),
384
- machineId: z7.string().optional(),
385
- /** The project's name, for a client that holds no path (the phone): the daemon resolves its folder. */
386
- project: ProjectIdSchema.optional()
387
- });
388
- var TeamJoinSchema = z7.object({ type: z7.literal("team.join"), team: TeamIdSchema, session: z7.string().min(1), role: RoleIdSchema });
389
- var TeamLeaveSchema = z7.object({ type: z7.literal("team.leave"), team: TeamIdSchema, session: z7.string().min(1) });
390
- var TeamResumeSchema = z7.object({ type: z7.literal("team.resume"), team: TeamIdSchema });
391
- var TeamDissolveSchema = z7.object({ type: z7.literal("team.dissolve"), team: TeamIdSchema });
392
- 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(), base: DefinitionHashSchema.optional() });
393
- var DefinitionScopeSchema = z7.enum(["home", "repo"]);
394
- var RoleDraftSchema = RoleSchema.pick({ id: true, label: true, prompt: true, tool: true, model: true, effort: true, autonomy: true });
395
- var DefinitionCodeSchema = z7.enum(["changed", "exists", "missing", "unknown_project", "invalid"]);
396
- var scopeFields = { rid: z7.string().min(1).max(100), scope: DefinitionScopeSchema, project: ProjectIdSchema.optional() };
397
- 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";
398
- var DefinitionBaseSchema = DefinitionHashSchema;
399
- var DefinitionsListSchema = z7.object({ type: z7.literal("definitions.list"), requestId: z7.string().max(100).optional() });
400
- var RoleWriteSchema = z7.object({ type: z7.literal("role.write"), ...scopeFields, role: RoleDraftSchema, base: DefinitionBaseSchema.nullable() });
401
- var RoleDeleteSchema = z7.object({ type: z7.literal("role.delete"), ...scopeFields, id: RoleIdSchema, base: DefinitionBaseSchema });
402
- var TemplateWriteSchema = z7.object({
403
- type: z7.literal("template.write"),
404
- ...scopeFields,
405
- id: TemplateIdSchema.optional(),
406
- name: TeamNameSchema,
407
- seats: SeatsSchema,
408
- base: DefinitionBaseSchema.nullable()
409
- });
410
- var TemplateDeleteSchema = z7.object({ type: z7.literal("template.delete"), ...scopeFields, id: TemplateIdSchema, base: DefinitionBaseSchema });
411
- var TeamComposeSchema = z7.object({ type: z7.literal("team.compose"), rid: z7.string().min(1).max(100), team: TeamIdSchema, seats: SeatsSchema });
412
- 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"]) });
413
- var DefinitionsListingSchema = z7.object({
414
- type: z7.literal("definitions.listing"),
415
- requestId: z7.string().optional(),
416
- scopes: z7.array(z7.object({
417
- scope: DefinitionScopeSchema,
418
- project: z7.string().nullable(),
419
- roles: z7.array(RoleSchema),
420
- templates: z7.array(TeamTemplateSchema),
421
- problems: z7.array(DefinitionProblemSchema)
422
- }))
423
- });
424
- 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() });
425
- var SeatModelOutcomeSchema = z7.object({ role: z7.string(), session: z7.string(), when: z7.enum(["now", "turn"]).optional(), code: ModelRefusalSchema.optional() });
426
- var TeamChangedSchema = z7.object({ type: z7.literal("team.changed"), rid: z7.string(), team: TeamSchema.optional(), reason: z7.string().optional(), models: z7.array(SeatModelOutcomeSchema).max(16).optional() });
427
- var TeamsMessageSchema = z7.object({ type: z7.literal("teams"), teams: z7.array(TeamSchema) });
428
- var TeamUpdatedSchema = z7.object({ type: z7.literal("team.updated"), team: TeamSchema });
429
- var TeamLaunchedSchema = z7.object({ type: z7.literal("team.launched"), rid: z7.string(), team: TeamSchema });
430
- var TeamFailedSchema = z7.object({ type: z7.literal("team.failed"), rid: z7.string(), reason: z7.string(), team: TeamSchema.optional() });
431
- var TeamSavedSchema = z7.object({ type: z7.literal("team.saved"), rid: z7.string(), path: z7.string().optional(), reason: z7.string().optional(), code: z7.enum(["exists", "changed"]).optional() });
432
- var isTeamLive = (t) => t.state !== "dissolved";
433
-
434
159
  // ../protocol/src/tasks.ts
435
- import { z as z8 } from "zod";
160
+ import { z as z3 } from "zod";
436
161
  var TASK_TITLE_MAX = 200;
437
162
  var TASK_TEXT_MAX = 2e4;
438
163
  var LEDGE_GIVER = "ledge";
439
164
  var TASK_OPS = ["give", "take", "pass", "done", "refuse", "cancel", "drop"];
440
165
  var TRANSMISSION_OPS = ["give", "pass", "done", "refuse", "cancel"];
441
- var TaskLogEntrySchema = z8.object({
442
- at: z8.string(),
443
- by: z8.string(),
444
- what: z8.string(),
445
- op: z8.enum(TASK_OPS).optional(),
446
- from: z8.string().optional(),
447
- to: z8.string().optional(),
448
- fromName: z8.string().optional(),
449
- toName: z8.string().optional(),
450
- note: z8.string().optional()
451
- });
452
- var TaskSchema = z8.object({
453
- id: z8.string(),
454
- title: z8.string(),
455
- text: z8.string().optional(),
456
- giver: z8.string(),
457
- giverName: z8.string(),
458
- owner: z8.string(),
459
- ownerName: z8.string(),
460
- state: z8.enum(["open", "taken", "done", "refused", "dropped"]),
461
- result: z8.string().optional(),
462
- /** The live team its owner sat in when it was given (or passed), so a team's tasks can be listed. */
463
- team: z8.string().optional(),
166
+ var TaskLogEntrySchema = z3.object({
167
+ at: z3.string(),
168
+ by: z3.string(),
169
+ what: z3.string(),
170
+ op: z3.enum(TASK_OPS).optional(),
171
+ from: z3.string().optional(),
172
+ to: z3.string().optional(),
173
+ fromName: z3.string().optional(),
174
+ toName: z3.string().optional(),
175
+ note: z3.string().optional()
176
+ });
177
+ var TaskSchema = z3.object({
178
+ id: z3.string(),
179
+ title: z3.string(),
180
+ text: z3.string().optional(),
181
+ giver: z3.string(),
182
+ giverName: z3.string(),
183
+ owner: z3.string(),
184
+ ownerName: z3.string(),
185
+ state: z3.enum(["open", "taken", "done", "refused", "dropped"]),
186
+ result: z3.string().optional(),
464
187
  /** A task Ledge gave and the user put away from « À toi » once closed. */
465
- seen: z8.boolean().optional(),
466
- at: z8.string(),
467
- updatedAt: z8.string(),
468
- log: z8.array(TaskLogEntrySchema)
188
+ seen: z3.boolean().optional(),
189
+ at: z3.string(),
190
+ updatedAt: z3.string(),
191
+ log: z3.array(TaskLogEntrySchema)
469
192
  });
470
193
  var handOver = (op) => TRANSMISSION_OPS.includes(op ?? "");
471
194
  function transmissions(t) {
@@ -474,56 +197,48 @@ function transmissions(t) {
474
197
  var givenByLedge = (t) => t.giver === LEDGE_GIVER;
475
198
  var taskClosed = (t) => t.state === "done" || t.state === "refused" || t.state === "dropped";
476
199
  var openDecision = (t) => t.owner === LEDGE_GIVER && !taskClosed(t);
477
- var TaskCmdSchema = z8.object({
478
- type: z8.literal("task.cmd"),
479
- rid: z8.string().min(1),
480
- by: z8.string().min(1),
481
- op: z8.enum(["give", "take", "done", "refuse", "pass", "show", "list", "seen", "cancel"]),
482
- task: z8.string().min(1).max(40).optional(),
483
- to: z8.string().min(1).optional(),
484
- title: z8.string().min(1).max(TASK_TITLE_MAX).optional(),
485
- text: z8.string().max(TASK_TEXT_MAX).optional(),
486
- all: z8.boolean().optional(),
487
- team: z8.string().min(1).max(40).optional(),
488
- qid: z8.string().min(1).optional(),
489
- row: z8.number().int().min(0).max(7).optional()
490
- });
491
- var TaskUpdatedSchema = z8.object({ type: z8.literal("task.updated"), task: TaskSchema });
492
- var TaskResultSchema = z8.object({
493
- type: z8.literal("task.result"),
494
- rid: z8.string(),
200
+ var TaskCmdSchema = z3.object({
201
+ type: z3.literal("task.cmd"),
202
+ rid: z3.string().min(1),
203
+ by: z3.string().min(1),
204
+ op: z3.enum(["give", "take", "done", "refuse", "pass", "show", "list", "seen", "cancel"]),
205
+ task: z3.string().min(1).max(40).optional(),
206
+ to: z3.string().min(1).optional(),
207
+ title: z3.string().min(1).max(TASK_TITLE_MAX).optional(),
208
+ text: z3.string().max(TASK_TEXT_MAX).optional(),
209
+ all: z3.boolean().optional(),
210
+ qid: z3.string().min(1).optional(),
211
+ row: z3.number().int().min(0).max(7).optional()
212
+ });
213
+ var TaskUpdatedSchema = z3.object({ type: z3.literal("task.updated"), task: TaskSchema });
214
+ var TaskResultSchema = z3.object({
215
+ type: z3.literal("task.result"),
216
+ rid: z3.string(),
495
217
  task: TaskSchema.optional(),
496
- tasks: z8.array(TaskSchema).optional(),
497
- reason: z8.string().optional()
218
+ tasks: z3.array(TaskSchema).optional(),
219
+ reason: z3.string().optional()
498
220
  });
499
221
 
500
222
  // ../protocol/src/actions.ts
501
- import { z as z11 } from "zod";
223
+ import { z as z7 } from "zod";
502
224
 
503
225
  // ../protocol/src/proposal.ts
504
- import { z as z9 } from "zod";
505
- var ProposalBlockSchema = z9.object({ cwd: z9.string().trim().min(1), prompt: z9.string().optional() });
506
- var RelayBlockSchema = z9.object({ session: z9.string().trim().min(1), text: z9.string().trim().min(1) });
507
- var ProjectBlockSchema = z9.object({
508
- name: z9.string().trim().min(1).max(80),
509
- description: z9.string().max(500).optional(),
510
- repos: z9.array(z9.object({ path: z9.string().min(1).max(4096), why: z9.string().trim().min(1).max(200) })).min(1).max(50),
511
- addTo: z9.string().trim().max(80).optional()
512
- });
513
- var CloseBlockSchema = z9.object({ session: z9.string().trim().min(1) });
514
- var TeamBlockSchema = z9.object({
515
- cwd: z9.string().trim().min(1),
516
- template: z9.string().trim().min(1).max(64).optional(),
517
- name: z9.string().trim().min(1).max(60).optional(),
518
- 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()
519
- }).refine((b) => !!b.template || !!b.seats?.length, "a template or seats");
520
- var TaskBlockSchema = z9.object({
521
- to: z9.string().trim().min(1).max(80),
522
- team: z9.string().trim().max(40).optional(),
523
- title: z9.string().trim().min(1).max(200),
524
- text: z9.string().max(2e4).optional()
525
- });
526
- var BLOCK = /```ledge-(session|relay|project|close|team|task|action)[ \t]*\n?([\s\S]*?)(?:```|$)/g;
226
+ import { z as z4 } from "zod";
227
+ var ProposalBlockSchema = z4.object({ cwd: z4.string().trim().min(1), prompt: z4.string().optional() });
228
+ var RelayBlockSchema = z4.object({ session: z4.string().trim().min(1), text: z4.string().trim().min(1) });
229
+ var ProjectBlockSchema = z4.object({
230
+ name: z4.string().trim().min(1).max(80),
231
+ description: z4.string().max(500).optional(),
232
+ repos: z4.array(z4.object({ path: z4.string().min(1).max(4096), why: z4.string().trim().min(1).max(200) })).min(1).max(50),
233
+ addTo: z4.string().trim().max(80).optional()
234
+ });
235
+ var CloseBlockSchema = z4.object({ session: z4.string().trim().min(1) });
236
+ var TaskBlockSchema = z4.object({
237
+ to: z4.string().trim().min(1).max(80),
238
+ title: z4.string().trim().min(1).max(200),
239
+ text: z4.string().max(2e4).optional()
240
+ });
241
+ var BLOCK = /```ledge-(session|relay|project|close|task|action)[ \t]*\n?([\s\S]*?)(?:```|$)/g;
527
242
  function extractProposal(answer) {
528
243
  const found = [];
529
244
  const text2 = answer.replace(BLOCK, (_m, kind, body) => {
@@ -549,14 +264,6 @@ function parseCloseBlock(raw) {
549
264
  return null;
550
265
  }
551
266
  }
552
- function parseTeamBlock(raw) {
553
- try {
554
- const r = TeamBlockSchema.safeParse(JSON.parse(raw));
555
- return r.success ? r.data : null;
556
- } catch {
557
- return null;
558
- }
559
- }
560
267
  function parseTaskBlock(raw) {
561
268
  try {
562
269
  const r = TaskBlockSchema.safeParse(JSON.parse(raw));
@@ -574,9 +281,37 @@ function parseProjectBlock(raw) {
574
281
  }
575
282
  }
576
283
 
284
+ // ../protocol/src/models.ts
285
+ import { z as z5 } from "zod";
286
+ var ModelIdSchema = z5.string().min(1).max(200).regex(/^[A-Za-z0-9][A-Za-z0-9._:/@[\]=,+-]*$/, "not a model id");
287
+ var EffortSchema = z5.string().min(1).max(20).regex(/^[a-z]+$/, "not an effort");
288
+ var ModelChoiceSchema = z5.object({
289
+ id: ModelIdSchema,
290
+ label: z5.string(),
291
+ description: z5.string().optional(),
292
+ efforts: z5.array(EffortSchema).optional(),
293
+ defaultEffort: EffortSchema.optional(),
294
+ isDefault: z5.boolean().optional()
295
+ });
296
+ var ModelsListSchema = z5.object({
297
+ type: z5.literal("models.list"),
298
+ requestId: z5.string().min(1).max(100),
299
+ tool: ToolSchema,
300
+ machineId: z5.string().optional()
301
+ });
302
+ var ModelsListingSchema = z5.object({
303
+ type: z5.literal("models.listing"),
304
+ requestId: z5.string(),
305
+ tool: ToolSchema,
306
+ models: z5.array(ModelChoiceSchema),
307
+ error: z5.string().optional()
308
+ });
309
+ var ModelRefusalSchema = z5.enum(["not_launched", "ended", "no_conversation", "not_running", "effort_in_model", "restart_failed", "refused"]);
310
+ var SessionModelAcceptedSchema = z5.object({ type: z5.literal("session.model.accepted"), id: z5.string(), when: z5.enum(["now", "turn", "none"]) });
311
+
577
312
  // ../protocol/src/decisions.ts
578
- import { z as z10 } from "zod";
579
- var DecisionSchema = z10.enum(["accept", "deny", "always"]);
313
+ import { z as z6 } from "zod";
314
+ var DecisionSchema = z6.enum(["accept", "deny", "always"]);
580
315
  var NOTE_MAX = 4e3;
581
316
  var NOTE_NOT_TYPED = "note_not_typed";
582
317
  var DECISION_OFFERS = {
@@ -606,13 +341,12 @@ function pendingKey(p) {
606
341
  }
607
342
 
608
343
  // ../protocol/src/actions.ts
609
- var ActionRiskSchema = z11.enum(["read", "reversible", "destructive"]);
344
+ var ActionRiskSchema = z7.enum(["read", "reversible", "destructive"]);
610
345
  var ACTION_IDS = [
611
346
  "session.launch",
612
347
  "session.relay",
613
348
  "session.close",
614
349
  "project.propose",
615
- "team.launch",
616
350
  "task.give",
617
351
  "session.model",
618
352
  "session.interrupt",
@@ -620,20 +354,14 @@ var ACTION_IDS = [
620
354
  "session.restore",
621
355
  "session.resume",
622
356
  "session.decide",
623
- "team.join",
624
- "team.leave",
625
- "team.resume",
626
- "team.dissolve",
627
- "team.save",
628
357
  "task.cancel",
629
358
  "task.pass",
630
359
  "task.answer"
631
360
  ];
632
- var ActionIdSchema = z11.enum(ACTION_IDS);
361
+ var ActionIdSchema = z7.enum(ACTION_IDS);
633
362
  var def = (d) => d;
634
- var SessionRef = z11.string().trim().min(1).max(80);
635
- var TeamRef = z11.string().trim().min(1).max(60);
636
- var TaskRef = z11.string().trim().min(1).max(40);
363
+ var SessionRef = z7.string().trim().min(1).max(80);
364
+ var TaskRef = z7.string().trim().min(1).max(40);
637
365
  var LaunchArgs = ProposalBlockSchema.extend({ model: ModelIdSchema.optional(), effort: EffortSchema.optional() });
638
366
  var ACTIONS = [
639
367
  def({
@@ -681,18 +409,6 @@ var ACTIONS = [
681
409
  when: "seulement si l'utilisateur demande explicitement de cr\xE9er ou de compl\xE9ter un projet : lis projects.md, ne cite que des chemins absolus lus dans sessions.md, folders.md ou projects.md, jamais un d\xE9p\xF4t qui appartient d\xE9j\xE0 \xE0 un projet ; ta r\xE9ponse dit le nom, chaque d\xE9p\xF4t et pourquoi",
682
410
  example: { name: "Facturation", description: "Le service et son front", repos: [{ path: "/home/alice/projets/billing-api", why: "le service" }] }
683
411
  }),
684
- def({
685
- id: "team.launch",
686
- args: TeamBlockSchema,
687
- card: "team",
688
- phone: "launch",
689
- risk: "reversible",
690
- max: 1,
691
- cli: "ledge team up <mod\xE8le> --cwd <dossier>",
692
- summary: "monter une \xE9quipe dans un dossier : un mod\xE8le de teams.md (template), ou des si\xE8ges (r\xF4le de roles.md, agent, et si demand\xE9 model, effort)",
693
- when: "quand l'utilisateur demande explicitement de monter, lancer ou composer une \xE9quipe, avec la m\xEAme r\xE8gle de dossier s\xFBr qu'une session ; 8 si\xE8ges au plus, un r\xF4le une seule fois, seulement des r\xF4les de roles.md disponibles dans ce dossier (s'il en manque un, dis lequel et le fichier \xE0 \xE9crire, ~/.ledge/roles/<id>.md). Ne choisis jamais l'autonomie : c'est celle du r\xF4le",
694
- example: { cwd: "/home/alice/projets/api", name: "api", seats: [{ role: "dev-back", tool: "claude" }, { role: "rev-back", tool: "codex" }] }
695
- }),
696
412
  def({
697
413
  id: "task.give",
698
414
  args: TaskBlockSchema,
@@ -700,10 +416,10 @@ var ACTIONS = [
700
416
  phone: null,
701
417
  risk: "reversible",
702
418
  max: 8,
703
- cli: 'ledge task give <session|@r\xF4le> "<titre>" "<d\xE9tail>"',
704
- summary: "confier une t\xE2che \xE0 une session, ou \xE0 un @r\xF4le d'une \xE9quipe (team : son id dans teams.md ; sans team, un si\xE8ge de l'\xE9quipe propos\xE9e dans la m\xEAme r\xE9ponse)",
705
- when: "quand l'utilisateur demande explicitement de confier une t\xE2che, ou juste apr\xE8s team.launch quand il a dit ce que l'\xE9quipe doit faire. Une fois l'\xE9quipe lanc\xE9e, ne propose rien pour ce que les si\xE8ges se confient entre eux",
706
- example: { to: "@dev-back", title: "Pagination de /invoices", text: "Ajoute la pagination par curseur et ses tests" }
419
+ cli: 'ledge task give <session> "<titre>" "<d\xE9tail>"',
420
+ summary: "confier une t\xE2che \xE0 une session (son id ou son nom, tels que sessions.md les donne)",
421
+ when: "quand l'utilisateur demande explicitement de confier une t\xE2che \xE0 une session ; ne propose rien pour ce que les sessions se confient entre elles",
422
+ example: { to: "Nova", title: "Pagination de /invoices", text: "Ajoute la pagination par curseur et ses tests" }
707
423
  }),
708
424
  def({
709
425
  id: "session.model",
@@ -711,14 +427,14 @@ var ACTIONS = [
711
427
  phone: null,
712
428
  risk: "reversible",
713
429
  max: 8,
714
- args: z11.object({ session: SessionRef, model: ModelIdSchema.nullable(), effort: EffortSchema.nullable() }),
430
+ args: z7.object({ session: SessionRef, model: ModelIdSchema.nullable(), effort: EffortSchema.nullable() }),
715
431
  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",
716
432
  when: "quand l'utilisateur demande de passer une session sur un autre mod\xE8le ou un autre effort",
717
433
  example: { session: "Nova", model: "claude-opus-5-5", effort: "high" }
718
434
  }),
719
435
  def({
720
436
  id: "session.interrupt",
721
- args: z11.object({ session: SessionRef }),
437
+ args: z7.object({ session: SessionRef }),
722
438
  card: "generic",
723
439
  phone: null,
724
440
  risk: "reversible",
@@ -729,7 +445,7 @@ var ACTIONS = [
729
445
  }),
730
446
  def({
731
447
  id: "session.archive",
732
- args: z11.object({ session: SessionRef }),
448
+ args: z7.object({ session: SessionRef }),
733
449
  card: "generic",
734
450
  phone: null,
735
451
  risk: "reversible",
@@ -740,7 +456,7 @@ var ACTIONS = [
740
456
  }),
741
457
  def({
742
458
  id: "session.restore",
743
- args: z11.object({ session: SessionRef }),
459
+ args: z7.object({ session: SessionRef }),
744
460
  card: "generic",
745
461
  phone: null,
746
462
  risk: "reversible",
@@ -751,7 +467,7 @@ var ACTIONS = [
751
467
  }),
752
468
  def({
753
469
  id: "session.resume",
754
- args: z11.object({ session: SessionRef }),
470
+ args: z7.object({ session: SessionRef }),
755
471
  card: "generic",
756
472
  phone: "act",
757
473
  risk: "reversible",
@@ -765,71 +481,15 @@ var ACTIONS = [
765
481
  card: "generic",
766
482
  phone: "act",
767
483
  max: 1,
768
- args: z11.object({ session: SessionRef, decision: z11.enum(["accept", "deny"]), note: z11.string().trim().min(1).max(NOTE_MAX).optional() }),
484
+ args: z7.object({ session: SessionRef, decision: z7.enum(["accept", "deny"]), note: z7.string().trim().min(1).max(NOTE_MAX).optional() }),
769
485
  risk: (a) => a.decision === "accept" ? "destructive" : "reversible",
770
486
  summary: "accepter ou refuser la demande en attente d'une session (permission, diff ou plan), note possible avec un refus ; jamais \xAB toujours \xBB",
771
487
  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",
772
488
  example: { session: "Nova", decision: "deny", note: "Pas sur main : cr\xE9e une branche" }
773
489
  }),
774
- def({
775
- id: "team.join",
776
- args: z11.object({ team: TeamRef, session: SessionRef, role: RoleIdSchema }),
777
- card: "generic",
778
- phone: null,
779
- risk: "reversible",
780
- max: 8,
781
- summary: "faire entrer une session dans une \xE9quipe en cours, \xE0 un r\xF4le de roles.md",
782
- when: "quand l'utilisateur demande d'ajouter une session existante \xE0 une \xE9quipe",
783
- example: { team: "team-3fa2", session: "Nova", role: "dev-back" }
784
- }),
785
- def({
786
- id: "team.leave",
787
- args: z11.object({ team: TeamRef, session: SessionRef }),
788
- card: "generic",
789
- phone: null,
790
- risk: "reversible",
791
- max: 8,
792
- summary: "faire sortir une session d'une \xE9quipe (la session continue)",
793
- when: "quand l'utilisateur demande de retirer une session d'une \xE9quipe",
794
- example: { team: "team-3fa2", session: "Nova" }
795
- }),
796
- def({
797
- id: "team.resume",
798
- args: z11.object({ team: TeamRef }),
799
- card: "generic",
800
- phone: "act",
801
- risk: "reversible",
802
- max: 1,
803
- summary: "reprendre une \xE9quipe au repos : chaque si\xE8ge reprend sa conversation",
804
- when: "quand l'utilisateur demande de reprendre ou relancer une \xE9quipe au repos",
805
- example: { team: "team-3fa2" }
806
- }),
807
- def({
808
- id: "team.dissolve",
809
- args: z11.object({ team: TeamRef }),
810
- card: "generic",
811
- phone: "act",
812
- risk: "destructive",
813
- max: 8,
814
- cli: "ledge team dissolve <\xE9quipe>",
815
- summary: "dissoudre une \xE9quipe : elle dispara\xEEt, ses sessions restent ; irr\xE9versible",
816
- when: "seulement quand l'utilisateur demande explicitement de dissoudre une \xE9quipe pr\xE9cise",
817
- example: { team: "team-3fa2" }
818
- }),
819
- def({
820
- id: "team.save",
821
- args: z11.object({ team: TeamRef, name: TeamNameSchema }),
822
- card: "generic",
823
- phone: null,
824
- risk: "reversible",
825
- max: 1,
826
- summary: "enregistrer une \xE9quipe en cours comme mod\xE8le (~/.ledge/teams/<nom>.yaml)",
827
- when: "quand l'utilisateur demande d'enregistrer ou de garder la composition d'une \xE9quipe",
828
- example: { team: "team-3fa2", name: "api" }
829
- }),
830
490
  def({
831
491
  id: "task.cancel",
832
- args: z11.object({ task: TaskRef, reason: z11.string().trim().min(1).max(500).optional() }),
492
+ args: z7.object({ task: TaskRef, reason: z7.string().trim().min(1).max(500).optional() }),
833
493
  card: "generic",
834
494
  phone: "act",
835
495
  risk: "destructive",
@@ -840,7 +500,7 @@ var ACTIONS = [
840
500
  }),
841
501
  def({
842
502
  id: "task.pass",
843
- args: z11.object({ task: TaskRef, to: SessionRef, note: z11.string().trim().min(1).max(TASK_TEXT_MAX).optional() }),
503
+ args: z7.object({ task: TaskRef, to: SessionRef, note: z7.string().trim().min(1).max(TASK_TEXT_MAX).optional() }),
844
504
  card: "generic",
845
505
  phone: null,
846
506
  risk: "reversible",
@@ -851,7 +511,7 @@ var ACTIONS = [
851
511
  }),
852
512
  def({
853
513
  id: "task.answer",
854
- args: z11.object({ task: TaskRef, answer: z11.string().trim().min(1).max(TASK_TEXT_MAX) }),
514
+ args: z7.object({ task: TaskRef, answer: z7.string().trim().min(1).max(TASK_TEXT_MAX) }),
855
515
  card: "generic",
856
516
  phone: "act",
857
517
  risk: "destructive",
@@ -864,13 +524,12 @@ var ACTIONS = [
864
524
  var byId = new Map(ACTIONS.map((a) => [a.id, a]));
865
525
  var actionById = (id) => byId.get(id);
866
526
  var riskOf = (a, args) => typeof a.risk === "function" ? a.risk(args) : a.risk;
867
- var ActionBlockSchema = z11.object({ action: z11.string().trim().min(1).max(40), args: z11.record(z11.unknown()).default({}) });
527
+ var ActionBlockSchema = z7.object({ action: z7.string().trim().min(1).max(40), args: z7.record(z7.unknown()).default({}) });
868
528
  var LEGACY_FENCE_ACTION = {
869
529
  session: "session.launch",
870
530
  relay: "session.relay",
871
531
  close: "session.close",
872
532
  project: "project.propose",
873
- team: "team.launch",
874
533
  task: "task.give"
875
534
  };
876
535
  function parseActionBlock(kind, raw) {
@@ -906,126 +565,345 @@ var NEVER_PROPOSED = [
906
565
  "r\xE9pondre \xAB toujours \xBB \xE0 une demande, ou r\xE9pondre aux questions \xE0 choix d'OMP"
907
566
  ];
908
567
 
568
+ // ../protocol/src/openrig.ts
569
+ import { z as z8 } from "zod";
570
+ var RigNameSchema = z8.string().min(1).max(100).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "not a rig name");
571
+ var RigSeatNameSchema = z8.string().min(3).max(200).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*@[A-Za-z0-9][A-Za-z0-9._-]*$/, "not a seat");
572
+ var SeatPermissionsSchema = z8.enum(["inherit", "floor", "auto", "full_bypass"]);
573
+ var KERNEL_RIG = "kernel";
574
+ var RigSeatSchema = z8.object({
575
+ logicalId: z8.string(),
576
+ session: z8.string(),
577
+ runtime: z8.string(),
578
+ model: z8.string().nullable(),
579
+ sessionStatus: z8.string(),
580
+ lifecycleState: z8.string(),
581
+ activity: z8.string(),
582
+ stopped: z8.boolean(),
583
+ work: z8.number().int().min(0)
584
+ });
585
+ var RigSchema = z8.object({
586
+ id: z8.string(),
587
+ name: z8.string(),
588
+ status: z8.string(),
589
+ lifecycleState: z8.string(),
590
+ seats: z8.number().int().min(0),
591
+ running: z8.number().int().min(0),
592
+ attention: z8.number().int().min(0),
593
+ uptime: z8.string().nullable(),
594
+ snapshot: z8.string().nullable(),
595
+ nodes: z8.array(RigSeatSchema)
596
+ });
597
+ var RigDaemonStateSchema = z8.enum(["running", "stopped", "stale", "unknown"]);
598
+ var RigKernelStateSchema = z8.enum(["ready", "starting", "stopped", "skipped", "absent", "unknown"]);
599
+ var OpenRigStateSchema = z8.object({
600
+ installed: z8.boolean(),
601
+ version: z8.string().optional(),
602
+ daemon: z8.object({ state: RigDaemonStateSchema, pid: z8.number().int().optional(), port: z8.number().int().optional(), message: z8.string().optional() }),
603
+ kernel: z8.object({ state: RigKernelStateSchema }),
604
+ rigs: z8.array(RigSchema),
605
+ /** When it was read (ISO). */
606
+ at: z8.string()
607
+ });
608
+ var OpenRigActionSchema = z8.discriminatedUnion("kind", [
609
+ /** `restore` `last`: `rig start --last` (the rigs that were running come back); `none`: `rig daemon start`. */
610
+ z8.object({ kind: z8.literal("daemon.start"), restore: z8.enum(["last", "none"]).optional(), noKernel: z8.boolean().optional() }),
611
+ z8.object({ kind: z8.literal("daemon.stop") }),
612
+ z8.object({ kind: z8.literal("daemon.restart"), restore: z8.enum(["last", "none"]).optional() }),
613
+ z8.object({ kind: z8.literal("kernel.start") }),
614
+ z8.object({ kind: z8.literal("kernel.stop") }),
615
+ z8.object({ kind: z8.literal("kernel.restart") }),
616
+ z8.object({ kind: z8.literal("rig.start"), rig: RigNameSchema }),
617
+ z8.object({ kind: z8.literal("rig.stop"), rig: RigNameSchema, snapshot: z8.boolean().optional(), force: z8.boolean().optional(), delete: z8.boolean().optional() }),
618
+ z8.object({ kind: z8.literal("rig.restart"), rig: RigNameSchema }),
619
+ /** A seat's settings (docs/mockups/ledge-openrig-groups.html, view 2). `runtime`: moves it now to the other harness (a successor
620
+ * takes its context, `rig seat set-runtime`), `model` and `effort` going with it; without it, `model`, `effort` and `permissions`
621
+ * apply at its next resume. `dryRun`: the move's plan only. */
622
+ z8.object({
623
+ kind: z8.literal("seat.set"),
624
+ seat: RigSeatNameSchema,
625
+ runtime: z8.enum(["claude-code", "codex"]).optional(),
626
+ model: ModelIdSchema.optional(),
627
+ effort: EffortSchema.optional(),
628
+ permissions: SeatPermissionsSchema.optional(),
629
+ dryRun: z8.boolean().optional()
630
+ })
631
+ ]);
632
+ var OpenRigStatusSchema = z8.object({ type: z8.literal("openrig.status"), requestId: z8.string().min(1).max(100), machineId: z8.string().optional() });
633
+ var OpenRigActSchema = z8.object({ type: z8.literal("openrig.act"), requestId: z8.string().min(1).max(100), action: OpenRigActionSchema, machineId: z8.string().optional() });
634
+ var OpenRigUnreachableSchema = z8.enum(["offline", "outdated"]);
635
+ var OpenRigStateMessageSchema = z8.object({
636
+ type: z8.literal("openrig.state"),
637
+ requestId: z8.string().optional(),
638
+ machineId: z8.string().optional(),
639
+ state: OpenRigStateSchema.optional(),
640
+ error: OpenRigUnreachableSchema.optional()
641
+ });
642
+ var OpenRigDoneSchema = z8.object({
643
+ type: z8.literal("openrig.done"),
644
+ requestId: z8.string(),
645
+ machineId: z8.string().optional(),
646
+ ok: z8.boolean(),
647
+ commands: z8.array(z8.string()),
648
+ output: z8.string().optional(),
649
+ error: z8.string().optional()
650
+ });
651
+ function rigCommands(a) {
652
+ const start = (restore, noKernel) => restore === "last" ? ["start", "--last", "--json"] : ["daemon", "start", ...noKernel ? ["--no-kernel"] : []];
653
+ const up = (rig) => ["up", rig, "--existing", "--yes", "--json"];
654
+ const down = (rig, o = {}) => ["down", rig, ...o.snapshot ? ["--snapshot"] : [], ...o.force ? ["--force"] : [], ...o.delete ? ["--delete"] : [], "--json"];
655
+ switch (a.kind) {
656
+ case "daemon.start":
657
+ return [start(a.restore, a.noKernel)];
658
+ case "daemon.stop":
659
+ return [["daemon", "stop"]];
660
+ case "daemon.restart":
661
+ return [["daemon", "stop"], start(a.restore)];
662
+ case "kernel.start":
663
+ return [up(KERNEL_RIG)];
664
+ case "kernel.stop":
665
+ return [down(KERNEL_RIG)];
666
+ case "kernel.restart":
667
+ return [down(KERNEL_RIG, { snapshot: true }), up(KERNEL_RIG)];
668
+ case "rig.start":
669
+ return [up(a.rig)];
670
+ case "rig.stop":
671
+ return [down(a.rig, a)];
672
+ case "rig.restart":
673
+ return [down(a.rig, { snapshot: true }), up(a.rig)];
674
+ case "seat.set": {
675
+ const why = ["--reason", "Ledge"];
676
+ if (a.runtime) return [[
677
+ "seat",
678
+ "set-runtime",
679
+ a.seat,
680
+ "--runtime",
681
+ a.runtime,
682
+ ...a.model ? ["--model", a.model] : [],
683
+ ...a.effort ? ["--effort", a.effort] : [],
684
+ ...a.permissions && a.permissions !== "inherit" ? ["--permission-mode", a.permissions] : [],
685
+ ...a.dryRun ? ["--dry-run"] : [],
686
+ ...why
687
+ ]];
688
+ return [
689
+ ...a.model ? [["seat", "set-model", a.seat, "--model", a.model, ...why, "--json"]] : [],
690
+ ...a.effort ? [["seat", "set-effort", a.seat, "--effort", a.effort, ...why, "--json"]] : [],
691
+ ...a.permissions ? [["seat", "set-permissions", a.seat, "--mode", a.permissions, ...why, "--json"]] : []
692
+ ];
693
+ }
694
+ }
695
+ }
696
+ var showRigCommand = (args) => ["rig", ...args.filter((x) => x !== "--json")].join(" ");
697
+ var RigSpecMemberSchema = z8.object({
698
+ id: z8.string(),
699
+ runtime: z8.string(),
700
+ model: z8.string().optional(),
701
+ agent: z8.string(),
702
+ /** Its `permission_policy`, as written. */
703
+ policy: z8.string().optional()
704
+ });
705
+ var RigSpecPodSchema = z8.object({ id: z8.string(), label: z8.string().optional(), members: z8.array(RigSpecMemberSchema) });
706
+ var RigSpecSchema = z8.object({
707
+ name: z8.string(),
708
+ source: z8.string(),
709
+ summary: z8.string().optional(),
710
+ path: z8.string(),
711
+ /** The rig's `permission_policy`, as written (`builtin:auto`, a file…). */
712
+ policy: z8.string().optional(),
713
+ pods: z8.array(RigSpecPodSchema),
714
+ edges: z8.number().int().min(0)
715
+ });
716
+ var OpenRigSpecsSchema = z8.object({ type: z8.literal("openrig.specs"), requestId: z8.string().min(1).max(100), machineId: z8.string().optional() });
717
+ var OpenRigSpecListSchema = z8.object({
718
+ type: z8.literal("openrig.specList"),
719
+ requestId: z8.string(),
720
+ machineId: z8.string().optional(),
721
+ specs: z8.array(RigSpecSchema),
722
+ error: z8.string().optional()
723
+ });
724
+ var RigRoleSchema = z8.string().min(3).max(201).regex(/^[A-Za-z0-9][A-Za-z0-9_-]*\.[A-Za-z0-9][A-Za-z0-9_-]*$/, "not a role");
725
+ var RuntimeSchema = z8.enum(["claude-code", "codex"]);
726
+ var RigPolicySchema = z8.enum(["auto", "standard", "open", "yolo", "locked"]);
727
+ var RIG_POLICIES = RigPolicySchema.options;
728
+ var RigLaunchSchema = z8.object({
729
+ spec: RigNameSchema,
730
+ cwd: z8.string().min(1).max(4096),
731
+ name: RigNameSchema,
732
+ seats: z8.record(RigRoleSchema, z8.number().int().min(0).max(9)).optional(),
733
+ runtimes: z8.record(RigRoleSchema, RuntimeSchema).optional(),
734
+ models: z8.record(RigRoleSchema, z8.string().min(1).max(200).regex(/^[A-Za-z0-9][A-Za-z0-9._:/@[\]=,+-]*$/)).optional(),
735
+ delegation: z8.enum(["pairs", "all"]).optional(),
736
+ save: z8.boolean().optional(),
737
+ plan: z8.boolean().optional(),
738
+ /** The rig's permission policy, in place of the spec's; `policies`: a role's, over the rig's. */
739
+ policy: RigPolicySchema.optional(),
740
+ policies: z8.record(RigRoleSchema, RigPolicySchema).optional(),
741
+ /** Accept the harnesses' first-launch warnings (`rig up --non-interruptive`), so a bypassing seat does not stop on Claude's dialog. */
742
+ nonInterruptive: z8.boolean().optional()
743
+ });
744
+ var OpenRigLaunchSchema = z8.object({ type: z8.literal("openrig.launch"), requestId: z8.string().min(1).max(100), launch: RigLaunchSchema, machineId: z8.string().optional() });
745
+ var OpenRigLaunchedSchema = z8.object({
746
+ type: z8.literal("openrig.launched"),
747
+ requestId: z8.string(),
748
+ machineId: z8.string().optional(),
749
+ ok: z8.boolean(),
750
+ plan: z8.boolean(),
751
+ commands: z8.array(z8.string()),
752
+ yaml: z8.string().optional(),
753
+ seats: z8.number().int().optional(),
754
+ output: z8.string().optional(),
755
+ error: z8.string().optional(),
756
+ /** What `rig up --plan` concluded: its status (`planned`…), its errors and its warnings (one per seat without a permission policy…). */
757
+ check: z8.object({ status: z8.string(), errors: z8.array(z8.string()), warnings: z8.array(z8.string()) }).optional()
758
+ });
759
+ var roleOf = (logicalId) => logicalId.replace(/-\d+$/, "");
760
+ var copyOf = (logicalId) => {
761
+ const m = /-(\d+)$/.exec(logicalId);
762
+ return m ? Number(m[1]) : 1;
763
+ };
764
+ function seatsByRole(nodes) {
765
+ const out = /* @__PURE__ */ new Map();
766
+ for (const n of nodes) out.set(roleOf(n.logicalId), [...out.get(roleOf(n.logicalId)) ?? [], n.logicalId]);
767
+ for (const [role, ids] of out) out.set(role, ids.sort((a, b) => copyOf(a) - copyOf(b)));
768
+ return out;
769
+ }
770
+ function seatPlan(nodes, seats) {
771
+ const by = seatsByRole(nodes);
772
+ const add = [], remove = [];
773
+ for (const [role, want] of Object.entries(seats)) {
774
+ const have = by.get(role) ?? [];
775
+ if (have.length === 0) continue;
776
+ if (want < have.length) {
777
+ remove.push(...have.slice(want).reverse());
778
+ continue;
779
+ }
780
+ const [pod, member] = role.split(".");
781
+ let next = Math.max(...have.map(copyOf));
782
+ for (let i = have.length; i < want; i++) add.push({ role, pod, id: `${member}-${++next}`, from: have[0] });
783
+ }
784
+ return { add, remove };
785
+ }
786
+ var OpenRigSeatsSchema = z8.object({
787
+ type: z8.literal("openrig.seats"),
788
+ requestId: z8.string().min(1).max(100),
789
+ machineId: z8.string().optional(),
790
+ rig: RigNameSchema,
791
+ seats: z8.record(RigRoleSchema, z8.number().int().min(0).max(9)),
792
+ /** How the added seats are linked, where OpenRig can add links to a running rig (0.7+): like a launch's. */
793
+ delegation: z8.enum(["pairs", "all"]).optional()
794
+ });
795
+ var OpenRigReseatedSchema = z8.object({
796
+ type: z8.literal("openrig.reseated"),
797
+ requestId: z8.string(),
798
+ machineId: z8.string().optional(),
799
+ ok: z8.boolean(),
800
+ commands: z8.array(z8.string()),
801
+ added: z8.array(z8.string()),
802
+ removed: z8.array(z8.string()),
803
+ output: z8.string().optional(),
804
+ error: z8.string().optional(),
805
+ /** The links ensured between the seats; `linksUnsupported`: this OpenRig cannot add links to a running rig (before 0.7). */
806
+ links: z8.number().int().optional(),
807
+ linksUnsupported: z8.boolean().optional()
808
+ });
809
+
909
810
  // ../protocol/src/messages.ts
910
811
  import { z as z21 } from "zod";
911
812
 
912
813
  // ../protocol/src/chat.ts
913
- import { z as z13 } from "zod";
814
+ import { z as z10 } from "zod";
914
815
 
915
816
  // ../protocol/src/attachments.ts
916
- import { z as z12 } from "zod";
817
+ import { z as z9 } from "zod";
917
818
  var ATTACHMENT_ID = /^[0-9a-f]{64}$/;
918
- var AttachmentIdSchema = z12.string().regex(ATTACHMENT_ID);
819
+ var AttachmentIdSchema = z9.string().regex(ATTACHMENT_ID);
919
820
  var IMAGE_MIMES = ["image/webp", "image/jpeg", "image/png", "image/gif"];
920
- var ImageMimeSchema = z12.enum(IMAGE_MIMES);
821
+ var ImageMimeSchema = z9.enum(IMAGE_MIMES);
921
822
  var ATTACHMENT_MAX = 4e5;
922
823
  var ATTACHMENT_LOCAL_MAX = 2e6;
923
824
  var PREVIEW_MAX = 4e4;
924
825
  var ATTACHMENTS_MAX = 5;
925
826
  var b64Max = (bytes) => Math.ceil(bytes / 3) * 4;
926
- var AttachmentRefSchema = z12.object({
827
+ var AttachmentRefSchema = z9.object({
927
828
  id: AttachmentIdSchema,
928
829
  mime: ImageMimeSchema,
929
- width: z12.number().int().positive(),
930
- height: z12.number().int().positive(),
931
- bytes: z12.number().int().positive(),
932
- preview: z12.boolean()
830
+ width: z9.number().int().positive(),
831
+ height: z9.number().int().positive(),
832
+ bytes: z9.number().int().positive(),
833
+ preview: z9.boolean()
933
834
  });
934
- var ImageUploadSchema = z12.object({
835
+ var ImageUploadSchema = z9.object({
935
836
  mime: ImageMimeSchema,
936
- data: z12.string().min(1).max(b64Max(ATTACHMENT_LOCAL_MAX)),
937
- preview: z12.object({ mime: ImageMimeSchema, data: z12.string().min(1).max(b64Max(PREVIEW_MAX)) }).optional()
938
- });
939
- var AttachmentErrorReasonSchema = z12.enum(["too_large", "not_image", "unreadable", "not_found", "offline"]);
940
- var requestId = z12.string().min(1).max(100);
941
- var AttachmentPutSchema = z12.object({ type: z12.literal("attachment.put"), requestId, id: z12.string().optional(), image: ImageUploadSchema });
942
- var AttachmentGetSchema = z12.object({ type: z12.literal("attachment.get"), requestId, attachment: AttachmentIdSchema, preview: z12.boolean().optional(), id: z12.string().optional(), machine: z12.string().optional() });
943
- var AttachmentStoredSchema = z12.object({ type: z12.literal("attachment.stored"), requestId, ref: AttachmentRefSchema });
944
- var AttachmentDataSchema = z12.object({ type: z12.literal("attachment.data"), requestId, attachment: AttachmentIdSchema, mime: ImageMimeSchema, data: z12.string() });
945
- var AttachmentErrorSchema = z12.object({ type: z12.literal("attachment.error"), requestId, reason: AttachmentErrorReasonSchema });
837
+ data: z9.string().min(1).max(b64Max(ATTACHMENT_LOCAL_MAX)),
838
+ preview: z9.object({ mime: ImageMimeSchema, data: z9.string().min(1).max(b64Max(PREVIEW_MAX)) }).optional()
839
+ });
840
+ var AttachmentErrorReasonSchema = z9.enum(["too_large", "not_image", "unreadable", "not_found", "offline"]);
841
+ var requestId = z9.string().min(1).max(100);
842
+ var AttachmentPutSchema = z9.object({ type: z9.literal("attachment.put"), requestId, id: z9.string().optional(), image: ImageUploadSchema });
843
+ var AttachmentGetSchema = z9.object({ type: z9.literal("attachment.get"), requestId, attachment: AttachmentIdSchema, preview: z9.boolean().optional(), id: z9.string().optional(), machine: z9.string().optional() });
844
+ var AttachmentStoredSchema = z9.object({ type: z9.literal("attachment.stored"), requestId, ref: AttachmentRefSchema });
845
+ var AttachmentDataSchema = z9.object({ type: z9.literal("attachment.data"), requestId, attachment: AttachmentIdSchema, mime: ImageMimeSchema, data: z9.string() });
846
+ var AttachmentErrorSchema = z9.object({ type: z9.literal("attachment.error"), requestId, reason: AttachmentErrorReasonSchema });
946
847
 
947
848
  // ../protocol/src/chat.ts
948
- var ChatStepSchema = z13.object({
949
- kind: z13.enum(["sessions", "pane", "reply", "git", "repo"]),
950
- id: z13.string().optional(),
951
- name: z13.string().optional(),
952
- path: z13.string().optional()
953
- });
954
- var ChatProposalSchema = z13.object({
955
- cwd: z13.string().min(1),
956
- project: z13.string(),
957
- prompt: z13.string().optional(),
849
+ var ChatStepSchema = z10.object({
850
+ kind: z10.enum(["sessions", "pane", "reply", "git", "repo"]),
851
+ id: z10.string().optional(),
852
+ name: z10.string().optional(),
853
+ path: z10.string().optional()
854
+ });
855
+ var ChatProposalSchema = z10.object({
856
+ cwd: z10.string().min(1),
857
+ project: z10.string(),
858
+ prompt: z10.string().optional(),
958
859
  tool: ToolSchema,
959
860
  /** What Ledge proposed on the card's picker (spec 2026-10-26 action registry §4), the agent's own default when left out. */
960
861
  model: ModelIdSchema.optional(),
961
862
  effort: EffortSchema.optional(),
962
- launchedId: z13.string().optional(),
963
- error: z13.string().optional()
863
+ launchedId: z10.string().optional(),
864
+ error: z10.string().optional()
964
865
  });
965
866
  var MAX_PROPOSALS = 8;
966
- var ChatProposalsSchema = z13.array(ChatProposalSchema).min(1).max(MAX_PROPOSALS);
967
- var ChatRelaySchema = z13.object({
968
- id: z13.string().min(1),
969
- name: z13.string(),
867
+ var ChatProposalsSchema = z10.array(ChatProposalSchema).min(1).max(MAX_PROPOSALS);
868
+ var ChatRelaySchema = z10.object({
869
+ id: z10.string().min(1),
870
+ name: z10.string(),
970
871
  tool: ToolSchema,
971
- text: z13.string().min(1),
972
- status: z13.enum(["queued", "sent"]).optional(),
973
- sentAt: z13.string().datetime().optional(),
974
- error: z13.string().optional(),
872
+ text: z10.string().min(1),
873
+ status: z10.enum(["queued", "sent"]).optional(),
874
+ sentAt: z10.string().datetime().optional(),
875
+ error: z10.string().optional(),
975
876
  /** Why it failed, as a code a front words itself (a RefusalCode, `ended`, or `failed` for the machinery); goes with `error`. */
976
- code: z13.string().max(40).optional()
877
+ code: z10.string().max(40).optional()
977
878
  });
978
- var ChatCloseSchema = z13.object({
979
- id: z13.string().min(1),
980
- name: z13.string(),
981
- tool: ToolSchema,
982
- closedAt: z13.string().datetime().optional(),
983
- how: z13.enum(["exit", "killed"]).optional(),
984
- error: z13.string().optional()
985
- });
986
- var ChatClosesSchema = z13.array(ChatCloseSchema).min(1).max(MAX_PROPOSALS);
987
- var ChatProjectProposalSchema = z13.object({
988
- name: z13.string().min(1).max(80),
989
- description: z13.string().max(500).optional(),
990
- repos: z13.array(z13.object({ path: z13.string().min(1).max(4096), why: z13.string().min(1).max(200) })).min(1).max(50),
991
- addTo: z13.string().min(1).max(80).optional()
992
- });
993
- var ChatTeamSeatSchema = z13.object({
994
- role: z13.string().min(1),
995
- label: z13.string(),
879
+ var ChatCloseSchema = z10.object({
880
+ id: z10.string().min(1),
881
+ name: z10.string(),
996
882
  tool: ToolSchema,
997
- model: z13.string().optional(),
998
- effort: z13.string().optional(),
999
- autonomy: AutonomySchema.optional(),
1000
- name: z13.string().optional()
1001
- });
1002
- var ChatTeamProposalSchema = z13.object({
1003
- cwd: z13.string().min(1),
1004
- project: z13.string(),
1005
- projectName: z13.string().optional(),
1006
- name: z13.string().min(1),
1007
- template: z13.string().optional(),
1008
- seats: z13.array(ChatTeamSeatSchema).min(1).max(8),
1009
- teamId: z13.string().optional(),
1010
- launchedAt: z13.string().datetime().optional(),
1011
- error: z13.string().optional(),
1012
- savedPath: z13.string().optional(),
1013
- saveError: z13.string().optional()
1014
- });
1015
- var ChatTaskProposalSchema = z13.object({
1016
- to: z13.string().min(1),
1017
- toName: z13.string().optional(),
1018
- team: z13.string().optional(),
1019
- title: z13.string().min(1).max(200),
1020
- text: z13.string().max(2e4).optional(),
1021
- taskId: z13.string().optional(),
1022
- ownerName: z13.string().optional(),
1023
- state: z13.enum(["open", "taken", "done", "refused", "dropped"]).optional(),
1024
- givenAt: z13.string().datetime().optional(),
1025
- error: z13.string().optional()
1026
- });
1027
- var ChatTasksSchema = z13.array(ChatTaskProposalSchema).min(1).max(MAX_PROPOSALS);
1028
- var ActionVarsSchema = z13.record(z13.string().max(40), z13.string().max(300));
883
+ closedAt: z10.string().datetime().optional(),
884
+ how: z10.enum(["exit", "killed"]).optional(),
885
+ error: z10.string().optional()
886
+ });
887
+ var ChatClosesSchema = z10.array(ChatCloseSchema).min(1).max(MAX_PROPOSALS);
888
+ var ChatProjectProposalSchema = z10.object({
889
+ name: z10.string().min(1).max(80),
890
+ description: z10.string().max(500).optional(),
891
+ repos: z10.array(z10.object({ path: z10.string().min(1).max(4096), why: z10.string().min(1).max(200) })).min(1).max(50),
892
+ addTo: z10.string().min(1).max(80).optional()
893
+ });
894
+ var ChatTaskProposalSchema = z10.object({
895
+ to: z10.string().min(1),
896
+ toName: z10.string().optional(),
897
+ title: z10.string().min(1).max(200),
898
+ text: z10.string().max(2e4).optional(),
899
+ taskId: z10.string().optional(),
900
+ ownerName: z10.string().optional(),
901
+ state: z10.enum(["open", "taken", "done", "refused", "dropped"]).optional(),
902
+ givenAt: z10.string().datetime().optional(),
903
+ error: z10.string().optional()
904
+ });
905
+ var ChatTasksSchema = z10.array(ChatTaskProposalSchema).min(1).max(MAX_PROPOSALS);
906
+ var ActionVarsSchema = z10.record(z10.string().max(40), z10.string().max(300));
1029
907
  var DETAIL_MAX = 4e3;
1030
908
  var ACTION_ERROR_CODES = [
1031
909
  "unknown",
@@ -1040,12 +918,6 @@ var ACTION_ERROR_CODES = [
1040
918
  "no_request",
1041
919
  "in_session",
1042
920
  "no_note",
1043
- "member",
1044
- "not_member",
1045
- "unknown_role",
1046
- "not_resting",
1047
- "dissolved",
1048
- "no_seat",
1049
921
  "closed",
1050
922
  "holder",
1051
923
  "changed",
@@ -1053,86 +925,84 @@ var ACTION_ERROR_CODES = [
1053
925
  "not_decision",
1054
926
  "failed"
1055
927
  ];
1056
- var ChatActionStateSchema = z13.enum(["running", "done", "denied", "failed", "refused"]);
1057
- var ChatActionSchema = z13.object({
1058
- action: z13.string().min(1).max(40),
1059
- args: z13.record(z13.unknown()),
1060
- summary: z13.string().min(1).max(300),
928
+ var ChatActionStateSchema = z10.enum(["running", "done", "denied", "failed", "refused"]);
929
+ var ChatActionSchema = z10.object({
930
+ action: z10.string().min(1).max(40),
931
+ args: z10.record(z10.unknown()),
932
+ summary: z10.string().min(1).max(300),
1061
933
  vars: ActionVarsSchema.optional(),
1062
- detail: z13.string().max(DETAIL_MAX).optional(),
1063
- detailCut: z13.literal(true).optional(),
934
+ detail: z10.string().max(DETAIL_MAX).optional(),
935
+ detailCut: z10.literal(true).optional(),
1064
936
  risk: ActionRiskSchema,
1065
- session: z13.string().optional(),
1066
- team: z13.string().optional(),
937
+ session: z10.string().optional(),
1067
938
  state: ChatActionStateSchema.optional(),
1068
- doneAt: z13.string().datetime().optional(),
1069
- error: z13.string().optional(),
1070
- code: z13.string().max(40).optional()
1071
- });
1072
- var ChatActionsSchema = z13.array(ChatActionSchema).min(1).max(MAX_PROPOSALS);
1073
- var ChatTurnSchema = z13.object({
1074
- machineId: z13.string().optional(),
1075
- machineName: z13.string().optional(),
1076
- choices: z13.array(z13.object({ id: z13.string(), label: z13.string() })).optional(),
1077
- qid: z13.string().min(1),
1078
- question: z13.string(),
1079
- askedAt: z13.string().datetime(),
1080
- steps: z13.array(ChatStepSchema),
1081
- answer: z13.string().optional(),
1082
- answeredAt: z13.string().datetime().optional(),
1083
- error: z13.string().optional(),
939
+ doneAt: z10.string().datetime().optional(),
940
+ error: z10.string().optional(),
941
+ code: z10.string().max(40).optional()
942
+ });
943
+ var ChatActionsSchema = z10.array(ChatActionSchema).min(1).max(MAX_PROPOSALS);
944
+ var ChatTurnSchema = z10.object({
945
+ machineId: z10.string().optional(),
946
+ machineName: z10.string().optional(),
947
+ choices: z10.array(z10.object({ id: z10.string(), label: z10.string() })).optional(),
948
+ qid: z10.string().min(1),
949
+ question: z10.string(),
950
+ askedAt: z10.string().datetime(),
951
+ steps: z10.array(ChatStepSchema),
952
+ answer: z10.string().optional(),
953
+ answeredAt: z10.string().datetime().optional(),
954
+ error: z10.string().optional(),
1084
955
  proposal: ChatProposalSchema.optional(),
1085
956
  proposals: ChatProposalsSchema.optional(),
1086
957
  relay: ChatRelaySchema.optional(),
1087
958
  closes: ChatClosesSchema.optional(),
1088
959
  projectProposal: ChatProjectProposalSchema.optional(),
1089
- team: ChatTeamProposalSchema.optional(),
1090
960
  tasks: ChatTasksSchema.optional(),
1091
961
  actions: ChatActionsSchema.optional(),
1092
- ignoredAt: z13.string().datetime().optional(),
1093
- attachments: z13.array(AttachmentRefSchema).optional()
962
+ ignoredAt: z10.string().datetime().optional(),
963
+ attachments: z10.array(AttachmentRefSchema).optional()
1094
964
  });
1095
965
  var proposalRows = (t) => t?.proposals ?? (t?.proposal ? [t.proposal] : []);
1096
966
 
1097
967
  // ../protocol/src/repos.ts
1098
- import { z as z14 } from "zod";
1099
- var ReposInspectSchema = z14.object({
1100
- type: z14.literal("repos.inspect"),
1101
- requestId: z14.string().min(1).max(100),
1102
- paths: z14.array(z14.string().min(1)).min(1).max(50),
1103
- machineId: z14.string().optional()
1104
- });
1105
- var RepoInfoSchema = z14.object({ path: z14.string(), exists: z14.boolean(), branch: z14.string().nullable() });
1106
- var ReposInfoSchema = z14.object({ type: z14.literal("repos.info"), requestId: z14.string(), repos: z14.array(RepoInfoSchema) });
968
+ import { z as z11 } from "zod";
969
+ var ReposInspectSchema = z11.object({
970
+ type: z11.literal("repos.inspect"),
971
+ requestId: z11.string().min(1).max(100),
972
+ paths: z11.array(z11.string().min(1)).min(1).max(50),
973
+ machineId: z11.string().optional()
974
+ });
975
+ var RepoInfoSchema = z11.object({ path: z11.string(), exists: z11.boolean(), branch: z11.string().nullable() });
976
+ var ReposInfoSchema = z11.object({ type: z11.literal("repos.info"), requestId: z11.string(), repos: z11.array(RepoInfoSchema) });
1107
977
 
1108
978
  // ../protocol/src/scan.ts
1109
- import { z as z15 } from "zod";
1110
- var ReposScanSchema = z15.object({ type: z15.literal("repos.scan"), requestId: z15.string().min(1).max(100), machineId: z15.string().optional() });
1111
- var FoundRepoSchema = z15.object({ path: z15.string(), branch: z15.string().nullable(), remote: z15.string().optional(), manifest: z15.string().max(200).optional() });
1112
- 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() });
979
+ import { z as z12 } from "zod";
980
+ var ReposScanSchema = z12.object({ type: z12.literal("repos.scan"), requestId: z12.string().min(1).max(100), machineId: z12.string().optional() });
981
+ var FoundRepoSchema = z12.object({ path: z12.string(), branch: z12.string().nullable(), remote: z12.string().optional(), manifest: z12.string().max(200).optional() });
982
+ 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() });
1113
983
 
1114
984
  // ../protocol/src/documents.ts
1115
- import { z as z16 } from "zod";
985
+ import { z as z13 } from "zod";
1116
986
  var DOCUMENT_MAX_BYTES = 1048576;
1117
- var path = z16.string().min(1).max(4096);
1118
- var requestId2 = z16.string().min(1);
1119
- var DocumentReadSchema = z16.object({
1120
- type: z16.literal("document.read"),
987
+ var path = z13.string().min(1).max(4096);
988
+ var requestId2 = z13.string().min(1);
989
+ var DocumentReadSchema = z13.object({
990
+ type: z13.literal("document.read"),
1121
991
  requestId: requestId2,
1122
992
  path,
1123
- machineId: z16.string().optional(),
1124
- sessionId: z16.string().min(1).optional(),
993
+ machineId: z13.string().optional(),
994
+ sessionId: z13.string().min(1).optional(),
1125
995
  basePath: path.optional()
1126
996
  });
1127
- var DocumentContentSchema = z16.object({
1128
- type: z16.literal("document.content"),
997
+ var DocumentContentSchema = z13.object({
998
+ type: z13.literal("document.content"),
1129
999
  requestId: requestId2,
1130
1000
  path,
1131
- text: z16.string(),
1132
- bytes: z16.number().int().nonnegative(),
1133
- modifiedAt: z16.string().datetime()
1001
+ text: z13.string(),
1002
+ bytes: z13.number().int().nonnegative(),
1003
+ modifiedAt: z13.string().datetime()
1134
1004
  });
1135
- var DocumentErrorCodeSchema = z16.enum([
1005
+ var DocumentErrorCodeSchema = z13.enum([
1136
1006
  "not_found",
1137
1007
  "not_file",
1138
1008
  "unsupported_path",
@@ -1144,62 +1014,152 @@ var DocumentErrorCodeSchema = z16.enum([
1144
1014
  "session_missing",
1145
1015
  "read_failed"
1146
1016
  ]);
1147
- var DocumentErrorSchema = z16.object({
1148
- type: z16.literal("document.error"),
1017
+ var DocumentErrorSchema = z13.object({
1018
+ type: z13.literal("document.error"),
1149
1019
  requestId: requestId2,
1150
1020
  path,
1151
1021
  code: DocumentErrorCodeSchema
1152
1022
  });
1153
1023
 
1154
1024
  // ../protocol/src/routing.ts
1155
- import { z as z17 } from "zod";
1156
- var MachineInventorySchema = z17.object({
1157
- id: z17.string().min(1).max(80),
1158
- label: z17.string().min(1).max(120),
1159
- online: z17.boolean(),
1160
- local: z17.boolean(),
1161
- 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),
1162
- folders: z17.array(z17.object({ project: z17.string(), cwd: z17.string() })).max(100)
1163
- });
1164
- var RoutingContextSchema = z17.object({
1165
- machines: z17.array(MachineInventorySchema).min(1).max(20),
1166
- history: z17.array(z17.object({ question: z17.string().max(2e4), answer: z17.string().max(2e4).optional(), machineId: z17.string().optional() })).max(50)
1167
- });
1168
- var RouteResultSchema = z17.object({
1025
+ import { z as z14 } from "zod";
1026
+ var MachineInventorySchema = z14.object({
1027
+ id: z14.string().min(1).max(80),
1028
+ label: z14.string().min(1).max(120),
1029
+ online: z14.boolean(),
1030
+ local: z14.boolean(),
1031
+ 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),
1032
+ folders: z14.array(z14.object({ project: z14.string(), cwd: z14.string() })).max(100)
1033
+ });
1034
+ var RoutingContextSchema = z14.object({
1035
+ machines: z14.array(MachineInventorySchema).min(1).max(20),
1036
+ history: z14.array(z14.object({ question: z14.string().max(2e4), answer: z14.string().max(2e4).optional(), machineId: z14.string().optional() })).max(50)
1037
+ });
1038
+ var RouteResultSchema = z14.object({
1169
1039
  /** Null means an answer or a clarification, never an implicit local destination. */
1170
- machineId: z17.string().nullable(),
1171
- text: z17.string().min(1).max(2e4),
1172
- choices: z17.array(z17.string()).max(20).optional()
1040
+ machineId: z14.string().nullable(),
1041
+ text: z14.string().min(1).max(2e4),
1042
+ choices: z14.array(z14.string()).max(20).optional()
1043
+ });
1044
+
1045
+ // ../protocol/src/ssh.ts
1046
+ import { z as z15 } from "zod";
1047
+ var SshAliasSchema = z15.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/);
1048
+
1049
+ // ../protocol/src/machines.ts
1050
+ import { z as z16 } from "zod";
1051
+ var MachineIdSchema = z16.string().regex(/^[a-zA-Z0-9_-]{1,64}$/);
1052
+ var MachineSchema = z16.object({
1053
+ id: MachineIdSchema,
1054
+ label: z16.string().trim().min(1).max(80),
1055
+ ssh: SshAliasSchema.optional(),
1056
+ /** Kept in the list but never connected to: no peer, no retry, no session shown until it is enabled again. */
1057
+ disabled: z16.boolean().optional()
1058
+ });
1059
+ var MachinesSchema = z16.array(MachineSchema).min(1).max(20).superRefine((list, ctx) => {
1060
+ if (list[0]?.id !== "local" || list[0].ssh !== void 0) ctx.addIssue({ code: "custom", message: "the first machine is local, without ssh", path: [0] });
1061
+ const ids = /* @__PURE__ */ new Set(), aliases = /* @__PURE__ */ new Set();
1062
+ list.forEach((m, i) => {
1063
+ if (i === 0 && m.disabled) ctx.addIssue({ code: "custom", message: "the local machine cannot be disabled", path: [0, "disabled"] });
1064
+ if (i > 0 && !m.ssh) ctx.addIssue({ code: "custom", message: "a remote machine needs an ssh alias", path: [i, "ssh"] });
1065
+ if (ids.has(m.id)) ctx.addIssue({ code: "custom", message: `duplicate id ${m.id}`, path: [i, "id"] });
1066
+ ids.add(m.id);
1067
+ if (m.ssh) {
1068
+ if (aliases.has(m.ssh)) ctx.addIssue({ code: "custom", message: `duplicate ssh alias ${m.ssh}`, path: [i, "ssh"] });
1069
+ aliases.add(m.ssh);
1070
+ }
1071
+ });
1173
1072
  });
1174
1073
 
1175
1074
  // ../protocol/src/island.ts
1176
- import { z as z18 } from "zod";
1177
- var IslandScaleSchema = z18.union([z18.literal("auto"), z18.literal(1), z18.literal(1.25), z18.literal(1.5), z18.literal(2)]);
1178
- var IslandPrefsSchema = z18.object({
1075
+ import { z as z17 } from "zod";
1076
+ var IslandScaleSchema = z17.union([z17.literal("auto"), z17.literal(1), z17.literal(1.25), z17.literal(1.5), z17.literal(2)]);
1077
+ var IslandPrefsSchema = z17.object({
1179
1078
  /** Shown at the top of the screen; hidden, Desktop still notifies. */
1180
- visible: z18.boolean(),
1079
+ visible: z17.boolean(),
1181
1080
  /** `primary` (whichever it is after a reconfiguration), or a monitor's id as the shell lists it (`list_monitors`: the OS
1182
1081
  * name, `#index` without one). `second`, written by older fronts, is the first monitor that is not the primary. */
1183
- screen: z18.string().trim().min(1).max(200),
1184
- position: z18.enum(["center", "left", "right"]),
1082
+ screen: z17.string().trim().min(1).max(200),
1083
+ position: z17.enum(["center", "left", "right"]),
1185
1084
  /** A strip under a maximised window. */
1186
- discreet: z18.boolean(),
1085
+ discreet: z17.boolean(),
1187
1086
  islandScale: IslandScaleSchema,
1188
1087
  panelScale: IslandScaleSchema,
1189
1088
  /** What the island shows besides asks and questions, which it always shows. */
1190
- shows: z18.object({
1089
+ shows: z17.object({
1191
1090
  /** Allow, deny or answer in a line from the island; off, its cards only say « Open in Ledge ». */
1192
- quick: z18.boolean(),
1091
+ quick: z17.boolean(),
1193
1092
  /** The 6 s bubble when an agent finishes. */
1194
- finished: z18.boolean(),
1093
+ finished: z17.boolean(),
1195
1094
  /** An agent's sentence in a bubble. */
1196
- say: z18.boolean(),
1095
+ say: z17.boolean(),
1197
1096
  /** The sub-agents next to their main agent. */
1198
- helpers: z18.boolean()
1097
+ helpers: z17.boolean()
1199
1098
  }),
1200
1099
  /** The global shortcut that opens the island, as shown (`Ctrl Alt L`). */
1201
- shortcut: z18.string().trim().min(1).max(40)
1100
+ shortcut: z17.string().trim().min(1).max(40)
1101
+ });
1102
+
1103
+ // ../protocol/src/projects.ts
1104
+ import { z as z18 } from "zod";
1105
+ var PROJECT_COLORS = { blue: "#3b82f6", green: "#10b981", amber: "#f59e0b", violet: "#8b5cf6", teal: "#14b8a6", pink: "#ec4899", red: "#ef4444", slate: "#64748b" };
1106
+ var ProjectColorSchema = z18.enum(["blue", "green", "amber", "violet", "teal", "pink", "red", "slate"]);
1107
+ var ProjectIdSchema = z18.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/);
1108
+ function normalizePath(raw) {
1109
+ const p = raw.trim().replace(/\/+/g, "/");
1110
+ return p.length > 1 && p.endsWith("/") ? p.slice(0, -1) : p;
1111
+ }
1112
+ var PathSchema = z18.string().max(4096).refine((p) => p.startsWith("/") && p === normalizePath(p), "an absolute, normalized path");
1113
+ var RepoSchema = z18.object({ machine: MachineIdSchema, path: PathSchema });
1114
+ var ProjectSchema = z18.object({
1115
+ id: ProjectIdSchema,
1116
+ name: z18.string().trim().min(1).max(80),
1117
+ color: ProjectColorSchema,
1118
+ description: z18.string().max(500).default(""),
1119
+ repos: z18.array(RepoSchema).max(50)
1120
+ });
1121
+ var RuleSchema = z18.object({ machine: MachineIdSchema, path: PathSchema, project: ProjectIdSchema });
1122
+ function projectsProblems(p) {
1123
+ const out = [];
1124
+ const ids = /* @__PURE__ */ new Set(), names = /* @__PURE__ */ new Set(), repos = /* @__PURE__ */ new Set(), rules = /* @__PURE__ */ new Set();
1125
+ p.projects.forEach((project, i) => {
1126
+ if (ids.has(project.id)) out.push({ code: "duplicate_id", path: ["projects", i, "id"] });
1127
+ ids.add(project.id);
1128
+ const name = project.name.trim().toLocaleLowerCase();
1129
+ if (names.has(name)) out.push({ code: "duplicate_name", path: ["projects", i, "name"] });
1130
+ names.add(name);
1131
+ project.repos.forEach((repo, j) => {
1132
+ const key = `${repo.machine}
1133
+ ${repo.path}`;
1134
+ if (repos.has(key)) out.push({ code: "duplicate_repo", path: ["projects", i, "repos", j] });
1135
+ repos.add(key);
1136
+ });
1137
+ });
1138
+ p.rules.forEach((rule, i) => {
1139
+ const key = `${rule.machine}
1140
+ ${rule.path}`;
1141
+ if (rules.has(key)) out.push({ code: "duplicate_rule", path: ["rules", i] });
1142
+ rules.add(key);
1143
+ if (!ids.has(rule.project)) out.push({ code: "unknown_project", path: ["rules", i, "project"] });
1144
+ });
1145
+ return out;
1146
+ }
1147
+ var ProjectsSchema = z18.object({ projects: z18.array(ProjectSchema).max(100), rules: z18.array(RuleSchema).max(1e3) }).superRefine((p, ctx) => {
1148
+ for (const problem of projectsProblems(p)) ctx.addIssue({ code: "custom", message: problem.code, path: problem.path });
1202
1149
  });
1150
+ var DEFAULT_PROJECTS = { projects: [], rules: [] };
1151
+ var under = (cwd, path2) => path2 === "/" || cwd === path2 || cwd.startsWith(`${path2}/`);
1152
+ function projectOf(session, state) {
1153
+ const machine = session.machineId ?? "local";
1154
+ const cwd = normalizePath(session.cwd);
1155
+ const known = new Set(state.projects.map((p) => p.id));
1156
+ const candidates = [
1157
+ ...state.projects.flatMap((p) => p.repos.filter((r) => r.machine === machine).map((r) => ({ project: p.id, path: r.path, rule: false }))),
1158
+ ...state.rules.filter((r) => r.machine === machine && known.has(r.project)).map((r) => ({ project: r.project, path: r.path, rule: true }))
1159
+ ].filter((c) => under(cwd, c.path));
1160
+ candidates.sort((x, y) => y.path.length - x.path.length || Number(y.rule) - Number(x.rule));
1161
+ return candidates[0]?.project ?? null;
1162
+ }
1203
1163
 
1204
1164
  // ../protocol/src/thread.ts
1205
1165
  import { z as z19 } from "zod";
@@ -1228,10 +1188,8 @@ var ThreadItemSchema = z19.discriminatedUnion("kind", [
1228
1188
  kind: z19.literal("notice"),
1229
1189
  ...base,
1230
1190
  notice: z19.enum(["idle", "exited", "unavailable", "expired", "delivery", "other"]),
1231
- /** An `other` notice from Ledge: `task`, the task a `<ledge-task>` is about; `team`, the team a `<ledge-notice team>` seated the
1232
- * session in (roles spec §3.3). An older front, which knows neither, shows it as any other notice. */
1191
+ /** An `other` notice from Ledge: `task`, the task a `<ledge-task>` is about. An older front, which does not know it, shows it as any other notice. */
1233
1192
  task: z19.string().optional(),
1234
- team: z19.string().optional(),
1235
1193
  /** A task this session handed over (`outgoing`), and how (issue #92). */
1236
1194
  taskOp: z19.enum(TRANSMISSION_OPS).optional(),
1237
1195
  outgoing: z19.literal(true).optional(),
@@ -1366,8 +1324,8 @@ var DaemonInfoSchema = z21.object({
1366
1324
  /** Its home folder, so a client shows the folders under it as `~` (absent from older daemons). */
1367
1325
  home: z21.string().optional(),
1368
1326
  mobile: z21.boolean().optional(),
1369
- /** Knows roles, teams and tasks given by Ledge (spec 2026-10-25 roles). */
1370
- teams: z21.boolean().optional()
1327
+ /** Answers `openrig.status` and `openrig.act`: drives OpenRig on its machine. */
1328
+ openrig: z21.boolean().optional()
1371
1329
  });
1372
1330
  var UpdateFailureSchema = z21.enum(["git-install", "no-systemd", "sessions-at-risk", "npm-failed", "busy"]);
1373
1331
  var ServerMessageSchema = z21.discriminatedUnion("type", [
@@ -1381,6 +1339,11 @@ var ServerMessageSchema = z21.discriminatedUnion("type", [
1381
1339
  ReposInfoSchema,
1382
1340
  ReposFoundSchema,
1383
1341
  ModelsListingSchema,
1342
+ OpenRigStateMessageSchema,
1343
+ OpenRigDoneSchema,
1344
+ OpenRigSpecListSchema,
1345
+ OpenRigLaunchedSchema,
1346
+ OpenRigReseatedSchema,
1384
1347
  /** `recents`: the folders of past sessions, most recent first. `launcher`: the command that runs `ledge` inside WSL
1385
1348
  * (`[node, cli]`), so the overlay can attach a terminal to a session with `<launcher> attach <id>`. `daemon`: absent
1386
1349
  * from daemons older than the auto-update. */
@@ -1422,7 +1385,7 @@ var ServerMessageSchema = z21.discriminatedUnion("type", [
1422
1385
  /** The chat (spec 2026-10-11 §5): what Ledge reads, its words as they come, the final text, or why it stopped; the day's turns after each snapshot. */
1423
1386
  z21.object({ type: z21.literal("chat.step"), qid: z21.string(), step: ChatStepSchema }),
1424
1387
  z21.object({ type: z21.literal("chat.delta"), qid: z21.string(), text: z21.string() }),
1425
- z21.object({ type: z21.literal("chat.done"), qid: z21.string(), text: z21.string(), at: z21.string().datetime(), proposal: ChatProposalSchema.optional(), proposals: ChatProposalsSchema.optional(), relay: ChatRelaySchema.optional(), closes: ChatClosesSchema.optional(), projectProposal: ChatProjectProposalSchema.optional(), team: ChatTeamProposalSchema.optional(), tasks: ChatTasksSchema.optional(), actions: ChatActionsSchema.optional() }),
1388
+ z21.object({ type: z21.literal("chat.done"), qid: z21.string(), text: z21.string(), at: z21.string().datetime(), proposal: ChatProposalSchema.optional(), proposals: ChatProposalsSchema.optional(), relay: ChatRelaySchema.optional(), closes: ChatClosesSchema.optional(), projectProposal: ChatProjectProposalSchema.optional(), tasks: ChatTasksSchema.optional(), actions: ChatActionsSchema.optional() }),
1426
1389
  /** What a `chat.act` applied: the rows done, and the one that failed with why (the rows after it stay proposed). */
1427
1390
  z21.object({ type: z21.literal("chat.acted"), rid: z21.string(), qid: z21.string(), done: z21.array(z21.number().int().min(0)), failed: z21.array(z21.object({
1428
1391
  row: z21.number().int().min(0),
@@ -1432,8 +1395,8 @@ var ServerMessageSchema = z21.discriminatedUnion("type", [
1432
1395
  })) }),
1433
1396
  /** What an `action.run` came to: `row` the action as the daemon resolved it (its summary, its risk); `reason` why it was not
1434
1397
  * done, with `code` (`refused`: not possible now; `agent`: a session may not run it; `confirm_required`: destructive, ask
1435
- * again; `failed`: the handler turned it down; a free string, as an `error`'s); `path` the template a `team.save` wrote. */
1436
- z21.object({ type: z21.literal("action.result"), rid: z21.string(), action: z21.string().min(1).max(40), row: ChatActionSchema.optional(), reason: z21.string().optional(), code: z21.string().optional(), path: z21.string().optional() }),
1398
+ * again; `failed`: the handler turned it down; a free string, as an `error`'s). */
1399
+ z21.object({ type: z21.literal("action.result"), rid: z21.string(), action: z21.string().min(1).max(40), row: ChatActionSchema.optional(), reason: z21.string().optional(), code: z21.string().optional() }),
1437
1400
  z21.object({ type: z21.literal("chat.error"), qid: z21.string(), message: z21.string() }),
1438
1401
  z21.object({ type: z21.literal("chat.history"), turns: z21.array(ChatTurnSchema) }),
1439
1402
  /** The daemon updating itself: npm is running, then the service restarts (the socket closes right after). */
@@ -1457,15 +1420,6 @@ var ServerMessageSchema = z21.discriminatedUnion("type", [
1457
1420
  ContextPrefsMessageSchema,
1458
1421
  HandoverResultSchema,
1459
1422
  TaskUpdatedSchema,
1460
- RolesListingSchema,
1461
- TeamsMessageSchema,
1462
- TeamUpdatedSchema,
1463
- TeamLaunchedSchema,
1464
- TeamFailedSchema,
1465
- TeamSavedSchema,
1466
- DefinitionsListingSchema,
1467
- DefinitionResultSchema,
1468
- TeamChangedSchema,
1469
1423
  z21.object({
1470
1424
  type: z21.literal("error"),
1471
1425
  message: z21.string(),
@@ -1487,6 +1441,11 @@ var ClientMessageSchema = z21.discriminatedUnion("type", [
1487
1441
  ReposInspectSchema,
1488
1442
  ReposScanSchema,
1489
1443
  ModelsListSchema,
1444
+ OpenRigStatusSchema,
1445
+ OpenRigActSchema,
1446
+ OpenRigSpecsSchema,
1447
+ OpenRigLaunchSchema,
1448
+ OpenRigSeatsSchema,
1490
1449
  /** The overlay starts a session: `cwd` is a WSL path (`~` allowed), `name` a preferred bot name (the daemon picks a
1491
1450
  * free one otherwise), `prompt` the agent's first instruction, `continue` resumes the folder's last conversation.
1492
1451
  * With `qid` it is the chat card of that turn: the daemon launches the turn's proposal and ignores the other fields
@@ -1508,10 +1467,6 @@ var ClientMessageSchema = z21.discriminatedUnion("type", [
1508
1467
  effort: EffortSchema.optional(),
1509
1468
  /** OMP only: its approval mode, `always-ask` when left out. */
1510
1469
  approval: OmpApprovalSchema.optional(),
1511
- /** A role (spec 2026-10-25 roles §3.4): its prompt reaches the agent at every start, its defaults fill what is left out. */
1512
- role: RoleIdSchema.optional(),
1513
- /** A live team the new session joins at once, in `role`. */
1514
- team: TeamIdSchema.optional(),
1515
1470
  /** Routing by the fleet, removed before the message reaches the daemon. */
1516
1471
  machineId: z21.string().optional()
1517
1472
  }),
@@ -1599,12 +1554,18 @@ var ClientMessageSchema = z21.discriminatedUnion("type", [
1599
1554
  z21.object({ type: z21.literal("session.delete"), id: z21.string() }),
1600
1555
  /** The user names the session's topic from the overlay (500 characters at most, the hook's prompt cap); an empty topic hands back to the automatic sources. */
1601
1556
  z21.object({ type: z21.literal("session.rename"), id: z21.string(), topic: z21.string().max(500) }),
1602
- /** A seat's hook told it its team as `key` names it (`seatKey`): at its start, or at a turn after the team changed. */
1603
- z21.object({ type: z21.literal("seat.seen"), id: z21.string(), key: z21.string().max(4e3) }),
1604
1557
  z21.object({ type: z21.literal("session.thread"), id: z21.string() }),
1605
1558
  z21.object({ type: z21.literal("session.register"), session: SessionSchema }),
1606
1559
  /** `agent` and `cwd` describe the session when the daemon does not know it yet (a hook from an agent started without ledge). */
1607
- z21.object({ type: z21.literal("session.event"), id: z21.string(), event: SessionEventSchema, agent: ToolSchema.optional(), cwd: z21.string().optional() }),
1560
+ z21.object({
1561
+ type: z21.literal("session.event"),
1562
+ id: z21.string(),
1563
+ event: SessionEventSchema,
1564
+ agent: ToolSchema.optional(),
1565
+ cwd: z21.string().optional(),
1566
+ /** The OpenRig seat the agent runs in (`OPENRIG_SESSION_NAME`, `pod-member@rig`), when OpenRig launched it. */
1567
+ rigSeat: RigSeatNameSchema.optional()
1568
+ }),
1608
1569
  z21.object({ type: z21.literal("session.unregister"), id: z21.string(), exitCode: z21.number().int().nullable() }),
1609
1570
  z21.object({ type: z21.literal("snapshot.request") }),
1610
1571
  z21.object({ type: z21.literal("chat.ask"), qid: z21.string().min(1), text: z21.string(), images: z21.array(ImageUploadSchema).max(ATTACHMENTS_MAX).optional(), tool: ToolSchema.optional() }),
@@ -1638,25 +1599,8 @@ var ClientMessageSchema = z21.discriminatedUnion("type", [
1638
1599
  SessionHandoverSchema,
1639
1600
  ContextSetSchema,
1640
1601
  HandoverBriefSchema,
1641
- HandoverShowSchema,
1642
- RolesListSchema,
1643
- TeamLaunchSchema,
1644
- TeamJoinSchema,
1645
- TeamLeaveSchema,
1646
- TeamResumeSchema,
1647
- TeamDissolveSchema,
1648
- TeamSaveSchema,
1649
- DefinitionsListSchema,
1650
- RoleWriteSchema,
1651
- RoleDeleteSchema,
1652
- TemplateWriteSchema,
1653
- TemplateDeleteSchema,
1654
- TeamComposeSchema,
1655
- TeamSeatSchema
1656
- ]).superRefine((m, ctx) => {
1657
- const issue = "scope" in m ? scopeIssue(m) : null;
1658
- if (issue) ctx.addIssue({ code: z21.ZodIssueCode.custom, message: issue, path: ["project"] });
1659
- });
1602
+ HandoverShowSchema
1603
+ ]);
1660
1604
  function parseClientMessage(raw) {
1661
1605
  return ClientMessageSchema.parse(raw);
1662
1606
  }
@@ -1745,6 +1689,7 @@ function pickName(taken, preferred) {
1745
1689
  if (first) return first;
1746
1690
  for (let i = 2; ; i++) if (free(`${NAMES[0]}-${i}`)) return `${NAMES[0]}-${i}`;
1747
1691
  }
1692
+ var namesInUse = (sessions) => [...sessions].filter((s) => s.state !== "exited" && !s.archivedAt).map((s) => s.name);
1748
1693
 
1749
1694
  // ../protocol/src/topic.ts
1750
1695
  var TOPIC_MAX = 80;
@@ -1827,7 +1772,7 @@ var MeResponseSchema = z23.object({
1827
1772
  });
1828
1773
 
1829
1774
  // ../protocol/src/phone.ts
1830
- import { z as z26 } from "zod";
1775
+ import { z as z25 } from "zod";
1831
1776
 
1832
1777
  // ../protocol/src/push.ts
1833
1778
  import { z as z24 } from "zod";
@@ -1873,51 +1818,6 @@ var PushPayloadSchema = z24.object({
1873
1818
  tag: z24.string().regex(/^[A-Za-z0-9_-]{1,32}$/)
1874
1819
  });
1875
1820
 
1876
- // ../protocol/src/phoneTeams.ts
1877
- import { z as z25 } from "zod";
1878
- var scope = DefinitionScopeSchema;
1879
- var PhoneSeatsSchema = z25.array(SeatSchema.strict()).min(1).max(TEAM_SEATS_MAX).refine(uniqueRoles, "a role twice in one team");
1880
- var PhoneRoleDraftSchema = RoleDraftSchema.strict();
1881
- var projectName = z25.string().max(80).nullable();
1882
- var PhoneRoleSchema = z25.object({
1883
- id: RoleIdSchema,
1884
- label: z25.string().min(1).max(ROLE_LABEL_MAX),
1885
- prompt: z25.string().max(ROLE_PROMPT_MAX),
1886
- cut: z25.literal(true).optional(),
1887
- tool: ToolSchema.optional(),
1888
- model: ModelIdSchema.optional(),
1889
- effort: EffortSchema.optional(),
1890
- autonomy: AutonomySchema.optional(),
1891
- scope,
1892
- project: projectName,
1893
- hash: DefinitionHashSchema,
1894
- shadows: z25.literal(true).optional(),
1895
- shadowed: z25.literal(true).optional(),
1896
- shadowedIn: z25.array(z25.string().max(80)).min(1).max(8).optional()
1897
- }).strict();
1898
- var PhoneTemplateSchema = z25.object({ id: TemplateIdSchema, name: TeamNameSchema, seats: PhoneSeatsSchema, scope, project: projectName, hash: DefinitionHashSchema }).strict();
1899
- var PhoneProblemSchema = z25.object({ file: z25.string().max(80), scope, project: projectName, reason: z25.string().max(200) }).strict();
1900
- var PhoneCatalogSchema = z25.object({
1901
- /** The names of the projects with a local repository: the ones a « Dépôt » scope or a « Lever » can name. */
1902
- projects: z25.array(z25.string().max(80)).max(50),
1903
- roles: z25.array(PhoneRoleSchema).max(200),
1904
- templates: z25.array(PhoneTemplateSchema).max(100),
1905
- problems: z25.array(PhoneProblemSchema).max(50)
1906
- }).strict();
1907
- var TEAMS_OPERATION_TYPES = ["role.write", "role.delete", "template.write", "template.delete", "team.launch", "team.compose", "team.seat", "team.dissolve"];
1908
- var isTeamsOperation = (m) => TEAMS_OPERATION_TYPES.includes(m.type);
1909
- function canonicalJson(v) {
1910
- const sort = (x) => {
1911
- if (Array.isArray(x)) return x.map(sort);
1912
- if (x !== null && typeof x === "object") {
1913
- const o = x;
1914
- return Object.fromEntries(Object.keys(o).sort().filter((k) => o[k] !== void 0).map((k) => [k, sort(o[k])]));
1915
- }
1916
- return x;
1917
- };
1918
- return JSON.stringify(sort(v));
1919
- }
1920
-
1921
1821
  // ../protocol/src/phone.ts
1922
1822
  var PHONE_PROTOCOL = 1;
1923
1823
  var PAD_TIERS = [1024, 4096, 16384, 65536, 262144, 655360];
@@ -1936,38 +1836,38 @@ var THREAD_TEXT_MAX = 8192;
1936
1836
  var TOOL_TEXT_MAX = 2048;
1937
1837
  var CHECKLIST_TASKS_MAX = 50;
1938
1838
  var CHECKLIST_TEXT_MAX = 200;
1939
- var ChecklistStatusSchema = z26.enum(["pending", "in_progress", "completed"]);
1940
- var PhoneChecklistSchema = z26.object({
1941
- tasks: z26.array(z26.object({ text: z26.string().max(CHECKLIST_TEXT_MAX), status: ChecklistStatusSchema })).max(CHECKLIST_TASKS_MAX),
1942
- done: z26.number().int().nonnegative(),
1943
- total: z26.number().int().nonnegative(),
1944
- cut: z26.literal(true).optional()
1945
- });
1946
- var PhoneChecklistSummarySchema = z26.object({
1947
- done: z26.number().int().nonnegative(),
1948
- total: z26.number().int().nonnegative(),
1949
- current: z26.string().max(CHECKLIST_TEXT_MAX).optional(),
1950
- cut: z26.literal(true).optional()
1839
+ var ChecklistStatusSchema = z25.enum(["pending", "in_progress", "completed"]);
1840
+ var PhoneChecklistSchema = z25.object({
1841
+ tasks: z25.array(z25.object({ text: z25.string().max(CHECKLIST_TEXT_MAX), status: ChecklistStatusSchema })).max(CHECKLIST_TASKS_MAX),
1842
+ done: z25.number().int().nonnegative(),
1843
+ total: z25.number().int().nonnegative(),
1844
+ cut: z25.literal(true).optional()
1845
+ });
1846
+ var PhoneChecklistSummarySchema = z25.object({
1847
+ done: z25.number().int().nonnegative(),
1848
+ total: z25.number().int().nonnegative(),
1849
+ current: z25.string().max(CHECKLIST_TEXT_MAX).optional(),
1850
+ cut: z25.literal(true).optional()
1951
1851
  });
1952
1852
  var PENDING_BODY_MAX = 65536;
1953
1853
  var SNAPSHOT_BODY_MAX = 2048;
1954
- var RiskSchema = z26.enum(["low", "high"]);
1955
- 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"]);
1956
- var OperationIdSchema = z26.string().uuid();
1957
- var OperationStatusSchema = z26.enum(["received", "applied", "rejected", "failed"]);
1958
- var OperationReasonSchema = z26.enum([...RefusalCodeSchema.options, "untypable", "confirm_required", "conflict", "assertion_invalid", "assertion_expired", "changed", "exists", "unknown_project", "seat_failed", "scheduled", ...ModelRefusalSchema.options]);
1959
- var CapabilitiesSchema = z26.object({
1854
+ var RiskSchema = z25.enum(["low", "high"]);
1855
+ 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"]);
1856
+ var OperationIdSchema = z25.string().uuid();
1857
+ var OperationStatusSchema = z25.enum(["received", "applied", "rejected", "failed"]);
1858
+ var OperationReasonSchema = z25.enum([...RefusalCodeSchema.options, "untypable", "confirm_required", "conflict", "assertion_invalid", "assertion_expired", "scheduled", ...ModelRefusalSchema.options]);
1859
+ var CapabilitiesSchema = z25.object({
1960
1860
  /** A question can be answered in free text. */
1961
- freeTextAnswer: z26.boolean(),
1861
+ freeTextAnswer: z25.boolean(),
1962
1862
  /** The session's accept/deny can be typed; absent = true. */
1963
- decide: z26.boolean().optional(),
1863
+ decide: z25.boolean().optional(),
1964
1864
  /** OMP's dialog questions can be answered from the phone; absent = false. */
1965
- questions: z26.boolean().optional()
1865
+ questions: z25.boolean().optional()
1966
1866
  });
1967
1867
  var UNTYPABLE = /[\u0000-\u001f\u007f-\u009f\u200b\u200e\u200f\u2028-\u202e\u2066-\u2069\ufeff]/;
1968
- var CapabilitiesByToolSchema = z26.object({ claude: CapabilitiesSchema, codex: CapabilitiesSchema, cursor: CapabilitiesSchema, omp: CapabilitiesSchema });
1969
- var PhonePendingSchema = PendingSchema.extend({ key: z26.string().max(64), risk: RiskSchema, riskReason: RiskReasonSchema, cut: z26.literal(true).optional() });
1970
- var SwitchableSessionSchema = SessionSchema.extend({ canSwitch: z26.literal(true).optional() });
1868
+ var CapabilitiesByToolSchema = z25.object({ claude: CapabilitiesSchema, codex: CapabilitiesSchema, cursor: CapabilitiesSchema, omp: CapabilitiesSchema });
1869
+ var PhonePendingSchema = PendingSchema.extend({ key: z25.string().max(64), risk: RiskSchema, riskReason: RiskReasonSchema, cut: z25.literal(true).optional() });
1870
+ var SwitchableSessionSchema = SessionSchema.extend({ canSwitch: z25.literal(true).optional() });
1971
1871
  var PhoneSessionSchema = SwitchableSessionSchema.pick({
1972
1872
  id: true,
1973
1873
  name: true,
@@ -1988,10 +1888,6 @@ var PhoneSessionSchema = SwitchableSessionSchema.pick({
1988
1888
  effort: true,
1989
1889
  modelNext: true,
1990
1890
  canSwitch: true,
1991
- /** Its role and its live team (ledge home spec §2.4): the agents screen groups a project's sessions by table. */
1992
- role: true,
1993
- roleLabel: true,
1994
- team: true,
1995
1891
  /** Its context and its relief (context handover spec §3.2): the phone shows the gauge; the relief is started from the PC. */
1996
1892
  context: true,
1997
1893
  relieves: true,
@@ -1999,373 +1895,291 @@ var PhoneSessionSchema = SwitchableSessionSchema.pick({
1999
1895
  exitedAt: true
2000
1896
  }).extend({
2001
1897
  pending: PhonePendingSchema.optional(),
2002
- unread: z26.boolean(),
2003
- handover: z26.object({ state: HandoverStateSchema, toName: z26.string().max(80).optional() }).strict().optional(),
1898
+ unread: z25.boolean(),
1899
+ handover: z25.object({ state: HandoverStateSchema, toName: z25.string().max(80).optional() }).strict().optional(),
2004
1900
  /** Absent: the agent has no checklist. */
2005
1901
  checklist: PhoneChecklistSummarySchema.optional(),
2006
1902
  /** Started without Ledge (`hook_only`): the phone can neither close nor resume it. */
2007
- readOnly: z26.literal(true).optional()
1903
+ readOnly: z25.literal(true).optional()
2008
1904
  });
2009
- var B64U2 = z26.string().regex(/^[A-Za-z0-9_-]*$/);
2010
- var CredentialSchema = z26.object({
1905
+ var B64U2 = z25.string().regex(/^[A-Za-z0-9_-]*$/);
1906
+ var CredentialSchema = z25.object({
2011
1907
  id: B64U2.max(1366),
2012
1908
  publicKey: B64U2.max(2048),
2013
- alg: z26.union([z26.literal(-7), z26.literal(-257)]),
1909
+ alg: z25.union([z25.literal(-7), z25.literal(-257)]),
2014
1910
  clientDataJSON: B64U2.max(4096),
2015
1911
  authenticatorData: B64U2.max(4096),
2016
- transports: z26.array(z26.string().max(20)).max(8).optional()
1912
+ transports: z25.array(z25.string().max(20)).max(8).optional()
2017
1913
  });
2018
- var AssertionSchema = z26.object({
1914
+ var AssertionSchema = z25.object({
2019
1915
  id: B64U2.max(1366),
2020
1916
  clientDataJSON: B64U2.max(4096),
2021
1917
  authenticatorData: B64U2.max(4096),
2022
1918
  signature: B64U2.max(1024)
2023
1919
  });
2024
- var TeamsDigestSchema = z26.string().regex(/^[0-9a-f]{64}$/);
2025
- var ConfirmPurposeSchema = z26.enum(["register", "decide", "launch", "close", "act", "define", "team", "pc"]);
1920
+ var ConfirmPurposeSchema = z25.enum(["register", "decide", "launch", "close", "act", "pc"]);
2026
1921
  var PhoneChatStepSchema = ChatStepSchema.pick({ kind: true, id: true, name: true }).strict();
2027
- var PhoneChatProposalSchema = z26.object({
2028
- project: z26.string().max(80),
1922
+ var PhoneChatProposalSchema = z25.object({
1923
+ project: z25.string().max(80),
2029
1924
  tool: ToolSchema,
2030
- prompt: z26.string().max(TOOL_TEXT_MAX).optional(),
2031
- launchedId: z26.string().optional(),
2032
- failed: z26.literal(true).optional()
1925
+ prompt: z25.string().max(TOOL_TEXT_MAX).optional(),
1926
+ launchedId: z25.string().optional(),
1927
+ failed: z25.literal(true).optional()
2033
1928
  }).strict();
2034
- var PhoneChatRelaySchema = z26.object({
2035
- id: z26.string().min(1),
2036
- name: z26.string(),
1929
+ var PhoneChatRelaySchema = z25.object({
1930
+ id: z25.string().min(1),
1931
+ name: z25.string(),
2037
1932
  tool: ToolSchema,
2038
- text: z26.string().max(TOOL_TEXT_MAX),
2039
- status: z26.enum(["queued", "sent"]).optional(),
2040
- sentAt: z26.string().datetime().optional(),
2041
- failed: z26.literal(true).optional(),
1933
+ text: z25.string().max(TOOL_TEXT_MAX),
1934
+ status: z25.enum(["queued", "sent"]).optional(),
1935
+ sentAt: z25.string().datetime().optional(),
1936
+ failed: z25.literal(true).optional(),
2042
1937
  /** With `failed`: why, as the PC's code (never its text). */
2043
- code: z26.string().max(40).optional()
1938
+ code: z25.string().max(40).optional()
2044
1939
  }).strict();
2045
- var CloseHowSchema = z26.enum(["exit", "killed"]);
2046
- var PhoneChatCloseSchema = z26.object({
2047
- id: z26.string().min(1),
2048
- name: z26.string(),
1940
+ var CloseHowSchema = z25.enum(["exit", "killed"]);
1941
+ var PhoneChatCloseSchema = z25.object({
1942
+ id: z25.string().min(1),
1943
+ name: z25.string(),
2049
1944
  tool: ToolSchema,
2050
1945
  how: CloseHowSchema.optional(),
2051
- closedAt: z26.string().datetime().optional(),
2052
- failed: z26.literal(true).optional()
1946
+ closedAt: z25.string().datetime().optional(),
1947
+ failed: z25.literal(true).optional()
2053
1948
  }).strict();
2054
- var PhoneChatTeamSchema = z26.object({
2055
- project: z26.string().max(80),
2056
- name: z26.string().max(60),
2057
- template: z26.string().max(64).optional(),
2058
- 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),
2059
- teamId: z26.string().max(40).optional(),
2060
- launchedAt: z26.string().datetime().optional(),
2061
- failed: z26.literal(true).optional()
1949
+ var PhoneChatTaskSchema = z25.object({
1950
+ to: z25.string().max(80),
1951
+ toName: z25.string().max(80).optional(),
1952
+ title: z25.string().max(200),
1953
+ text: z25.string().max(TOOL_TEXT_MAX).optional(),
1954
+ taskId: z25.string().max(40).optional(),
1955
+ ownerName: z25.string().max(80).optional(),
1956
+ state: z25.enum(["open", "taken", "done", "refused", "dropped"]).optional(),
1957
+ failed: z25.literal(true).optional()
2062
1958
  }).strict();
2063
- var PhoneChatTaskSchema = z26.object({
2064
- to: z26.string().max(80),
2065
- toName: z26.string().max(80).optional(),
2066
- title: z26.string().max(200),
2067
- text: z26.string().max(TOOL_TEXT_MAX).optional(),
2068
- taskId: z26.string().max(40).optional(),
2069
- ownerName: z26.string().max(80).optional(),
2070
- state: z26.enum(["open", "taken", "done", "refused", "dropped"]).optional(),
2071
- failed: z26.literal(true).optional()
2072
- }).strict();
2073
- var PhoneChatActionSchema = z26.object({
2074
- action: z26.string().min(1).max(40),
2075
- summary: z26.string().max(300),
1959
+ var PhoneChatActionSchema = z25.object({
1960
+ action: z25.string().min(1).max(40),
1961
+ summary: z25.string().max(300),
2076
1962
  vars: ActionVarsSchema.optional(),
2077
- detail: z26.string().max(TOOL_TEXT_MAX).optional(),
2078
- detailCut: z26.literal(true).optional(),
1963
+ detail: z25.string().max(TOOL_TEXT_MAX).optional(),
1964
+ detailCut: z25.literal(true).optional(),
2079
1965
  risk: ActionRiskSchema,
2080
- session: z26.string().max(100).optional(),
2081
- team: z26.string().max(40).optional(),
1966
+ session: z25.string().max(100).optional(),
2082
1967
  state: ChatActionStateSchema.optional(),
2083
- doneAt: z26.string().datetime().optional(),
2084
- code: z26.string().max(40).optional()
2085
- }).strict();
2086
- var PhoneTeamSchema = z26.object({
2087
- id: z26.string().max(40),
2088
- name: z26.string().max(60),
2089
- project: z26.string().max(80).nullable(),
2090
- state: z26.enum(["active", "resting"]),
2091
- template: z26.string().max(64).optional(),
2092
- /** Absent from a daemon older than the phone: the phone then says no start time. */
2093
- createdAt: z26.string().optional(),
2094
- /** `tool`, `model` and `effort` are what the seat was composed with; `leaving` is a seat that finishes its turn and is then closed. */
2095
- seats: z26.array(z26.object({
2096
- role: z26.string().max(40),
2097
- sessionId: z26.string().max(100).nullable(),
2098
- tool: ToolSchema.optional(),
2099
- model: ModelIdSchema.optional(),
2100
- effort: EffortSchema.optional(),
2101
- leaving: z26.literal(true).optional()
2102
- }).strict()).max(16),
2103
- done: z26.number().int().min(0),
2104
- given: z26.number().int().min(0)
1968
+ doneAt: z25.string().datetime().optional(),
1969
+ code: z25.string().max(40).optional()
2105
1970
  }).strict();
2106
- var PhoneTaskSchema = z26.object({
2107
- id: z26.string().max(40),
2108
- title: z26.string().max(200),
2109
- owner: z26.string().max(100),
2110
- ownerName: z26.string().max(80),
2111
- ownerRole: z26.string().max(40).optional(),
1971
+ var PhoneTaskSchema = z25.object({
1972
+ id: z25.string().max(40),
1973
+ title: z25.string().max(200),
1974
+ owner: z25.string().max(100),
1975
+ ownerName: z25.string().max(80),
2112
1976
  /** Who gave it: `ledge` for Ledge's own; a session for a decision it put to the user (owner `ledge`), with its detail (the options). */
2113
- giver: z26.string().max(100).optional(),
2114
- giverName: z26.string().max(80).optional(),
2115
- text: z26.string().max(TOOL_TEXT_MAX).optional(),
2116
- team: z26.string().max(40).optional(),
2117
- teamName: z26.string().max(60).optional(),
2118
- state: z26.enum(["open", "taken", "done", "refused", "dropped"]),
2119
- result: z26.string().max(TOOL_TEXT_MAX).optional(),
2120
- cut: z26.literal(true).optional(),
2121
- at: z26.string(),
2122
- updatedAt: z26.string(),
2123
- seen: z26.literal(true).optional()
1977
+ giver: z25.string().max(100).optional(),
1978
+ giverName: z25.string().max(80).optional(),
1979
+ text: z25.string().max(TOOL_TEXT_MAX).optional(),
1980
+ state: z25.enum(["open", "taken", "done", "refused", "dropped"]),
1981
+ result: z25.string().max(TOOL_TEXT_MAX).optional(),
1982
+ cut: z25.literal(true).optional(),
1983
+ at: z25.string(),
1984
+ updatedAt: z25.string(),
1985
+ seen: z25.literal(true).optional()
2124
1986
  }).strict();
2125
- var ChatErrorCodeSchema = z26.enum(["busy", "timeout", "cancelled", "failed"]);
2126
- var PhoneChatTurnSchema = z26.object({
1987
+ var ChatErrorCodeSchema = z25.enum(["busy", "timeout", "cancelled", "failed"]);
1988
+ var PhoneChatTurnSchema = z25.object({
2127
1989
  qid: OperationIdSchema,
2128
- question: z26.string().max(MESSAGE_MAX),
2129
- askedAt: z26.string().datetime(),
2130
- steps: z26.array(PhoneChatStepSchema).max(50),
2131
- answer: z26.string().max(THREAD_TEXT_MAX).optional(),
2132
- answeredAt: z26.string().datetime().optional(),
1990
+ question: z25.string().max(MESSAGE_MAX),
1991
+ askedAt: z25.string().datetime(),
1992
+ steps: z25.array(PhoneChatStepSchema).max(50),
1993
+ answer: z25.string().max(THREAD_TEXT_MAX).optional(),
1994
+ answeredAt: z25.string().datetime().optional(),
2133
1995
  error: ChatErrorCodeSchema.optional(),
2134
- proposals: z26.array(PhoneChatProposalSchema).max(MAX_PROPOSALS).optional(),
1996
+ proposals: z25.array(PhoneChatProposalSchema).max(MAX_PROPOSALS).optional(),
2135
1997
  relay: PhoneChatRelaySchema.optional(),
2136
- closes: z26.array(PhoneChatCloseSchema).min(1).max(MAX_PROPOSALS).optional(),
2137
- cut: z26.literal(true).optional(),
2138
- team: PhoneChatTeamSchema.optional(),
2139
- tasks: z26.array(PhoneChatTaskSchema).min(1).max(MAX_PROPOSALS).optional(),
2140
- actions: z26.array(PhoneChatActionSchema).min(1).max(MAX_PROPOSALS).optional(),
2141
- ignoredAt: z26.string().datetime().optional(),
2142
- attachments: z26.array(AttachmentRefSchema).max(ATTACHMENTS_MAX).optional()
1998
+ closes: z25.array(PhoneChatCloseSchema).min(1).max(MAX_PROPOSALS).optional(),
1999
+ cut: z25.literal(true).optional(),
2000
+ tasks: z25.array(PhoneChatTaskSchema).min(1).max(MAX_PROPOSALS).optional(),
2001
+ actions: z25.array(PhoneChatActionSchema).min(1).max(MAX_PROPOSALS).optional(),
2002
+ ignoredAt: z25.string().datetime().optional(),
2003
+ attachments: z25.array(AttachmentRefSchema).max(ATTACHMENTS_MAX).optional()
2143
2004
  }).strict();
2144
2005
  var CHAT_HISTORY_BUDGET = 393216;
2145
- var sessionId = z26.string().min(1).max(100);
2146
- var PhoneExpectSchema = PendingSchema.pick({ kind: true, text: true }).extend({ key: z26.string().min(1).max(64) });
2147
- 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");
2148
- var teamsOp = { op: OperationIdSchema, assertion: AssertionSchema.optional() };
2149
- var PcActionSchema = z26.enum(["update", "restart"]);
2006
+ var sessionId = z25.string().min(1).max(100);
2007
+ var PhoneExpectSchema = PendingSchema.pick({ kind: true, text: true }).extend({ key: z25.string().min(1).max(64) });
2008
+ 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");
2009
+ var pcOp = { op: OperationIdSchema, assertion: AssertionSchema.optional() };
2010
+ var PcActionSchema = z25.enum(["update", "restart"]);
2150
2011
  var pcSubject = (action, version) => action === "update" ? `update@${version ?? ""}` : "restart";
2151
- var teamsScope = { scope: DefinitionScopeSchema, project: z26.string().min(1).max(80).optional() };
2152
- var PhoneClientMessageSchema = z26.discriminatedUnion("type", [
2153
- z26.object({ type: z26.literal("snapshot.request") }),
2154
- z26.object({ type: z26.literal("session.thread"), id: sessionId }),
2012
+ var PhoneClientMessageSchema = z25.discriminatedUnion("type", [
2013
+ z25.object({ type: z25.literal("snapshot.request") }),
2014
+ z25.object({ type: z25.literal("session.thread"), id: sessionId }),
2155
2015
  /** The session's request with its whole body (up to `PENDING_BODY_MAX`). */
2156
- z26.object({ type: z26.literal("session.pending"), id: sessionId }),
2016
+ z25.object({ type: z25.literal("session.pending"), id: sessionId }),
2157
2017
  /** The session whose terminal the phone shows; null when it shows none. */
2158
- z26.object({ type: z26.literal("session.watch"), id: sessionId.nullable() }),
2159
- z26.object({ type: z26.literal("session.read"), id: sessionId, at: z26.string().datetime() }),
2018
+ z25.object({ type: z25.literal("session.watch"), id: sessionId.nullable() }),
2019
+ z25.object({ type: z25.literal("session.read"), id: sessionId, at: z25.string().datetime() }),
2160
2020
  /**
2161
2021
  * Asks for a challenge. One object for every purpose: the gateway refuses a `decide` without `id` and `expect`. A `close`
2162
2022
  * or `act` names a turn of the chat (`qid`) or a session (`id`, for `session.close` and `session.resume`).
2163
2023
  */
2164
- z26.object({
2165
- type: z26.literal("confirm.prepare"),
2024
+ z25.object({
2025
+ type: z25.literal("confirm.prepare"),
2166
2026
  purpose: ConfirmPurposeSchema,
2167
2027
  id: sessionId.optional(),
2168
2028
  expect: PhoneExpectSchema.optional(),
2169
2029
  qid: OperationIdSchema.optional(),
2170
- /** sha256 of the `define` or `team` operation the challenge is for (`teamsDigest`). */
2171
- digest: TeamsDigestSchema.optional(),
2172
2030
  /** A `pc` challenge: what it is for, and for an update the version it covers. */
2173
2031
  action: PcActionSchema.optional(),
2174
- version: z26.string().regex(SEMVER).optional()
2032
+ version: z25.string().regex(SEMVER).optional()
2175
2033
  }),
2176
- z26.object({ type: z26.literal("credential.register"), op: OperationIdSchema, credential: CredentialSchema }),
2177
- z26.object({
2178
- type: z26.literal("session.decide"),
2034
+ z25.object({ type: z25.literal("credential.register"), op: OperationIdSchema, credential: CredentialSchema }),
2035
+ z25.object({
2036
+ type: z25.literal("session.decide"),
2179
2037
  op: OperationIdSchema,
2180
2038
  id: sessionId,
2181
2039
  decision: DecisionSchema,
2182
- note: z26.string().trim().min(1).max(NOTE_MAX).optional(),
2040
+ note: z25.string().trim().min(1).max(NOTE_MAX).optional(),
2183
2041
  /** The request the phone showed: refused unless it is still the pending one. */
2184
2042
  expect: PhoneExpectSchema,
2185
2043
  /** The device check over the challenge of `confirm.prepare`; required by the daemon for a high-risk accept. */
2186
2044
  assertion: AssertionSchema.optional()
2187
2045
  }),
2188
- z26.object({
2189
- type: z26.literal("session.reply"),
2046
+ z25.object({
2047
+ type: z25.literal("session.reply"),
2190
2048
  op: OperationIdSchema,
2191
2049
  id: sessionId,
2192
- text: z26.string().max(MESSAGE_MAX),
2193
- attachments: z26.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional(),
2050
+ text: z25.string().max(MESSAGE_MAX),
2051
+ attachments: z25.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional(),
2194
2052
  /** The request the reply answers, or null when the phone showed none: refused if the session's request is no longer that one. */
2195
2053
  expect: PhoneExpectSchema.nullable(),
2196
2054
  assertion: AssertionSchema.optional()
2197
2055
  }),
2198
2056
  /** OMP's `ask`: the answers to every question of the dialog `requestId`, in order; `cancel` declines it. Bounds as the local `session.answer`. */
2199
- z26.object({
2200
- type: z26.literal("session.answer"),
2057
+ z25.object({
2058
+ type: z25.literal("session.answer"),
2201
2059
  op: OperationIdSchema,
2202
2060
  id: sessionId,
2203
- requestId: z26.string().min(1).max(200),
2204
- 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),
2205
- cancel: z26.literal(true).optional(),
2061
+ requestId: z25.string().min(1).max(200),
2062
+ 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),
2063
+ cancel: z25.literal(true).optional(),
2206
2064
  expect: PhoneExpectSchema
2207
2065
  }),
2208
- z26.object({ type: z26.literal("session.interrupt"), op: OperationIdSchema, id: sessionId }),
2066
+ z25.object({ type: z25.literal("session.interrupt"), op: OperationIdSchema, id: sessionId }),
2209
2067
  /** Ends a live session as `/exit` would, killed as a last resort; answered with its `how`. Passkey, purpose `close`, over the session. */
2210
- z26.object({ type: z26.literal("session.close"), op: OperationIdSchema, id: sessionId, assertion: AssertionSchema.optional() }),
2068
+ z25.object({ type: z25.literal("session.close"), op: OperationIdSchema, id: sessionId, assertion: AssertionSchema.optional() }),
2211
2069
  /** Starts an ended session again on its conversation. Passkey, purpose `act`, over the session. */
2212
- z26.object({ type: z26.literal("session.resume"), op: OperationIdSchema, id: sessionId, assertion: AssertionSchema.optional() }),
2070
+ z25.object({ type: z25.literal("session.resume"), op: OperationIdSchema, id: sessionId, assertion: AssertionSchema.optional() }),
2213
2071
  /** Changes a live session's model and effort, `null` for the agent's own default; answered by `operation.result` and, when refused, `session.model.failed`. */
2214
- z26.object({ type: z26.literal("session.model"), op: OperationIdSchema, id: sessionId, model: ModelIdSchema.nullable(), effort: EffortSchema.nullable() }),
2072
+ z25.object({ type: z25.literal("session.model"), op: OperationIdSchema, id: sessionId, model: ModelIdSchema.nullable(), effort: EffortSchema.nullable() }),
2215
2073
  /** The models an agent offers on the PC. */
2216
- z26.object({ type: z26.literal("models.list"), tool: ToolSchema }),
2074
+ z25.object({ type: z25.literal("models.list"), tool: ToolSchema }),
2217
2075
  /** The phone drops its passkey from the daemon. */
2218
- z26.object({ type: z26.literal("device.forget"), op: OperationIdSchema }),
2076
+ z25.object({ type: z25.literal("device.forget"), op: OperationIdSchema }),
2219
2077
  /** The phone's push subscription, with the VAPID key it was made with (so a key change is seen). */
2220
- z26.object({ type: z26.literal("push.subscribe"), op: OperationIdSchema, subscription: PushSubscriptionSchema, key: B64U2.length(87) }),
2221
- z26.object({ type: z26.literal("push.unsubscribe"), op: OperationIdSchema }),
2078
+ z25.object({ type: z25.literal("push.subscribe"), op: OperationIdSchema, subscription: PushSubscriptionSchema, key: B64U2.length(87) }),
2079
+ z25.object({ type: z25.literal("push.unsubscribe"), op: OperationIdSchema }),
2222
2080
  /** The phone's own chat with Ledge. */
2223
- z26.object({ type: z26.literal("chat.ask"), qid: OperationIdSchema, text: z26.string().trim().max(MESSAGE_MAX), attachments: z26.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional() }),
2224
- z26.object({ type: z26.literal("chat.cancel"), qid: OperationIdSchema }),
2225
- z26.object({ type: z26.literal("chat.reset") }),
2226
- z26.object({ type: z26.literal("chat.history") }),
2081
+ z25.object({ type: z25.literal("chat.ask"), qid: OperationIdSchema, text: z25.string().trim().max(MESSAGE_MAX), attachments: z25.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional() }),
2082
+ z25.object({ type: z25.literal("chat.cancel"), qid: OperationIdSchema }),
2083
+ z25.object({ type: z25.literal("chat.reset") }),
2084
+ z25.object({ type: z25.literal("chat.history") }),
2227
2085
  /** An image to store, sent alone before the message that names it; no `id`, and at most `ATTACHMENT_MAX` bytes. */
2228
- AttachmentPutSchema.pick({ type: true, requestId: true }).extend({ image: ImageUploadSchema.extend({ data: z26.string().min(1).max(b64Max(ATTACHMENT_MAX)) }) }),
2086
+ AttachmentPutSchema.pick({ type: true, requestId: true }).extend({ image: ImageUploadSchema.extend({ data: z25.string().min(1).max(b64Max(ATTACHMENT_MAX)) }) }),
2229
2087
  AttachmentGetSchema.pick({ type: true, requestId: true, attachment: true, preview: true }),
2230
- z26.object({ type: z26.literal("chat.relay"), op: OperationIdSchema, qid: OperationIdSchema }),
2088
+ z25.object({ type: z25.literal("chat.relay"), op: OperationIdSchema, qid: OperationIdSchema }),
2231
2089
  /** Takes the card's queued instruction back out of the queue, as the local `session.relay.cancel`. */
2232
- z26.object({ type: z26.literal("chat.relay.cancel"), op: OperationIdSchema, qid: OperationIdSchema }),
2233
- z26.object({ type: z26.literal("chat.launch"), op: OperationIdSchema, qid: OperationIdSchema, rows: CardRowsSchema.optional(), assertion: AssertionSchema.optional() }),
2234
- z26.object({ type: z26.literal("chat.close"), op: OperationIdSchema, qid: OperationIdSchema, rows: CardRowsSchema.optional(), assertion: AssertionSchema.optional() }),
2235
- /** The turn's team card (roles spec §3.8): launched like a session card, with the device check (purpose `launch`, the turn). */
2236
- z26.object({ type: z26.literal("chat.team"), op: OperationIdSchema, qid: OperationIdSchema, assertion: AssertionSchema.optional() }),
2090
+ z25.object({ type: z25.literal("chat.relay.cancel"), op: OperationIdSchema, qid: OperationIdSchema }),
2091
+ z25.object({ type: z25.literal("chat.launch"), op: OperationIdSchema, qid: OperationIdSchema, rows: CardRowsSchema.optional(), assertion: AssertionSchema.optional() }),
2092
+ z25.object({ type: z25.literal("chat.close"), op: OperationIdSchema, qid: OperationIdSchema, rows: CardRowsSchema.optional(), assertion: AssertionSchema.optional() }),
2237
2093
  /** A row of the turn's task card: given by Ledge. */
2238
- z26.object({ type: z26.literal("chat.task"), op: OperationIdSchema, qid: OperationIdSchema, row: z26.number().int().min(0).max(MAX_PROPOSALS - 1) }),
2094
+ z25.object({ type: z25.literal("chat.task"), op: OperationIdSchema, qid: OperationIdSchema, row: z25.number().int().min(0).max(MAX_PROPOSALS - 1) }),
2239
2095
  /** Rows of the turn's generic card (action registry spec §5): `confirmed` as the local `chat.act`; a row whose action asks
2240
2096
  * for a device check (`phone`) needs one assertion, purpose `act`, over the turn. */
2241
- z26.object({
2242
- type: z26.literal("chat.act"),
2097
+ z25.object({
2098
+ type: z25.literal("chat.act"),
2243
2099
  op: OperationIdSchema,
2244
2100
  qid: OperationIdSchema,
2245
2101
  rows: CardRowsSchema.optional(),
2246
- confirmed: z26.literal(true).optional(),
2102
+ confirmed: z25.literal(true).optional(),
2247
2103
  assertion: AssertionSchema.optional(),
2248
2104
  /** « Refuser », as the local `chat.act`: no passkey, no confirmation. */
2249
- deny: z26.literal(true).optional()
2105
+ deny: z25.literal(true).optional()
2250
2106
  }),
2251
2107
  /** « Ignorer » the turn's cards, or `undo` (« Revoir »), as the local `chat.ignore`. */
2252
- z26.object({ type: z26.literal("chat.ignore"), op: OperationIdSchema, qid: OperationIdSchema, undo: z26.literal(true).optional() }),
2253
- /** « Reprendre » a resting team. */
2254
- z26.object({ type: z26.literal("team.resume"), op: OperationIdSchema, team: z26.string().min(1).max(40) }),
2108
+ z25.object({ type: z25.literal("chat.ignore"), op: OperationIdSchema, qid: OperationIdSchema, undo: z25.literal(true).optional() }),
2255
2109
  /** Puts a closed task Ledge gave away from « À traiter ». */
2256
- z26.object({ type: z26.literal("task.seen"), op: OperationIdSchema, task: z26.string().min(1).max(40) }),
2110
+ z25.object({ type: z25.literal("task.seen"), op: OperationIdSchema, task: z25.string().min(1).max(40) }),
2257
2111
  /** Whether the phone's app is in front: a device that is visible gets no push. */
2258
- z26.object({ type: z26.literal("presence"), visible: z26.boolean() }),
2259
- /** The roles, templates and problems of every scope the phone may name; then one role whole, when the catalog cut its prompt. */
2260
- z26.object({ type: z26.literal("teams.catalog") }),
2261
- z26.object({ type: z26.literal("teams.role"), ...teamsScope, id: RoleIdSchema }).strict(),
2262
- /** `base` is the hash the phone was shown, null to create. */
2263
- z26.object({ type: z26.literal("role.write"), ...teamsOp, ...teamsScope, role: PhoneRoleDraftSchema, base: DefinitionHashSchema.nullable() }).strict(),
2264
- z26.object({ type: z26.literal("role.delete"), ...teamsOp, ...teamsScope, id: RoleIdSchema, base: DefinitionHashSchema }).strict(),
2265
- /** No `id`: create, the id comes from the name. */
2266
- z26.object({ type: z26.literal("template.write"), ...teamsOp, ...teamsScope, id: TemplateIdSchema.optional(), name: TeamNameSchema, seats: PhoneSeatsSchema, base: DefinitionHashSchema.nullable() }).strict(),
2267
- z26.object({ type: z26.literal("template.delete"), ...teamsOp, ...teamsScope, id: TemplateIdSchema, base: DefinitionHashSchema }).strict(),
2268
- 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(),
2269
- z26.object({ type: z26.literal("team.compose"), ...teamsOp, team: TeamIdSchema, seats: PhoneSeatsSchema }).strict(),
2270
- z26.object({ type: z26.literal("team.seat"), ...teamsOp, team: TeamIdSchema, role: RoleIdSchema, action: z26.enum(["start", "restart"]) }).strict(),
2271
- z26.object({ type: z26.literal("team.dissolve"), ...teamsOp, team: TeamIdSchema }).strict(),
2112
+ z25.object({ type: z25.literal("presence"), visible: z25.boolean() }),
2272
2113
  /** Installs `version` on the PC, then restarts its daemon; the phone asks for its own build's version. Passkey, purpose `pc`. */
2273
- z26.object({ type: z26.literal("daemon.update"), ...teamsOp, version: z26.string().regex(SEMVER) }).strict(),
2114
+ z25.object({ type: z25.literal("daemon.update"), ...pcOp, version: z25.string().regex(SEMVER) }).strict(),
2274
2115
  /** Restarts the PC's daemon without installing anything. Passkey, purpose `pc`. */
2275
- z26.object({ type: z26.literal("daemon.restart"), ...teamsOp }).strict()
2276
- ]).superRefine((m, ctx) => {
2277
- const issue = "scope" in m ? scopeIssue(m) : null;
2278
- if (issue) ctx.addIssue({ code: z26.ZodIssueCode.custom, message: issue, path: ["project"] });
2279
- });
2280
- var PhoneModelChoiceSchema = z26.object({
2116
+ z25.object({ type: z25.literal("daemon.restart"), ...pcOp }).strict()
2117
+ ]);
2118
+ var PhoneModelChoiceSchema = z25.object({
2281
2119
  id: ModelChoiceSchema.shape.id.max(120),
2282
- label: z26.string().max(80),
2283
- description: z26.string().max(200).optional(),
2284
- efforts: z26.array(EffortSchema).max(8).optional(),
2120
+ label: z25.string().max(80),
2121
+ description: z25.string().max(200).optional(),
2122
+ efforts: z25.array(EffortSchema).max(8).optional(),
2285
2123
  defaultEffort: EffortSchema.optional(),
2286
- isDefault: z26.boolean().optional()
2124
+ isDefault: z25.boolean().optional()
2287
2125
  }).strict();
2288
- var PhoneSeatModelSchema = z26.object({ role: z26.string().max(40), session: sessionId, status: z26.enum(["applied", "scheduled", "refused"]), reason: ModelRefusalSchema.optional() });
2289
- var PhoneServerMessageSchema = z26.discriminatedUnion("type", [
2290
- z26.object({ type: z26.literal("snapshot"), protocol: z26.literal(PHONE_PROTOCOL), sessions: z26.array(PhoneSessionSchema), capabilities: CapabilitiesByToolSchema, daemon: z26.object({
2291
- version: z26.string(),
2292
- name: z26.string().max(40),
2293
- boot: z26.string().uuid().optional(),
2294
- teams: z26.literal(true).optional(),
2126
+ var PhoneServerMessageSchema = z25.discriminatedUnion("type", [
2127
+ z25.object({ type: z25.literal("snapshot"), protocol: z25.literal(PHONE_PROTOCOL), sessions: z25.array(PhoneSessionSchema), capabilities: CapabilitiesByToolSchema, daemon: z25.object({
2128
+ version: z25.string(),
2129
+ name: z25.string().max(40),
2130
+ boot: z25.string().uuid().optional(),
2295
2131
  /** The daemon takes `session.model`. */
2296
- models: z26.literal(true).optional(),
2132
+ models: z25.literal(true).optional(),
2297
2133
  /** The daemon sends `session.checklist` and a session's `checklist` summary. */
2298
- checklist: z26.literal(true).optional(),
2134
+ checklist: z25.literal(true).optional(),
2299
2135
  /** `update`: the daemon can install a version and restart (npm, systemd); `restart`: it can restart (systemd). */
2300
- update: z26.literal(true).optional(),
2301
- restart: z26.literal(true).optional(),
2136
+ update: z25.literal(true).optional(),
2137
+ restart: z25.literal(true).optional(),
2302
2138
  /** The daemon takes `session.close` and `session.resume`. */
2303
- sessionClose: z26.literal(true).optional()
2304
- }), 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() }),
2305
- z26.object({
2306
- type: z26.literal("confirm.challenge"),
2307
- purpose: ConfirmPurposeSchema,
2308
- challenge: B64U2.max(64),
2309
- rpId: z26.string().max(253),
2310
- credentialId: B64U2.max(1366).optional(),
2311
- expiresInMs: z26.number().int().positive(),
2312
- /** 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. */
2313
- digest: TeamsDigestSchema.optional()
2314
- }),
2315
- z26.object({ type: z26.literal("session.updated"), session: PhoneSessionSchema }),
2316
- z26.object({ type: z26.literal("session.removed"), id: z26.string() }),
2139
+ sessionClose: z25.literal(true).optional()
2140
+ }), 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() }),
2141
+ 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() }),
2142
+ z25.object({ type: z25.literal("session.updated"), session: PhoneSessionSchema }),
2143
+ z25.object({ type: z25.literal("session.removed"), id: z25.string() }),
2317
2144
  /** A session's checklist, sent to the phone that watches it; `null`: it has none (any more). */
2318
- z26.object({ type: z26.literal("session.checklist"), id: z26.string(), checklist: PhoneChecklistSchema.nullable() }),
2145
+ z25.object({ type: z25.literal("session.checklist"), id: z25.string(), checklist: PhoneChecklistSchema.nullable() }),
2319
2146
  /** `pending.cut` is set when even this body was shortened. */
2320
- z26.object({ type: z26.literal("session.pending"), id: z26.string(), pending: PhonePendingSchema }),
2321
- z26.object({ type: z26.literal("session.preview"), id: z26.string(), lines: z26.array(z26.string()) }),
2147
+ z25.object({ type: z25.literal("session.pending"), id: z25.string(), pending: PhonePendingSchema }),
2148
+ z25.object({ type: z25.literal("session.preview"), id: z25.string(), lines: z25.array(z25.string()) }),
2322
2149
  /** `cut`: the ids of the items shortened; `more`: older items were left out. */
2323
- z26.object({ type: z26.literal("session.thread"), id: z26.string(), items: z26.array(ThreadItemSchema), cut: z26.array(z26.string()), more: z26.boolean() }),
2324
- z26.object({ type: z26.literal("session.thread.item"), id: z26.string(), item: ThreadItemSchema, cut: z26.literal(true).optional() }),
2325
- z26.object({
2326
- type: z26.literal("operation.result"),
2150
+ z25.object({ type: z25.literal("session.thread"), id: z25.string(), items: z25.array(ThreadItemSchema), cut: z25.array(z25.string()), more: z25.boolean() }),
2151
+ z25.object({ type: z25.literal("session.thread.item"), id: z25.string(), item: ThreadItemSchema, cut: z25.literal(true).optional() }),
2152
+ z25.object({
2153
+ type: z25.literal("operation.result"),
2327
2154
  op: OperationIdSchema,
2328
2155
  status: OperationStatusSchema,
2329
2156
  reason: OperationReasonSchema.optional(),
2330
- models: z26.array(PhoneSeatModelSchema).max(16).optional(),
2331
2157
  /** How an applied `session.close` ended the agent: `killed` when it had to be forced. */
2332
2158
  how: CloseHowSchema.optional()
2333
2159
  }),
2334
2160
  /** The models an agent offers; `error`: it could not be asked, `models` is then what Ledge knows without it. */
2335
- z26.object({ type: z26.literal("models.listing"), tool: ToolSchema, models: z26.array(PhoneModelChoiceSchema).max(40), error: z26.literal(true).optional() }),
2161
+ z25.object({ type: z25.literal("models.listing"), tool: ToolSchema, models: z25.array(PhoneModelChoiceSchema).max(40), error: z25.literal(true).optional() }),
2336
2162
  /** A model change that was accepted and then failed (the agent could not restart). */
2337
- z26.object({ type: z26.literal("session.model.failed"), id: z26.string(), reason: ModelRefusalSchema }),
2338
- z26.object({ type: z26.literal("chat.history"), turns: z26.array(PhoneChatTurnSchema).max(50) }),
2339
- z26.object({ type: z26.literal("chat.step"), qid: OperationIdSchema, step: PhoneChatStepSchema }),
2163
+ z25.object({ type: z25.literal("session.model.failed"), id: z25.string(), reason: ModelRefusalSchema }),
2164
+ z25.object({ type: z25.literal("chat.history"), turns: z25.array(PhoneChatTurnSchema).max(50) }),
2165
+ z25.object({ type: z25.literal("chat.step"), qid: OperationIdSchema, step: PhoneChatStepSchema }),
2340
2166
  /** The whole text so far, not an increment. */
2341
- z26.object({ type: z26.literal("chat.delta"), qid: OperationIdSchema, text: z26.string().max(THREAD_TEXT_MAX) }),
2342
- z26.object({ type: z26.literal("chat.done"), qid: OperationIdSchema, turn: PhoneChatTurnSchema }),
2343
- z26.object({ type: z26.literal("chat.error"), qid: OperationIdSchema, code: ChatErrorCodeSchema }),
2344
- z26.object({ type: z26.literal("teams.catalog"), catalog: PhoneCatalogSchema }),
2167
+ z25.object({ type: z25.literal("chat.delta"), qid: OperationIdSchema, text: z25.string().max(THREAD_TEXT_MAX) }),
2168
+ z25.object({ type: z25.literal("chat.done"), qid: OperationIdSchema, turn: PhoneChatTurnSchema }),
2169
+ z25.object({ type: z25.literal("chat.error"), qid: OperationIdSchema, code: ChatErrorCodeSchema }),
2345
2170
  /** The daemon updating or restarting itself, whoever asked: npm runs, then the service restarts (the link drops right after). */
2346
- z26.object({ type: z26.literal("daemon.progress"), version: z26.string().max(40), step: z26.enum(["installing", "restarting"]) }),
2171
+ z25.object({ type: z25.literal("daemon.progress"), version: z25.string().max(40), step: z25.enum(["installing", "restarting"]) }),
2347
2172
  /** Nothing was changed. Never npm's output nor a command: both hold the PC's paths. */
2348
- z26.object({ type: z26.literal("daemon.failed"), version: z26.string().max(40), reason: UpdateFailureSchema }),
2349
- z26.object({ type: z26.literal("teams.role"), role: PhoneRoleSchema }),
2350
- /** The live teams, after each snapshot and on every change. */
2351
- z26.object({ type: z26.literal("teams"), teams: z26.array(PhoneTeamSchema).max(50) }),
2173
+ z25.object({ type: z25.literal("daemon.failed"), version: z25.string().max(40), reason: UpdateFailureSchema }),
2352
2174
  /** The tasks Ledge gave, open or closed lately, after each snapshot; then each change. */
2353
- z26.object({ type: z26.literal("tasks"), tasks: z26.array(PhoneTaskSchema).max(200) }),
2354
- z26.object({ type: z26.literal("task.updated"), task: PhoneTaskSchema }),
2175
+ z25.object({ type: z25.literal("tasks"), tasks: z25.array(PhoneTaskSchema).max(200) }),
2176
+ z25.object({ type: z25.literal("task.updated"), task: PhoneTaskSchema }),
2355
2177
  AttachmentStoredSchema,
2356
2178
  AttachmentDataSchema,
2357
2179
  AttachmentErrorSchema,
2358
2180
  /** Never carries free text. */
2359
- z26.object({ type: z26.literal("error"), code: z26.enum(["invalid", "unknown_session", "too_large"]), request: z26.string().max(40).optional() })
2181
+ z25.object({ type: z25.literal("error"), code: z25.enum(["invalid", "unknown_session", "too_large"]), request: z25.string().max(40).optional() })
2360
2182
  ]);
2361
- var teamsPurpose = (type) => type.startsWith("team.") ? "team" : "define";
2362
- var DIGEST_OP = "00000000-0000-4000-8000-000000000000";
2363
- async function teamsDigest(m) {
2364
- const { op: _op, assertion: _assertion, ...raw } = m;
2365
- const { op: _parsedOp, assertion: _parsedAssertion, ...rest } = PhoneClientMessageSchema.parse({ ...raw, op: DIGEST_OP });
2366
- const bytes = new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(canonicalJson(rest))));
2367
- return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
2368
- }
2369
2183
 
2370
2184
  // ../protocol/src/todos.ts
2371
2185
  var TODO_TOOLS = /* @__PURE__ */ new Set(["TodoWrite", "update_plan", "todo"]);
@@ -2558,8 +2372,6 @@ export {
2558
2372
  contextNear,
2559
2373
  BRIEF_MAX,
2560
2374
  ToolSchema,
2561
- autonomyArgs,
2562
- ompApprovalFor,
2563
2375
  SessionSchema,
2564
2376
  backendOf,
2565
2377
  isArchived,
@@ -2569,25 +2381,8 @@ export {
2569
2381
  extractProposal,
2570
2382
  parseRelayBlock,
2571
2383
  parseCloseBlock,
2572
- parseTeamBlock,
2573
2384
  parseTaskBlock,
2574
2385
  parseProjectBlock,
2575
- SshAliasSchema,
2576
- MachinesSchema,
2577
- PROJECT_COLORS,
2578
- ProjectsSchema,
2579
- DEFAULT_PROJECTS,
2580
- projectOf,
2581
- RoleIdSchema,
2582
- ROLE_LABEL_MAX,
2583
- ROLE_PROMPT_MAX,
2584
- RoleSchema,
2585
- TEAM_SEATS_MAX,
2586
- SeatsSchema,
2587
- TeamNameSchema,
2588
- TemplateIdSchema,
2589
- TeamSchema,
2590
- isTeamLive,
2591
2386
  NOTE_MAX,
2592
2387
  NOTE_NOT_TYPED,
2593
2388
  offers,
@@ -2611,7 +2406,20 @@ export {
2611
2406
  ChatTurnSchema,
2612
2407
  proposalRows,
2613
2408
  DOCUMENT_MAX_BYTES,
2409
+ SshAliasSchema,
2410
+ MachinesSchema,
2614
2411
  IslandPrefsSchema,
2412
+ PROJECT_COLORS,
2413
+ ProjectsSchema,
2414
+ DEFAULT_PROJECTS,
2415
+ projectOf,
2416
+ RigSeatNameSchema,
2417
+ KERNEL_RIG,
2418
+ rigCommands,
2419
+ showRigCommand,
2420
+ RIG_POLICIES,
2421
+ seatsByRole,
2422
+ seatPlan,
2615
2423
  RouteResultSchema,
2616
2424
  DEFAULT_RELAY_URL,
2617
2425
  MobileConfigSchema,
@@ -2625,6 +2433,7 @@ export {
2625
2433
  parseServerMessage,
2626
2434
  NAMES,
2627
2435
  pickName,
2436
+ namesInUse,
2628
2437
  TOPIC_MAX,
2629
2438
  cleanTopic,
2630
2439
  sessionTitle,
@@ -2637,11 +2446,6 @@ export {
2637
2446
  pushEndpointAllowed,
2638
2447
  PushSendResultSchema,
2639
2448
  PushPayloadSchema,
2640
- PhoneRoleSchema,
2641
- PhoneTemplateSchema,
2642
- TEAMS_OPERATION_TYPES,
2643
- isTeamsOperation,
2644
- canonicalJson,
2645
2449
  PHONE_PROTOCOL,
2646
2450
  padPlain,
2647
2451
  THREAD_ITEMS_MAX,
@@ -2658,8 +2462,6 @@ export {
2658
2462
  pcSubject,
2659
2463
  PhoneClientMessageSchema,
2660
2464
  PhoneModelChoiceSchema,
2661
- teamsPurpose,
2662
- teamsDigest,
2663
2465
  TODO_TOOLS,
2664
2466
  latestTodos,
2665
2467
  doneCount,