@paradow/ledge 0.32.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-HUKZUHQ7.js → action-K42H5BDA.js} +5 -5
  2. package/dist/cli/{attach-ILMHKRUI.js → attach-KEE4A5YP.js} +28 -15
  3. package/dist/cli/{bridge-LFKUCKQP.js → bridge-X327AZY4.js} +2 -2
  4. package/dist/cli/{chunk-VGAPV4DC.js → chunk-25RVT5MR.js} +3 -103
  5. package/dist/cli/{chunk-Q6RMLRPI.js → chunk-3OJCWJAA.js} +2 -2
  6. package/dist/cli/chunk-4OYVM4MT.js +49 -0
  7. package/dist/cli/{chunk-IE52REEI.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-CXZETRPA.js → chunk-7NHQGP6J.js} +1 -1
  11. package/dist/cli/{chunk-U7J2AN3F.js → chunk-G7XPEVCG.js} +5 -5
  12. package/dist/cli/{chunk-2BLPGRLO.js → chunk-IWY7DSSO.js} +835 -1030
  13. package/dist/cli/{chunk-SUBKKCGA.js → chunk-KPDTYX7F.js} +3 -3
  14. package/dist/cli/chunk-RPH773TY.js +6 -0
  15. package/dist/cli/{chunk-YHZIHIGI.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-OPUIV6PR.js → chunk-ULOMKEB6.js} +4 -4
  19. package/dist/cli/{chunk-5JNJFBKZ.js → chunk-V4XKKL6K.js} +13 -40
  20. package/dist/cli/{chunk-EGXOBQZI.js → daemon-RO43S3S5.js} +4655 -2964
  21. package/dist/cli/{decide-3B6LGVNN.js → decide-KZFYL3HY.js} +5 -5
  22. package/dist/cli/{handover-IX7EFDIP.js → handover-BWNMI2RA.js} +5 -5
  23. package/dist/cli/{hook-G7UA6MB6.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-55RWY4LZ.js → send-SXZAPVRH.js} +5 -5
  27. package/dist/cli/{setup-K42IVMHS.js → setup-TJ32FMVJ.js} +4 -4
  28. package/dist/cli/{status-NT5ZUYM6.js → status-YDVRES4E.js} +3 -3
  29. package/dist/cli/{task-GABQ4SKY.js → task-TUSOVJK7.js} +5 -5
  30. package/dist/cli/{tui-AMW2XAH5.js → tui-TCVIRZCQ.js} +1411 -1277
  31. package/dist/cli/{uninstall-4IMMR55T.js → uninstall-QO7YMSLA.js} +4 -4
  32. package/dist/cli/{version-35XLTEMX.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-5FKHISVK.js +0 -160
  37. package/dist/cli/chunk-M7364G3S.js +0 -6
  38. package/dist/cli/chunk-QQVWFOPU.js +0 -290
  39. package/dist/cli/daemon-UJTMG3D4.js +0 -2322
  40. package/dist/cli/launch-2GZIRF3A.js +0 -36
  41. package/dist/cli/team-IK2RYXW2.js +0 -205
  42. package/dist/cli/who-4FRIGYVT.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,290 +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
- });
230
- var MachinesSchema = z5.array(MachineSchema).min(1).max(20).superRefine((list, ctx) => {
231
- if (list[0]?.id !== "local" || list[0].ssh !== void 0) ctx.addIssue({ code: "custom", message: "the first machine is local, without ssh", path: [0] });
232
- const ids = /* @__PURE__ */ new Set(), aliases = /* @__PURE__ */ new Set();
233
- list.forEach((m, i) => {
234
- if (i > 0 && !m.ssh) ctx.addIssue({ code: "custom", message: "a remote machine needs an ssh alias", path: [i, "ssh"] });
235
- if (ids.has(m.id)) ctx.addIssue({ code: "custom", message: `duplicate id ${m.id}`, path: [i, "id"] });
236
- ids.add(m.id);
237
- if (m.ssh) {
238
- if (aliases.has(m.ssh)) ctx.addIssue({ code: "custom", message: `duplicate ssh alias ${m.ssh}`, path: [i, "ssh"] });
239
- aliases.add(m.ssh);
240
- }
241
- });
242
- });
243
-
244
- // ../protocol/src/projects.ts
245
- var PROJECT_COLORS = { blue: "#3b82f6", green: "#10b981", amber: "#f59e0b", violet: "#8b5cf6", teal: "#14b8a6", pink: "#ec4899", red: "#ef4444", slate: "#64748b" };
246
- var ProjectColorSchema = z6.enum(["blue", "green", "amber", "violet", "teal", "pink", "red", "slate"]);
247
- var ProjectIdSchema = z6.string().regex(/^[a-z0-9][a-z0-9-]{0,63}$/);
248
- function normalizePath(raw) {
249
- const p = raw.trim().replace(/\/+/g, "/");
250
- return p.length > 1 && p.endsWith("/") ? p.slice(0, -1) : p;
251
- }
252
- var PathSchema = z6.string().max(4096).refine((p) => p.startsWith("/") && p === normalizePath(p), "an absolute, normalized path");
253
- var RepoSchema = z6.object({ machine: MachineIdSchema, path: PathSchema });
254
- var ProjectSchema = z6.object({
255
- id: ProjectIdSchema,
256
- name: z6.string().trim().min(1).max(80),
257
- color: ProjectColorSchema,
258
- description: z6.string().max(500).default(""),
259
- repos: z6.array(RepoSchema).max(50)
260
- });
261
- var RuleSchema = z6.object({ machine: MachineIdSchema, path: PathSchema, project: ProjectIdSchema });
262
- function projectsProblems(p) {
263
- const out = [];
264
- const ids = /* @__PURE__ */ new Set(), names = /* @__PURE__ */ new Set(), repos = /* @__PURE__ */ new Set(), rules = /* @__PURE__ */ new Set();
265
- p.projects.forEach((project, i) => {
266
- if (ids.has(project.id)) out.push({ code: "duplicate_id", path: ["projects", i, "id"] });
267
- ids.add(project.id);
268
- const name = project.name.trim().toLocaleLowerCase();
269
- if (names.has(name)) out.push({ code: "duplicate_name", path: ["projects", i, "name"] });
270
- names.add(name);
271
- project.repos.forEach((repo, j) => {
272
- const key = `${repo.machine}
273
- ${repo.path}`;
274
- if (repos.has(key)) out.push({ code: "duplicate_repo", path: ["projects", i, "repos", j] });
275
- repos.add(key);
276
- });
277
- });
278
- p.rules.forEach((rule, i) => {
279
- const key = `${rule.machine}
280
- ${rule.path}`;
281
- if (rules.has(key)) out.push({ code: "duplicate_rule", path: ["rules", i] });
282
- rules.add(key);
283
- if (!ids.has(rule.project)) out.push({ code: "unknown_project", path: ["rules", i, "project"] });
284
- });
285
- return out;
286
- }
287
- var ProjectsSchema = z6.object({ projects: z6.array(ProjectSchema).max(100), rules: z6.array(RuleSchema).max(1e3) }).superRefine((p, ctx) => {
288
- for (const problem of projectsProblems(p)) ctx.addIssue({ code: "custom", message: problem.code, path: problem.path });
289
- });
290
- var DEFAULT_PROJECTS = { projects: [], rules: [] };
291
- var under = (cwd, path2) => path2 === "/" || cwd === path2 || cwd.startsWith(`${path2}/`);
292
- function projectOf(session, state) {
293
- const machine = session.machineId ?? "local";
294
- const cwd = normalizePath(session.cwd);
295
- const known = new Set(state.projects.map((p) => p.id));
296
- const candidates = [
297
- ...state.projects.flatMap((p) => p.repos.filter((r) => r.machine === machine).map((r) => ({ project: p.id, path: r.path, rule: false }))),
298
- ...state.rules.filter((r) => r.machine === machine && known.has(r.project)).map((r) => ({ project: r.project, path: r.path, rule: true }))
299
- ].filter((c) => under(cwd, c.path));
300
- candidates.sort((x, y) => y.path.length - x.path.length || Number(y.rule) - Number(x.rule));
301
- return candidates[0]?.project ?? null;
302
- }
303
-
304
- // ../protocol/src/teams.ts
305
- var RoleIdSchema = z7.string().regex(/^[a-z0-9][a-z0-9_-]{0,39}$/);
306
- var ROLE_LABEL_MAX = 40;
307
- var ROLE_PROMPT_MAX = 8e3;
308
- var DefinitionHashSchema = z7.string().regex(/^[0-9a-f]{16}$/);
309
- var RoleSchema = z7.object({
310
- id: RoleIdSchema,
311
- label: z7.string().min(1).max(ROLE_LABEL_MAX),
312
- prompt: z7.string().max(ROLE_PROMPT_MAX),
313
- tool: ToolSchema.optional(),
314
- model: ModelIdSchema.optional(),
315
- effort: EffortSchema.optional(),
316
- autonomy: AutonomySchema.optional(),
317
- source: z7.enum(["repo", "home"]),
318
- path: z7.string(),
319
- shadows: z7.string().optional(),
320
- /** 16 hex chars of the file's text: what a write or delete must name as its base (absent from older daemons). */
321
- hash: DefinitionHashSchema.optional()
322
- });
323
- var DefinitionProblemSchema = z7.object({ path: z7.string(), reason: z7.string() });
324
- var TEAM_SEATS_MAX = 8;
325
- var SeatSchema = z7.object({
326
- role: RoleIdSchema,
327
- tool: ToolSchema.optional(),
328
- model: ModelIdSchema.optional(),
329
- effort: EffortSchema.optional(),
330
- name: z7.string().min(1).max(40).optional()
331
- });
332
- var uniqueRoles = (seats) => new Set(seats.map((s) => s.role)).size === seats.length;
333
- var SeatsSchema = z7.array(SeatSchema).min(1).max(TEAM_SEATS_MAX).refine(uniqueRoles, "a role twice in one team");
334
- var TeamNameSchema = z7.string().trim().min(1).max(60);
335
- var TemplateIdSchema = z7.string().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/);
336
- 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() });
337
- var TeamIdSchema = z7.string().regex(/^team-[0-9a-f]{4,8}$/);
338
- var TeamStateSchema = z7.enum(["active", "resting", "dissolved"]);
339
- var TeamSchema = z7.object({
340
- id: TeamIdSchema,
341
- name: TeamNameSchema,
342
- template: z7.string().optional(),
343
- project: z7.string().nullable(),
344
- machine: z7.string(),
345
- cwd: z7.string(),
346
- state: TeamStateSchema,
347
- /** A live seat: `tool`, `model` and `effort` are what it was composed with over the role's defaults, `name` the bot name it asks
348
- * for (its template's or its composition's); `leaving` marks a seat removed from the composition that finishes its turn and then is closed. */
349
- seats: z7.array(z7.object({
350
- role: RoleIdSchema,
351
- sessionId: z7.string().nullable(),
352
- tool: ToolSchema.optional(),
353
- model: ModelIdSchema.optional(),
354
- effort: EffortSchema.optional(),
355
- name: SeatSchema.shape.name,
356
- leaving: z7.literal(true).optional()
357
- })).max(TEAM_SEATS_MAX * 2),
358
- createdAt: z7.string(),
359
- updatedAt: z7.string(),
360
- restingAt: z7.string().optional(),
361
- dissolvedAt: z7.string().optional()
362
- });
363
- 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() });
364
- var RolesListingSchema = z7.object({
365
- type: z7.literal("roles.listing"),
366
- requestId: z7.string().optional(),
367
- roles: z7.array(RoleSchema),
368
- templates: z7.array(TeamTemplateSchema).default([]),
369
- problems: z7.array(DefinitionProblemSchema),
370
- /** Set by the fleet when the project's machine could not answer (#99): 'offline', or 'outdated' for a daemon without roles.list. */
371
- error: z7.string().optional()
372
- });
373
- var TeamLaunchSchema = z7.object({
374
- type: z7.literal("team.launch"),
375
- rid: z7.string().min(1).max(100),
376
- cwd: z7.string().min(1).optional(),
377
- template: z7.string().min(1).max(64).optional(),
378
- seats: SeatsSchema.optional(),
379
- name: TeamNameSchema.optional(),
380
- qid: z7.string().min(1).optional(),
381
- machineId: z7.string().optional(),
382
- /** The project's name, for a client that holds no path (the phone): the daemon resolves its folder. */
383
- project: ProjectIdSchema.optional()
384
- });
385
- var TeamJoinSchema = z7.object({ type: z7.literal("team.join"), team: TeamIdSchema, session: z7.string().min(1), role: RoleIdSchema });
386
- var TeamLeaveSchema = z7.object({ type: z7.literal("team.leave"), team: TeamIdSchema, session: z7.string().min(1) });
387
- var TeamResumeSchema = z7.object({ type: z7.literal("team.resume"), team: TeamIdSchema });
388
- var TeamDissolveSchema = z7.object({ type: z7.literal("team.dissolve"), team: TeamIdSchema });
389
- 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() });
390
- var DefinitionScopeSchema = z7.enum(["home", "repo"]);
391
- var RoleDraftSchema = RoleSchema.pick({ id: true, label: true, prompt: true, tool: true, model: true, effort: true, autonomy: true });
392
- var DefinitionCodeSchema = z7.enum(["changed", "exists", "missing", "unknown_project", "invalid"]);
393
- var scopeFields = { rid: z7.string().min(1).max(100), scope: DefinitionScopeSchema, project: ProjectIdSchema.optional() };
394
- 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";
395
- var DefinitionBaseSchema = DefinitionHashSchema;
396
- var DefinitionsListSchema = z7.object({ type: z7.literal("definitions.list"), requestId: z7.string().max(100).optional() });
397
- var RoleWriteSchema = z7.object({ type: z7.literal("role.write"), ...scopeFields, role: RoleDraftSchema, base: DefinitionBaseSchema.nullable() });
398
- var RoleDeleteSchema = z7.object({ type: z7.literal("role.delete"), ...scopeFields, id: RoleIdSchema, base: DefinitionBaseSchema });
399
- var TemplateWriteSchema = z7.object({
400
- type: z7.literal("template.write"),
401
- ...scopeFields,
402
- id: TemplateIdSchema.optional(),
403
- name: TeamNameSchema,
404
- seats: SeatsSchema,
405
- base: DefinitionBaseSchema.nullable()
406
- });
407
- var TemplateDeleteSchema = z7.object({ type: z7.literal("template.delete"), ...scopeFields, id: TemplateIdSchema, base: DefinitionBaseSchema });
408
- var TeamComposeSchema = z7.object({ type: z7.literal("team.compose"), rid: z7.string().min(1).max(100), team: TeamIdSchema, seats: SeatsSchema });
409
- 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"]) });
410
- var DefinitionsListingSchema = z7.object({
411
- type: z7.literal("definitions.listing"),
412
- requestId: z7.string().optional(),
413
- scopes: z7.array(z7.object({
414
- scope: DefinitionScopeSchema,
415
- project: z7.string().nullable(),
416
- roles: z7.array(RoleSchema),
417
- templates: z7.array(TeamTemplateSchema),
418
- problems: z7.array(DefinitionProblemSchema)
419
- }))
420
- });
421
- 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() });
422
- var SeatModelOutcomeSchema = z7.object({ role: z7.string(), session: z7.string(), when: z7.enum(["now", "turn"]).optional(), code: ModelRefusalSchema.optional() });
423
- 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() });
424
- var TeamsMessageSchema = z7.object({ type: z7.literal("teams"), teams: z7.array(TeamSchema) });
425
- var TeamUpdatedSchema = z7.object({ type: z7.literal("team.updated"), team: TeamSchema });
426
- var TeamLaunchedSchema = z7.object({ type: z7.literal("team.launched"), rid: z7.string(), team: TeamSchema });
427
- var TeamFailedSchema = z7.object({ type: z7.literal("team.failed"), rid: z7.string(), reason: z7.string(), team: TeamSchema.optional() });
428
- 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() });
429
- var isTeamLive = (t) => t.state !== "dissolved";
430
-
431
159
  // ../protocol/src/tasks.ts
