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