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