432
- import { z as z8 } from "zod";
160
+ import { z as z3 } from "zod";
433
161
  var TASK_TITLE_MAX = 200;
434
162
  var TASK_TEXT_MAX = 2e4;
435
163
  var LEDGE_GIVER = "ledge";
436
164
  var TASK_OPS = ["give", "take", "pass", "done", "refuse", "cancel", "drop"];
437
165
  var TRANSMISSION_OPS = ["give", "pass", "done", "refuse", "cancel"];
438
- var TaskLogEntrySchema = z8.object({
439
- at: z8.string(),
440
- by: z8.string(),
441
- what: z8.string(),
442
- op: z8.enum(TASK_OPS).optional(),
443
- from: z8.string().optional(),
444
- to: z8.string().optional(),
445
- fromName: z8.string().optional(),
446
- toName: z8.string().optional(),
447
- note: z8.string().optional()
448
- });
449
- var TaskSchema = z8.object({
450
- id: z8.string(),
451
- title: z8.string(),
452
- text: z8.string().optional(),
453
- giver: z8.string(),
454
- giverName: z8.string(),
455
- owner: z8.string(),
456
- ownerName: z8.string(),
457
- state: z8.enum(["open", "taken", "done", "refused", "dropped"]),
458
- result: z8.string().optional(),
459
- /** The live team its owner sat in when it was given (or passed), so a team's tasks can be listed. */
460
- 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(),
461
187
  /** A task Ledge gave and the user put away from « À toi » once closed. */
462
- seen: z8.boolean().optional(),
463
- at: z8.string(),
464
- updatedAt: z8.string(),
465
- log: z8.array(TaskLogEntrySchema)
188
+ seen: z3.boolean().optional(),
189
+ at: z3.string(),
190
+ updatedAt: z3.string(),
191
+ log: z3.array(TaskLogEntrySchema)
466
192
  });
467
193
  var handOver = (op) => TRANSMISSION_OPS.includes(op ?? "");
468
194
  function transmissions(t) {
@@ -471,56 +197,48 @@ function transmissions(t) {
471
197
  var givenByLedge = (t) => t.giver === LEDGE_GIVER;
472
198
  var taskClosed = (t) => t.state === "done" || t.state === "refused" || t.state === "dropped";
473
199
  var openDecision = (t) => t.owner === LEDGE_GIVER && !taskClosed(t);
474
- var TaskCmdSchema = z8.object({
475
- type: z8.literal("task.cmd"),
476
- rid: z8.string().min(1),
477
- by: z8.string().min(1),
478
- op: z8.enum(["give", "take", "done", "refuse", "pass", "show", "list", "seen", "cancel"]),
479
- task: z8.string().min(1).max(40).optional(),
480
- to: z8.string().min(1).optional(),
481
- title: z8.string().min(1).max(TASK_TITLE_MAX).optional(),
482
- text: z8.string().max(TASK_TEXT_MAX).optional(),
483
- all: z8.boolean().optional(),
484
- team: z8.string().min(1).max(40).optional(),
485
- qid: z8.string().min(1).optional(),
486
- row: z8.number().int().min(0).max(7).optional()
487
- });
488
- var TaskUpdatedSchema = z8.object({ type: z8.literal("task.updated"), task: TaskSchema });
489
- var TaskResultSchema = z8.object({
490
- type: z8.literal("task.result"),
491
- 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(),
492
217
  task: TaskSchema.optional(),
493
- tasks: z8.array(TaskSchema).optional(),
494
- reason: z8.string().optional()
218
+ tasks: z3.array(TaskSchema).optional(),
219
+ reason: z3.string().optional()
495
220
  });
496
221
 
497
222
  // ../protocol/src/actions.ts
498
- import { z as z11 } from "zod";
223
+ import { z as z7 } from "zod";
499
224
 
500
225
  // ../protocol/src/proposal.ts
501
- import { z as z9 } from "zod";
502
- var ProposalBlockSchema = z9.object({ cwd: z9.string().trim().min(1), prompt: z9.string().optional() });
503
- var RelayBlockSchema = z9.object({ session: z9.string().trim().min(1), text: z9.string().trim().min(1) });
504
- var ProjectBlockSchema = z9.object({
505
- name: z9.string().trim().min(1).max(80),
506
- description: z9.string().max(500).optional(),
507
- repos: z9.array(z9.object({ path: z9.string().min(1).max(4096), why: z9.string().trim().min(1).max(200) })).min(1).max(50),
508
- addTo: z9.string().trim().max(80).optional()
509
- });
510
- var CloseBlockSchema = z9.object({ session: z9.string().trim().min(1) });
511
- var TeamBlockSchema = z9.object({
512
- cwd: z9.string().trim().min(1),
513
- template: z9.string().trim().min(1).max(64).optional(),
514
- name: z9.string().trim().min(1).max(60).optional(),
515
- 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()
516
- }).refine((b) => !!b.template || !!b.seats?.length, "a template or seats");
517
- var TaskBlockSchema = z9.object({
518
- to: z9.string().trim().min(1).max(80),
519
- team: z9.string().trim().max(40).optional(),
520
- title: z9.string().trim().min(1).max(200),
521
- text: z9.string().max(2e4).optional()
522
- });
523
- 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;
524
242
  function extractProposal(answer) {
525
243
  const found = [];
526
244
  const text2 = answer.replace(BLOCK, (_m, kind, body) => {
@@ -546,14 +264,6 @@ function parseCloseBlock(raw) {
546
264
  return null;
547
265
  }
548
266
  }
549
- function parseTeamBlock(raw) {
550
- try {
551
- const r = TeamBlockSchema.safeParse(JSON.parse(raw));
552
- return r.success ? r.data : null;
553
- } catch {
554
- return null;
555
- }
556
- }
557
267
  function parseTaskBlock(raw) {
558
268
  try {
559
269
  const r = TaskBlockSchema.safeParse(JSON.parse(raw));
@@ -571,9 +281,37 @@ function parseProjectBlock(raw) {
571
281
  }
572
282
  }
573
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
+
574
312
  // ../protocol/src/decisions.ts
575
- import { z as z10 } from "zod";
576
- var DecisionSchema = z10.enum(["accept", "deny", "always"]);
313
+ import { z as z6 } from "zod";
314
+ var DecisionSchema = z6.enum(["accept", "deny", "always"]);
577
315
  var NOTE_MAX = 4e3;
578
316
  var NOTE_NOT_TYPED = "note_not_typed";
579
317
  var DECISION_OFFERS = {
@@ -603,13 +341,12 @@ function pendingKey(p) {
603
341
  }
604
342
 
605
343
  // ../protocol/src/actions.ts
606
- var ActionRiskSchema = z11.enum(["read", "reversible", "destructive"]);
344
+ var ActionRiskSchema = z7.enum(["read", "reversible", "destructive"]);
607
345
  var ACTION_IDS = [
608
346
  "session.launch",
609
347
  "session.relay",
610
348
  "session.close",
611
349
  "project.propose",
612
- "team.launch",
613
350
  "task.give",
614
351
  "session.model",
615
352
  "session.interrupt",
@@ -617,20 +354,14 @@ var ACTION_IDS = [
617
354
  "session.restore",
618
355
  "session.resume",
619
356
  "session.decide",
620
- "team.join",
621
- "team.leave",
622
- "team.resume",
623
- "team.dissolve",
624
- "team.save",
625
357
  "task.cancel",
626
358
  "task.pass",
627
359
  "task.answer"
628
360
  ];
629
- var ActionIdSchema = z11.enum(ACTION_IDS);
361
+ var ActionIdSchema = z7.enum(ACTION_IDS);
630
362
  var def = (d) => d;
631
- var SessionRef = z11.string().trim().min(1).max(80);
632
- var TeamRef = z11.string().trim().min(1).max(60);
633
- 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);
634
365
  var LaunchArgs = ProposalBlockSchema.extend({ model: ModelIdSchema.optional(), effort: EffortSchema.optional() });
635
366
  var ACTIONS = [
636
367
  def({
@@ -678,18 +409,6 @@ var ACTIONS = [
678
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",
679
410
  example: { name: "Facturation", description: "Le service et son front", repos: [{ path: "/home/alice/projets/billing-api", why: "le service" }] }
680
411
  }),
681
- def({
682
- id: "team.launch",
683
- args: TeamBlockSchema,
684
- card: "team",
685
- phone: "launch",
686
- risk: "reversible",
687
- max: 1,
688
- cli: "ledge team up <mod\xE8le> --cwd <dossier>",
689
- 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)",
690
- 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",
691
- example: { cwd: "/home/alice/projets/api", name: "api", seats: [{ role: "dev-back", tool: "claude" }, { role: "rev-back", tool: "codex" }] }
692
- }),
693
412
  def({
694
413
  id: "task.give",
695
414
  args: TaskBlockSchema,
@@ -697,10 +416,10 @@ var ACTIONS = [
697
416
  phone: null,
698
417
  risk: "reversible",
699
418
  max: 8,
700
- cli: 'ledge task give <session|@r\xF4le> "<titre>" "<d\xE9tail>"',
701
- 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)",
702
- 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",
703
- 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" }
704
423
  }),
705
424
  def({
706
425
  id: "session.model",
@@ -708,14 +427,14 @@ var ACTIONS = [
708
427
  phone: null,
709
428
  risk: "reversible",
710
429
  max: 8,
711
- args: z11.object({ session: SessionRef, model: ModelIdSchema.nullable(), effort: EffortSchema.nullable() }),
430
+ args: z7.object({ session: SessionRef, model: ModelIdSchema.nullable(), effort: EffortSchema.nullable() }),
712
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",
713
432
  when: "quand l'utilisateur demande de passer une session sur un autre mod\xE8le ou un autre effort",
714
433
  example: { session: "Nova", model: "claude-opus-5-5", effort: "high" }
715
434
  }),
716
435
  def({
717
436
  id: "session.interrupt",
718
- args: z11.object({ session: SessionRef }),
437
+ args: z7.object({ session: SessionRef }),
719
438
  card: "generic",
720
439
  phone: null,
721
440
  risk: "reversible",
@@ -726,7 +445,7 @@ var ACTIONS = [
726
445
  }),
727
446
  def({
728
447
  id: "session.archive",
729
- args: z11.object({ session: SessionRef }),
448
+ args: z7.object({ session: SessionRef }),
730
449
  card: "generic",
731
450
  phone: null,
732
451
  risk: "reversible",
@@ -737,7 +456,7 @@ var ACTIONS = [
737
456
  }),
738
457
  def({
739
458
  id: "session.restore",
740
- args: z11.object({ session: SessionRef }),
459
+ args: z7.object({ session: SessionRef }),
741
460
  card: "generic",
742
461
  phone: null,
743
462
  risk: "reversible",
@@ -748,7 +467,7 @@ var ACTIONS = [
748
467
  }),
749
468
  def({
750
469
  id: "session.resume",
751
- args: z11.object({ session: SessionRef }),
470
+ args: z7.object({ session: SessionRef }),
752
471
  card: "generic",
753
472
  phone: "act",
754
473
  risk: "reversible",
@@ -762,71 +481,15 @@ var ACTIONS = [
762
481
  card: "generic",
763
482
  phone: "act",
764
483
  max: 1,
765
- 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() }),
766
485
  risk: (a) => a.decision === "accept" ? "destructive" : "reversible",
767
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",
768
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",
769
488
  example: { session: "Nova", decision: "deny", note: "Pas sur main : cr\xE9e une branche" }
770
489
  }),
771
- def({
772
- id: "team.join",
773
- args: z11.object({ team: TeamRef, session: SessionRef, role: RoleIdSchema }),
774
- card: "generic",
775
- phone: null,
776
- risk: "reversible",
777
- max: 8,
778
- summary: "faire entrer une session dans une \xE9quipe en cours, \xE0 un r\xF4le de roles.md",
779
- when: "quand l'utilisateur demande d'ajouter une session existante \xE0 une \xE9quipe",
780
- example: { team: "team-3fa2", session: "Nova", role: "dev-back" }
781
- }),
782
- def({
783
- id: "team.leave",
784
- args: z11.object({ team: TeamRef, session: SessionRef }),
785
- card: "generic",
786
- phone: null,
787
- risk: "reversible",
788
- max: 8,
789
- summary: "faire sortir une session d'une \xE9quipe (la session continue)",
790
- when: "quand l'utilisateur demande de retirer une session d'une \xE9quipe",
791
- example: { team: "team-3fa2", session: "Nova" }
792
- }),
793
- def({
794
- id: "team.resume",
795
- args: z11.object({ team: TeamRef }),
796
- card: "generic",
797
- phone: "act",
798
- risk: "reversible",
799
- max: 1,
800
- summary: "reprendre une \xE9quipe au repos : chaque si\xE8ge reprend sa conversation",
801
- when: "quand l'utilisateur demande de reprendre ou relancer une \xE9quipe au repos",
802
- example: { team: "team-3fa2" }
803
- }),
804
- def({
805
- id: "team.dissolve",
806
- args: z11.object({ team: TeamRef }),
807
- card: "generic",
808
- phone: "act",
809
- risk: "destructive",
810
- max: 8,
811
- cli: "ledge team dissolve <\xE9quipe>",
812
- summary: "dissoudre une \xE9quipe : elle dispara\xEEt, ses sessions restent ; irr\xE9versible",
813
- when: "seulement quand l'utilisateur demande explicitement de dissoudre une \xE9quipe pr\xE9cise",
814
- example: { team: "team-3fa2" }
815
- }),
816
- def({
817
- id: "team.save",
818
- args: z11.object({ team: TeamRef, name: TeamNameSchema }),
819
- card: "generic",
820
- phone: null,
821
- risk: "reversible",
822
- max: 1,
823
- summary: "enregistrer une \xE9quipe en cours comme mod\xE8le (~/.ledge/teams/<nom>.yaml)",
824
- when: "quand l'utilisateur demande d'enregistrer ou de garder la composition d'une \xE9quipe",
825
- example: { team: "team-3fa2", name: "api" }
826
- }),
827
490
  def({
828
491
  id: "task.cancel",
829
- 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() }),
830
493
  card: "generic",
831
494
  phone: "act",
832
495
  risk: "destructive",
@@ -837,7 +500,7 @@ var ACTIONS = [
837
500
  }),
838
501
  def({
839
502
  id: "task.pass",
840
- 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() }),
841
504
  card: "generic",
842
505
  phone: null,
843
506
  risk: "reversible",
@@ -848,7 +511,7 @@ var ACTIONS = [
848
511
  }),
849
512
  def({
850
513
  id: "task.answer",
851
- 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) }),
852
515
  card: "generic",
853
516
  phone: "act",
854
517
  risk: "destructive",
@@ -861,13 +524,12 @@ var ACTIONS = [
861
524
  var byId = new Map(ACTIONS.map((a) => [a.id, a]));
862
525
  var actionById = (id) => byId.get(id);
863
526
  var riskOf = (a, args) => typeof a.risk === "function" ? a.risk(args) : a.risk;
864
- 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({}) });
865
528
  var LEGACY_FENCE_ACTION = {
866
529
  session: "session.launch",
867
530
  relay: "session.relay",
868
531
  close: "session.close",
869
532
  project: "project.propose",
870
- team: "team.launch",
871
533
  task: "task.give"
872
534
  };
873
535
  function parseActionBlock(kind, raw) {
@@ -903,126 +565,345 @@ var NEVER_PROPOSED = [
903
565
  "r\xE9pondre \xAB toujours \xBB \xE0 une demande, ou r\xE9pondre aux questions \xE0 choix d'OMP"
904
566
  ];
905
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
+
906
810
  // ../protocol/src/messages.ts
907
811
  import { z as z21 } from "zod";
908
812
 
909
813
  // ../protocol/src/chat.ts
910
- import { z as z13 } from "zod";
814
+ import { z as z10 } from "zod";
911
815
 
912
816
  // ../protocol/src/attachments.ts
913
- import { z as z12 } from "zod";
817
+ import { z as z9 } from "zod";
914
818
  var ATTACHMENT_ID = /^[0-9a-f]{64}$/;
915
- var AttachmentIdSchema = z12.string().regex(ATTACHMENT_ID);
819
+ var AttachmentIdSchema = z9.string().regex(ATTACHMENT_ID);
916
820
  var IMAGE_MIMES = ["image/webp", "image/jpeg", "image/png", "image/gif"];
917
- var ImageMimeSchema = z12.enum(IMAGE_MIMES);
821
+ var ImageMimeSchema = z9.enum(IMAGE_MIMES);
918
822
  var ATTACHMENT_MAX = 4e5;
919
823
  var ATTACHMENT_LOCAL_MAX = 2e6;
920
824
  var PREVIEW_MAX = 4e4;
921
825
  var ATTACHMENTS_MAX = 5;
922
826
  var b64Max = (bytes) => Math.ceil(bytes / 3) * 4;
923
- var AttachmentRefSchema = z12.object({
827
+ var AttachmentRefSchema = z9.object({
924
828
  id: AttachmentIdSchema,
925
829
  mime: ImageMimeSchema,
926
- width: z12.number().int().positive(),
927
- height: z12.number().int().positive(),
928
- bytes: z12.number().int().positive(),
929
- 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()
930
834
  });
931
- var ImageUploadSchema = z12.object({
835
+ var ImageUploadSchema = z9.object({
932
836
  mime: ImageMimeSchema,
933
- data: z12.string().min(1).max(b64Max(ATTACHMENT_LOCAL_MAX)),
934
- preview: z12.object({ mime: ImageMimeSchema, data: z12.string().min(1).max(b64Max(PREVIEW_MAX)) }).optional()
935
- });
936
- var AttachmentErrorReasonSchema = z12.enum(["too_large", "not_image", "unreadable", "not_found", "offline"]);
937
- var requestId = z12.string().min(1).max(100);
938
- var AttachmentPutSchema = z12.object({ type: z12.literal("attachment.put"), requestId, id: z12.string().optional(), image: ImageUploadSchema });
939
- var AttachmentGetSchema = z12.object({ type: z12.literal("attachment.get"), requestId, attachment: AttachmentIdSchema, preview: z12.boolean().optional(), id: z12.string().optional(), machine: z12.string().optional() });
940
- var AttachmentStoredSchema = z12.object({ type: z12.literal("attachment.stored"), requestId, ref: AttachmentRefSchema });
941
- var AttachmentDataSchema = z12.object({ type: z12.literal("attachment.data"), requestId, attachment: AttachmentIdSchema, mime: ImageMimeSchema, data: z12.string() });
942
- 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 });
943
847
 
944
848
  // ../protocol/src/chat.ts
945
- var ChatStepSchema = z13.object({
946
- kind: z13.enum(["sessions", "pane", "reply", "git", "repo"]),
947
- id: z13.string().optional(),
948
- name: z13.string().optional(),
949
- path: z13.string().optional()
950
- });
951
- var ChatProposalSchema = z13.object({
952
- cwd: z13.string().min(1),
953
- project: z13.string(),
954
- 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(),
955
859
  tool: ToolSchema,
956
860
  /** What Ledge proposed on the card's picker (spec 2026-10-26 action registry §4), the agent's own default when left out. */
957
861
  model: ModelIdSchema.optional(),
958
862
  effort: EffortSchema.optional(),
959
- launchedId: z13.string().optional(),
960
- error: z13.string().optional()
863
+ launchedId: z10.string().optional(),
864
+ error: z10.string().optional()
961
865
  });
962
866
  var MAX_PROPOSALS = 8;
963
- var ChatProposalsSchema = z13.array(ChatProposalSchema).min(1).max(MAX_PROPOSALS);
964
- var ChatRelaySchema = z13.object({
965
- id: z13.string().min(1),
966
- 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(),
967
871
  tool: ToolSchema,
968
- text: z13.string().min(1),
969
- status: z13.enum(["queued", "sent"]).optional(),
970
- sentAt: z13.string().datetime().optional(),
971
- 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(),
972
876
  /** Why it failed, as a code a front words itself (a RefusalCode, `ended`, or `failed` for the machinery); goes with `error`. */
973
- code: z13.string().max(40).optional()
877
+ code: z10.string().max(40).optional()
974
878
  });
975
- var ChatCloseSchema = z13.object({
976
- id: z13.string().min(1),
977
- name: z13.string(),
879
+ var ChatCloseSchema = z10.object({
880
+ id: z10.string().min(1),
881
+ name: z10.string(),
978
882
  tool: ToolSchema,
979
- closedAt: z13.string().datetime().optional(),
980
- how: z13.enum(["exit", "killed"]).optional(),
981
- error: z13.string().optional()
982
- });
983
- var ChatClosesSchema = z13.array(ChatCloseSchema).min(1).max(MAX_PROPOSALS);
984
- var ChatProjectProposalSchema = z13.object({
985
- name: z13.string().min(1).max(80),
986
- description: z13.string().max(500).optional(),
987
- repos: z13.array(z13.object({ path: z13.string().min(1).max(4096), why: z13.string().min(1).max(200) })).min(1).max(50),
988
- addTo: z13.string().min(1).max(80).optional()
989
- });
990
- var ChatTeamSeatSchema = z13.object({
991
- role: z13.string().min(1),
992
- label: z13.string(),
993
- tool: ToolSchema,
994
- model: z13.string().optional(),
995
- effort: z13.string().optional(),
996
- autonomy: AutonomySchema.optional(),
997
- name: z13.string().optional()
998
- });
999
- var ChatTeamProposalSchema = z13.object({
1000
- cwd: z13.string().min(1),
1001
- project: z13.string(),
1002
- projectName: z13.string().optional(),
1003
- name: z13.string().min(1),
1004
- template: z13.string().optional(),
1005
- seats: z13.array(ChatTeamSeatSchema).min(1).max(8),
1006
- teamId: z13.string().optional(),
1007
- launchedAt: z13.string().datetime().optional(),
1008
- error: z13.string().optional(),
1009
- savedPath: z13.string().optional(),
1010
- saveError: z13.string().optional()
1011
- });
1012
- var ChatTaskProposalSchema = z13.object({
1013
- to: z13.string().min(1),
1014
- toName: z13.string().optional(),
1015
- team: z13.string().optional(),
1016
- title: z13.string().min(1).max(200),
1017
- text: z13.string().max(2e4).optional(),
1018
- taskId: z13.string().optional(),
1019
- ownerName: z13.string().optional(),
1020
- state: z13.enum(["open", "taken", "done", "refused", "dropped"]).optional(),
1021
- givenAt: z13.string().datetime().optional(),
1022
- error: z13.string().optional()
1023
- });
1024
- var ChatTasksSchema = z13.array(ChatTaskProposalSchema).min(1).max(MAX_PROPOSALS);
1025
- 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));
1026
907
  var DETAIL_MAX = 4e3;
1027
908
  var ACTION_ERROR_CODES = [
1028
909
  "unknown",
@@ -1037,12 +918,6 @@ var ACTION_ERROR_CODES = [
1037
918
  "no_request",
1038
919
  "in_session",
1039
920
  "no_note",
1040
- "member",
1041
- "not_member",
1042
- "unknown_role",
1043
- "not_resting",
1044
- "dissolved",
1045
- "no_seat",
1046
921
  "closed",
1047
922
  "holder",
1048
923
  "changed",
@@ -1050,86 +925,84 @@ var ACTION_ERROR_CODES = [
1050
925
  "not_decision",
1051
926
  "failed"
1052
927
  ];
1053
- var ChatActionStateSchema = z13.enum(["running", "done", "denied", "failed", "refused"]);
1054
- var ChatActionSchema = z13.object({
1055
- action: z13.string().min(1).max(40),
1056
- args: z13.record(z13.unknown()),
1057
- 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),
1058
933
  vars: ActionVarsSchema.optional(),
1059
- detail: z13.string().max(DETAIL_MAX).optional(),
1060
- detailCut: z13.literal(true).optional(),
934
+ detail: z10.string().max(DETAIL_MAX).optional(),
935
+ detailCut: z10.literal(true).optional(),
1061
936
  risk: ActionRiskSchema,
1062
- session: z13.string().optional(),
1063
- team: z13.string().optional(),
937
+ session: z10.string().optional(),
1064
938
  state: ChatActionStateSchema.optional(),
1065
- doneAt: z13.string().datetime().optional(),
1066
- error: z13.string().optional(),
1067
- code: z13.string().max(40).optional()
1068
- });
1069
- var ChatActionsSchema = z13.array(ChatActionSchema).min(1).max(MAX_PROPOSALS);
1070
- var ChatTurnSchema = z13.object({
1071
- machineId: z13.string().optional(),
1072
- machineName: z13.string().optional(),
1073
- choices: z13.array(z13.object({ id: z13.string(), label: z13.string() })).optional(),
1074
- qid: z13.string().min(1),
1075
- question: z13.string(),
1076
- askedAt: z13.string().datetime(),
1077
- steps: z13.array(ChatStepSchema),
1078
- answer: z13.string().optional(),
1079
- answeredAt: z13.string().datetime().optional(),
1080
- 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(),
1081
955
  proposal: ChatProposalSchema.optional(),
1082
956
  proposals: ChatProposalsSchema.optional(),
1083
957
  relay: ChatRelaySchema.optional(),
1084
958
  closes: ChatClosesSchema.optional(),
1085
959
  projectProposal: ChatProjectProposalSchema.optional(),
1086
- team: ChatTeamProposalSchema.optional(),
1087
960
  tasks: ChatTasksSchema.optional(),
1088
961
  actions: ChatActionsSchema.optional(),
1089
- ignoredAt: z13.string().datetime().optional(),
1090
- attachments: z13.array(AttachmentRefSchema).optional()
962
+ ignoredAt: z10.string().datetime().optional(),
963
+ attachments: z10.array(AttachmentRefSchema).optional()
1091
964
  });
1092
965
  var proposalRows = (t) => t?.proposals ?? (t?.proposal ? [t.proposal] : []);
1093
966
 
1094
967
  // ../protocol/src/repos.ts
1095
- import { z as z14 } from "zod";
1096
- var ReposInspectSchema = z14.object({
1097
- type: z14.literal("repos.inspect"),
1098
- requestId: z14.string().min(1).max(100),
1099
- paths: z14.array(z14.string().min(1)).min(1).max(50),
1100
- machineId: z14.string().optional()
1101
- });
1102
- var RepoInfoSchema = z14.object({ path: z14.string(), exists: z14.boolean(), branch: z14.string().nullable() });
1103
- 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) });
1104
977
 
1105
978
  // ../protocol/src/scan.ts
1106
- import { z as z15 } from "zod";
1107
- var ReposScanSchema = z15.object({ type: z15.literal("repos.scan"), requestId: z15.string().min(1).max(100), machineId: z15.string().optional() });
1108
- var FoundRepoSchema = z15.object({ path: z15.string(), branch: z15.string().nullable(), remote: z15.string().optional(), manifest: z15.string().max(200).optional() });
1109
- 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() });
1110
983
 
1111
984
  // ../protocol/src/documents.ts
1112
- import { z as z16 } from "zod";
985
+ import { z as z13 } from "zod";
1113
986
  var DOCUMENT_MAX_BYTES = 1048576;
1114
- var path = z16.string().min(1).max(4096);
1115
- var requestId2 = z16.string().min(1);
1116
- var DocumentReadSchema = z16.object({
1117
- 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"),
1118
991
  requestId: requestId2,
1119
992
  path,
1120
- machineId: z16.string().optional(),
1121
- sessionId: z16.string().min(1).optional(),
993
+ machineId: z13.string().optional(),
994
+ sessionId: z13.string().min(1).optional(),
1122
995
  basePath: path.optional()
1123
996
  });
1124
- var DocumentContentSchema = z16.object({
1125
- type: z16.literal("document.content"),
997
+ var DocumentContentSchema = z13.object({
998
+ type: z13.literal("document.content"),
1126
999
  requestId: requestId2,
1127
1000
  path,
1128
- text: z16.string(),
1129
- bytes: z16.number().int().nonnegative(),
1130
- modifiedAt: z16.string().datetime()
1001
+ text: z13.string(),
1002
+ bytes: z13.number().int().nonnegative(),
1003
+ modifiedAt: z13.string().datetime()
1131
1004
  });
1132
- var DocumentErrorCodeSchema = z16.enum([
1005
+ var DocumentErrorCodeSchema = z13.enum([
1133
1006
  "not_found",
1134
1007
  "not_file",
1135
1008
  "unsupported_path",
@@ -1141,63 +1014,153 @@ var DocumentErrorCodeSchema = z16.enum([
1141
1014
  "session_missing",
1142
1015
  "read_failed"
1143
1016
  ]);
1144
- var DocumentErrorSchema = z16.object({
1145
- type: z16.literal("document.error"),
1017
+ var DocumentErrorSchema = z13.object({
1018
+ type: z13.literal("document.error"),
1146
1019
  requestId: requestId2,
1147
1020
  path,
1148
1021
  code: DocumentErrorCodeSchema
1149
1022
  });
1150
1023
 
1151
1024
  // ../protocol/src/routing.ts
1152
- import { z as z17 } from "zod";
1153
- var MachineInventorySchema = z17.object({
1154
- id: z17.string().min(1).max(80),
1155
- label: z17.string().min(1).max(120),
1156
- online: z17.boolean(),
1157
- local: z17.boolean(),
1158
- 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),
1159
- folders: z17.array(z17.object({ project: z17.string(), cwd: z17.string() })).max(100)
1160
- });
1161
- var RoutingContextSchema = z17.object({
1162
- machines: z17.array(MachineInventorySchema).min(1).max(20),
1163
- history: z17.array(z17.object({ question: z17.string().max(2e4), answer: z17.string().max(2e4).optional(), machineId: z17.string().optional() })).max(50)
1164
- });
1165
- 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({
1166
1039
  /** Null means an answer or a clarification, never an implicit local destination. */
1167
- machineId: z17.string().nullable(),
1168
- text: z17.string().min(1).max(2e4),
1169
- 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
+ });
1170
1072
  });
1171
1073
 
1172
1074
  // ../protocol/src/island.ts
1173
- import { z as z18 } from "zod";
1174
- var IslandScaleSchema = z18.union([z18.literal("auto"), z18.literal(1), z18.literal(1.25), z18.literal(1.5), z18.literal(2)]);
1175
- 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({
1176
1078
  /** Shown at the top of the screen; hidden, Desktop still notifies. */
1177
- visible: z18.boolean(),
1079
+ visible: z17.boolean(),
1178
1080
  /** `primary` (whichever it is after a reconfiguration), or a monitor's id as the shell lists it (`list_monitors`: the OS
1179
1081
  * name, `#index` without one). `second`, written by older fronts, is the first monitor that is not the primary. */
1180
- screen: z18.string().trim().min(1).max(200),
1181
- position: z18.enum(["center", "left", "right"]),
1082
+ screen: z17.string().trim().min(1).max(200),
1083
+ position: z17.enum(["center", "left", "right"]),
1182
1084
  /** A strip under a maximised window. */
1183
- discreet: z18.boolean(),
1085
+ discreet: z17.boolean(),
1184
1086
  islandScale: IslandScaleSchema,
1185
1087
  panelScale: IslandScaleSchema,
1186
1088
  /** What the island shows besides asks and questions, which it always shows. */
1187
- shows: z18.object({
1089
+ shows: z17.object({
1188
1090
  /** Allow, deny or answer in a line from the island; off, its cards only say « Open in Ledge ». */
1189
- quick: z18.boolean(),
1091
+ quick: z17.boolean(),
1190
1092
  /** The 6 s bubble when an agent finishes. */
1191
- finished: z18.boolean(),
1093
+ finished: z17.boolean(),
1192
1094
  /** An agent's sentence in a bubble. */
1193
- say: z18.boolean(),
1095
+ say: z17.boolean(),
1194
1096
  /** The sub-agents next to their main agent. */
1195
- helpers: z18.boolean()
1097
+ helpers: z17.boolean()
1196
1098
  }),
1197
1099
  /** The global shortcut that opens the island, as shown (`Ctrl Alt L`). */
1198
- shortcut: z18.string().trim().min(1).max(40)
1100
+ shortcut: z17.string().trim().min(1).max(40)
1199
1101
  });
1200
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 });
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
+ }
1163
+
1201
1164
  // ../protocol/src/thread.ts
1202
1165
  import { z as z19 } from "zod";
1203
1166
  var ToolStatusSchema = z19.enum(["running", "success", "failed", "unknown"]);
@@ -1225,10 +1188,8 @@ var ThreadItemSchema = z19.discriminatedUnion("kind", [
1225
1188
  kind: z19.literal("notice"),
1226
1189
  ...base,
1227
1190
  notice: z19.enum(["idle", "exited", "unavailable", "expired", "delivery", "other"]),
1228
- /** An `other` notice from Ledge: `task`, the task a `<ledge-task>` is about; `team`, the team a `<ledge-notice team>` seated the
1229
- * 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. */
1230
1192
  task: z19.string().optional(),
1231
- team: z19.string().optional(),
1232
1193
  /** A task this session handed over (`outgoing`), and how (issue #92). */
1233
1194
  taskOp: z19.enum(TRANSMISSION_OPS).optional(),
1234
1195
  outgoing: z19.literal(true).optional(),
@@ -1363,8 +1324,8 @@ var DaemonInfoSchema = z21.object({
1363
1324
  /** Its home folder, so a client shows the folders under it as `~` (absent from older daemons). */
1364
1325
  home: z21.string().optional(),
1365
1326
  mobile: z21.boolean().optional(),
1366
- /** Knows roles, teams and tasks given by Ledge (spec 2026-10-25 roles). */
1367
- teams: z21.boolean().optional()
1327
+ /** Answers `openrig.status` and `openrig.act`: drives OpenRig on its machine. */
1328
+ openrig: z21.boolean().optional()
1368
1329
  });
1369
1330
  var UpdateFailureSchema = z21.enum(["git-install", "no-systemd", "sessions-at-risk", "npm-failed", "busy"]);
1370
1331
  var ServerMessageSchema = z21.discriminatedUnion("type", [
@@ -1378,6 +1339,11 @@ var ServerMessageSchema = z21.discriminatedUnion("type", [
1378
1339
  ReposInfoSchema,
1379
1340
  ReposFoundSchema,
1380
1341
  ModelsListingSchema,
1342
+ OpenRigStateMessageSchema,
1343
+ OpenRigDoneSchema,
1344
+ OpenRigSpecListSchema,
1345
+ OpenRigLaunchedSchema,
1346
+ OpenRigReseatedSchema,
1381
1347
  /** `recents`: the folders of past sessions, most recent first. `launcher`: the command that runs `ledge` inside WSL
1382
1348
  * (`[node, cli]`), so the overlay can attach a terminal to a session with `<launcher> attach <id>`. `daemon`: absent
1383
1349
  * from daemons older than the auto-update. */
@@ -1419,7 +1385,7 @@ var ServerMessageSchema = z21.discriminatedUnion("type", [
1419
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. */
1420
1386
  z21.object({ type: z21.literal("chat.step"), qid: z21.string(), step: ChatStepSchema }),
1421
1387
  z21.object({ type: z21.literal("chat.delta"), qid: z21.string(), text: z21.string() }),
1422
- 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() }),
1423
1389
  /** What a `chat.act` applied: the rows done, and the one that failed with why (the rows after it stay proposed). */
1424
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({
1425
1391
  row: z21.number().int().min(0),
@@ -1429,8 +1395,8 @@ var ServerMessageSchema = z21.discriminatedUnion("type", [
1429
1395
  })) }),
1430
1396
  /** What an `action.run` came to: `row` the action as the daemon resolved it (its summary, its risk); `reason` why it was not
1431
1397
  * done, with `code` (`refused`: not possible now; `agent`: a session may not run it; `confirm_required`: destructive, ask
1432
- * again; `failed`: the handler turned it down; a free string, as an `error`'s); `path` the template a `team.save` wrote. */
1433
- 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() }),
1434
1400
  z21.object({ type: z21.literal("chat.error"), qid: z21.string(), message: z21.string() }),
1435
1401
  z21.object({ type: z21.literal("chat.history"), turns: z21.array(ChatTurnSchema) }),
1436
1402
  /** The daemon updating itself: npm is running, then the service restarts (the socket closes right after). */
@@ -1454,15 +1420,6 @@ var ServerMessageSchema = z21.discriminatedUnion("type", [
1454
1420
  ContextPrefsMessageSchema,
1455
1421
  HandoverResultSchema,
1456
1422
  TaskUpdatedSchema,
1457
- RolesListingSchema,
1458
- TeamsMessageSchema,
1459
- TeamUpdatedSchema,
1460
- TeamLaunchedSchema,
1461
- TeamFailedSchema,
1462
- TeamSavedSchema,
1463
- DefinitionsListingSchema,
1464
- DefinitionResultSchema,
1465
- TeamChangedSchema,
1466
1423
  z21.object({
1467
1424
  type: z21.literal("error"),
1468
1425
  message: z21.string(),
@@ -1484,6 +1441,11 @@ var ClientMessageSchema = z21.discriminatedUnion("type", [
1484
1441
  ReposInspectSchema,
1485
1442
  ReposScanSchema,
1486
1443
  ModelsListSchema,
1444
+ OpenRigStatusSchema,
1445
+ OpenRigActSchema,
1446
+ OpenRigSpecsSchema,
1447
+ OpenRigLaunchSchema,
1448
+ OpenRigSeatsSchema,
1487
1449
  /** The overlay starts a session: `cwd` is a WSL path (`~` allowed), `name` a preferred bot name (the daemon picks a
1488
1450
  * free one otherwise), `prompt` the agent's first instruction, `continue` resumes the folder's last conversation.
1489
1451
  * With `qid` it is the chat card of that turn: the daemon launches the turn's proposal and ignores the other fields
@@ -1505,10 +1467,6 @@ var ClientMessageSchema = z21.discriminatedUnion("type", [
1505
1467
  effort: EffortSchema.optional(),
1506
1468
  /** OMP only: its approval mode, `always-ask` when left out. */
1507
1469
  approval: OmpApprovalSchema.optional(),
1508
- /** A role (spec 2026-10-25 roles §3.4): its prompt reaches the agent at every start, its defaults fill what is left out. */
1509
- role: RoleIdSchema.optional(),
1510
- /** A live team the new session joins at once, in `role`. */
1511
- team: TeamIdSchema.optional(),
1512
1470
  /** Routing by the fleet, removed before the message reaches the daemon. */
1513
1471
  machineId: z21.string().optional()
1514
1472
  }),
@@ -1596,12 +1554,18 @@ var ClientMessageSchema = z21.discriminatedUnion("type", [
1596
1554
  z21.object({ type: z21.literal("session.delete"), id: z21.string() }),
1597
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. */
1598
1556
  z21.object({ type: z21.literal("session.rename"), id: z21.string(), topic: z21.string().max(500) }),
1599
- /** A seat's hook told it its team as `key` names it (`seatKey`): at its start, or at a turn after the team changed. */
1600
- z21.object({ type: z21.literal("seat.seen"), id: z21.string(), key: z21.string().max(4e3) }),
1601
1557
  z21.object({ type: z21.literal("session.thread"), id: z21.string() }),
1602
1558
  z21.object({ type: z21.literal("session.register"), session: SessionSchema }),
1603
1559
  /** `agent` and `cwd` describe the session when the daemon does not know it yet (a hook from an agent started without ledge). */
1604
- 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
+ }),
1605
1569
  z21.object({ type: z21.literal("session.unregister"), id: z21.string(), exitCode: z21.number().int().nullable() }),
1606
1570
  z21.object({ type: z21.literal("snapshot.request") }),
1607
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() }),
@@ -1635,25 +1599,8 @@ var ClientMessageSchema = z21.discriminatedUnion("type", [
1635
1599
  SessionHandoverSchema,
1636
1600
  ContextSetSchema,
1637
1601
  HandoverBriefSchema,
1638
- HandoverShowSchema,
1639
- RolesListSchema,
1640
- TeamLaunchSchema,
1641
- TeamJoinSchema,
1642
- TeamLeaveSchema,
1643
- TeamResumeSchema,
1644
- TeamDissolveSchema,
1645
- TeamSaveSchema,
1646
- DefinitionsListSchema,
1647
- RoleWriteSchema,
1648
- RoleDeleteSchema,
1649
- TemplateWriteSchema,
1650
- TemplateDeleteSchema,
1651
- TeamComposeSchema,
1652
- TeamSeatSchema
1653
- ]).superRefine((m, ctx) => {
1654
- const issue = "scope" in m ? scopeIssue(m) : null;
1655
- if (issue) ctx.addIssue({ code: z21.ZodIssueCode.custom, message: issue, path: ["project"] });
1656
- });
1602
+ HandoverShowSchema
1603
+ ]);
1657
1604
  function parseClientMessage(raw) {
1658
1605
  return ClientMessageSchema.parse(raw);
1659
1606
  }
@@ -1742,6 +1689,7 @@ function pickName(taken, preferred) {
1742
1689
  if (first) return first;
1743
1690
  for (let i = 2; ; i++) if (free(`${NAMES[0]}-${i}`)) return `${NAMES[0]}-${i}`;
1744
1691
  }
1692
+ var namesInUse = (sessions) => [...sessions].filter((s) => s.state !== "exited" && !s.archivedAt).map((s) => s.name);
1745
1693
 
1746
1694
  // ../protocol/src/topic.ts
1747
1695
  var TOPIC_MAX = 80;
@@ -1824,7 +1772,7 @@ var MeResponseSchema = z23.object({
1824
1772
  });
1825
1773
 
1826
1774
  // ../protocol/src/phone.ts
1827
- import { z as z26 } from "zod";
1775
+ import { z as z25 } from "zod";
1828
1776
 
1829
1777
  // ../protocol/src/push.ts
1830
1778
  import { z as z24 } from "zod";
@@ -1870,51 +1818,6 @@ var PushPayloadSchema = z24.object({
1870
1818
  tag: z24.string().regex(/^[A-Za-z0-9_-]{1,32}$/)
1871
1819
  });
1872
1820
 
1873
- // ../protocol/src/phoneTeams.ts
1874
- import { z as z25 } from "zod";
1875
- var scope = DefinitionScopeSchema;
1876
- var PhoneSeatsSchema = z25.array(SeatSchema.strict()).min(1).max(TEAM_SEATS_MAX).refine(uniqueRoles, "a role twice in one team");
1877
- var PhoneRoleDraftSchema = RoleDraftSchema.strict();
1878
- var projectName = z25.string().max(80).nullable();
1879
- var PhoneRoleSchema = z25.object({
1880
- id: RoleIdSchema,
1881
- label: z25.string().min(1).max(ROLE_LABEL_MAX),
1882
- prompt: z25.string().max(ROLE_PROMPT_MAX),
1883
- cut: z25.literal(true).optional(),
1884
- tool: ToolSchema.optional(),
1885
- model: ModelIdSchema.optional(),
1886
- effort: EffortSchema.optional(),
1887
- autonomy: AutonomySchema.optional(),
1888
- scope,
1889
- project: projectName,
1890
- hash: DefinitionHashSchema,
1891
- shadows: z25.literal(true).optional(),
1892
- shadowed: z25.literal(true).optional(),
1893
- shadowedIn: z25.array(z25.string().max(80)).min(1).max(8).optional()
1894
- }).strict();
1895
- var PhoneTemplateSchema = z25.object({ id: TemplateIdSchema, name: TeamNameSchema, seats: PhoneSeatsSchema, scope, project: projectName, hash: DefinitionHashSchema }).strict();
1896
- var PhoneProblemSchema = z25.object({ file: z25.string().max(80), scope, project: projectName, reason: z25.string().max(200) }).strict();
1897
- var PhoneCatalogSchema = z25.object({
1898
- /** The names of the projects with a local repository: the ones a « Dépôt » scope or a « Lever » can name. */
1899
- projects: z25.array(z25.string().max(80)).max(50),
1900
- roles: z25.array(PhoneRoleSchema).max(200),
1901
- templates: z25.array(PhoneTemplateSchema).max(100),
1902
- problems: z25.array(PhoneProblemSchema).max(50)
1903
- }).strict();
1904
- var TEAMS_OPERATION_TYPES = ["role.write", "role.delete", "template.write", "template.delete", "team.launch", "team.compose", "team.seat", "team.dissolve"];
1905
- var isTeamsOperation = (m) => TEAMS_OPERATION_TYPES.includes(m.type);
1906
- function canonicalJson(v) {
1907
- const sort = (x) => {
1908
- if (Array.isArray(x)) return x.map(sort);
1909
- if (x !== null && typeof x === "object") {
1910
- const o = x;
1911
- return Object.fromEntries(Object.keys(o).sort().filter((k) => o[k] !== void 0).map((k) => [k, sort(o[k])]));
1912
- }
1913
- return x;
1914
- };
1915
- return JSON.stringify(sort(v));
1916
- }
1917
-
1918
1821
  // ../protocol/src/phone.ts
1919
1822
  var PHONE_PROTOCOL = 1;
1920
1823
  var PAD_TIERS = [1024, 4096, 16384, 65536, 262144, 655360];
@@ -1933,38 +1836,38 @@ var THREAD_TEXT_MAX = 8192;
1933
1836
  var TOOL_TEXT_MAX = 2048;
1934
1837
  var CHECKLIST_TASKS_MAX = 50;
1935
1838
  var CHECKLIST_TEXT_MAX = 200;
1936
- var ChecklistStatusSchema = z26.enum(["pending", "in_progress", "completed"]);
1937
- var PhoneChecklistSchema = z26.object({
1938
- tasks: z26.array(z26.object({ text: z26.string().max(CHECKLIST_TEXT_MAX), status: ChecklistStatusSchema })).max(CHECKLIST_TASKS_MAX),
1939
- done: z26.number().int().nonnegative(),
1940
- total: z26.number().int().nonnegative(),
1941
- cut: z26.literal(true).optional()
1942
- });
1943
- var PhoneChecklistSummarySchema = z26.object({
1944
- done: z26.number().int().nonnegative(),
1945
- total: z26.number().int().nonnegative(),
1946
- current: z26.string().max(CHECKLIST_TEXT_MAX).optional(),
1947
- 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()
1948
1851
  });
1949
1852
  var PENDING_BODY_MAX = 65536;
1950
1853
  var SNAPSHOT_BODY_MAX = 2048;
1951
- var RiskSchema = z26.enum(["low", "high"]);
1952
- 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"]);
1953
- var OperationIdSchema = z26.string().uuid();
1954
- var OperationStatusSchema = z26.enum(["received", "applied", "rejected", "failed"]);
1955
- var OperationReasonSchema = z26.enum([...RefusalCodeSchema.options, "untypable", "confirm_required", "conflict", "assertion_invalid", "assertion_expired", "changed", "exists", "unknown_project", "seat_failed", "scheduled", ...ModelRefusalSchema.options]);
1956
- 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({
1957
1860
  /** A question can be answered in free text. */
1958
- freeTextAnswer: z26.boolean(),
1861
+ freeTextAnswer: z25.boolean(),
1959
1862
  /** The session's accept/deny can be typed; absent = true. */
1960
- decide: z26.boolean().optional(),
1863
+ decide: z25.boolean().optional(),
1961
1864
  /** OMP's dialog questions can be answered from the phone; absent = false. */
1962
- questions: z26.boolean().optional()
1865
+ questions: z25.boolean().optional()
1963
1866
  });
1964
1867
  var UNTYPABLE = /[\u0000-\u001f\u007f-\u009f\u200b\u200e\u200f\u2028-\u202e\u2066-\u2069\ufeff]/;
1965
- var CapabilitiesByToolSchema = z26.object({ claude: CapabilitiesSchema, codex: CapabilitiesSchema, cursor: CapabilitiesSchema, omp: CapabilitiesSchema });
1966
- var PhonePendingSchema = PendingSchema.extend({ key: z26.string().max(64), risk: RiskSchema, riskReason: RiskReasonSchema, cut: z26.literal(true).optional() });
1967
- 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() });
1968
1871
  var PhoneSessionSchema = SwitchableSessionSchema.pick({
1969
1872
  id: true,
1970
1873
  name: true,
@@ -1985,10 +1888,6 @@ var PhoneSessionSchema = SwitchableSessionSchema.pick({
1985
1888
  effort: true,
1986
1889
  modelNext: true,
1987
1890
  canSwitch: true,
1988
- /** Its role and its live team (ledge home spec §2.4): the agents screen groups a project's sessions by table. */
1989
- role: true,
1990
- roleLabel: true,
1991
- team: true,
1992
1891
  /** Its context and its relief (context handover spec §3.2): the phone shows the gauge; the relief is started from the PC. */
1993
1892
  context: true,
1994
1893
  relieves: true,
@@ -1996,373 +1895,291 @@ var PhoneSessionSchema = SwitchableSessionSchema.pick({
1996
1895
  exitedAt: true
1997
1896
  }).extend({
1998
1897
  pending: PhonePendingSchema.optional(),
1999
- unread: z26.boolean(),
2000
- 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(),
2001
1900
  /** Absent: the agent has no checklist. */
2002
1901
  checklist: PhoneChecklistSummarySchema.optional(),
2003
1902
  /** Started without Ledge (`hook_only`): the phone can neither close nor resume it. */
2004
- readOnly: z26.literal(true).optional()
1903
+ readOnly: z25.literal(true).optional()
2005
1904
  });
2006
- var B64U2 = z26.string().regex(/^[A-Za-z0-9_-]*$/);
2007
- var CredentialSchema = z26.object({
1905
+ var B64U2 = z25.string().regex(/^[A-Za-z0-9_-]*$/);
1906
+ var CredentialSchema = z25.object({
2008
1907
  id: B64U2.max(1366),
2009
1908
  publicKey: B64U2.max(2048),
2010
- alg: z26.union([z26.literal(-7), z26.literal(-257)]),
1909
+ alg: z25.union([z25.literal(-7), z25.literal(-257)]),
2011
1910
  clientDataJSON: B64U2.max(4096),
2012
1911
  authenticatorData: B64U2.max(4096),
2013
- transports: z26.array(z26.string().max(20)).max(8).optional()
1912
+ transports: z25.array(z25.string().max(20)).max(8).optional()
2014
1913
  });
2015
- var AssertionSchema = z26.object({
1914
+ var AssertionSchema = z25.object({
2016
1915
  id: B64U2.max(1366),
2017
1916
  clientDataJSON: B64U2.max(4096),
2018
1917
  authenticatorData: B64U2.max(4096),
2019
1918
  signature: B64U2.max(1024)
2020
1919
  });
2021
- var TeamsDigestSchema = z26.string().regex(/^[0-9a-f]{64}$/);
2022
- var ConfirmPurposeSchema = z26.enum(["register", "decide", "launch", "close", "act", "define", "team", "pc"]);
1920
+ var ConfirmPurposeSchema = z25.enum(["register", "decide", "launch", "close", "act", "pc"]);
2023
1921
  var PhoneChatStepSchema = ChatStepSchema.pick({ kind: true, id: true, name: true }).strict();
2024
- var PhoneChatProposalSchema = z26.object({
2025
- project: z26.string().max(80),
1922
+ var PhoneChatProposalSchema = z25.object({
1923
+ project: z25.string().max(80),
2026
1924
  tool: ToolSchema,
2027
- prompt: z26.string().max(TOOL_TEXT_MAX).optional(),
2028
- launchedId: z26.string().optional(),
2029
- 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()
2030
1928
  }).strict();
2031
- var PhoneChatRelaySchema = z26.object({
2032
- id: z26.string().min(1),
2033
- name: z26.string(),
1929
+ var PhoneChatRelaySchema = z25.object({
1930
+ id: z25.string().min(1),
1931
+ name: z25.string(),
2034
1932
  tool: ToolSchema,
2035
- text: z26.string().max(TOOL_TEXT_MAX),
2036
- status: z26.enum(["queued", "sent"]).optional(),
2037
- sentAt: z26.string().datetime().optional(),
2038
- 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(),
2039
1937
  /** With `failed`: why, as the PC's code (never its text). */
2040
- code: z26.string().max(40).optional()
1938
+ code: z25.string().max(40).optional()
2041
1939
  }).strict();
2042
- var CloseHowSchema = z26.enum(["exit", "killed"]);
2043
- var PhoneChatCloseSchema = z26.object({
2044
- id: z26.string().min(1),
2045
- 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(),
2046
1944
  tool: ToolSchema,
2047
1945
  how: CloseHowSchema.optional(),
2048
- closedAt: z26.string().datetime().optional(),
2049
- failed: z26.literal(true).optional()
2050
- }).strict();
2051
- var PhoneChatTeamSchema = z26.object({
2052
- project: z26.string().max(80),
2053
- name: z26.string().max(60),
2054
- template: z26.string().max(64).optional(),
2055
- 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),
2056
- teamId: z26.string().max(40).optional(),
2057
- launchedAt: z26.string().datetime().optional(),
2058
- failed: z26.literal(true).optional()
1946
+ closedAt: z25.string().datetime().optional(),
1947
+ failed: z25.literal(true).optional()
2059
1948
  }).strict();
2060
- var PhoneChatTaskSchema = z26.object({
2061
- to: z26.string().max(80),
2062
- toName: z26.string().max(80).optional(),
2063
- title: z26.string().max(200),
2064
- text: z26.string().max(TOOL_TEXT_MAX).optional(),
2065
- taskId: z26.string().max(40).optional(),
2066
- ownerName: z26.string().max(80).optional(),
2067
- state: z26.enum(["open", "taken", "done", "refused", "dropped"]).optional(),
2068
- 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()
2069
1958
  }).strict();
2070
- var PhoneChatActionSchema = z26.object({
2071
- action: z26.string().min(1).max(40),
2072
- summary: z26.string().max(300),
1959
+ var PhoneChatActionSchema = z25.object({
1960
+ action: z25.string().min(1).max(40),
1961
+ summary: z25.string().max(300),
2073
1962
  vars: ActionVarsSchema.optional(),
2074
- detail: z26.string().max(TOOL_TEXT_MAX).optional(),
2075
- detailCut: z26.literal(true).optional(),
1963
+ detail: z25.string().max(TOOL_TEXT_MAX).optional(),
1964
+ detailCut: z25.literal(true).optional(),
2076
1965
  risk: ActionRiskSchema,
2077
- session: z26.string().max(100).optional(),
2078
- team: z26.string().max(40).optional(),
1966
+ session: z25.string().max(100).optional(),
2079
1967
  state: ChatActionStateSchema.optional(),
2080
- doneAt: z26.string().datetime().optional(),
2081
- code: z26.string().max(40).optional()
1968
+ doneAt: z25.string().datetime().optional(),
1969
+ code: z25.string().max(40).optional()
2082
1970
  }).strict();
2083
- var PhoneTeamSchema = z26.object({
2084
- id: z26.string().max(40),
2085
- name: z26.string().max(60),
2086
- project: z26.string().max(80).nullable(),
2087
- state: z26.enum(["active", "resting"]),
2088
- template: z26.string().max(64).optional(),
2089
- /** Absent from a daemon older than the phone: the phone then says no start time. */
2090
- createdAt: z26.string().optional(),
2091
- /** `tool`, `model` and `effort` are what the seat was composed with; `leaving` is a seat that finishes its turn and is then closed. */
2092
- seats: z26.array(z26.object({
2093
- role: z26.string().max(40),
2094
- sessionId: z26.string().max(100).nullable(),
2095
- tool: ToolSchema.optional(),
2096
- model: ModelIdSchema.optional(),
2097
- effort: EffortSchema.optional(),
2098
- leaving: z26.literal(true).optional()
2099
- }).strict()).max(16),
2100
- done: z26.number().int().min(0),
2101
- given: z26.number().int().min(0)
2102
- }).strict();
2103
- var PhoneTaskSchema = z26.object({
2104
- id: z26.string().max(40),
2105
- title: z26.string().max(200),
2106
- owner: z26.string().max(100),
2107
- ownerName: z26.string().max(80),
2108
- 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),
2109
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). */
2110
- giver: z26.string().max(100).optional(),
2111
- giverName: z26.string().max(80).optional(),
2112
- text: z26.string().max(TOOL_TEXT_MAX).optional(),
2113
- team: z26.string().max(40).optional(),
2114
- teamName: z26.string().max(60).optional(),
2115
- state: z26.enum(["open", "taken", "done", "refused", "dropped"]),
2116
- result: z26.string().max(TOOL_TEXT_MAX).optional(),
2117
- cut: z26.literal(true).optional(),
2118
- at: z26.string(),
2119
- updatedAt: z26.string(),
2120
- 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()
2121
1986
  }).strict();
2122
- var ChatErrorCodeSchema = z26.enum(["busy", "timeout", "cancelled", "failed"]);
2123
- var PhoneChatTurnSchema = z26.object({
1987
+ var ChatErrorCodeSchema = z25.enum(["busy", "timeout", "cancelled", "failed"]);
1988
+ var PhoneChatTurnSchema = z25.object({
2124
1989
  qid: OperationIdSchema,
2125
- question: z26.string().max(MESSAGE_MAX),
2126
- askedAt: z26.string().datetime(),
2127
- steps: z26.array(PhoneChatStepSchema).max(50),
2128
- answer: z26.string().max(THREAD_TEXT_MAX).optional(),
2129
- 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(),
2130
1995
  error: ChatErrorCodeSchema.optional(),
2131
- proposals: z26.array(PhoneChatProposalSchema).max(MAX_PROPOSALS).optional(),
1996
+ proposals: z25.array(PhoneChatProposalSchema).max(MAX_PROPOSALS).optional(),
2132
1997
  relay: PhoneChatRelaySchema.optional(),
2133
- closes: z26.array(PhoneChatCloseSchema).min(1).max(MAX_PROPOSALS).optional(),
2134
- cut: z26.literal(true).optional(),
2135
- team: PhoneChatTeamSchema.optional(),
2136
- tasks: z26.array(PhoneChatTaskSchema).min(1).max(MAX_PROPOSALS).optional(),
2137
- actions: z26.array(PhoneChatActionSchema).min(1).max(MAX_PROPOSALS).optional(),
2138
- ignoredAt: z26.string().datetime().optional(),
2139
- 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()
2140
2004
  }).strict();
2141
2005
  var CHAT_HISTORY_BUDGET = 393216;
2142
- var sessionId = z26.string().min(1).max(100);
2143
- var PhoneExpectSchema = PendingSchema.pick({ kind: true, text: true }).extend({ key: z26.string().min(1).max(64) });
2144
- 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");
2145
- var teamsOp = { op: OperationIdSchema, assertion: AssertionSchema.optional() };
2146
- 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"]);
2147
2011
  var pcSubject = (action, version) => action === "update" ? `update@${version ?? ""}` : "restart";
2148
- var teamsScope = { scope: DefinitionScopeSchema, project: z26.string().min(1).max(80).optional() };
2149
- var PhoneClientMessageSchema = z26.discriminatedUnion("type", [
2150
- z26.object({ type: z26.literal("snapshot.request") }),
2151
- 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 }),
2152
2015
  /** The session's request with its whole body (up to `PENDING_BODY_MAX`). */
2153
- z26.object({ type: z26.literal("session.pending"), id: sessionId }),
2016
+ z25.object({ type: z25.literal("session.pending"), id: sessionId }),
2154
2017
  /** The session whose terminal the phone shows; null when it shows none. */
2155
- z26.object({ type: z26.literal("session.watch"), id: sessionId.nullable() }),
2156
- 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() }),
2157
2020
  /**
2158
2021
  * Asks for a challenge. One object for every purpose: the gateway refuses a `decide` without `id` and `expect`. A `close`
2159
2022
  * or `act` names a turn of the chat (`qid`) or a session (`id`, for `session.close` and `session.resume`).
2160
2023
  */
2161
- z26.object({
2162
- type: z26.literal("confirm.prepare"),
2024
+ z25.object({
2025
+ type: z25.literal("confirm.prepare"),
2163
2026
  purpose: ConfirmPurposeSchema,
2164
2027
  id: sessionId.optional(),
2165
2028
  expect: PhoneExpectSchema.optional(),
2166
2029
  qid: OperationIdSchema.optional(),
2167
- /** sha256 of the `define` or `team` operation the challenge is for (`teamsDigest`). */
2168
- digest: TeamsDigestSchema.optional(),
2169
2030
  /** A `pc` challenge: what it is for, and for an update the version it covers. */
2170
2031
  action: PcActionSchema.optional(),
2171
- version: z26.string().regex(SEMVER).optional()
2032
+ version: z25.string().regex(SEMVER).optional()
2172
2033
  }),
2173
- z26.object({ type: z26.literal("credential.register"), op: OperationIdSchema, credential: CredentialSchema }),
2174
- z26.object({
2175
- 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"),
2176
2037
  op: OperationIdSchema,
2177
2038
  id: sessionId,
2178
2039
  decision: DecisionSchema,
2179
- note: z26.string().trim().min(1).max(NOTE_MAX).optional(),
2040
+ note: z25.string().trim().min(1).max(NOTE_MAX).optional(),
2180
2041
  /** The request the phone showed: refused unless it is still the pending one. */
2181
2042
  expect: PhoneExpectSchema,
2182
2043
  /** The device check over the challenge of `confirm.prepare`; required by the daemon for a high-risk accept. */
2183
2044
  assertion: AssertionSchema.optional()
2184
2045
  }),
2185
- z26.object({
2186
- type: z26.literal("session.reply"),
2046
+ z25.object({
2047
+ type: z25.literal("session.reply"),
2187
2048
  op: OperationIdSchema,
2188
2049
  id: sessionId,
2189
- text: z26.string().max(MESSAGE_MAX),
2190
- attachments: z26.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional(),
2050
+ text: z25.string().max(MESSAGE_MAX),
2051
+ attachments: z25.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional(),
2191
2052
  /** The request the reply answers, or null when the phone showed none: refused if the session's request is no longer that one. */
2192
2053
  expect: PhoneExpectSchema.nullable(),
2193
2054
  assertion: AssertionSchema.optional()
2194
2055
  }),
2195
2056
  /** OMP's `ask`: the answers to every question of the dialog `requestId`, in order; `cancel` declines it. Bounds as the local `session.answer`. */
2196
- z26.object({
2197
- type: z26.literal("session.answer"),
2057
+ z25.object({
2058
+ type: z25.literal("session.answer"),
2198
2059
  op: OperationIdSchema,
2199
2060
  id: sessionId,
2200
- requestId: z26.string().min(1).max(200),
2201
- 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),
2202
- 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(),
2203
2064
  expect: PhoneExpectSchema
2204
2065
  }),
2205
- z26.object({ type: z26.literal("session.interrupt"), op: OperationIdSchema, id: sessionId }),
2066
+ z25.object({ type: z25.literal("session.interrupt"), op: OperationIdSchema, id: sessionId }),
2206
2067
  /** Ends a live session as `/exit` would, killed as a last resort; answered with its `how`. Passkey, purpose `close`, over the session. */
2207
- 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() }),
2208
2069
  /** Starts an ended session again on its conversation. Passkey, purpose `act`, over the session. */
2209
- 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() }),
2210
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`. */
2211
- 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() }),
2212
2073
  /** The models an agent offers on the PC. */
2213
- z26.object({ type: z26.literal("models.list"), tool: ToolSchema }),
2074
+ z25.object({ type: z25.literal("models.list"), tool: ToolSchema }),
2214
2075
  /** The phone drops its passkey from the daemon. */
2215
- z26.object({ type: z26.literal("device.forget"), op: OperationIdSchema }),
2076
+ z25.object({ type: z25.literal("device.forget"), op: OperationIdSchema }),
2216
2077
  /** The phone's push subscription, with the VAPID key it was made with (so a key change is seen). */
2217
- z26.object({ type: z26.literal("push.subscribe"), op: OperationIdSchema, subscription: PushSubscriptionSchema, key: B64U2.length(87) }),
2218
- 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 }),
2219
2080
  /** The phone's own chat with Ledge. */
2220
- z26.object({ type: z26.literal("chat.ask"), qid: OperationIdSchema, text: z26.string().trim().max(MESSAGE_MAX), attachments: z26.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional() }),
2221
- z26.object({ type: z26.literal("chat.cancel"), qid: OperationIdSchema }),
2222
- z26.object({ type: z26.literal("chat.reset") }),
2223
- 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") }),
2224
2085
  /** An image to store, sent alone before the message that names it; no `id`, and at most `ATTACHMENT_MAX` bytes. */
2225
- 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)) }) }),
2226
2087
  AttachmentGetSchema.pick({ type: true, requestId: true, attachment: true, preview: true }),
2227
- z26.object({ type: z26.literal("chat.relay"), op: OperationIdSchema, qid: OperationIdSchema }),
2088
+ z25.object({ type: z25.literal("chat.relay"), op: OperationIdSchema, qid: OperationIdSchema }),
2228
2089
  /** Takes the card's queued instruction back out of the queue, as the local `session.relay.cancel`. */
2229
- z26.object({ type: z26.literal("chat.relay.cancel"), op: OperationIdSchema, qid: OperationIdSchema }),
2230
- z26.object({ type: z26.literal("chat.launch"), op: OperationIdSchema, qid: OperationIdSchema, rows: CardRowsSchema.optional(), assertion: AssertionSchema.optional() }),
2231
- z26.object({ type: z26.literal("chat.close"), op: OperationIdSchema, qid: OperationIdSchema, rows: CardRowsSchema.optional(), assertion: AssertionSchema.optional() }),
2232
- /** The turn's team card (roles spec §3.8): launched like a session card, with the device check (purpose `launch`, the turn). */
2233
- 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() }),
2234
2093
  /** A row of the turn's task card: given by Ledge. */
2235
- 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) }),
2236
2095
  /** Rows of the turn's generic card (action registry spec §5): `confirmed` as the local `chat.act`; a row whose action asks
2237
2096
  * for a device check (`phone`) needs one assertion, purpose `act`, over the turn. */
2238
- z26.object({
2239
- type: z26.literal("chat.act"),
2097
+ z25.object({
2098
+ type: z25.literal("chat.act"),
2240
2099
  op: OperationIdSchema,
2241
2100
  qid: OperationIdSchema,
2242
2101
  rows: CardRowsSchema.optional(),
2243
- confirmed: z26.literal(true).optional(),
2102
+ confirmed: z25.literal(true).optional(),
2244
2103
  assertion: AssertionSchema.optional(),
2245
2104
  /** « Refuser », as the local `chat.act`: no passkey, no confirmation. */
2246
- deny: z26.literal(true).optional()
2105
+ deny: z25.literal(true).optional()
2247
2106
  }),
2248
2107
  /** « Ignorer » the turn's cards, or `undo` (« Revoir »), as the local `chat.ignore`. */
2249
- z26.object({ type: z26.literal("chat.ignore"), op: OperationIdSchema, qid: OperationIdSchema, undo: z26.literal(true).optional() }),
2250
- /** « Reprendre » a resting team. */
2251
- 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() }),
2252
2109
  /** Puts a closed task Ledge gave away from « À traiter ». */
2253
- 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) }),
2254
2111
  /** Whether the phone's app is in front: a device that is visible gets no push. */
2255
- z26.object({ type: z26.literal("presence"), visible: z26.boolean() }),
2256
- /** The roles, templates and problems of every scope the phone may name; then one role whole, when the catalog cut its prompt. */
2257
- z26.object({ type: z26.literal("teams.catalog") }),
2258
- z26.object({ type: z26.literal("teams.role"), ...teamsScope, id: RoleIdSchema }).strict(),
2259
- /** `base` is the hash the phone was shown, null to create. */
2260
- z26.object({ type: z26.literal("role.write"), ...teamsOp, ...teamsScope, role: PhoneRoleDraftSchema, base: DefinitionHashSchema.nullable() }).strict(),
2261
- z26.object({ type: z26.literal("role.delete"), ...teamsOp, ...teamsScope, id: RoleIdSchema, base: DefinitionHashSchema }).strict(),
2262
- /** No `id`: create, the id comes from the name. */
2263
- z26.object({ type: z26.literal("template.write"), ...teamsOp, ...teamsScope, id: TemplateIdSchema.optional(), name: TeamNameSchema, seats: PhoneSeatsSchema, base: DefinitionHashSchema.nullable() }).strict(),
2264
- z26.object({ type: z26.literal("template.delete"), ...teamsOp, ...teamsScope, id: TemplateIdSchema, base: DefinitionHashSchema }).strict(),
2265
- 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(),
2266
- z26.object({ type: z26.literal("team.compose"), ...teamsOp, team: TeamIdSchema, seats: PhoneSeatsSchema }).strict(),
2267
- z26.object({ type: z26.literal("team.seat"), ...teamsOp, team: TeamIdSchema, role: RoleIdSchema, action: z26.enum(["start", "restart"]) }).strict(),
2268
- z26.object({ type: z26.literal("team.dissolve"), ...teamsOp, team: TeamIdSchema }).strict(),
2112
+ z25.object({ type: z25.literal("presence"), visible: z25.boolean() }),
2269
2113
  /** Installs `version` on the PC, then restarts its daemon; the phone asks for its own build's version. Passkey, purpose `pc`. */
2270
- 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(),
2271
2115
  /** Restarts the PC's daemon without installing anything. Passkey, purpose `pc`. */
2272
- z26.object({ type: z26.literal("daemon.restart"), ...teamsOp }).strict()
2273
- ]).superRefine((m, ctx) => {
2274
- const issue = "scope" in m ? scopeIssue(m) : null;
2275
- if (issue) ctx.addIssue({ code: z26.ZodIssueCode.custom, message: issue, path: ["project"] });
2276
- });
2277
- var PhoneModelChoiceSchema = z26.object({
2116
+ z25.object({ type: z25.literal("daemon.restart"), ...pcOp }).strict()
2117
+ ]);
2118
+ var PhoneModelChoiceSchema = z25.object({
2278
2119
  id: ModelChoiceSchema.shape.id.max(120),
2279
- label: z26.string().max(80),
2280
- description: z26.string().max(200).optional(),
2281
- 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(),
2282
2123
  defaultEffort: EffortSchema.optional(),
2283
- isDefault: z26.boolean().optional()
2124
+ isDefault: z25.boolean().optional()
2284
2125
  }).strict();
2285
- var PhoneSeatModelSchema = z26.object({ role: z26.string().max(40), session: sessionId, status: z26.enum(["applied", "scheduled", "refused"]), reason: ModelRefusalSchema.optional() });
2286
- var PhoneServerMessageSchema = z26.discriminatedUnion("type", [
2287
- z26.object({ type: z26.literal("snapshot"), protocol: z26.literal(PHONE_PROTOCOL), sessions: z26.array(PhoneSessionSchema), capabilities: CapabilitiesByToolSchema, daemon: z26.object({
2288
- version: z26.string(),
2289
- name: z26.string().max(40),
2290
- boot: z26.string().uuid().optional(),
2291
- 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(),
2292
2131
  /** The daemon takes `session.model`. */
2293
- models: z26.literal(true).optional(),
2132
+ models: z25.literal(true).optional(),
2294
2133
  /** The daemon sends `session.checklist` and a session's `checklist` summary. */
2295
- checklist: z26.literal(true).optional(),
2134
+ checklist: z25.literal(true).optional(),
2296
2135
  /** `update`: the daemon can install a version and restart (npm, systemd); `restart`: it can restart (systemd). */
2297
- update: z26.literal(true).optional(),
2298
- restart: z26.literal(true).optional(),
2136
+ update: z25.literal(true).optional(),
2137
+ restart: z25.literal(true).optional(),
2299
2138
  /** The daemon takes `session.close` and `session.resume`. */
2300
- sessionClose: z26.literal(true).optional()
2301
- }), 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() }),
2302
- z26.object({
2303
- type: z26.literal("confirm.challenge"),
2304
- purpose: ConfirmPurposeSchema,
2305
- challenge: B64U2.max(64),
2306
- rpId: z26.string().max(253),
2307
- credentialId: B64U2.max(1366).optional(),
2308
- expiresInMs: z26.number().int().positive(),
2309
- /** 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. */
2310
- digest: TeamsDigestSchema.optional()
2311
- }),
2312
- z26.object({ type: z26.literal("session.updated"), session: PhoneSessionSchema }),
2313
- 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() }),
2314
2144
  /** A session's checklist, sent to the phone that watches it; `null`: it has none (any more). */
2315
- 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() }),
2316
2146
  /** `pending.cut` is set when even this body was shortened. */
2317
- z26.object({ type: z26.literal("session.pending"), id: z26.string(), pending: PhonePendingSchema }),
2318
- 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()) }),
2319
2149
  /** `cut`: the ids of the items shortened; `more`: older items were left out. */
2320
- z26.object({ type: z26.literal("session.thread"), id: z26.string(), items: z26.array(ThreadItemSchema), cut: z26.array(z26.string()), more: z26.boolean() }),
2321
- z26.object({ type: z26.literal("session.thread.item"), id: z26.string(), item: ThreadItemSchema, cut: z26.literal(true).optional() }),
2322
- z26.object({
2323
- 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"),
2324
2154
  op: OperationIdSchema,
2325
2155
  status: OperationStatusSchema,
2326
2156
  reason: OperationReasonSchema.optional(),
2327
- models: z26.array(PhoneSeatModelSchema).max(16).optional(),
2328
2157
  /** How an applied `session.close` ended the agent: `killed` when it had to be forced. */
2329
2158
  how: CloseHowSchema.optional()
2330
2159
  }),
2331
2160
  /** The models an agent offers; `error`: it could not be asked, `models` is then what Ledge knows without it. */
2332
- 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() }),
2333
2162
  /** A model change that was accepted and then failed (the agent could not restart). */
2334
- z26.object({ type: z26.literal("session.model.failed"), id: z26.string(), reason: ModelRefusalSchema }),
2335
- z26.object({ type: z26.literal("chat.history"), turns: z26.array(PhoneChatTurnSchema).max(50) }),
2336
- 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 }),
2337
2166
  /** The whole text so far, not an increment. */
2338
- z26.object({ type: z26.literal("chat.delta"), qid: OperationIdSchema, text: z26.string().max(THREAD_TEXT_MAX) }),
2339
- z26.object({ type: z26.literal("chat.done"), qid: OperationIdSchema, turn: PhoneChatTurnSchema }),
2340
- z26.object({ type: z26.literal("chat.error"), qid: OperationIdSchema, code: ChatErrorCodeSchema }),
2341
- 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 }),
2342
2170
  /** The daemon updating or restarting itself, whoever asked: npm runs, then the service restarts (the link drops right after). */
2343
- 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"]) }),
2344
2172
  /** Nothing was changed. Never npm's output nor a command: both hold the PC's paths. */
2345
- z26.object({ type: z26.literal("daemon.failed"), version: z26.string().max(40), reason: UpdateFailureSchema }),
2346
- z26.object({ type: z26.literal("teams.role"), role: PhoneRoleSchema }),
2347
- /** The live teams, after each snapshot and on every change. */
2348
- 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 }),
2349
2174
  /** The tasks Ledge gave, open or closed lately, after each snapshot; then each change. */
2350
- z26.object({ type: z26.literal("tasks"), tasks: z26.array(PhoneTaskSchema).max(200) }),
2351
- 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 }),
2352
2177
  AttachmentStoredSchema,
2353
2178
  AttachmentDataSchema,
2354
2179
  AttachmentErrorSchema,
2355
2180
  /** Never carries free text. */
2356
- 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() })
2357
2182
  ]);
2358
- var teamsPurpose = (type) => type.startsWith("team.") ? "team" : "define";
2359
- var DIGEST_OP = "00000000-0000-4000-8000-000000000000";
2360
- async function teamsDigest(m) {
2361
- const { op: _op, assertion: _assertion, ...raw } = m;
2362
- const { op: _parsedOp, assertion: _parsedAssertion, ...rest } = PhoneClientMessageSchema.parse({ ...raw, op: DIGEST_OP });
2363
- const bytes = new Uint8Array(await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(canonicalJson(rest))));
2364
- return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
2365
- }
2366
2183
 
2367
2184
  // ../protocol/src/todos.ts
2368
2185
  var TODO_TOOLS = /* @__PURE__ */ new Set(["TodoWrite", "update_plan", "todo"]);
@@ -2555,8 +2372,6 @@ export {
2555
2372
  contextNear,
2556
2373
  BRIEF_MAX,
2557
2374
  ToolSchema,
2558
- autonomyArgs,
2559
- ompApprovalFor,
2560
2375
  SessionSchema,
2561
2376
  backendOf,
2562
2377
  isArchived,
@@ -2566,25 +2381,8 @@ export {
2566
2381
  extractProposal,
2567
2382
  parseRelayBlock,
2568
2383
  parseCloseBlock,
2569
- parseTeamBlock,
2570
2384
  parseTaskBlock,
2571
2385
  parseProjectBlock,
2572
- SshAliasSchema,
2573
- MachinesSchema,
2574
- PROJECT_COLORS,
2575
- ProjectsSchema,
2576
- DEFAULT_PROJECTS,
2577
- projectOf,
2578
- RoleIdSchema,
2579
- ROLE_LABEL_MAX,
2580
- ROLE_PROMPT_MAX,
2581
- RoleSchema,
2582
- TEAM_SEATS_MAX,
2583
- SeatsSchema,
2584
- TeamNameSchema,
2585
- TemplateIdSchema,
2586
- TeamSchema,
2587
- isTeamLive,
2588
2386
  NOTE_MAX,
2589
2387
  NOTE_NOT_TYPED,
2590
2388
  offers,
@@ -2608,7 +2406,20 @@ export {
2608
2406
  ChatTurnSchema,
2609
2407
  proposalRows,
2610
2408
  DOCUMENT_MAX_BYTES,
2409
+ SshAliasSchema,
2410
+ MachinesSchema,
2611
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,
2612
2423
  RouteResultSchema,
2613
2424
  DEFAULT_RELAY_URL,
2614
2425
  MobileConfigSchema,
@@ -2622,6 +2433,7 @@ export {
2622
2433
  parseServerMessage,
2623
2434
  NAMES,
2624
2435
  pickName,
2436
+ namesInUse,
2625
2437
  TOPIC_MAX,
2626
2438
  cleanTopic,
2627
2439
  sessionTitle,
@@ -2634,11 +2446,6 @@ export {
2634
2446
  pushEndpointAllowed,
2635
2447
  PushSendResultSchema,
2636
2448
  PushPayloadSchema,
2637
- PhoneRoleSchema,
2638
- PhoneTemplateSchema,
2639
- TEAMS_OPERATION_TYPES,
2640
- isTeamsOperation,
2641
- canonicalJson,
2642
2449
  PHONE_PROTOCOL,
2643
2450
  padPlain,
2644
2451
  THREAD_ITEMS_MAX,
@@ -2655,8 +2462,6 @@ export {
2655
2462
  pcSubject,
2656
2463
  PhoneClientMessageSchema,
2657
2464
  PhoneModelChoiceSchema,
2658
- teamsPurpose,
2659
- teamsDigest,
2660
2465
  TODO_TOOLS,
2661
2466
  latestTodos,
2662
2467
  doneCount,