@paradow/ledge 0.36.0 → 0.37.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/index.js +2683 -1313
- package/dist/cli/reduceWorker.js +916 -797
- package/dist/ledge-guide.md +11 -2
- package/package.json +1 -1
package/dist/cli/reduceWorker.js
CHANGED
|
@@ -728,8 +728,12 @@ var ProjectsSchema = z14.object({ projects: z14.array(ProjectSchema).max(100), r
|
|
|
728
728
|
for (const problem of projectsProblems(p)) ctx.addIssue({ code: "custom", message: problem.code, path: problem.path });
|
|
729
729
|
});
|
|
730
730
|
|
|
731
|
+
// ../protocol/src/broadcast.ts
|
|
732
|
+
var BROADCAST_SESSIONS_MAX = 32;
|
|
733
|
+
var BROADCAST_LABEL_MAX = 120;
|
|
734
|
+
|
|
731
735
|
// ../protocol/src/messages.ts
|
|
732
|
-
import { z as
|
|
736
|
+
import { z as z23 } from "zod";
|
|
733
737
|
|
|
734
738
|
// ../protocol/src/repos.ts
|
|
735
739
|
import { z as z15 } from "zod";
|
|
@@ -742,437 +746,461 @@ var ReposInspectSchema = z15.object({
|
|
|
742
746
|
var RepoInfoSchema = z15.object({ path: z15.string(), exists: z15.boolean(), branch: z15.string().nullable() });
|
|
743
747
|
var ReposInfoSchema = z15.object({ type: z15.literal("repos.info"), requestId: z15.string(), repos: z15.array(RepoInfoSchema) });
|
|
744
748
|
|
|
745
|
-
// ../protocol/src/
|
|
749
|
+
// ../protocol/src/commands.ts
|
|
746
750
|
import { z as z16 } from "zod";
|
|
747
|
-
var
|
|
748
|
-
var
|
|
749
|
-
var
|
|
751
|
+
var SlashSourceSchema = z16.enum(["builtin", "project", "user", "plugin", "extension"]);
|
|
752
|
+
var SLASH_COMMANDS_MAX = 400;
|
|
753
|
+
var SLASH_DESCRIPTION_MAX = 300;
|
|
754
|
+
var SlashCommandSchema = z16.object({
|
|
755
|
+
name: z16.string().min(1).max(200),
|
|
756
|
+
description: z16.string().max(SLASH_DESCRIPTION_MAX).optional(),
|
|
757
|
+
argumentHint: z16.string().max(200).optional(),
|
|
758
|
+
aliases: z16.array(z16.string().min(1).max(200)).max(10).optional(),
|
|
759
|
+
source: SlashSourceSchema,
|
|
760
|
+
blocked: z16.enum(["panel", "close"]).optional(),
|
|
761
|
+
bare: z16.literal("panel").optional()
|
|
762
|
+
});
|
|
763
|
+
var SessionCommandsSchema = z16.object({ type: z16.literal("session.commands"), requestId: z16.string().min(1).max(100), id: z16.string() });
|
|
764
|
+
var SessionCommandsListingSchema = z16.object({
|
|
765
|
+
type: z16.literal("session.commands.listing"),
|
|
766
|
+
requestId: z16.string(),
|
|
767
|
+
id: z16.string(),
|
|
768
|
+
tool: ToolSchema.optional(),
|
|
769
|
+
commands: z16.array(SlashCommandSchema).max(SLASH_COMMANDS_MAX),
|
|
770
|
+
error: z16.string().max(200).optional()
|
|
771
|
+
});
|
|
750
772
|
|
|
751
|
-
// ../protocol/src/
|
|
773
|
+
// ../protocol/src/scan.ts
|
|
752
774
|
import { z as z17 } from "zod";
|
|
753
|
-
var
|
|
754
|
-
var
|
|
755
|
-
var
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
775
|
+
var ReposScanSchema = z17.object({ type: z17.literal("repos.scan"), requestId: z17.string().min(1).max(100), machineId: z17.string().optional() });
|
|
776
|
+
var FoundRepoSchema = z17.object({ path: z17.string(), branch: z17.string().nullable(), remote: z17.string().optional(), manifest: z17.string().max(200).optional() });
|
|
777
|
+
var ReposFoundSchema = z17.object({ type: z17.literal("repos.found"), requestId: z17.string(), repos: z17.array(FoundRepoSchema).max(500), truncated: z17.boolean(), error: z17.string().optional() });
|
|
778
|
+
|
|
779
|
+
// ../protocol/src/openrig.ts
|
|
780
|
+
import { z as z18 } from "zod";
|
|
781
|
+
var RigNameSchema = z18.string().min(1).max(100).regex(/^[A-Za-z0-9][A-Za-z0-9._-]*$/, "not a rig name");
|
|
782
|
+
var RigSeatNameSchema = z18.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");
|
|
783
|
+
var SeatPermissionsSchema = z18.enum(["inherit", "floor", "auto", "full_bypass"]);
|
|
784
|
+
var RigSeatSchema = z18.object({
|
|
785
|
+
logicalId: z18.string(),
|
|
786
|
+
session: z18.string(),
|
|
787
|
+
runtime: z18.string(),
|
|
788
|
+
model: z18.string().nullable(),
|
|
789
|
+
sessionStatus: z18.string(),
|
|
790
|
+
lifecycleState: z18.string(),
|
|
791
|
+
activity: z18.string(),
|
|
792
|
+
stopped: z18.boolean(),
|
|
793
|
+
work: z18.number().int().min(0)
|
|
794
|
+
});
|
|
795
|
+
var RigSchema = z18.object({
|
|
796
|
+
id: z18.string(),
|
|
797
|
+
name: z18.string(),
|
|
798
|
+
status: z18.string(),
|
|
799
|
+
lifecycleState: z18.string(),
|
|
800
|
+
seats: z18.number().int().min(0),
|
|
801
|
+
running: z18.number().int().min(0),
|
|
802
|
+
attention: z18.number().int().min(0),
|
|
803
|
+
uptime: z18.string().nullable(),
|
|
804
|
+
snapshot: z18.string().nullable(),
|
|
805
|
+
nodes: z18.array(RigSeatSchema)
|
|
806
|
+
});
|
|
807
|
+
var RigDaemonStateSchema = z18.enum(["running", "stopped", "stale", "unknown"]);
|
|
808
|
+
var RigKernelStateSchema = z18.enum(["ready", "starting", "stopped", "skipped", "absent", "unknown"]);
|
|
809
|
+
var OpenRigStateSchema = z18.object({
|
|
810
|
+
installed: z18.boolean(),
|
|
811
|
+
version: z18.string().optional(),
|
|
812
|
+
daemon: z18.object({ state: RigDaemonStateSchema, pid: z18.number().int().optional(), port: z18.number().int().optional(), message: z18.string().optional() }),
|
|
813
|
+
kernel: z18.object({ state: RigKernelStateSchema }),
|
|
814
|
+
rigs: z18.array(RigSchema),
|
|
787
815
|
/** When it was read (ISO). */
|
|
788
|
-
at:
|
|
816
|
+
at: z18.string()
|
|
789
817
|
});
|
|
790
|
-
var OpenRigActionSchema =
|
|
818
|
+
var OpenRigActionSchema = z18.discriminatedUnion("kind", [
|
|
791
819
|
/** `restore` `last`: `rig start --last` (the rigs that were running come back); `none`: `rig daemon start`. */
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
820
|
+
z18.object({ kind: z18.literal("daemon.start"), restore: z18.enum(["last", "none"]).optional(), noKernel: z18.boolean().optional() }),
|
|
821
|
+
z18.object({ kind: z18.literal("daemon.stop") }),
|
|
822
|
+
z18.object({ kind: z18.literal("daemon.restart"), restore: z18.enum(["last", "none"]).optional() }),
|
|
823
|
+
z18.object({ kind: z18.literal("kernel.start") }),
|
|
824
|
+
z18.object({ kind: z18.literal("kernel.stop") }),
|
|
825
|
+
z18.object({ kind: z18.literal("kernel.restart") }),
|
|
826
|
+
z18.object({ kind: z18.literal("rig.start"), rig: RigNameSchema }),
|
|
827
|
+
z18.object({ kind: z18.literal("rig.stop"), rig: RigNameSchema, snapshot: z18.boolean().optional(), force: z18.boolean().optional(), delete: z18.boolean().optional() }),
|
|
828
|
+
z18.object({ kind: z18.literal("rig.restart"), rig: RigNameSchema }),
|
|
801
829
|
/** A seat's settings (docs/mockups/ledge-openrig-groups.html, view 2). `runtime`: moves it now to the other harness (a successor
|
|
802
830
|
* takes its context, `rig seat set-runtime`), `model` and `effort` going with it; without it, `model`, `effort` and `permissions`
|
|
803
831
|
* apply at its next resume. `dryRun`: the move's plan only. */
|
|
804
|
-
|
|
805
|
-
kind:
|
|
832
|
+
z18.object({
|
|
833
|
+
kind: z18.literal("seat.set"),
|
|
806
834
|
seat: RigSeatNameSchema,
|
|
807
|
-
runtime:
|
|
835
|
+
runtime: z18.enum(["claude-code", "codex"]).optional(),
|
|
808
836
|
model: ModelIdSchema.optional(),
|
|
809
837
|
effort: EffortSchema.optional(),
|
|
810
838
|
permissions: SeatPermissionsSchema.optional(),
|
|
811
|
-
dryRun:
|
|
839
|
+
dryRun: z18.boolean().optional()
|
|
812
840
|
})
|
|
813
841
|
]);
|
|
814
|
-
var OpenRigStatusSchema =
|
|
815
|
-
var OpenRigActSchema =
|
|
816
|
-
var OpenRigUnreachableSchema =
|
|
817
|
-
var OpenRigStateMessageSchema =
|
|
818
|
-
type:
|
|
819
|
-
requestId:
|
|
820
|
-
machineId:
|
|
842
|
+
var OpenRigStatusSchema = z18.object({ type: z18.literal("openrig.status"), requestId: z18.string().min(1).max(100), machineId: z18.string().optional() });
|
|
843
|
+
var OpenRigActSchema = z18.object({ type: z18.literal("openrig.act"), requestId: z18.string().min(1).max(100), action: OpenRigActionSchema, machineId: z18.string().optional() });
|
|
844
|
+
var OpenRigUnreachableSchema = z18.enum(["offline", "outdated"]);
|
|
845
|
+
var OpenRigStateMessageSchema = z18.object({
|
|
846
|
+
type: z18.literal("openrig.state"),
|
|
847
|
+
requestId: z18.string().optional(),
|
|
848
|
+
machineId: z18.string().optional(),
|
|
821
849
|
state: OpenRigStateSchema.optional(),
|
|
822
850
|
error: OpenRigUnreachableSchema.optional()
|
|
823
851
|
});
|
|
824
|
-
var OpenRigDoneSchema =
|
|
825
|
-
type:
|
|
826
|
-
requestId:
|
|
827
|
-
machineId:
|
|
828
|
-
ok:
|
|
829
|
-
commands:
|
|
830
|
-
output:
|
|
831
|
-
error:
|
|
832
|
-
});
|
|
833
|
-
var RigSpecMemberSchema =
|
|
834
|
-
id:
|
|
835
|
-
runtime:
|
|
836
|
-
model:
|
|
837
|
-
agent:
|
|
852
|
+
var OpenRigDoneSchema = z18.object({
|
|
853
|
+
type: z18.literal("openrig.done"),
|
|
854
|
+
requestId: z18.string(),
|
|
855
|
+
machineId: z18.string().optional(),
|
|
856
|
+
ok: z18.boolean(),
|
|
857
|
+
commands: z18.array(z18.string()),
|
|
858
|
+
output: z18.string().optional(),
|
|
859
|
+
error: z18.string().optional()
|
|
860
|
+
});
|
|
861
|
+
var RigSpecMemberSchema = z18.object({
|
|
862
|
+
id: z18.string(),
|
|
863
|
+
runtime: z18.string(),
|
|
864
|
+
model: z18.string().optional(),
|
|
865
|
+
agent: z18.string(),
|
|
838
866
|
/** Its `permission_policy`, as written. */
|
|
839
|
-
policy:
|
|
840
|
-
});
|
|
841
|
-
var RigSpecPodSchema =
|
|
842
|
-
var RigSpecSchema =
|
|
843
|
-
name:
|
|
844
|
-
source:
|
|
845
|
-
summary:
|
|
846
|
-
path:
|
|
867
|
+
policy: z18.string().optional()
|
|
868
|
+
});
|
|
869
|
+
var RigSpecPodSchema = z18.object({ id: z18.string(), label: z18.string().optional(), members: z18.array(RigSpecMemberSchema) });
|
|
870
|
+
var RigSpecSchema = z18.object({
|
|
871
|
+
name: z18.string(),
|
|
872
|
+
source: z18.string(),
|
|
873
|
+
summary: z18.string().optional(),
|
|
874
|
+
path: z18.string(),
|
|
847
875
|
/** The rig's `permission_policy`, as written (`builtin:auto`, a file…). */
|
|
848
|
-
policy:
|
|
849
|
-
pods:
|
|
850
|
-
edges:
|
|
851
|
-
});
|
|
852
|
-
var OpenRigSpecsSchema =
|
|
853
|
-
var OpenRigSpecListSchema =
|
|
854
|
-
type:
|
|
855
|
-
requestId:
|
|
856
|
-
machineId:
|
|
857
|
-
specs:
|
|
858
|
-
error:
|
|
859
|
-
});
|
|
860
|
-
var RigRoleSchema =
|
|
861
|
-
var RuntimeSchema =
|
|
862
|
-
var RigPolicySchema =
|
|
876
|
+
policy: z18.string().optional(),
|
|
877
|
+
pods: z18.array(RigSpecPodSchema),
|
|
878
|
+
edges: z18.number().int().min(0)
|
|
879
|
+
});
|
|
880
|
+
var OpenRigSpecsSchema = z18.object({ type: z18.literal("openrig.specs"), requestId: z18.string().min(1).max(100), machineId: z18.string().optional() });
|
|
881
|
+
var OpenRigSpecListSchema = z18.object({
|
|
882
|
+
type: z18.literal("openrig.specList"),
|
|
883
|
+
requestId: z18.string(),
|
|
884
|
+
machineId: z18.string().optional(),
|
|
885
|
+
specs: z18.array(RigSpecSchema),
|
|
886
|
+
error: z18.string().optional()
|
|
887
|
+
});
|
|
888
|
+
var RigRoleSchema = z18.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");
|
|
889
|
+
var RuntimeSchema = z18.enum(["claude-code", "codex"]);
|
|
890
|
+
var RigPolicySchema = z18.enum(["auto", "standard", "open", "yolo", "locked"]);
|
|
863
891
|
var RIG_POLICIES = RigPolicySchema.options;
|
|
864
|
-
var RigLaunchSchema =
|
|
892
|
+
var RigLaunchSchema = z18.object({
|
|
865
893
|
spec: RigNameSchema,
|
|
866
|
-
cwd:
|
|
894
|
+
cwd: z18.string().min(1).max(4096),
|
|
867
895
|
name: RigNameSchema,
|
|
868
|
-
seats:
|
|
869
|
-
runtimes:
|
|
870
|
-
models:
|
|
871
|
-
delegation:
|
|
872
|
-
save:
|
|
873
|
-
plan:
|
|
896
|
+
seats: z18.record(RigRoleSchema, z18.number().int().min(0).max(9)).optional(),
|
|
897
|
+
runtimes: z18.record(RigRoleSchema, RuntimeSchema).optional(),
|
|
898
|
+
models: z18.record(RigRoleSchema, z18.string().min(1).max(200).regex(/^[A-Za-z0-9][A-Za-z0-9._:/@[\]=,+-]*$/)).optional(),
|
|
899
|
+
delegation: z18.enum(["pairs", "all"]).optional(),
|
|
900
|
+
save: z18.boolean().optional(),
|
|
901
|
+
plan: z18.boolean().optional(),
|
|
874
902
|
/** The rig's permission policy, in place of the spec's; `policies`: a role's, over the rig's. */
|
|
875
903
|
policy: RigPolicySchema.optional(),
|
|
876
|
-
policies:
|
|
904
|
+
policies: z18.record(RigRoleSchema, RigPolicySchema).optional(),
|
|
877
905
|
/** Accept the harnesses' first-launch warnings (`rig up --non-interruptive`), so a bypassing seat does not stop on Claude's dialog. */
|
|
878
|
-
nonInterruptive:
|
|
879
|
-
});
|
|
880
|
-
var OpenRigLaunchSchema =
|
|
881
|
-
var OpenRigLaunchedSchema =
|
|
882
|
-
type:
|
|
883
|
-
requestId:
|
|
884
|
-
machineId:
|
|
885
|
-
ok:
|
|
886
|
-
plan:
|
|
887
|
-
commands:
|
|
888
|
-
yaml:
|
|
889
|
-
seats:
|
|
890
|
-
output:
|
|
891
|
-
error:
|
|
906
|
+
nonInterruptive: z18.boolean().optional()
|
|
907
|
+
});
|
|
908
|
+
var OpenRigLaunchSchema = z18.object({ type: z18.literal("openrig.launch"), requestId: z18.string().min(1).max(100), launch: RigLaunchSchema, machineId: z18.string().optional() });
|
|
909
|
+
var OpenRigLaunchedSchema = z18.object({
|
|
910
|
+
type: z18.literal("openrig.launched"),
|
|
911
|
+
requestId: z18.string(),
|
|
912
|
+
machineId: z18.string().optional(),
|
|
913
|
+
ok: z18.boolean(),
|
|
914
|
+
plan: z18.boolean(),
|
|
915
|
+
commands: z18.array(z18.string()),
|
|
916
|
+
yaml: z18.string().optional(),
|
|
917
|
+
seats: z18.number().int().optional(),
|
|
918
|
+
output: z18.string().optional(),
|
|
919
|
+
error: z18.string().optional(),
|
|
892
920
|
/** What `rig up --plan` concluded: its status (`planned`…), its errors and its warnings (one per seat without a permission policy…). */
|
|
893
|
-
check:
|
|
921
|
+
check: z18.object({ status: z18.string(), errors: z18.array(z18.string()), warnings: z18.array(z18.string()) }).optional()
|
|
894
922
|
});
|
|
895
|
-
var OpenRigSeatsSchema =
|
|
896
|
-
type:
|
|
897
|
-
requestId:
|
|
898
|
-
machineId:
|
|
923
|
+
var OpenRigSeatsSchema = z18.object({
|
|
924
|
+
type: z18.literal("openrig.seats"),
|
|
925
|
+
requestId: z18.string().min(1).max(100),
|
|
926
|
+
machineId: z18.string().optional(),
|
|
899
927
|
rig: RigNameSchema,
|
|
900
|
-
seats:
|
|
928
|
+
seats: z18.record(RigRoleSchema, z18.number().int().min(0).max(9)),
|
|
901
929
|
/** How the added seats are linked, where OpenRig can add links to a running rig (0.7+): like a launch's. */
|
|
902
|
-
delegation:
|
|
903
|
-
});
|
|
904
|
-
var OpenRigReseatedSchema =
|
|
905
|
-
type:
|
|
906
|
-
requestId:
|
|
907
|
-
machineId:
|
|
908
|
-
ok:
|
|
909
|
-
commands:
|
|
910
|
-
added:
|
|
911
|
-
removed:
|
|
912
|
-
output:
|
|
913
|
-
error:
|
|
930
|
+
delegation: z18.enum(["pairs", "all"]).optional()
|
|
931
|
+
});
|
|
932
|
+
var OpenRigReseatedSchema = z18.object({
|
|
933
|
+
type: z18.literal("openrig.reseated"),
|
|
934
|
+
requestId: z18.string(),
|
|
935
|
+
machineId: z18.string().optional(),
|
|
936
|
+
ok: z18.boolean(),
|
|
937
|
+
commands: z18.array(z18.string()),
|
|
938
|
+
added: z18.array(z18.string()),
|
|
939
|
+
removed: z18.array(z18.string()),
|
|
940
|
+
output: z18.string().optional(),
|
|
941
|
+
error: z18.string().optional(),
|
|
914
942
|
/** The links ensured between the seats; `linksUnsupported`: this OpenRig cannot add links to a running rig (before 0.7). */
|
|
915
|
-
links:
|
|
916
|
-
linksUnsupported:
|
|
943
|
+
links: z18.number().int().optional(),
|
|
944
|
+
linksUnsupported: z18.boolean().optional()
|
|
917
945
|
});
|
|
918
946
|
|
|
919
947
|
// ../protocol/src/openrigRoles.ts
|
|
920
|
-
import { z as
|
|
921
|
-
var RoleUnknownWhySchema =
|
|
922
|
-
var RoleFromSchema =
|
|
923
|
-
var OriginSchema =
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
948
|
+
import { z as z19 } from "zod";
|
|
949
|
+
var RoleUnknownWhySchema = z19.enum(["resolved_at_launch", "not_exposed", "unreadable", "ambiguous", "not_found", "missing_from_guidance"]);
|
|
950
|
+
var RoleFromSchema = z19.enum(["import", "defaults", "profile", "rig", "pod", "member", "launch", "openrig", "plugin", "seat"]);
|
|
951
|
+
var OriginSchema = z19.discriminatedUnion("kind", [
|
|
952
|
+
z19.object({ kind: z19.literal("here"), key: z19.string().optional() }),
|
|
953
|
+
z19.object({ kind: z19.literal("inherited"), from: RoleFromSchema, ref: z19.string().optional(), key: z19.string().optional(), path: z19.string().optional() }),
|
|
954
|
+
z19.object({ kind: z19.literal("absent") }),
|
|
955
|
+
z19.object({ kind: z19.literal("unknown"), why: RoleUnknownWhySchema, detail: z19.string().optional() })
|
|
928
956
|
]);
|
|
929
|
-
var SourcedStringSchema =
|
|
930
|
-
var RoleResourceCategorySchema =
|
|
931
|
-
var RoleResourceSchema =
|
|
957
|
+
var SourcedStringSchema = z19.object({ value: z19.string().nullable(), origin: OriginSchema });
|
|
958
|
+
var RoleResourceCategorySchema = z19.enum(["skill", "guidance", "plugin", "subagent", "runtime_resource"]);
|
|
959
|
+
var RoleResourceSchema = z19.object({
|
|
932
960
|
category: RoleResourceCategorySchema,
|
|
933
|
-
id:
|
|
934
|
-
path:
|
|
935
|
-
absolutePath:
|
|
936
|
-
runtime:
|
|
937
|
-
type:
|
|
938
|
-
target:
|
|
939
|
-
plugin:
|
|
961
|
+
id: z19.string(),
|
|
962
|
+
path: z19.string().optional(),
|
|
963
|
+
absolutePath: z19.string().optional(),
|
|
964
|
+
runtime: z19.string().optional(),
|
|
965
|
+
type: z19.string().optional(),
|
|
966
|
+
target: z19.string().optional(),
|
|
967
|
+
plugin: z19.object({ version: z19.string().optional(), skills: z19.array(z19.string()), hooks: z19.number().int().min(0) }).optional(),
|
|
940
968
|
origin: OriginSchema
|
|
941
969
|
});
|
|
942
|
-
var RoleUsesListSchema =
|
|
943
|
-
var StartupLayerSchema =
|
|
944
|
-
var StartupEntrySchema =
|
|
945
|
-
kind:
|
|
946
|
-
path:
|
|
947
|
-
absolutePath:
|
|
948
|
-
size:
|
|
949
|
-
value:
|
|
950
|
-
builtin:
|
|
970
|
+
var RoleUsesListSchema = z19.object({ declared: z19.boolean(), key: z19.string(), items: z19.array(RoleResourceSchema) });
|
|
971
|
+
var StartupLayerSchema = z19.enum(["agent", "profile", "culture", "rig", "pod", "member", "openrig", "seat", "unknown"]);
|
|
972
|
+
var StartupEntrySchema = z19.object({
|
|
973
|
+
kind: z19.enum(["file", "action"]),
|
|
974
|
+
path: z19.string().optional(),
|
|
975
|
+
absolutePath: z19.string().optional(),
|
|
976
|
+
size: z19.number().int().min(0).optional(),
|
|
977
|
+
value: z19.string().optional(),
|
|
978
|
+
builtin: z19.string().optional(),
|
|
951
979
|
layer: StartupLayerSchema,
|
|
952
|
-
layerInferred:
|
|
953
|
-
delivery:
|
|
954
|
-
into:
|
|
955
|
-
delivered:
|
|
956
|
-
required:
|
|
957
|
-
orientation:
|
|
958
|
-
appliesOn:
|
|
980
|
+
layerInferred: z19.boolean(),
|
|
981
|
+
delivery: z19.string(),
|
|
982
|
+
into: z19.string().optional(),
|
|
983
|
+
delivered: z19.boolean().optional(),
|
|
984
|
+
required: z19.boolean().optional(),
|
|
985
|
+
orientation: z19.string().optional(),
|
|
986
|
+
appliesOn: z19.array(z19.string()),
|
|
959
987
|
origin: OriginSchema
|
|
960
988
|
});
|
|
961
|
-
var RoleFileErrorSchema =
|
|
962
|
-
var RoleSummarySchema =
|
|
963
|
-
id:
|
|
964
|
-
name:
|
|
965
|
-
version:
|
|
966
|
-
description:
|
|
967
|
-
source:
|
|
968
|
-
path:
|
|
969
|
-
runtime:
|
|
970
|
-
importOnly:
|
|
971
|
-
seats:
|
|
972
|
-
running:
|
|
973
|
-
skills:
|
|
974
|
-
startupFiles:
|
|
989
|
+
var RoleFileErrorSchema = z19.object({ kind: z19.enum(["missing", "invalid"]), message: z19.string(), line: z19.number().int().optional(), col: z19.number().int().optional() });
|
|
990
|
+
var RoleSummarySchema = z19.object({
|
|
991
|
+
id: z19.string(),
|
|
992
|
+
name: z19.string(),
|
|
993
|
+
version: z19.string().optional(),
|
|
994
|
+
description: z19.string().optional(),
|
|
995
|
+
source: z19.enum(["builtin", "user"]),
|
|
996
|
+
path: z19.string(),
|
|
997
|
+
runtime: z19.string().optional(),
|
|
998
|
+
importOnly: z19.boolean(),
|
|
999
|
+
seats: z19.number().int().min(0),
|
|
1000
|
+
running: z19.number().int().min(0),
|
|
1001
|
+
skills: z19.array(z19.string()),
|
|
1002
|
+
startupFiles: z19.array(z19.string()),
|
|
975
1003
|
/** The seats that run it, so a seat of the Rigs page opens its role « seen from » it (`openrig.role` with `id`, then the seat by `rig` + `logicalId`). */
|
|
976
|
-
seatRefs:
|
|
977
|
-
error:
|
|
978
|
-
});
|
|
979
|
-
var RoleImportSchema =
|
|
980
|
-
ref:
|
|
981
|
-
key:
|
|
982
|
-
name:
|
|
983
|
-
path:
|
|
984
|
-
version:
|
|
985
|
-
resolved:
|
|
986
|
-
error:
|
|
987
|
-
});
|
|
988
|
-
var RoleProfileSchema =
|
|
989
|
-
name:
|
|
990
|
-
description:
|
|
1004
|
+
seatRefs: z19.array(z19.object({ rig: z19.string(), logicalId: z19.string(), session: z19.string().optional() })),
|
|
1005
|
+
error: z19.enum(["missing", "invalid"]).optional()
|
|
1006
|
+
});
|
|
1007
|
+
var RoleImportSchema = z19.object({
|
|
1008
|
+
ref: z19.string(),
|
|
1009
|
+
key: z19.string(),
|
|
1010
|
+
name: z19.string().optional(),
|
|
1011
|
+
path: z19.string().optional(),
|
|
1012
|
+
version: z19.string().optional(),
|
|
1013
|
+
resolved: z19.boolean(),
|
|
1014
|
+
error: z19.string().optional()
|
|
1015
|
+
});
|
|
1016
|
+
var RoleProfileSchema = z19.object({
|
|
1017
|
+
name: z19.string(),
|
|
1018
|
+
description: z19.string().optional(),
|
|
991
1019
|
runtime: SourcedStringSchema,
|
|
992
1020
|
model: SourcedStringSchema,
|
|
993
1021
|
effort: SourcedStringSchema,
|
|
994
|
-
uses:
|
|
1022
|
+
uses: z19.object({ skills: RoleUsesListSchema, guidance: RoleUsesListSchema, subagents: RoleUsesListSchema, plugins: RoleUsesListSchema, runtimeResources: RoleUsesListSchema }),
|
|
995
1023
|
/** The role's share of the startup: agent then profile files and actions, in that order. */
|
|
996
|
-
startup:
|
|
997
|
-
});
|
|
998
|
-
var RoleSeatSchema =
|
|
999
|
-
rig:
|
|
1000
|
-
rigId:
|
|
1001
|
-
rigSpecPath:
|
|
1002
|
-
composed:
|
|
1003
|
-
logicalId:
|
|
1004
|
-
session:
|
|
1005
|
-
label:
|
|
1006
|
-
profile:
|
|
1007
|
-
running:
|
|
1008
|
-
activity:
|
|
1024
|
+
startup: z19.array(StartupEntrySchema)
|
|
1025
|
+
});
|
|
1026
|
+
var RoleSeatSchema = z19.object({
|
|
1027
|
+
rig: z19.string(),
|
|
1028
|
+
rigId: z19.string(),
|
|
1029
|
+
rigSpecPath: z19.string().optional(),
|
|
1030
|
+
composed: z19.boolean(),
|
|
1031
|
+
logicalId: z19.string(),
|
|
1032
|
+
session: z19.string().optional(),
|
|
1033
|
+
label: z19.string().optional(),
|
|
1034
|
+
profile: z19.string(),
|
|
1035
|
+
running: z19.boolean(),
|
|
1036
|
+
activity: z19.string(),
|
|
1009
1037
|
runtime: SourcedStringSchema,
|
|
1010
1038
|
model: SourcedStringSchema,
|
|
1011
1039
|
effort: SourcedStringSchema,
|
|
1012
1040
|
cwd: SourcedStringSchema,
|
|
1013
1041
|
cultureFile: SourcedStringSchema,
|
|
1014
|
-
member:
|
|
1015
|
-
memberStartup:
|
|
1042
|
+
member: z19.string().optional(),
|
|
1043
|
+
memberStartup: z19.array(StartupEntrySchema),
|
|
1016
1044
|
/** The Role tab of this seat: its role guidance (`role.md`), then the startup files of its own (member layer), in delivery
|
|
1017
1045
|
* order — OpenRig's when the seat was launched, else the spec's. */
|
|
1018
|
-
roleDocs:
|
|
1019
|
-
live:
|
|
1020
|
-
resolvedSpec:
|
|
1021
|
-
resources:
|
|
1046
|
+
roleDocs: z19.array(StartupEntrySchema),
|
|
1047
|
+
live: z19.object({
|
|
1048
|
+
resolvedSpec: z19.object({ name: z19.string().optional(), version: z19.string().optional(), hash: z19.string().optional() }),
|
|
1049
|
+
resources: z19.array(RoleResourceSchema),
|
|
1022
1050
|
/** In the order OpenRig returns them. */
|
|
1023
|
-
startup:
|
|
1051
|
+
startup: z19.array(StartupEntrySchema),
|
|
1024
1052
|
/** `rig skill loadout --seat`: the skills projected for this seat; absent when it could not be read. */
|
|
1025
|
-
skills:
|
|
1053
|
+
skills: z19.array(z19.object({ id: z19.string(), trigger: z19.string().optional() })).optional()
|
|
1026
1054
|
}).optional()
|
|
1027
1055
|
});
|
|
1028
|
-
var RoleUnavailableSchema =
|
|
1029
|
-
var RoleDetailSchema =
|
|
1056
|
+
var RoleUnavailableSchema = z19.enum(["harness_prompt", "effective_settings", "delivered_content", "harness_own_files"]);
|
|
1057
|
+
var RoleDetailSchema = z19.object({
|
|
1030
1058
|
summary: RoleSummarySchema,
|
|
1031
|
-
file:
|
|
1032
|
-
path:
|
|
1033
|
-
relativePath:
|
|
1034
|
-
modifiedAt:
|
|
1035
|
-
copies:
|
|
1059
|
+
file: z19.object({
|
|
1060
|
+
path: z19.string(),
|
|
1061
|
+
relativePath: z19.string().optional(),
|
|
1062
|
+
modifiedAt: z19.string().optional(),
|
|
1063
|
+
copies: z19.array(z19.object({ kind: z19.literal("repo"), path: z19.string(), identical: z19.boolean(), modifiedAt: z19.string().optional() }))
|
|
1036
1064
|
}),
|
|
1037
1065
|
error: RoleFileErrorSchema.optional(),
|
|
1038
|
-
role:
|
|
1039
|
-
defaults:
|
|
1040
|
-
imports:
|
|
1041
|
-
importedBy:
|
|
1042
|
-
profiles:
|
|
1066
|
+
role: z19.object({ path: z19.string(), absolutePath: z19.string(), origin: OriginSchema }).nullable(),
|
|
1067
|
+
defaults: z19.object({ runtime: SourcedStringSchema, model: SourcedStringSchema, effort: SourcedStringSchema }),
|
|
1068
|
+
imports: z19.array(RoleImportSchema),
|
|
1069
|
+
importedBy: z19.array(z19.string()),
|
|
1070
|
+
profiles: z19.array(RoleProfileSchema),
|
|
1043
1071
|
/** What the file declares in `resources`. */
|
|
1044
|
-
resources:
|
|
1045
|
-
seats:
|
|
1046
|
-
unavailable:
|
|
1047
|
-
warnings:
|
|
1048
|
-
openrigVersion:
|
|
1049
|
-
});
|
|
1050
|
-
var RoleErrorSchema =
|
|
1051
|
-
var LibraryIdSchema =
|
|
1052
|
-
var OpenRigRolesSchema =
|
|
1053
|
-
var OpenRigRoleListSchema =
|
|
1054
|
-
type:
|
|
1055
|
-
requestId:
|
|
1056
|
-
machineId:
|
|
1057
|
-
roles:
|
|
1058
|
-
openrigVersion:
|
|
1072
|
+
resources: z19.array(RoleResourceSchema),
|
|
1073
|
+
seats: z19.array(RoleSeatSchema),
|
|
1074
|
+
unavailable: z19.array(RoleUnavailableSchema),
|
|
1075
|
+
warnings: z19.array(z19.string()),
|
|
1076
|
+
openrigVersion: z19.string().optional()
|
|
1077
|
+
});
|
|
1078
|
+
var RoleErrorSchema = z19.string();
|
|
1079
|
+
var LibraryIdSchema = z19.string().min(1).max(200).regex(/^[A-Za-z0-9][A-Za-z0-9._:-]*$/, "not a library id");
|
|
1080
|
+
var OpenRigRolesSchema = z19.object({ type: z19.literal("openrig.roles"), requestId: z19.string().min(1).max(100), machineId: z19.string().optional() });
|
|
1081
|
+
var OpenRigRoleListSchema = z19.object({
|
|
1082
|
+
type: z19.literal("openrig.roleList"),
|
|
1083
|
+
requestId: z19.string(),
|
|
1084
|
+
machineId: z19.string().optional(),
|
|
1085
|
+
roles: z19.array(RoleSummarySchema),
|
|
1086
|
+
openrigVersion: z19.string().optional(),
|
|
1059
1087
|
error: RoleErrorSchema.optional()
|
|
1060
1088
|
});
|
|
1061
|
-
var OpenRigRoleSchema =
|
|
1062
|
-
var OpenRigRoleDetailSchema =
|
|
1063
|
-
type:
|
|
1064
|
-
requestId:
|
|
1065
|
-
machineId:
|
|
1066
|
-
roleId:
|
|
1089
|
+
var OpenRigRoleSchema = z19.object({ type: z19.literal("openrig.role"), requestId: z19.string().min(1).max(100), machineId: z19.string().optional(), roleId: LibraryIdSchema });
|
|
1090
|
+
var OpenRigRoleDetailSchema = z19.object({
|
|
1091
|
+
type: z19.literal("openrig.roleDetail"),
|
|
1092
|
+
requestId: z19.string(),
|
|
1093
|
+
machineId: z19.string().optional(),
|
|
1094
|
+
roleId: z19.string(),
|
|
1067
1095
|
role: RoleDetailSchema.optional(),
|
|
1068
1096
|
error: RoleErrorSchema.optional()
|
|
1069
1097
|
});
|
|
1070
|
-
var OpenRigRoleFileSchema =
|
|
1071
|
-
type:
|
|
1072
|
-
requestId:
|
|
1073
|
-
machineId:
|
|
1098
|
+
var OpenRigRoleFileSchema = z19.object({
|
|
1099
|
+
type: z19.literal("openrig.roleFile"),
|
|
1100
|
+
requestId: z19.string().min(1).max(100),
|
|
1101
|
+
machineId: z19.string().optional(),
|
|
1074
1102
|
roleId: LibraryIdSchema,
|
|
1075
|
-
path:
|
|
1076
|
-
});
|
|
1077
|
-
var OpenRigRoleFileContentSchema =
|
|
1078
|
-
type:
|
|
1079
|
-
requestId:
|
|
1080
|
-
machineId:
|
|
1081
|
-
roleId:
|
|
1082
|
-
path:
|
|
1083
|
-
content:
|
|
1084
|
-
size:
|
|
1085
|
-
truncated:
|
|
1103
|
+
path: z19.string().min(1).max(4096)
|
|
1104
|
+
});
|
|
1105
|
+
var OpenRigRoleFileContentSchema = z19.object({
|
|
1106
|
+
type: z19.literal("openrig.roleFileContent"),
|
|
1107
|
+
requestId: z19.string(),
|
|
1108
|
+
machineId: z19.string().optional(),
|
|
1109
|
+
roleId: z19.string(),
|
|
1110
|
+
path: z19.string(),
|
|
1111
|
+
content: z19.string().optional(),
|
|
1112
|
+
size: z19.number().int().min(0).optional(),
|
|
1113
|
+
truncated: z19.boolean().optional(),
|
|
1086
1114
|
error: RoleErrorSchema.optional()
|
|
1087
1115
|
});
|
|
1088
1116
|
var ROLE_FILE_MAX = 512 * 1024;
|
|
1089
1117
|
|
|
1090
1118
|
// ../protocol/src/routing.ts
|
|
1091
|
-
import { z as
|
|
1092
|
-
var MachineInventorySchema =
|
|
1093
|
-
id:
|
|
1094
|
-
label:
|
|
1095
|
-
online:
|
|
1096
|
-
local:
|
|
1097
|
-
sessions:
|
|
1098
|
-
folders:
|
|
1099
|
-
});
|
|
1100
|
-
var RoutingContextSchema =
|
|
1101
|
-
machines:
|
|
1102
|
-
history:
|
|
1103
|
-
});
|
|
1104
|
-
var RouteResultSchema =
|
|
1119
|
+
import { z as z20 } from "zod";
|
|
1120
|
+
var MachineInventorySchema = z20.object({
|
|
1121
|
+
id: z20.string().min(1).max(80),
|
|
1122
|
+
label: z20.string().min(1).max(120),
|
|
1123
|
+
online: z20.boolean(),
|
|
1124
|
+
local: z20.boolean(),
|
|
1125
|
+
sessions: z20.array(z20.object({ id: z20.string(), name: z20.string(), project: z20.string(), cwd: z20.string(), topic: z20.string().optional(), state: z20.string(), readOnly: z20.boolean() })).max(500),
|
|
1126
|
+
folders: z20.array(z20.object({ project: z20.string(), cwd: z20.string() })).max(100)
|
|
1127
|
+
});
|
|
1128
|
+
var RoutingContextSchema = z20.object({
|
|
1129
|
+
machines: z20.array(MachineInventorySchema).min(1).max(20),
|
|
1130
|
+
history: z20.array(z20.object({ question: z20.string().max(2e4), answer: z20.string().max(2e4).optional(), machineId: z20.string().optional() })).max(50)
|
|
1131
|
+
});
|
|
1132
|
+
var RouteResultSchema = z20.object({
|
|
1105
1133
|
/** Null means an answer or a clarification, never an implicit local destination. */
|
|
1106
|
-
machineId:
|
|
1107
|
-
text:
|
|
1108
|
-
choices:
|
|
1134
|
+
machineId: z20.string().nullable(),
|
|
1135
|
+
text: z20.string().min(1).max(2e4),
|
|
1136
|
+
choices: z20.array(z20.string()).max(20).optional()
|
|
1109
1137
|
});
|
|
1110
1138
|
|
|
1111
1139
|
// ../protocol/src/thread.ts
|
|
1112
|
-
import { z as
|
|
1113
|
-
var ToolStatusSchema =
|
|
1114
|
-
var FileChangeSchema =
|
|
1115
|
-
var base = { id:
|
|
1116
|
-
var ThreadItemSchema =
|
|
1117
|
-
|
|
1118
|
-
|
|
1140
|
+
import { z as z21 } from "zod";
|
|
1141
|
+
var ToolStatusSchema = z21.enum(["running", "success", "failed", "unknown"]);
|
|
1142
|
+
var FileChangeSchema = z21.object({ path: z21.string().min(1), from: z21.string().min(1).optional(), change: z21.enum(["add", "edit", "delete", "write"]), diff: z21.string().optional() });
|
|
1143
|
+
var base = { id: z21.string().min(1), at: z21.string().datetime(), turn: z21.number().int().nonnegative(), helperId: z21.string().optional() };
|
|
1144
|
+
var ThreadItemSchema = z21.discriminatedUnion("kind", [
|
|
1145
|
+
z21.object({ kind: z21.literal("prompt"), ...base, text: z21.string(), images: z21.array(AttachmentRefSchema).optional() }),
|
|
1146
|
+
z21.object({ kind: z21.literal("message"), ...base, text: z21.string() }),
|
|
1119
1147
|
/** `id` is the harness's tool_use_id when it gives one, so the result updates the same row; `byClose`: a question
|
|
1120
1148
|
* dismissed by Ledge closing the session. */
|
|
1121
|
-
|
|
1122
|
-
kind:
|
|
1149
|
+
z21.object({
|
|
1150
|
+
kind: z21.literal("tool"),
|
|
1123
1151
|
...base,
|
|
1124
|
-
tool:
|
|
1125
|
-
label:
|
|
1126
|
-
input:
|
|
1127
|
-
output:
|
|
1128
|
-
error:
|
|
1152
|
+
tool: z21.string(),
|
|
1153
|
+
label: z21.string(),
|
|
1154
|
+
input: z21.string().optional(),
|
|
1155
|
+
output: z21.string().optional(),
|
|
1156
|
+
error: z21.string().optional(),
|
|
1129
1157
|
status: ToolStatusSchema,
|
|
1130
|
-
durationMs:
|
|
1131
|
-
files:
|
|
1132
|
-
byClose:
|
|
1158
|
+
durationMs: z21.number().nonnegative().optional(),
|
|
1159
|
+
files: z21.array(FileChangeSchema).default([]),
|
|
1160
|
+
byClose: z21.literal(true).optional(),
|
|
1133
1161
|
/** Images the tool returned (a browser screenshot), in order; `imagesDropped`: some were not kept. */
|
|
1134
|
-
images:
|
|
1135
|
-
imagesDropped:
|
|
1162
|
+
images: z21.array(AttachmentRefSchema).max(ATTACHMENTS_MAX).optional(),
|
|
1163
|
+
imagesDropped: z21.literal(true).optional()
|
|
1136
1164
|
}),
|
|
1137
1165
|
/** `unknown`: answered in the terminal, the daemon only saw the prompt go away; `always`: allowed and not asked again;
|
|
1138
1166
|
* `byClose`: denied by Ledge closing the session. */
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1167
|
+
z21.object({ kind: z21.literal("permission"), ...base, tool: z21.string(), text: z21.string(), decision: z21.enum(["accept", "deny", "always", "unknown"]).optional(), byClose: z21.literal(true).optional() }),
|
|
1168
|
+
z21.object({ kind: z21.literal("reply"), ...base, text: z21.string() }),
|
|
1169
|
+
z21.object({ kind: z21.literal("helper"), ...base, task: z21.string(), agentType: z21.string().optional(), state: z21.enum(["working", "exited"]) }),
|
|
1142
1170
|
/** A message this session sent to another agent; `id` is the tool_use_id, `to` the address it used, `peer` the Ledge session id, `received` the paired item's id in the peer's thread, `via` set when Ledge's mailbox carries it. */
|
|
1143
|
-
|
|
1171
|
+
z21.object({ kind: z21.literal("sent"), ...base, to: z21.string(), peer: z21.string().optional(), summary: z21.string().optional(), text: z21.string(), status: z21.enum(["sending", "delivered", "read", "failed"]), received: z21.string().optional(), via: z21.literal("ledge").optional() }),
|
|
1144
1172
|
/** A message another agent sent to this session; `from` is its from-name (else its address), `sent` the paired item's id in the peer's thread. */
|
|
1145
|
-
|
|
1173
|
+
z21.object({ kind: z21.literal("received"), ...base, from: z21.string(), peer: z21.string().optional(), text: z21.string(), sent: z21.string().optional() }),
|
|
1146
1174
|
/** An automated notice of the agent's harness about messages between sessions (Claude Code's `[Cross-session idle
|
|
1147
1175
|
* notice]` / `[Cross-session delivery notice]`): a system event, never the user's words. `name` is the session it is
|
|
1148
1176
|
* about as quoted, `peer` its Ledge session id; a delivery notice says the outcome of `count` messages to `recipients`. */
|
|
1149
|
-
|
|
1150
|
-
kind:
|
|
1177
|
+
z21.object({
|
|
1178
|
+
kind: z21.literal("notice"),
|
|
1151
1179
|
...base,
|
|
1152
|
-
notice:
|
|
1180
|
+
notice: z21.enum(["idle", "exited", "unavailable", "expired", "delivery", "other"]),
|
|
1153
1181
|
/** 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. */
|
|
1154
|
-
task:
|
|
1182
|
+
task: z21.string().optional(),
|
|
1155
1183
|
/** A task this session handed over (`outgoing`), and how (issue #92). */
|
|
1156
|
-
taskOp:
|
|
1157
|
-
outgoing:
|
|
1158
|
-
name:
|
|
1159
|
-
peer:
|
|
1160
|
-
time:
|
|
1161
|
-
summary:
|
|
1162
|
-
status:
|
|
1163
|
-
count:
|
|
1164
|
-
recipients:
|
|
1165
|
-
reason:
|
|
1166
|
-
text:
|
|
1184
|
+
taskOp: z21.enum(TRANSMISSION_OPS).optional(),
|
|
1185
|
+
outgoing: z21.literal(true).optional(),
|
|
1186
|
+
name: z21.string().optional(),
|
|
1187
|
+
peer: z21.string().optional(),
|
|
1188
|
+
time: z21.string().optional(),
|
|
1189
|
+
summary: z21.string().optional(),
|
|
1190
|
+
status: z21.enum(["held", "denied", "expired", "delivered", "refused", "dropped", "unknown"]).optional(),
|
|
1191
|
+
count: z21.number().int().positive().optional(),
|
|
1192
|
+
recipients: z21.array(z21.string()).optional(),
|
|
1193
|
+
reason: z21.string().optional(),
|
|
1194
|
+
text: z21.string()
|
|
1167
1195
|
})
|
|
1168
1196
|
]);
|
|
1169
1197
|
|
|
1170
1198
|
// ../protocol/src/mobile.ts
|
|
1171
|
-
import { z as
|
|
1172
|
-
var RelayUrlSchema =
|
|
1199
|
+
import { z as z22 } from "zod";
|
|
1200
|
+
var RelayUrlSchema = z22.string().transform((v, ctx) => {
|
|
1173
1201
|
const bad = () => {
|
|
1174
|
-
ctx.addIssue({ code:
|
|
1175
|
-
return
|
|
1202
|
+
ctx.addIssue({ code: z22.ZodIssueCode.custom, message: "invalid relay URL" });
|
|
1203
|
+
return z22.NEVER;
|
|
1176
1204
|
};
|
|
1177
1205
|
let u;
|
|
1178
1206
|
try {
|
|
@@ -1185,116 +1213,122 @@ var RelayUrlSchema = z21.string().transform((v, ctx) => {
|
|
|
1185
1213
|
if (u.username || u.password || u.pathname !== "/" || u.search || u.hash) return bad();
|
|
1186
1214
|
return u.origin;
|
|
1187
1215
|
});
|
|
1188
|
-
var MobileConfigSchema =
|
|
1189
|
-
var MobileLinkStateSchema =
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1216
|
+
var MobileConfigSchema = z22.object({ enabled: z22.boolean(), relayUrl: RelayUrlSchema, terminalInput: z22.boolean().optional() });
|
|
1217
|
+
var MobileLinkStateSchema = z22.discriminatedUnion("state", [
|
|
1218
|
+
z22.object({ state: z22.literal("off") }),
|
|
1219
|
+
z22.object({ state: z22.literal("connecting") }),
|
|
1220
|
+
z22.object({ state: z22.literal("online") }),
|
|
1221
|
+
z22.object({ state: z22.literal("offline"), retryAt: z22.string().datetime(), error: z22.string() }),
|
|
1222
|
+
z22.object({ state: z22.literal("signed_out"), reason: z22.enum(["other_pc", "session_invalid"]) }),
|
|
1195
1223
|
/** The mobile service did not start (a broken mobile.json, a missing key store): nothing is linked until the daemon restarts. */
|
|
1196
|
-
|
|
1224
|
+
z22.object({ state: z22.literal("unavailable"), error: z22.string().max(200) })
|
|
1197
1225
|
]);
|
|
1198
|
-
var MobilePairingSchema =
|
|
1199
|
-
id:
|
|
1200
|
-
label:
|
|
1201
|
-
code:
|
|
1202
|
-
expiresAt:
|
|
1203
|
-
state:
|
|
1204
|
-
});
|
|
1205
|
-
var MobileStateSchema =
|
|
1206
|
-
enabled:
|
|
1207
|
-
relayUrl:
|
|
1208
|
-
account:
|
|
1209
|
-
signin:
|
|
1226
|
+
var MobilePairingSchema = z22.object({
|
|
1227
|
+
id: z22.string(),
|
|
1228
|
+
label: z22.string(),
|
|
1229
|
+
code: z22.string().nullable(),
|
|
1230
|
+
expiresAt: z22.string().datetime(),
|
|
1231
|
+
state: z22.enum(["waiting", "confirm", "approved", "linked", "expired", "refused"])
|
|
1232
|
+
});
|
|
1233
|
+
var MobileStateSchema = z22.object({
|
|
1234
|
+
enabled: z22.boolean(),
|
|
1235
|
+
relayUrl: z22.string(),
|
|
1236
|
+
account: z22.object({ login: z22.string(), accountId: z22.string() }).nullable(),
|
|
1237
|
+
signin: z22.object({ userCode: z22.string(), verificationUri: z22.string(), expiresAt: z22.string().datetime() }).nullable(),
|
|
1210
1238
|
/** The last sign-in that did not end with a session; cleared by the next one. */
|
|
1211
|
-
signinError:
|
|
1239
|
+
signinError: z22.enum(["expired", "denied", "not_allowed", "failed"]).nullable(),
|
|
1212
1240
|
link: MobileLinkStateSchema,
|
|
1213
|
-
devices:
|
|
1214
|
-
pairings:
|
|
1241
|
+
devices: z22.array(z22.object({ id: z22.string(), label: z22.string(), approvedAt: z22.string(), online: z22.boolean(), lastSeenAt: z22.string().optional() })),
|
|
1242
|
+
pairings: z22.array(MobilePairingSchema),
|
|
1243
|
+
/** « Taper dans les terminaux depuis le téléphone »: absent from an older daemon, which has no phone terminal. */
|
|
1244
|
+
terminalInput: z22.boolean().optional()
|
|
1215
1245
|
});
|
|
1216
1246
|
|
|
1217
1247
|
// ../protocol/src/messages.ts
|
|
1218
|
-
var RefusalCodeSchema =
|
|
1219
|
-
var SessionEventSchema =
|
|
1220
|
-
name:
|
|
1221
|
-
at:
|
|
1222
|
-
source:
|
|
1223
|
-
tool:
|
|
1224
|
-
text:
|
|
1225
|
-
options:
|
|
1248
|
+
var RefusalCodeSchema = z23.enum(["stale", "read_only", "no_prompt", "not_taken", "busy", "unknown_session", "nothing_to_decide", "not_offered", "free_text", "note_not_typed", "unavailable", "invalid", "attachment_missing", "attachments_not_accepted"]);
|
|
1249
|
+
var SessionEventSchema = z23.object({
|
|
1250
|
+
name: z23.enum(["SessionStart", "UserPromptSubmit", "PreToolUse", "PermissionRequest", "Notification", "Stop", "SessionEnd", "PaneChanged", "PaneGone", "PanePrompt", "PaneIdle", "InjectFailed", "Decided", "PostToolUse", "PostToolUseFailure", "StopFailure", "SubagentStart", "SubagentStop", "PaneTitle", "Renamed", "NativeRequest", "AgentMessage", "QueueUpdate"]),
|
|
1251
|
+
at: z23.string().datetime(),
|
|
1252
|
+
source: z23.enum(["hook", "pane", "daemon"]),
|
|
1253
|
+
tool: z23.string().optional(),
|
|
1254
|
+
text: z23.string().optional(),
|
|
1255
|
+
options: z23.array(z23.string()).optional(),
|
|
1226
1256
|
/** Each option's description, by index ('' when it has none); left out when no option has one. */
|
|
1227
|
-
optionDetails:
|
|
1228
|
-
kind:
|
|
1257
|
+
optionDetails: z23.array(z23.string()).optional(),
|
|
1258
|
+
kind: z23.enum(["question", "permission", "plan", "diff"]).optional(),
|
|
1229
1259
|
/** PanePrompt: what to review in full before deciding (a plan read in the terminal), when `text` is its summary. */
|
|
1230
|
-
body:
|
|
1231
|
-
exitCode:
|
|
1232
|
-
helperId:
|
|
1260
|
+
body: z23.string().optional(),
|
|
1261
|
+
exitCode: z23.number().int().nullable().optional(),
|
|
1262
|
+
helperId: z23.string().optional(),
|
|
1233
1263
|
/** The helper's description, once known (Claude Code: its `.meta.json`, written after SubagentStart). */
|
|
1234
|
-
task:
|
|
1264
|
+
task: z23.string().optional(),
|
|
1235
1265
|
/** PostToolUseFailure: the user interrupted the turn (Esc); Claude then waits for input with no Stop. */
|
|
1236
|
-
interrupt:
|
|
1266
|
+
interrupt: z23.boolean().optional(),
|
|
1237
1267
|
/** UserPromptSubmit, PostToolUse: the images the prompt or the tool result carried, by attachment id. */
|
|
1238
|
-
attachments:
|
|
1268
|
+
attachments: z23.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional(),
|
|
1239
1269
|
/** PostToolUse: some of the result's images were not kept. */
|
|
1240
|
-
imagesDropped:
|
|
1270
|
+
imagesDropped: z23.boolean().optional(),
|
|
1241
1271
|
/** QueueUpdate: OMP's queue as it stands. */
|
|
1242
|
-
queue:
|
|
1272
|
+
queue: z23.array(z23.object({ text: z23.string(), mode: z23.enum(["steer", "follow_up"]) })).optional(),
|
|
1243
1273
|
/** AgentMessage: the harness's own message, its text so far (`streaming`) or whole. `messageId` is unique for the session's life. */
|
|
1244
|
-
messageId:
|
|
1245
|
-
streaming:
|
|
1274
|
+
messageId: z23.string().optional(),
|
|
1275
|
+
streaming: z23.boolean().optional(),
|
|
1246
1276
|
/** NativeRequest: the dialog's id, and OMP's `ask` questions when it is one. */
|
|
1247
|
-
requestId:
|
|
1248
|
-
questions:
|
|
1277
|
+
requestId: z23.string().optional(),
|
|
1278
|
+
questions: z23.array(AskQuestionSchema).optional(),
|
|
1249
1279
|
/** Stop: its text is already in the thread as AgentMessage cards, which the reply card must not repeat. */
|
|
1250
|
-
streamed:
|
|
1280
|
+
streamed: z23.boolean().optional(),
|
|
1251
1281
|
/** Native tracking (spec 2026-10-13 §2): the harness's id of the tool call, so its result lands on the same row. */
|
|
1252
|
-
toolUseId:
|
|
1282
|
+
toolUseId: z23.string().optional(),
|
|
1253
1283
|
/** The tool's input as the harness gave it, every string capped by the hook. */
|
|
1254
|
-
toolInput:
|
|
1284
|
+
toolInput: z23.record(z23.string(), z23.unknown()).optional(),
|
|
1255
1285
|
/** PostToolUse: the result as text; SubagentStop: nothing (the report travels in `text`). */
|
|
1256
|
-
output:
|
|
1257
|
-
durationMs:
|
|
1286
|
+
output: z23.string().optional(),
|
|
1287
|
+
durationMs: z23.number().nonnegative().optional(),
|
|
1258
1288
|
/** PostToolUseFailure: the harness's error message. */
|
|
1259
|
-
error:
|
|
1289
|
+
error: z23.string().optional(),
|
|
1260
1290
|
/** The session's transcript, or the helper's on SubagentStop; the daemon reads its tail for the agent's messages. */
|
|
1261
|
-
transcriptPath:
|
|
1291
|
+
transcriptPath: z23.string().optional(),
|
|
1262
1292
|
/** Decided: what was chosen when the daemon knows it. */
|
|
1263
1293
|
decision: DecisionSchema.optional(),
|
|
1264
1294
|
/** Decided: the request was refused by Ledge closing the session (its interrupt keys), not by the user's answer. */
|
|
1265
|
-
byClose:
|
|
1295
|
+
byClose: z23.literal(true).optional(),
|
|
1266
1296
|
/** The agent's own session id when the hook names it, so the daemon can resume that conversation. */
|
|
1267
|
-
agentSessionId:
|
|
1297
|
+
agentSessionId: z23.string().optional()
|
|
1268
1298
|
});
|
|
1269
|
-
var RecentSchema =
|
|
1299
|
+
var RecentSchema = z23.object({ cwd: z23.string().min(1), project: z23.string().min(1), lastAt: z23.string().datetime() });
|
|
1270
1300
|
var SEMVER = /^\d+\.\d+\.\d+$/;
|
|
1271
|
-
var DaemonInfoSchema =
|
|
1272
|
-
version:
|
|
1273
|
-
install:
|
|
1274
|
-
systemd:
|
|
1275
|
-
manual:
|
|
1276
|
-
routing:
|
|
1277
|
-
archive:
|
|
1301
|
+
var DaemonInfoSchema = z23.object({
|
|
1302
|
+
version: z23.string(),
|
|
1303
|
+
install: z23.enum(["npm", "git", "unknown"]),
|
|
1304
|
+
systemd: z23.boolean(),
|
|
1305
|
+
manual: z23.string().optional(),
|
|
1306
|
+
routing: z23.boolean().optional(),
|
|
1307
|
+
archive: z23.boolean().optional(),
|
|
1278
1308
|
/** Takes `model` and `effort` on `session.launch` and answers `models.list` (#58). */
|
|
1279
|
-
models:
|
|
1309
|
+
models: z23.boolean().optional(),
|
|
1280
1310
|
/** Drives OMP over its RPC: launching `omp` sessions is possible when the binary is there (`models.list` says so). */
|
|
1281
|
-
omp:
|
|
1311
|
+
omp: z23.boolean().optional(),
|
|
1282
1312
|
/** Takes `session.model`: a live session's model and effort changed (#58, lot 2). */
|
|
1283
|
-
modelSwitch:
|
|
1313
|
+
modelSwitch: z23.boolean().optional(),
|
|
1314
|
+
/** Answers `session.commands`: the slash commands a session's agent offers. */
|
|
1315
|
+
commands: z23.boolean().optional(),
|
|
1284
1316
|
/** Takes `approval` on an OMP `session.launch` (auto mode). */
|
|
1285
|
-
ompApproval:
|
|
1317
|
+
ompApproval: z23.boolean().optional(),
|
|
1286
1318
|
/** Its home folder, so a client shows the folders under it as `~` (absent from older daemons). */
|
|
1287
|
-
home:
|
|
1288
|
-
mobile:
|
|
1319
|
+
home: z23.string().optional(),
|
|
1320
|
+
mobile: z23.boolean().optional(),
|
|
1289
1321
|
/** Answers `openrig.status` and `openrig.act`: drives OpenRig on its machine. */
|
|
1290
|
-
openrig:
|
|
1322
|
+
openrig: z23.boolean().optional(),
|
|
1291
1323
|
/** Answers `openrig.roles`, `openrig.role` and `openrig.roleFile`: reads OpenRig's roles (agent specs). */
|
|
1292
|
-
openrigRoles:
|
|
1324
|
+
openrigRoles: z23.boolean().optional(),
|
|
1325
|
+
/** Takes `session.broadcast` (its `ledge bridge` too, on this machine): a client sends it only when this is set. */
|
|
1326
|
+
broadcast: z23.boolean().optional()
|
|
1293
1327
|
});
|
|
1294
|
-
var UpdateFailureSchema =
|
|
1295
|
-
var ServerMessageSchema =
|
|
1328
|
+
var UpdateFailureSchema = z23.enum(["git-install", "no-systemd", "sessions-at-risk", "npm-failed", "busy"]);
|
|
1329
|
+
var ServerMessageSchema = z23.discriminatedUnion("type", [
|
|
1296
1330
|
SessionModelAcceptedSchema,
|
|
1297
|
-
|
|
1331
|
+
z23.object({ type: z23.literal("chat.routed"), qid: z23.string(), result: RouteResultSchema }),
|
|
1298
1332
|
DocumentContentSchema,
|
|
1299
1333
|
DocumentErrorSchema,
|
|
1300
1334
|
AttachmentStoredSchema,
|
|
@@ -1303,6 +1337,7 @@ var ServerMessageSchema = z22.discriminatedUnion("type", [
|
|
|
1303
1337
|
ReposInfoSchema,
|
|
1304
1338
|
ReposFoundSchema,
|
|
1305
1339
|
ModelsListingSchema,
|
|
1340
|
+
SessionCommandsListingSchema,
|
|
1306
1341
|
OpenRigStateMessageSchema,
|
|
1307
1342
|
OpenRigDoneSchema,
|
|
1308
1343
|
OpenRigSpecListSchema,
|
|
@@ -1314,94 +1349,105 @@ var ServerMessageSchema = z22.discriminatedUnion("type", [
|
|
|
1314
1349
|
/** `recents`: the folders of past sessions, most recent first. `launcher`: the command that runs `ledge` inside WSL
|
|
1315
1350
|
* (`[node, cli]`), so the overlay can attach a terminal to a session with `<launcher> attach <id>`. `daemon`: absent
|
|
1316
1351
|
* from daemons older than the auto-update. */
|
|
1317
|
-
|
|
1318
|
-
|
|
1352
|
+
z23.object({ type: z23.literal("snapshot"), sessions: z23.array(SessionSchema), recents: z23.array(RecentSchema).optional(), launcher: z23.array(z23.string()).optional(), daemon: DaemonInfoSchema.optional(), sshAlias: SshAliasSchema.optional() }),
|
|
1353
|
+
z23.object({ type: z23.literal("session.updated"), session: SessionSchema }),
|
|
1319
1354
|
/** OMP: the instructions taken back from its queue by an interrupt that restores it; the asker puts them back in its draft. */
|
|
1320
|
-
|
|
1321
|
-
type:
|
|
1322
|
-
id:
|
|
1323
|
-
texts:
|
|
1355
|
+
z23.object({
|
|
1356
|
+
type: z23.literal("session.queue.restored"),
|
|
1357
|
+
id: z23.string(),
|
|
1358
|
+
texts: z23.array(z23.string()),
|
|
1324
1359
|
/** The same instructions with the images they carried; `imagesDropped`: some images could not be put back. */
|
|
1325
|
-
entries:
|
|
1326
|
-
imagesDropped:
|
|
1360
|
+
entries: z23.array(z23.object({ text: z23.string(), attachments: z23.array(AttachmentIdSchema).optional() })).optional(),
|
|
1361
|
+
imagesDropped: z23.boolean().optional()
|
|
1327
1362
|
}),
|
|
1328
|
-
|
|
1329
|
-
|
|
1363
|
+
z23.object({ type: z23.literal("session.removed"), id: z23.string() }),
|
|
1364
|
+
z23.object({ type: z23.literal("session.preview"), id: z23.string(), lines: z23.array(z23.string()) }),
|
|
1330
1365
|
/** A session's thread, on request (spec 2026-10-13 §5); then each created or updated item, broadcast. */
|
|
1331
|
-
|
|
1332
|
-
|
|
1366
|
+
z23.object({ type: z23.literal("session.thread"), id: z23.string(), items: z23.array(ThreadItemSchema) }),
|
|
1367
|
+
z23.object({ type: z23.literal("session.thread.item"), id: z23.string(), item: ThreadItemSchema }),
|
|
1333
1368
|
/** Answer to the requester of a `session.launch`: the session exists (its `session.updated` is broadcast as usual). */
|
|
1334
|
-
|
|
1369
|
+
z23.object({ type: z23.literal("session.launched"), id: z23.string() }),
|
|
1335
1370
|
/** Answer to the requester of a `session.close`, once per row closed: the session `id` and how it ended. */
|
|
1336
|
-
|
|
1337
|
-
|
|
1371
|
+
z23.object({ type: z23.literal("session.closed"), qid: z23.string(), row: z23.number().int().min(0), id: z23.string(), how: z23.enum(["exit", "killed"]) }),
|
|
1372
|
+
z23.object({ type: z23.literal("recents"), recents: z23.array(RecentSchema) }),
|
|
1338
1373
|
/** Answer to the requester of a `folder.list` or `folder.create`: `path` resolved (`~` expanded), `parent` null at the
|
|
1339
1374
|
* root, `entries` its subfolders by name (hidden ones left out). A failure keeps the asked path and says why in `error`,
|
|
1340
1375
|
* never in an `error` message, which the launch form reads as a failed launch. */
|
|
1341
|
-
|
|
1342
|
-
type:
|
|
1343
|
-
path:
|
|
1344
|
-
parent:
|
|
1345
|
-
entries:
|
|
1346
|
-
error:
|
|
1376
|
+
z23.object({
|
|
1377
|
+
type: z23.literal("folder.listing"),
|
|
1378
|
+
path: z23.string(),
|
|
1379
|
+
parent: z23.string().nullable(),
|
|
1380
|
+
entries: z23.array(z23.string()),
|
|
1381
|
+
error: z23.string().optional(),
|
|
1347
1382
|
/** The request this answers, when it carried one. */
|
|
1348
|
-
requestId:
|
|
1383
|
+
requestId: z23.string().optional(),
|
|
1349
1384
|
/** Those `entries` that are Git repositories, with their branch (the short commit when HEAD is detached). */
|
|
1350
|
-
repos:
|
|
1385
|
+
repos: z23.array(z23.object({ name: z23.string(), branch: z23.string() })).optional()
|
|
1351
1386
|
}),
|
|
1352
1387
|
/** 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. */
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1388
|
+
z23.object({ type: z23.literal("chat.step"), qid: z23.string(), step: ChatStepSchema }),
|
|
1389
|
+
z23.object({ type: z23.literal("chat.delta"), qid: z23.string(), text: z23.string() }),
|
|
1390
|
+
z23.object({ type: z23.literal("chat.done"), qid: z23.string(), text: z23.string(), at: z23.string().datetime(), proposal: ChatProposalSchema.optional(), proposals: ChatProposalsSchema.optional(), relay: ChatRelaySchema.optional(), closes: ChatClosesSchema.optional(), projectProposal: ChatProjectProposalSchema.optional(), tasks: ChatTasksSchema.optional(), actions: ChatActionsSchema.optional() }),
|
|
1356
1391
|
/** What a `chat.act` applied: the rows done, and the one that failed with why (the rows after it stay proposed). */
|
|
1357
|
-
|
|
1358
|
-
row:
|
|
1359
|
-
message:
|
|
1392
|
+
z23.object({ type: z23.literal("chat.acted"), rid: z23.string(), qid: z23.string(), done: z23.array(z23.number().int().min(0)), failed: z23.array(z23.object({
|
|
1393
|
+
row: z23.number().int().min(0),
|
|
1394
|
+
message: z23.string(),
|
|
1360
1395
|
/** nothing was sent */
|
|
1361
|
-
refused:
|
|
1396
|
+
refused: z23.literal(true).optional()
|
|
1362
1397
|
})) }),
|
|
1363
1398
|
/** What an `action.run` came to: `row` the action as the daemon resolved it (its summary, its risk); `reason` why it was not
|
|
1364
1399
|
* done, with `code` (`refused`: not possible now; `agent`: a session may not run it; `confirm_required`: destructive, ask
|
|
1365
1400
|
* again; `failed`: the handler turned it down; a free string, as an `error`'s). */
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1401
|
+
z23.object({ type: z23.literal("action.result"), rid: z23.string(), action: z23.string().min(1).max(40), row: ChatActionSchema.optional(), reason: z23.string().optional(), code: z23.string().optional() }),
|
|
1402
|
+
z23.object({ type: z23.literal("chat.error"), qid: z23.string(), message: z23.string() }),
|
|
1403
|
+
z23.object({ type: z23.literal("chat.history"), turns: z23.array(ChatTurnSchema) }),
|
|
1369
1404
|
/** The daemon updating itself: npm is running, then the service restarts (the socket closes right after). */
|
|
1370
|
-
|
|
1405
|
+
z23.object({ type: z23.literal("update.progress"), version: z23.string(), step: z23.enum(["installing", "restarting"]) }),
|
|
1371
1406
|
/** Nothing was changed. `detail`: the useful end of npm's output; `command`: what the person can run instead. */
|
|
1372
|
-
|
|
1407
|
+
z23.object({ type: z23.literal("update.failed"), version: z23.string(), reason: UpdateFailureSchema, detail: z23.string().optional(), command: z23.string().optional() }),
|
|
1373
1408
|
/** The shared machines list (spec 2026-10-14 §5), sent to local clients only. */
|
|
1374
|
-
|
|
1409
|
+
z23.object({ type: z23.literal("machines"), machines: MachinesSchema }),
|
|
1375
1410
|
/** The local daemon's projects and folder rules (spec 2026-10-16 build §5), sent to local clients only. */
|
|
1376
|
-
|
|
1411
|
+
z23.object({ type: z23.literal("projects"), projects: ProjectsSchema }),
|
|
1377
1412
|
/** The island's settings shared by the local fronts; null until a front sets them (the island then sends its own). Local clients only. */
|
|
1378
|
-
|
|
1413
|
+
z23.object({ type: z23.literal("island"), prefs: IslandPrefsSchema.nullable() }),
|
|
1379
1414
|
/** Mobile access (lot 3), after the island in each snapshot and on every change. Local clients only. */
|
|
1380
|
-
|
|
1415
|
+
z23.object({ type: z23.literal("mobile"), state: MobileStateSchema }),
|
|
1416
|
+
/** The sessions a phone types into (« Téléphone au clavier »), after each snapshot and each change; `device` is its label. */
|
|
1417
|
+
z23.object({ type: z23.literal("terminal.holders"), holds: z23.array(z23.object({ id: z23.string(), device: z23.string() })) }),
|
|
1381
1418
|
/** The daemon's immediate answer to a `session.message`: delivered (`accepted`), held for later (`queued`), left to Claude's own SendMessage (`native`), or refused with a `reason`. */
|
|
1382
|
-
|
|
1419
|
+
z23.object({
|
|
1420
|
+
type: z23.literal("message.ack"),
|
|
1421
|
+
rid: z23.string(),
|
|
1422
|
+
outcome: z23.enum(["accepted", "queued", "native", "refused"]),
|
|
1423
|
+
reason: z23.string().optional(),
|
|
1424
|
+
/** A broadcast's per-recipient outcome, by name. */
|
|
1425
|
+
recipients: z23.object({ sent: z23.array(z23.string()), refused: z23.array(z23.object({ name: z23.string(), reason: z23.string() })) }).optional()
|
|
1426
|
+
}),
|
|
1427
|
+
/** The answer to a `session.broadcast`: who got it (`sent`) and who did not; `reason`: the whole broadcast was refused. */
|
|
1428
|
+
z23.object({ type: z23.literal("session.broadcast.result"), rid: z23.string(), sent: z23.array(z23.object({ id: z23.string(), name: z23.string() })), refused: z23.array(z23.object({ name: z23.string(), reason: z23.string() })), reason: z23.string().optional() }),
|
|
1383
1429
|
/** The answer to a `message.read`: the body with its sender, target and time, or the refusal's `reason`. */
|
|
1384
|
-
|
|
1430
|
+
z23.object({ type: z23.literal("message.body"), id: z23.string(), from: z23.string().optional(), to: z23.string().optional(), at: z23.string().optional(), text: z23.string().optional(), reason: z23.string().optional() }),
|
|
1385
1431
|
TaskResultSchema,
|
|
1386
1432
|
SessionHandoverResultSchema,
|
|
1387
1433
|
ContextPrefsMessageSchema,
|
|
1388
1434
|
HandoverResultSchema,
|
|
1389
1435
|
TaskUpdatedSchema,
|
|
1390
|
-
|
|
1391
|
-
type:
|
|
1392
|
-
message:
|
|
1393
|
-
id:
|
|
1436
|
+
z23.object({
|
|
1437
|
+
type: z23.literal("error"),
|
|
1438
|
+
message: z23.string(),
|
|
1439
|
+
id: z23.string().optional(),
|
|
1394
1440
|
/** Le type du message client refusé. */
|
|
1395
|
-
request:
|
|
1441
|
+
request: z23.string().optional(),
|
|
1396
1442
|
/** Ce que le front doit reconnaître au-delà du texte (NOTE_NOT_TYPED) ; une chaîne libre, qu'un front plus ancien ignore. */
|
|
1397
|
-
code:
|
|
1443
|
+
code: z23.string().optional()
|
|
1398
1444
|
})
|
|
1399
1445
|
]);
|
|
1400
1446
|
var MESSAGE_MAX = 2e4;
|
|
1401
1447
|
var SUMMARY_MAX = 500;
|
|
1402
|
-
var launchRows =
|
|
1403
|
-
var ClientMessageSchema =
|
|
1404
|
-
|
|
1448
|
+
var launchRows = z23.array(z23.number().int().min(0).max(MAX_PROPOSALS - 1)).min(1).max(MAX_PROPOSALS).refine((r) => new Set(r).size === r.length, "a row twice");
|
|
1449
|
+
var ClientMessageSchema = z23.discriminatedUnion("type", [
|
|
1450
|
+
z23.object({ type: z23.literal("chat.route"), qid: z23.string().min(1).max(100), text: z23.string().min(1).max(2e4), tool: ToolSchema.optional(), context: RoutingContextSchema }),
|
|
1405
1451
|
DocumentReadSchema,
|
|
1406
1452
|
AttachmentPutSchema,
|
|
1407
1453
|
AttachmentCaptureSchema,
|
|
@@ -1409,6 +1455,7 @@ var ClientMessageSchema = z22.discriminatedUnion("type", [
|
|
|
1409
1455
|
ReposInspectSchema,
|
|
1410
1456
|
ReposScanSchema,
|
|
1411
1457
|
ModelsListSchema,
|
|
1458
|
+
SessionCommandsSchema,
|
|
1412
1459
|
OpenRigStatusSchema,
|
|
1413
1460
|
OpenRigActSchema,
|
|
1414
1461
|
OpenRigSpecsSchema,
|
|
@@ -1421,151 +1468,165 @@ var ClientMessageSchema = z22.discriminatedUnion("type", [
|
|
|
1421
1468
|
* free one otherwise), `prompt` the agent's first instruction, `continue` resumes the folder's last conversation.
|
|
1422
1469
|
* With `qid` it is the chat card of that turn: the daemon launches the turn's proposal and ignores the other fields
|
|
1423
1470
|
* but `rows`, `model` and `effort`. */
|
|
1424
|
-
|
|
1425
|
-
type:
|
|
1471
|
+
z23.object({
|
|
1472
|
+
type: z23.literal("session.launch"),
|
|
1426
1473
|
tool: ToolSchema,
|
|
1427
|
-
cwd:
|
|
1428
|
-
name:
|
|
1429
|
-
prompt:
|
|
1430
|
-
continue:
|
|
1431
|
-
qid:
|
|
1474
|
+
cwd: z23.string().min(1),
|
|
1475
|
+
name: z23.string().optional(),
|
|
1476
|
+
prompt: z23.string().optional(),
|
|
1477
|
+
continue: z23.boolean().optional(),
|
|
1478
|
+
qid: z23.string().min(1).optional(),
|
|
1432
1479
|
/** With `qid`: the card's rows to launch (#24), indexes into the turn's `proposals`, each once; the first row without it. */
|
|
1433
1480
|
rows: launchRows.optional(),
|
|
1434
1481
|
/** Folders in addition to `cwd` (Claude: `--add-dir`); resolved like `cwd`. */
|
|
1435
|
-
dirs:
|
|
1482
|
+
dirs: z23.array(z23.string().min(1)).max(20).optional(),
|
|
1436
1483
|
/** The agent's model and effort (#58), the agent's own default when left out; with `qid`, for every row launched. */
|
|
1437
1484
|
model: ModelIdSchema.optional(),
|
|
1438
1485
|
effort: EffortSchema.optional(),
|
|
1439
1486
|
/** OMP only: its approval mode, `always-ask` when left out. */
|
|
1440
1487
|
approval: OmpApprovalSchema.optional(),
|
|
1441
1488
|
/** Routing by the fleet, removed before the message reaches the daemon. */
|
|
1442
|
-
machineId:
|
|
1489
|
+
machineId: z23.string().optional()
|
|
1443
1490
|
}),
|
|
1444
1491
|
/** The launch form's folder browser: list a folder's subfolders (home when no `path`), or make `name` inside `parent`
|
|
1445
1492
|
* and list it. Both are answered with a `folder.listing`. */
|
|
1446
|
-
|
|
1447
|
-
type:
|
|
1448
|
-
path:
|
|
1493
|
+
z23.object({
|
|
1494
|
+
type: z23.literal("folder.list"),
|
|
1495
|
+
path: z23.string().optional(),
|
|
1449
1496
|
/** Routing by the fleet, removed before the message reaches the daemon. */
|
|
1450
|
-
machineId:
|
|
1497
|
+
machineId: z23.string().optional(),
|
|
1451
1498
|
/** Copied into the `folder.listing` that answers; the fleet relays only that listing, from the machine asked. */
|
|
1452
|
-
requestId:
|
|
1499
|
+
requestId: z23.string().min(1).max(100).optional()
|
|
1453
1500
|
}),
|
|
1454
|
-
|
|
1455
|
-
type:
|
|
1456
|
-
parent:
|
|
1457
|
-
name:
|
|
1501
|
+
z23.object({
|
|
1502
|
+
type: z23.literal("folder.create"),
|
|
1503
|
+
parent: z23.string().min(1),
|
|
1504
|
+
name: z23.string().min(1),
|
|
1458
1505
|
/** As for `folder.list`: routing by the fleet, and the request its `folder.listing` answers. */
|
|
1459
|
-
machineId:
|
|
1460
|
-
requestId:
|
|
1506
|
+
machineId: z23.string().optional(),
|
|
1507
|
+
requestId: z23.string().min(1).max(100).optional()
|
|
1461
1508
|
}),
|
|
1462
1509
|
/** `steer`: OMP only, redirect the turn running now instead of queueing the text after it. */
|
|
1463
1510
|
/** OMP's `ask`: the answers to every question of the dialog `requestId`, in order (`selected` labels, and/or free `text`); `cancel` declines it. */
|
|
1464
|
-
|
|
1465
|
-
|
|
1511
|
+
z23.object({ type: z23.literal("session.answer"), id: z23.string(), requestId: z23.string().min(1).max(200), answers: z23.array(z23.object({ id: z23.string(), selected: z23.array(z23.string().max(2e3)).max(100), text: z23.string().max(2e4).optional() })).max(50), cancel: z23.boolean().optional() }),
|
|
1512
|
+
z23.object({ type: z23.literal("session.reply"), id: z23.string(), text: z23.string(), attachments: z23.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional(), steer: z23.boolean().optional() }),
|
|
1466
1513
|
/** The chat card's instruction (spec 2026-10-12 relay §4): sent now if the session is free, else queued until it is. */
|
|
1467
|
-
|
|
1514
|
+
z23.object({ type: z23.literal("session.relay"), qid: z23.string().min(1) }),
|
|
1468
1515
|
/** Takes the card's queued instruction back out of the queue. */
|
|
1469
|
-
|
|
1516
|
+
z23.object({ type: z23.literal("session.relay.cancel"), qid: z23.string().min(1) }),
|
|
1470
1517
|
/** The chat's generic card (action registry spec §5.1): applies its rows in order (all of them without `rows`), stopping at
|
|
1471
1518
|
* the first failure. `confirmed` says the front asked again; refused without it when a row is destructive. */
|
|
1472
|
-
|
|
1473
|
-
type:
|
|
1474
|
-
rid:
|
|
1475
|
-
qid:
|
|
1519
|
+
z23.object({
|
|
1520
|
+
type: z23.literal("chat.act"),
|
|
1521
|
+
rid: z23.string().min(1).max(100),
|
|
1522
|
+
qid: z23.string().min(1),
|
|
1476
1523
|
rows: launchRows.optional(),
|
|
1477
|
-
confirmed:
|
|
1524
|
+
confirmed: z23.literal(true).optional(),
|
|
1478
1525
|
/** « Refuser »: each row (session.decide only) answers its session's request with deny, whatever its own decision; never
|
|
1479
1526
|
* confirmed, and allowed on a request shown cut. The rows become `denied`. */
|
|
1480
|
-
deny:
|
|
1527
|
+
deny: z23.literal(true).optional()
|
|
1481
1528
|
}),
|
|
1482
1529
|
/** « Ignorer » the turn's cards, for every device and for Ledge (who is told at the next question); `undo` opens them
|
|
1483
1530
|
* again (« Revoir »). Refused while one of them is under way. Every client gets the turn's `ignoredAt` through chat.history. */
|
|
1484
|
-
|
|
1531
|
+
z23.object({ type: z23.literal("chat.ignore"), qid: z23.string().min(1), undo: z23.literal(true).optional() }),
|
|
1485
1532
|
/** A registry action run outside the chat (#93, the CLI): the daemon resolves `args` as it does a generic card's row, then
|
|
1486
1533
|
* applies it through its own handler. `by` the session that asks, left out for the user; `confirmed` for a destructive one. */
|
|
1487
|
-
|
|
1488
|
-
type:
|
|
1489
|
-
rid:
|
|
1490
|
-
by:
|
|
1534
|
+
z23.object({
|
|
1535
|
+
type: z23.literal("action.run"),
|
|
1536
|
+
rid: z23.string().min(1).max(100),
|
|
1537
|
+
by: z23.string().min(1).optional(),
|
|
1491
1538
|
/** `by`'s key (LEDGE_SESSION_KEY) */
|
|
1492
|
-
key:
|
|
1539
|
+
key: z23.string().max(128).optional(),
|
|
1493
1540
|
action: ActionIdSchema,
|
|
1494
|
-
args:
|
|
1495
|
-
confirmed:
|
|
1541
|
+
args: z23.record(z23.unknown()),
|
|
1542
|
+
confirmed: z23.literal(true).optional()
|
|
1496
1543
|
}),
|
|
1497
1544
|
/** The chat's close card: closes the turn's sessions, `rows` (indexes into its `closes`) or all of them. */
|
|
1498
|
-
|
|
1545
|
+
z23.object({ type: z23.literal("session.close"), qid: z23.string().min(1), rows: launchRows.optional() }),
|
|
1499
1546
|
/** `always` and `note` only where the harness offers them (`offers`); a note goes with `deny`, for the agent to read. */
|
|
1500
|
-
|
|
1501
|
-
type:
|
|
1502
|
-
id:
|
|
1547
|
+
z23.object({
|
|
1548
|
+
type: z23.literal("session.decide"),
|
|
1549
|
+
id: z23.string(),
|
|
1503
1550
|
decision: DecisionSchema,
|
|
1504
|
-
note:
|
|
1551
|
+
note: z23.string().trim().min(1).max(NOTE_MAX).optional(),
|
|
1505
1552
|
/** The request the user saw when deciding: refused (the request changed) unless it is still the pending one. Left out by older fronts and the island.
|
|
1506
1553
|
* `key` (pendingKey) covers its whole content; older fronts send kind and text only. */
|
|
1507
|
-
expect: PendingSchema.pick({ kind: true, text: true }).extend({ key:
|
|
1554
|
+
expect: PendingSchema.pick({ kind: true, text: true }).extend({ key: z23.string().max(64).optional() }).optional()
|
|
1508
1555
|
}),
|
|
1509
|
-
|
|
1510
|
-
|
|
1556
|
+
z23.object({ type: z23.literal("session.focus"), id: z23.string() }),
|
|
1557
|
+
z23.object({ type: z23.literal("session.kill"), id: z23.string() }),
|
|
1511
1558
|
/** `restoreQueue` (OMP): also take back what waits in its queue, returned as `session.queue.restored` to put in the draft. */
|
|
1512
|
-
|
|
1559
|
+
z23.object({ type: z23.literal("session.interrupt"), id: z23.string(), restoreQueue: z23.boolean().optional() }),
|
|
1513
1560
|
/** Removes a finished (exited) or read-only (hook_only) session from the list; refused for a live launcher session. */
|
|
1514
|
-
|
|
1561
|
+
z23.object({ type: z23.literal("session.dismiss"), id: z23.string() }),
|
|
1515
1562
|
/** Puts a session in the archive: it leaves the live list but is kept. */
|
|
1516
|
-
|
|
1563
|
+
z23.object({ type: z23.literal("session.archive"), id: z23.string() }),
|
|
1517
1564
|
/** Takes an archived session back out of the archive, as it was. */
|
|
1518
|
-
|
|
1565
|
+
z23.object({ type: z23.literal("session.restore"), id: z23.string() }),
|
|
1519
1566
|
/** Starts the agent again on an archived session's conversation. */
|
|
1520
|
-
|
|
1567
|
+
z23.object({ type: z23.literal("session.resume"), id: z23.string() }),
|
|
1521
1568
|
/** Changes a live session's model and effort (#58, lot 2), `null` for the agent's own default: the daemon restarts the
|
|
1522
1569
|
* agent on the same conversation with them, at once when the session is free, else at its next free moment. */
|
|
1523
|
-
|
|
1570
|
+
z23.object({ type: z23.literal("session.model"), id: z23.string(), model: ModelIdSchema.nullable(), effort: EffortSchema.nullable() }),
|
|
1524
1571
|
/** Deletes a session for good, archived or not. */
|
|
1525
|
-
|
|
1572
|
+
z23.object({ type: z23.literal("session.delete"), id: z23.string() }),
|
|
1526
1573
|
/** 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. */
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1574
|
+
z23.object({ type: z23.literal("session.rename"), id: z23.string(), topic: z23.string().max(500) }),
|
|
1575
|
+
z23.object({ type: z23.literal("session.thread"), id: z23.string() }),
|
|
1576
|
+
z23.object({ type: z23.literal("session.register"), session: SessionSchema }),
|
|
1530
1577
|
/** `agent` and `cwd` describe the session when the daemon does not know it yet (a hook from an agent started without ledge). */
|
|
1531
|
-
|
|
1532
|
-
type:
|
|
1533
|
-
id:
|
|
1578
|
+
z23.object({
|
|
1579
|
+
type: z23.literal("session.event"),
|
|
1580
|
+
id: z23.string(),
|
|
1534
1581
|
event: SessionEventSchema,
|
|
1535
1582
|
agent: ToolSchema.optional(),
|
|
1536
|
-
cwd:
|
|
1583
|
+
cwd: z23.string().optional(),
|
|
1537
1584
|
/** The OpenRig seat the agent runs in (`OPENRIG_SESSION_NAME`, `pod-member@rig`), when OpenRig launched it. */
|
|
1538
1585
|
rigSeat: RigSeatNameSchema.optional()
|
|
1539
1586
|
}),
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1587
|
+
z23.object({ type: z23.literal("session.unregister"), id: z23.string(), exitCode: z23.number().int().nullable() }),
|
|
1588
|
+
z23.object({ type: z23.literal("snapshot.request") }),
|
|
1589
|
+
z23.object({ type: z23.literal("chat.ask"), qid: z23.string().min(1), text: z23.string(), images: z23.array(ImageUploadSchema).max(ATTACHMENTS_MAX).optional(), tool: ToolSchema.optional() }),
|
|
1590
|
+
z23.object({ type: z23.literal("chat.cancel"), qid: z23.string().min(1) }),
|
|
1544
1591
|
/** Starts a new conversation with Ledge: the day's turns are cleared and the next question opens a new harness session. */
|
|
1545
|
-
|
|
1592
|
+
z23.object({ type: z23.literal("chat.reset") }),
|
|
1546
1593
|
/** Installs `@paradow/ledge@version` and restarts the service (spec 2026-10-12 auto-update §6). */
|
|
1547
|
-
|
|
1594
|
+
z23.object({ type: z23.literal("update.daemon"), version: z23.string().regex(SEMVER) }),
|
|
1548
1595
|
/** Replaces the daemon's machines list (first connected front wins); refused unless valid. */
|
|
1549
|
-
|
|
1596
|
+
z23.object({ type: z23.literal("machines.set"), machines: MachinesSchema }),
|
|
1550
1597
|
/** Replaces the local daemon's projects and rules as a whole; refused unless valid. */
|
|
1551
|
-
|
|
1598
|
+
z23.object({ type: z23.literal("projects.set"), projects: ProjectsSchema }),
|
|
1552
1599
|
/** Replaces the island's settings as a whole; refused unless valid. */
|
|
1553
|
-
|
|
1600
|
+
z23.object({ type: z23.literal("island.set"), prefs: IslandPrefsSchema }),
|
|
1554
1601
|
/** Mobile access (lot 3), local fronts only. A changed `relayUrl` drops the relay session. */
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1602
|
+
z23.object({ type: z23.literal("mobile.set"), enabled: z23.boolean(), relayUrl: RelayUrlSchema }),
|
|
1603
|
+
z23.object({ type: z23.literal("mobile.signin") }),
|
|
1604
|
+
z23.object({ type: z23.literal("mobile.signin.cancel") }),
|
|
1605
|
+
z23.object({ type: z23.literal("mobile.signout") }),
|
|
1559
1606
|
/** While the link is offline: try again now. */
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1607
|
+
z23.object({ type: z23.literal("mobile.retry") }),
|
|
1608
|
+
z23.object({ type: z23.literal("mobile.pairing.approve"), id: z23.string().min(1).max(100) }),
|
|
1609
|
+
z23.object({ type: z23.literal("mobile.pairing.deny"), id: z23.string().min(1).max(100) }),
|
|
1563
1610
|
/** `id`: the device's fingerprint. */
|
|
1564
|
-
|
|
1611
|
+
z23.object({ type: z23.literal("mobile.device.revoke"), id: z23.string().min(1).max(100) }),
|
|
1612
|
+
/** « Taper dans les terminaux depuis le téléphone »; turned off, every phone loses the hand. */
|
|
1613
|
+
z23.object({ type: z23.literal("mobile.terminal"), input: z23.boolean() }),
|
|
1614
|
+
/** « Reprendre la main »: the phone typing into the session's terminal goes back to reading it. */
|
|
1615
|
+
z23.object({ type: z23.literal("terminal.release"), id: z23.string().min(1) }),
|
|
1565
1616
|
/** One session writing to another by Ledge name (`to` may end in ` [ref]`); `intercept` (the Claude hook): answer `native` unless `to` is a live non-Claude session. */
|
|
1566
|
-
|
|
1617
|
+
z23.object({ type: z23.literal("session.message"), rid: z23.string().min(1), from: z23.string().min(1), to: z23.string().min(1), text: z23.string().min(1).max(MESSAGE_MAX), summary: z23.string().max(SUMMARY_MAX).optional(), intercept: z23.boolean().optional() }),
|
|
1618
|
+
/** The user writing to every session of a project, or to several sessions (ids or names). */
|
|
1619
|
+
z23.object({
|
|
1620
|
+
type: z23.literal("session.broadcast"),
|
|
1621
|
+
rid: z23.string().min(1).max(100),
|
|
1622
|
+
to: z23.union([z23.object({ project: z23.string().min(1).max(80) }), z23.object({ sessions: z23.array(z23.string().min(1)).min(1).max(BROADCAST_SESSIONS_MAX) })]),
|
|
1623
|
+
text: z23.string().trim().min(1).max(MESSAGE_MAX),
|
|
1624
|
+
summary: z23.string().max(SUMMARY_MAX).optional(),
|
|
1625
|
+
/** How the recipients are told who it went to (« (à <label>) »), instead of the names: a project the fleet turned into sessions. */
|
|
1626
|
+
label: z23.string().min(1).max(BROADCAST_LABEL_MAX).optional()
|
|
1627
|
+
}),
|
|
1567
1628
|
/** `ledge read <id>`: a message's whole body, for its receiver or its sender (`by`, a session id). */
|
|
1568
|
-
|
|
1629
|
+
z23.object({ type: z23.literal("message.read"), id: z23.string().min(1).max(40), by: z23.string().min(1) }),
|
|
1569
1630
|
TaskCmdSchema,
|
|
1570
1631
|
SessionHandoverSchema,
|
|
1571
1632
|
ContextSetSchema,
|
|
@@ -1574,79 +1635,79 @@ var ClientMessageSchema = z22.discriminatedUnion("type", [
|
|
|
1574
1635
|
]);
|
|
1575
1636
|
|
|
1576
1637
|
// ../protocol/src/relay.ts
|
|
1577
|
-
import { z as
|
|
1638
|
+
import { z as z24 } from "zod";
|
|
1578
1639
|
var SEALED_MAX = 1048576;
|
|
1579
|
-
var RelayPeerSchema =
|
|
1580
|
-
var RelayClientMessageSchema =
|
|
1581
|
-
type:
|
|
1640
|
+
var RelayPeerSchema = z24.union([z24.literal("pc"), z24.string().regex(/^d_[A-Za-z0-9_-]{16,40}$/)]);
|
|
1641
|
+
var RelayClientMessageSchema = z24.object({
|
|
1642
|
+
type: z24.literal("send"),
|
|
1582
1643
|
to: RelayPeerSchema,
|
|
1583
|
-
body:
|
|
1644
|
+
body: z24.string().max(SEALED_MAX)
|
|
1584
1645
|
});
|
|
1585
|
-
var RelayServerMessageSchema =
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1646
|
+
var RelayServerMessageSchema = z24.discriminatedUnion("type", [
|
|
1647
|
+
z24.object({ type: z24.literal("welcome"), accountId: z24.string(), self: RelayPeerSchema, online: z24.array(RelayPeerSchema) }),
|
|
1648
|
+
z24.object({ type: z24.literal("deliver"), from: RelayPeerSchema, body: z24.string() }),
|
|
1649
|
+
z24.object({ type: z24.literal("presence"), peer: RelayPeerSchema, online: z24.boolean() }),
|
|
1589
1650
|
/**
|
|
1590
1651
|
* A frame was refused; `to` names the target when it is known.
|
|
1591
1652
|
* Contract: an error concerning a sealed body (`offline`, `too_large`, or a socket closed with 4008
|
|
1592
1653
|
* `rate_limited`) means that body was not delivered, so the sequence on that channel is lost: the
|
|
1593
1654
|
* sender must re-handshake with that peer before sending to it again.
|
|
1594
1655
|
*/
|
|
1595
|
-
|
|
1596
|
-
type:
|
|
1597
|
-
code:
|
|
1656
|
+
z24.object({
|
|
1657
|
+
type: z24.literal("error"),
|
|
1658
|
+
code: z24.enum(["bad_frame", "too_large", "bad_target", "offline", "rate_limited"]),
|
|
1598
1659
|
to: RelayPeerSchema.optional()
|
|
1599
1660
|
})
|
|
1600
1661
|
]);
|
|
1601
1662
|
var PAIR_LABEL_MAX = 40;
|
|
1602
|
-
var KeyB64 =
|
|
1603
|
-
var Nonce =
|
|
1604
|
-
var Fingerprint =
|
|
1605
|
-
var SealedFrameSchema =
|
|
1663
|
+
var KeyB64 = z24.string().regex(/^[A-Za-z0-9_-]{87}$/);
|
|
1664
|
+
var Nonce = z24.string().regex(/^[A-Za-z0-9_-]{43}$/);
|
|
1665
|
+
var Fingerprint = z24.string().regex(/^[A-Za-z0-9_-]{22}$/);
|
|
1666
|
+
var SealedFrameSchema = z24.discriminatedUnion("k", [
|
|
1606
1667
|
/** `e` is the ephemeral key, `f` the fingerprint of the sender's static key. */
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1668
|
+
z24.object({ k: z24.literal("hello"), e: KeyB64, f: Fingerprint }),
|
|
1669
|
+
z24.object({ k: z24.literal("msg"), s: z24.string() }),
|
|
1670
|
+
z24.object({ k: z24.literal("pair_commit"), c: Nonce, label: z24.string().trim().min(1).max(PAIR_LABEL_MAX) }),
|
|
1671
|
+
z24.object({ k: z24.literal("pair_offer"), pc: KeyB64, n: Nonce }),
|
|
1672
|
+
z24.object({ k: z24.literal("pair_reveal"), d: KeyB64, n: Nonce }),
|
|
1673
|
+
z24.object({ k: z24.literal("pair_ok") }),
|
|
1674
|
+
z24.object({ k: z24.literal("pair_no") }),
|
|
1675
|
+
z24.object({ k: z24.literal("denied") }),
|
|
1676
|
+
z24.object({ k: z24.literal("rekey") })
|
|
1616
1677
|
]);
|
|
1617
1678
|
|
|
1618
1679
|
// ../protocol/src/relayAuth.ts
|
|
1619
|
-
import { z as
|
|
1620
|
-
var DeviceStartResponseSchema =
|
|
1621
|
-
deviceCode:
|
|
1622
|
-
userCode:
|
|
1623
|
-
verificationUri:
|
|
1624
|
-
expiresIn:
|
|
1625
|
-
interval:
|
|
1626
|
-
});
|
|
1627
|
-
var DevicePollResponseSchema =
|
|
1628
|
-
|
|
1629
|
-
|
|
1680
|
+
import { z as z25 } from "zod";
|
|
1681
|
+
var DeviceStartResponseSchema = z25.object({
|
|
1682
|
+
deviceCode: z25.string().min(1),
|
|
1683
|
+
userCode: z25.string().min(1),
|
|
1684
|
+
verificationUri: z25.string().min(1),
|
|
1685
|
+
expiresIn: z25.number().int().positive(),
|
|
1686
|
+
interval: z25.number().int().positive()
|
|
1687
|
+
});
|
|
1688
|
+
var DevicePollResponseSchema = z25.discriminatedUnion("status", [
|
|
1689
|
+
z25.object({ status: z25.literal("pending") }),
|
|
1690
|
+
z25.object({ status: z25.literal("slow_down"), interval: z25.number().int().positive() }),
|
|
1630
1691
|
/** `token` is the relay session token, shown this once only. */
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1692
|
+
z25.object({ status: z25.literal("ok"), token: z25.string().min(1), accountId: z25.string().min(1), login: z25.string().min(1) }),
|
|
1693
|
+
z25.object({ status: z25.literal("expired") }),
|
|
1694
|
+
z25.object({ status: z25.literal("denied") }),
|
|
1695
|
+
z25.object({ status: z25.literal("not_allowed") })
|
|
1635
1696
|
]);
|
|
1636
|
-
var DeviceRevokeResponseSchema =
|
|
1637
|
-
var MeResponseSchema =
|
|
1638
|
-
accountId:
|
|
1639
|
-
login:
|
|
1697
|
+
var DeviceRevokeResponseSchema = z25.object({ revoked: z25.number().int().min(0) });
|
|
1698
|
+
var MeResponseSchema = z25.object({
|
|
1699
|
+
accountId: z25.string().min(1),
|
|
1700
|
+
login: z25.string().min(1),
|
|
1640
1701
|
peer: RelayPeerSchema,
|
|
1641
|
-
kind:
|
|
1702
|
+
kind: z25.enum(["pc", "device"])
|
|
1642
1703
|
});
|
|
1643
1704
|
|
|
1644
1705
|
// ../protocol/src/phone.ts
|
|
1645
|
-
import { z as
|
|
1706
|
+
import { z as z27 } from "zod";
|
|
1646
1707
|
|
|
1647
1708
|
// ../protocol/src/push.ts
|
|
1648
|
-
import { z as
|
|
1649
|
-
var B64U =
|
|
1709
|
+
import { z as z26 } from "zod";
|
|
1710
|
+
var B64U = z26.string().regex(/^[A-Za-z0-9_-]*$/);
|
|
1650
1711
|
var PUSH_HOSTS = ["*.push.apple.com", "fcm.googleapis.com", "updates.push.services.mozilla.com", "*.notify.windows.com"];
|
|
1651
1712
|
function pushEndpointAllowed(url) {
|
|
1652
1713
|
let u;
|
|
@@ -1663,29 +1724,29 @@ function pushEndpointAllowed(url) {
|
|
|
1663
1724
|
return host.length > suffix.length && host.endsWith(suffix);
|
|
1664
1725
|
});
|
|
1665
1726
|
}
|
|
1666
|
-
var PushSendSchema =
|
|
1667
|
-
endpoint:
|
|
1727
|
+
var PushSendSchema = z26.object({
|
|
1728
|
+
endpoint: z26.string().url().max(1024),
|
|
1668
1729
|
body: B64U.max(5462),
|
|
1669
|
-
ttl:
|
|
1670
|
-
urgency:
|
|
1671
|
-
topic:
|
|
1672
|
-
});
|
|
1673
|
-
var PushSendResultSchema =
|
|
1674
|
-
result:
|
|
1675
|
-
status:
|
|
1676
|
-
});
|
|
1677
|
-
var PushSubscriptionSchema =
|
|
1678
|
-
endpoint:
|
|
1679
|
-
keys:
|
|
1680
|
-
});
|
|
1681
|
-
var PushPayloadSchema =
|
|
1682
|
-
v:
|
|
1683
|
-
kind:
|
|
1684
|
-
title:
|
|
1685
|
-
body:
|
|
1686
|
-
url:
|
|
1687
|
-
badge:
|
|
1688
|
-
tag:
|
|
1730
|
+
ttl: z26.number().int().min(0).max(86400),
|
|
1731
|
+
urgency: z26.enum(["normal", "high"]),
|
|
1732
|
+
topic: z26.string().regex(/^[A-Za-z0-9_-]{1,32}$/)
|
|
1733
|
+
});
|
|
1734
|
+
var PushSendResultSchema = z26.object({
|
|
1735
|
+
result: z26.enum(["sent", "gone", "failed"]),
|
|
1736
|
+
status: z26.number().int().optional()
|
|
1737
|
+
});
|
|
1738
|
+
var PushSubscriptionSchema = z26.object({
|
|
1739
|
+
endpoint: z26.string().url().max(1024).refine(pushEndpointAllowed),
|
|
1740
|
+
keys: z26.object({ p256dh: B64U.length(87), auth: B64U.length(22) })
|
|
1741
|
+
});
|
|
1742
|
+
var PushPayloadSchema = z26.object({
|
|
1743
|
+
v: z26.literal(1),
|
|
1744
|
+
kind: z26.enum(["request", "question", "finished", "chat", "decision"]),
|
|
1745
|
+
title: z26.string().max(80),
|
|
1746
|
+
body: z26.string().max(120),
|
|
1747
|
+
url: z26.string().regex(/^\/#\/[A-Za-z0-9/%._~-]*$/).max(300),
|
|
1748
|
+
badge: z26.number().int().min(0).max(999),
|
|
1749
|
+
tag: z26.string().regex(/^[A-Za-z0-9_-]{1,32}$/)
|
|
1689
1750
|
});
|
|
1690
1751
|
|
|
1691
1752
|
// ../protocol/src/phone.ts
|
|
@@ -1695,35 +1756,35 @@ var THREAD_TEXT_MAX = 8192;
|
|
|
1695
1756
|
var TOOL_TEXT_MAX = 2048;
|
|
1696
1757
|
var CHECKLIST_TASKS_MAX = 50;
|
|
1697
1758
|
var CHECKLIST_TEXT_MAX = 200;
|
|
1698
|
-
var ChecklistStatusSchema =
|
|
1699
|
-
var PhoneChecklistSchema =
|
|
1700
|
-
tasks:
|
|
1701
|
-
done:
|
|
1702
|
-
total:
|
|
1703
|
-
cut:
|
|
1704
|
-
});
|
|
1705
|
-
var PhoneChecklistSummarySchema =
|
|
1706
|
-
done:
|
|
1707
|
-
total:
|
|
1708
|
-
current:
|
|
1709
|
-
cut:
|
|
1710
|
-
});
|
|
1711
|
-
var RiskSchema =
|
|
1712
|
-
var RiskReasonSchema =
|
|
1713
|
-
var OperationIdSchema =
|
|
1714
|
-
var OperationStatusSchema =
|
|
1715
|
-
var OperationReasonSchema =
|
|
1716
|
-
var CapabilitiesSchema =
|
|
1759
|
+
var ChecklistStatusSchema = z27.enum(["pending", "in_progress", "completed"]);
|
|
1760
|
+
var PhoneChecklistSchema = z27.object({
|
|
1761
|
+
tasks: z27.array(z27.object({ text: z27.string().max(CHECKLIST_TEXT_MAX), status: ChecklistStatusSchema })).max(CHECKLIST_TASKS_MAX),
|
|
1762
|
+
done: z27.number().int().nonnegative(),
|
|
1763
|
+
total: z27.number().int().nonnegative(),
|
|
1764
|
+
cut: z27.literal(true).optional()
|
|
1765
|
+
});
|
|
1766
|
+
var PhoneChecklistSummarySchema = z27.object({
|
|
1767
|
+
done: z27.number().int().nonnegative(),
|
|
1768
|
+
total: z27.number().int().nonnegative(),
|
|
1769
|
+
current: z27.string().max(CHECKLIST_TEXT_MAX).optional(),
|
|
1770
|
+
cut: z27.literal(true).optional()
|
|
1771
|
+
});
|
|
1772
|
+
var RiskSchema = z27.enum(["low", "high"]);
|
|
1773
|
+
var RiskReasonSchema = z27.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"]);
|
|
1774
|
+
var OperationIdSchema = z27.string().uuid();
|
|
1775
|
+
var OperationStatusSchema = z27.enum(["received", "applied", "rejected", "failed"]);
|
|
1776
|
+
var OperationReasonSchema = z27.enum([...RefusalCodeSchema.options, "untypable", "confirm_required", "conflict", "assertion_invalid", "assertion_expired", "scheduled", ...ModelRefusalSchema.options]);
|
|
1777
|
+
var CapabilitiesSchema = z27.object({
|
|
1717
1778
|
/** A question can be answered in free text. */
|
|
1718
|
-
freeTextAnswer:
|
|
1779
|
+
freeTextAnswer: z27.boolean(),
|
|
1719
1780
|
/** The session's accept/deny can be typed; absent = true. */
|
|
1720
|
-
decide:
|
|
1781
|
+
decide: z27.boolean().optional(),
|
|
1721
1782
|
/** OMP's dialog questions can be answered from the phone; absent = false. */
|
|
1722
|
-
questions:
|
|
1783
|
+
questions: z27.boolean().optional()
|
|
1723
1784
|
});
|
|
1724
|
-
var CapabilitiesByToolSchema =
|
|
1725
|
-
var PhonePendingSchema = PendingSchema.extend({ key:
|
|
1726
|
-
var SwitchableSessionSchema = SessionSchema.extend({ canSwitch:
|
|
1785
|
+
var CapabilitiesByToolSchema = z27.object({ claude: CapabilitiesSchema, codex: CapabilitiesSchema, cursor: CapabilitiesSchema, omp: CapabilitiesSchema });
|
|
1786
|
+
var PhonePendingSchema = PendingSchema.extend({ key: z27.string().max(64), risk: RiskSchema, riskReason: RiskReasonSchema, cut: z27.literal(true).optional() });
|
|
1787
|
+
var SwitchableSessionSchema = SessionSchema.extend({ canSwitch: z27.literal(true).optional() });
|
|
1727
1788
|
var PhoneSessionSchema = SwitchableSessionSchema.pick({
|
|
1728
1789
|
id: true,
|
|
1729
1790
|
name: true,
|
|
@@ -1751,288 +1812,346 @@ var PhoneSessionSchema = SwitchableSessionSchema.pick({
|
|
|
1751
1812
|
exitedAt: true
|
|
1752
1813
|
}).extend({
|
|
1753
1814
|
pending: PhonePendingSchema.optional(),
|
|
1754
|
-
unread:
|
|
1755
|
-
handover:
|
|
1815
|
+
unread: z27.boolean(),
|
|
1816
|
+
handover: z27.object({ state: HandoverStateSchema, toName: z27.string().max(80).optional() }).strict().optional(),
|
|
1756
1817
|
/** Absent: the agent has no checklist. */
|
|
1757
1818
|
checklist: PhoneChecklistSummarySchema.optional(),
|
|
1758
1819
|
/** Started without Ledge (`hook_only`): the phone can neither close nor resume it. */
|
|
1759
|
-
readOnly:
|
|
1820
|
+
readOnly: z27.literal(true).optional()
|
|
1760
1821
|
});
|
|
1761
|
-
var B64U2 =
|
|
1762
|
-
var CredentialSchema =
|
|
1822
|
+
var B64U2 = z27.string().regex(/^[A-Za-z0-9_-]*$/);
|
|
1823
|
+
var CredentialSchema = z27.object({
|
|
1763
1824
|
id: B64U2.max(1366),
|
|
1764
1825
|
publicKey: B64U2.max(2048),
|
|
1765
|
-
alg:
|
|
1826
|
+
alg: z27.union([z27.literal(-7), z27.literal(-257)]),
|
|
1766
1827
|
clientDataJSON: B64U2.max(4096),
|
|
1767
1828
|
authenticatorData: B64U2.max(4096),
|
|
1768
|
-
transports:
|
|
1829
|
+
transports: z27.array(z27.string().max(20)).max(8).optional()
|
|
1769
1830
|
});
|
|
1770
|
-
var AssertionSchema =
|
|
1831
|
+
var AssertionSchema = z27.object({
|
|
1771
1832
|
id: B64U2.max(1366),
|
|
1772
1833
|
clientDataJSON: B64U2.max(4096),
|
|
1773
1834
|
authenticatorData: B64U2.max(4096),
|
|
1774
1835
|
signature: B64U2.max(1024)
|
|
1775
1836
|
});
|
|
1776
|
-
var ConfirmPurposeSchema =
|
|
1837
|
+
var ConfirmPurposeSchema = z27.enum(["register", "decide", "launch", "close", "act", "pc", "terminal"]);
|
|
1777
1838
|
var PhoneChatStepSchema = ChatStepSchema.pick({ kind: true, id: true, name: true }).strict();
|
|
1778
|
-
var PhoneChatProposalSchema =
|
|
1779
|
-
project:
|
|
1839
|
+
var PhoneChatProposalSchema = z27.object({
|
|
1840
|
+
project: z27.string().max(80),
|
|
1780
1841
|
tool: ToolSchema,
|
|
1781
|
-
prompt:
|
|
1782
|
-
launchedId:
|
|
1783
|
-
failed:
|
|
1842
|
+
prompt: z27.string().max(TOOL_TEXT_MAX).optional(),
|
|
1843
|
+
launchedId: z27.string().optional(),
|
|
1844
|
+
failed: z27.literal(true).optional()
|
|
1784
1845
|
}).strict();
|
|
1785
|
-
var PhoneChatRelaySchema =
|
|
1786
|
-
id:
|
|
1787
|
-
name:
|
|
1846
|
+
var PhoneChatRelaySchema = z27.object({
|
|
1847
|
+
id: z27.string().min(1),
|
|
1848
|
+
name: z27.string(),
|
|
1788
1849
|
tool: ToolSchema,
|
|
1789
|
-
text:
|
|
1790
|
-
status:
|
|
1791
|
-
sentAt:
|
|
1792
|
-
failed:
|
|
1850
|
+
text: z27.string().max(TOOL_TEXT_MAX),
|
|
1851
|
+
status: z27.enum(["queued", "sent"]).optional(),
|
|
1852
|
+
sentAt: z27.string().datetime().optional(),
|
|
1853
|
+
failed: z27.literal(true).optional(),
|
|
1793
1854
|
/** With `failed`: why, as the PC's code (never its text). */
|
|
1794
|
-
code:
|
|
1855
|
+
code: z27.string().max(40).optional()
|
|
1795
1856
|
}).strict();
|
|
1796
|
-
var CloseHowSchema =
|
|
1797
|
-
var PhoneChatCloseSchema =
|
|
1798
|
-
id:
|
|
1799
|
-
name:
|
|
1857
|
+
var CloseHowSchema = z27.enum(["exit", "killed"]);
|
|
1858
|
+
var PhoneChatCloseSchema = z27.object({
|
|
1859
|
+
id: z27.string().min(1),
|
|
1860
|
+
name: z27.string(),
|
|
1800
1861
|
tool: ToolSchema,
|
|
1801
1862
|
how: CloseHowSchema.optional(),
|
|
1802
|
-
closedAt:
|
|
1803
|
-
failed:
|
|
1863
|
+
closedAt: z27.string().datetime().optional(),
|
|
1864
|
+
failed: z27.literal(true).optional()
|
|
1804
1865
|
}).strict();
|
|
1805
|
-
var PhoneChatTaskSchema =
|
|
1806
|
-
to:
|
|
1807
|
-
toName:
|
|
1808
|
-
title:
|
|
1809
|
-
text:
|
|
1810
|
-
taskId:
|
|
1811
|
-
ownerName:
|
|
1812
|
-
state:
|
|
1813
|
-
failed:
|
|
1866
|
+
var PhoneChatTaskSchema = z27.object({
|
|
1867
|
+
to: z27.string().max(80),
|
|
1868
|
+
toName: z27.string().max(80).optional(),
|
|
1869
|
+
title: z27.string().max(200),
|
|
1870
|
+
text: z27.string().max(TOOL_TEXT_MAX).optional(),
|
|
1871
|
+
taskId: z27.string().max(40).optional(),
|
|
1872
|
+
ownerName: z27.string().max(80).optional(),
|
|
1873
|
+
state: z27.enum(["open", "taken", "done", "refused", "dropped"]).optional(),
|
|
1874
|
+
failed: z27.literal(true).optional()
|
|
1814
1875
|
}).strict();
|
|
1815
|
-
var PhoneChatActionSchema =
|
|
1816
|
-
action:
|
|
1817
|
-
summary:
|
|
1876
|
+
var PhoneChatActionSchema = z27.object({
|
|
1877
|
+
action: z27.string().min(1).max(40),
|
|
1878
|
+
summary: z27.string().max(300),
|
|
1818
1879
|
vars: ActionVarsSchema.optional(),
|
|
1819
|
-
detail:
|
|
1820
|
-
detailCut:
|
|
1880
|
+
detail: z27.string().max(TOOL_TEXT_MAX).optional(),
|
|
1881
|
+
detailCut: z27.literal(true).optional(),
|
|
1821
1882
|
risk: ActionRiskSchema,
|
|
1822
|
-
session:
|
|
1883
|
+
session: z27.string().max(100).optional(),
|
|
1823
1884
|
state: ChatActionStateSchema.optional(),
|
|
1824
|
-
doneAt:
|
|
1825
|
-
code:
|
|
1885
|
+
doneAt: z27.string().datetime().optional(),
|
|
1886
|
+
code: z27.string().max(40).optional()
|
|
1826
1887
|
}).strict();
|
|
1827
|
-
var PhoneTaskSchema =
|
|
1828
|
-
id:
|
|
1829
|
-
title:
|
|
1830
|
-
owner:
|
|
1831
|
-
ownerName:
|
|
1888
|
+
var PhoneTaskSchema = z27.object({
|
|
1889
|
+
id: z27.string().max(40),
|
|
1890
|
+
title: z27.string().max(200),
|
|
1891
|
+
owner: z27.string().max(100),
|
|
1892
|
+
ownerName: z27.string().max(80),
|
|
1832
1893
|
/** 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). */
|
|
1833
|
-
giver:
|
|
1834
|
-
giverName:
|
|
1835
|
-
text:
|
|
1836
|
-
state:
|
|
1837
|
-
result:
|
|
1838
|
-
cut:
|
|
1839
|
-
at:
|
|
1840
|
-
updatedAt:
|
|
1841
|
-
seen:
|
|
1894
|
+
giver: z27.string().max(100).optional(),
|
|
1895
|
+
giverName: z27.string().max(80).optional(),
|
|
1896
|
+
text: z27.string().max(TOOL_TEXT_MAX).optional(),
|
|
1897
|
+
state: z27.enum(["open", "taken", "done", "refused", "dropped"]),
|
|
1898
|
+
result: z27.string().max(TOOL_TEXT_MAX).optional(),
|
|
1899
|
+
cut: z27.literal(true).optional(),
|
|
1900
|
+
at: z27.string(),
|
|
1901
|
+
updatedAt: z27.string(),
|
|
1902
|
+
seen: z27.literal(true).optional()
|
|
1842
1903
|
}).strict();
|
|
1843
|
-
var ChatErrorCodeSchema =
|
|
1844
|
-
var PhoneChatTurnSchema =
|
|
1904
|
+
var ChatErrorCodeSchema = z27.enum(["busy", "timeout", "cancelled", "failed"]);
|
|
1905
|
+
var PhoneChatTurnSchema = z27.object({
|
|
1845
1906
|
qid: OperationIdSchema,
|
|
1846
|
-
question:
|
|
1847
|
-
askedAt:
|
|
1848
|
-
steps:
|
|
1849
|
-
answer:
|
|
1850
|
-
answeredAt:
|
|
1907
|
+
question: z27.string().max(MESSAGE_MAX),
|
|
1908
|
+
askedAt: z27.string().datetime(),
|
|
1909
|
+
steps: z27.array(PhoneChatStepSchema).max(50),
|
|
1910
|
+
answer: z27.string().max(THREAD_TEXT_MAX).optional(),
|
|
1911
|
+
answeredAt: z27.string().datetime().optional(),
|
|
1851
1912
|
error: ChatErrorCodeSchema.optional(),
|
|
1852
|
-
proposals:
|
|
1913
|
+
proposals: z27.array(PhoneChatProposalSchema).max(MAX_PROPOSALS).optional(),
|
|
1853
1914
|
relay: PhoneChatRelaySchema.optional(),
|
|
1854
|
-
closes:
|
|
1855
|
-
cut:
|
|
1856
|
-
tasks:
|
|
1857
|
-
actions:
|
|
1858
|
-
ignoredAt:
|
|
1859
|
-
attachments:
|
|
1915
|
+
closes: z27.array(PhoneChatCloseSchema).min(1).max(MAX_PROPOSALS).optional(),
|
|
1916
|
+
cut: z27.literal(true).optional(),
|
|
1917
|
+
tasks: z27.array(PhoneChatTaskSchema).min(1).max(MAX_PROPOSALS).optional(),
|
|
1918
|
+
actions: z27.array(PhoneChatActionSchema).min(1).max(MAX_PROPOSALS).optional(),
|
|
1919
|
+
ignoredAt: z27.string().datetime().optional(),
|
|
1920
|
+
attachments: z27.array(AttachmentRefSchema).max(ATTACHMENTS_MAX).optional()
|
|
1860
1921
|
}).strict();
|
|
1861
|
-
var sessionId =
|
|
1862
|
-
var PhoneExpectSchema = PendingSchema.pick({ kind: true, text: true }).extend({ key:
|
|
1863
|
-
var CardRowsSchema =
|
|
1922
|
+
var sessionId = z27.string().min(1).max(100);
|
|
1923
|
+
var PhoneExpectSchema = PendingSchema.pick({ kind: true, text: true }).extend({ key: z27.string().min(1).max(64) });
|
|
1924
|
+
var CardRowsSchema = z27.array(z27.number().int().min(0).max(MAX_PROPOSALS - 1)).min(1).max(MAX_PROPOSALS).refine((r) => new Set(r).size === r.length, "a row twice");
|
|
1864
1925
|
var pcOp = { op: OperationIdSchema, assertion: AssertionSchema.optional() };
|
|
1865
|
-
var PcActionSchema =
|
|
1866
|
-
var
|
|
1867
|
-
|
|
1868
|
-
|
|
1926
|
+
var PcActionSchema = z27.enum(["update", "restart"]);
|
|
1927
|
+
var TerminalIdSchema = z27.string().regex(/^t_[A-Za-z0-9_-]{8,40}$/);
|
|
1928
|
+
var TERM_INPUT_MAX = 4096;
|
|
1929
|
+
var TERM_SCREEN_MAX = 65536;
|
|
1930
|
+
var TERM_OUTPUT_MAX = 32768;
|
|
1931
|
+
var TermDimSchema = z27.number().int().min(1).max(1e4);
|
|
1932
|
+
var TermReleaseWhySchema = z27.enum(["asked", "pc", "idle", "expired", "background", "link"]);
|
|
1933
|
+
var TermExitWhySchema = z27.enum(["ended", "gone", "closed", "superseded", "failed"]);
|
|
1934
|
+
var PhoneClientMessageSchema = z27.discriminatedUnion("type", [
|
|
1935
|
+
z27.object({ type: z27.literal("snapshot.request") }),
|
|
1936
|
+
z27.object({ type: z27.literal("session.thread"), id: sessionId }),
|
|
1869
1937
|
/** The session's request with its whole body (up to `PENDING_BODY_MAX`). */
|
|
1870
|
-
|
|
1938
|
+
z27.object({ type: z27.literal("session.pending"), id: sessionId }),
|
|
1871
1939
|
/** The session whose terminal the phone shows; null when it shows none. */
|
|
1872
|
-
|
|
1873
|
-
|
|
1940
|
+
z27.object({ type: z27.literal("session.watch"), id: sessionId.nullable() }),
|
|
1941
|
+
z27.object({ type: z27.literal("session.read"), id: sessionId, at: z27.string().datetime() }),
|
|
1874
1942
|
/**
|
|
1875
1943
|
* Asks for a challenge. One object for every purpose: the gateway refuses a `decide` without `id` and `expect`. A `close`
|
|
1876
1944
|
* or `act` names a turn of the chat (`qid`) or a session (`id`, for `session.close` and `session.resume`).
|
|
1877
1945
|
*/
|
|
1878
|
-
|
|
1879
|
-
type:
|
|
1946
|
+
z27.object({
|
|
1947
|
+
type: z27.literal("confirm.prepare"),
|
|
1880
1948
|
purpose: ConfirmPurposeSchema,
|
|
1881
1949
|
id: sessionId.optional(),
|
|
1882
1950
|
expect: PhoneExpectSchema.optional(),
|
|
1883
1951
|
qid: OperationIdSchema.optional(),
|
|
1884
1952
|
/** A `pc` challenge: what it is for, and for an update the version it covers. */
|
|
1885
1953
|
action: PcActionSchema.optional(),
|
|
1886
|
-
version:
|
|
1954
|
+
version: z27.string().regex(SEMVER).optional()
|
|
1887
1955
|
}),
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
type:
|
|
1956
|
+
z27.object({ type: z27.literal("credential.register"), op: OperationIdSchema, credential: CredentialSchema }),
|
|
1957
|
+
z27.object({
|
|
1958
|
+
type: z27.literal("session.decide"),
|
|
1891
1959
|
op: OperationIdSchema,
|
|
1892
1960
|
id: sessionId,
|
|
1893
1961
|
decision: DecisionSchema,
|
|
1894
|
-
note:
|
|
1962
|
+
note: z27.string().trim().min(1).max(NOTE_MAX).optional(),
|
|
1895
1963
|
/** The request the phone showed: refused unless it is still the pending one. */
|
|
1896
1964
|
expect: PhoneExpectSchema,
|
|
1897
1965
|
/** The device check over the challenge of `confirm.prepare`; required by the daemon for a high-risk accept. */
|
|
1898
1966
|
assertion: AssertionSchema.optional()
|
|
1899
1967
|
}),
|
|
1900
|
-
|
|
1901
|
-
type:
|
|
1968
|
+
z27.object({
|
|
1969
|
+
type: z27.literal("session.reply"),
|
|
1902
1970
|
op: OperationIdSchema,
|
|
1903
1971
|
id: sessionId,
|
|
1904
|
-
text:
|
|
1905
|
-
attachments:
|
|
1972
|
+
text: z27.string().max(MESSAGE_MAX),
|
|
1973
|
+
attachments: z27.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional(),
|
|
1906
1974
|
/** The request the reply answers, or null when the phone showed none: refused if the session's request is no longer that one. */
|
|
1907
1975
|
expect: PhoneExpectSchema.nullable(),
|
|
1908
1976
|
assertion: AssertionSchema.optional()
|
|
1909
1977
|
}),
|
|
1910
1978
|
/** OMP's `ask`: the answers to every question of the dialog `requestId`, in order; `cancel` declines it. Bounds as the local `session.answer`. */
|
|
1911
|
-
|
|
1912
|
-
type:
|
|
1979
|
+
z27.object({
|
|
1980
|
+
type: z27.literal("session.answer"),
|
|
1913
1981
|
op: OperationIdSchema,
|
|
1914
1982
|
id: sessionId,
|
|
1915
|
-
requestId:
|
|
1916
|
-
answers:
|
|
1917
|
-
cancel:
|
|
1983
|
+
requestId: z27.string().min(1).max(200),
|
|
1984
|
+
answers: z27.array(z27.object({ id: z27.string().max(200), selected: z27.array(z27.string().max(2e3)).max(100), text: z27.string().max(2e4).optional() })).max(50),
|
|
1985
|
+
cancel: z27.literal(true).optional(),
|
|
1918
1986
|
expect: PhoneExpectSchema
|
|
1919
1987
|
}),
|
|
1920
|
-
|
|
1988
|
+
z27.object({ type: z27.literal("session.interrupt"), op: OperationIdSchema, id: sessionId }),
|
|
1921
1989
|
/** Ends a live session as `/exit` would, killed as a last resort; answered with its `how`. Passkey, purpose `close`, over the session. */
|
|
1922
|
-
|
|
1990
|
+
z27.object({ type: z27.literal("session.close"), op: OperationIdSchema, id: sessionId, assertion: AssertionSchema.optional() }),
|
|
1923
1991
|
/** Starts an ended session again on its conversation. Passkey, purpose `act`, over the session. */
|
|
1924
|
-
|
|
1992
|
+
z27.object({ type: z27.literal("session.resume"), op: OperationIdSchema, id: sessionId, assertion: AssertionSchema.optional() }),
|
|
1925
1993
|
/** 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`. */
|
|
1926
|
-
|
|
1994
|
+
z27.object({ type: z27.literal("session.model"), op: OperationIdSchema, id: sessionId, model: ModelIdSchema.nullable(), effort: EffortSchema.nullable() }),
|
|
1995
|
+
/** One message to several sessions (ids); answered by `operation.result` with `sent` and `refused`. */
|
|
1996
|
+
z27.object({ type: z27.literal("session.broadcast"), op: OperationIdSchema, sessions: z27.array(sessionId).min(1).max(BROADCAST_SESSIONS_MAX), text: z27.string().trim().min(1).max(MESSAGE_MAX) }).strict(),
|
|
1927
1997
|
/** The models an agent offers on the PC. */
|
|
1928
|
-
|
|
1998
|
+
z27.object({ type: z27.literal("models.list"), tool: ToolSchema }),
|
|
1999
|
+
/** The slash commands of a session's agent, for the « / » list of its field. */
|
|
2000
|
+
z27.object({ type: z27.literal("session.commands"), id: sessionId }),
|
|
1929
2001
|
/** The phone drops its passkey from the daemon. */
|
|
1930
|
-
|
|
2002
|
+
z27.object({ type: z27.literal("device.forget"), op: OperationIdSchema }),
|
|
1931
2003
|
/** The phone's push subscription, with the VAPID key it was made with (so a key change is seen). */
|
|
1932
|
-
|
|
1933
|
-
|
|
2004
|
+
z27.object({ type: z27.literal("push.subscribe"), op: OperationIdSchema, subscription: PushSubscriptionSchema, key: B64U2.length(87) }),
|
|
2005
|
+
z27.object({ type: z27.literal("push.unsubscribe"), op: OperationIdSchema }),
|
|
1934
2006
|
/** The phone's own chat with Ledge. */
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
2007
|
+
z27.object({ type: z27.literal("chat.ask"), qid: OperationIdSchema, text: z27.string().trim().max(MESSAGE_MAX), attachments: z27.array(AttachmentIdSchema).max(ATTACHMENTS_MAX).optional() }),
|
|
2008
|
+
z27.object({ type: z27.literal("chat.cancel"), qid: OperationIdSchema }),
|
|
2009
|
+
z27.object({ type: z27.literal("chat.reset") }),
|
|
2010
|
+
z27.object({ type: z27.literal("chat.history") }),
|
|
1939
2011
|
/** An image to store, sent alone before the message that names it; no `id`, and at most `ATTACHMENT_MAX` bytes. */
|
|
1940
|
-
AttachmentPutSchema.pick({ type: true, requestId: true }).extend({ image: ImageUploadSchema.extend({ data:
|
|
2012
|
+
AttachmentPutSchema.pick({ type: true, requestId: true }).extend({ image: ImageUploadSchema.extend({ data: z27.string().min(1).max(b64Max(ATTACHMENT_MAX)) }) }),
|
|
1941
2013
|
AttachmentGetSchema.pick({ type: true, requestId: true, attachment: true, preview: true }),
|
|
1942
|
-
|
|
2014
|
+
z27.object({ type: z27.literal("chat.relay"), op: OperationIdSchema, qid: OperationIdSchema }),
|
|
1943
2015
|
/** Takes the card's queued instruction back out of the queue, as the local `session.relay.cancel`. */
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
2016
|
+
z27.object({ type: z27.literal("chat.relay.cancel"), op: OperationIdSchema, qid: OperationIdSchema }),
|
|
2017
|
+
z27.object({ type: z27.literal("chat.launch"), op: OperationIdSchema, qid: OperationIdSchema, rows: CardRowsSchema.optional(), assertion: AssertionSchema.optional() }),
|
|
2018
|
+
z27.object({ type: z27.literal("chat.close"), op: OperationIdSchema, qid: OperationIdSchema, rows: CardRowsSchema.optional(), assertion: AssertionSchema.optional() }),
|
|
1947
2019
|
/** A row of the turn's task card: given by Ledge. */
|
|
1948
|
-
|
|
2020
|
+
z27.object({ type: z27.literal("chat.task"), op: OperationIdSchema, qid: OperationIdSchema, row: z27.number().int().min(0).max(MAX_PROPOSALS - 1) }),
|
|
1949
2021
|
/** Rows of the turn's generic card (action registry spec §5): `confirmed` as the local `chat.act`; a row whose action asks
|
|
1950
2022
|
* for a device check (`phone`) needs one assertion, purpose `act`, over the turn. */
|
|
1951
|
-
|
|
1952
|
-
type:
|
|
2023
|
+
z27.object({
|
|
2024
|
+
type: z27.literal("chat.act"),
|
|
1953
2025
|
op: OperationIdSchema,
|
|
1954
2026
|
qid: OperationIdSchema,
|
|
1955
2027
|
rows: CardRowsSchema.optional(),
|
|
1956
|
-
confirmed:
|
|
2028
|
+
confirmed: z27.literal(true).optional(),
|
|
1957
2029
|
assertion: AssertionSchema.optional(),
|
|
1958
2030
|
/** « Refuser », as the local `chat.act`: no passkey, no confirmation. */
|
|
1959
|
-
deny:
|
|
2031
|
+
deny: z27.literal(true).optional()
|
|
1960
2032
|
}),
|
|
1961
2033
|
/** « Ignorer » the turn's cards, or `undo` (« Revoir »), as the local `chat.ignore`. */
|
|
1962
|
-
|
|
2034
|
+
z27.object({ type: z27.literal("chat.ignore"), op: OperationIdSchema, qid: OperationIdSchema, undo: z27.literal(true).optional() }),
|
|
1963
2035
|
/** Puts a closed task Ledge gave away from « À traiter ». */
|
|
1964
|
-
|
|
2036
|
+
z27.object({ type: z27.literal("task.seen"), op: OperationIdSchema, task: z27.string().min(1).max(40) }),
|
|
2037
|
+
/** Streams a session's pane, read-only; answered by `term.opened` or `operation.result` (rejected). */
|
|
2038
|
+
z27.object({ type: z27.literal("term.open"), op: OperationIdSchema, id: sessionId }),
|
|
2039
|
+
/** « Prendre la main »: passkey, purpose `terminal`, over the session; answered by `term.held` or `operation.result` (rejected). */
|
|
2040
|
+
z27.object({ type: z27.literal("term.hold"), op: OperationIdSchema, tid: TerminalIdSchema, assertion: AssertionSchema.optional() }),
|
|
2041
|
+
/** Keys to type, as xterm produced them; `n` counts from 0 for the terminal, so a duplicate is dropped and a gap seen. Refused unless held. */
|
|
2042
|
+
z27.object({ type: z27.literal("term.input"), tid: TerminalIdSchema, n: z27.number().int().nonnegative(), data: z27.string().min(1).max(TERM_INPUT_MAX) }),
|
|
2043
|
+
/** « Rendre la main »: back to read-only. */
|
|
2044
|
+
z27.object({ type: z27.literal("term.release"), tid: TerminalIdSchema }),
|
|
2045
|
+
/** The phone saw a gap in `seq`: a fresh `term.opened`, please. */
|
|
2046
|
+
z27.object({ type: z27.literal("term.resync"), tid: TerminalIdSchema }),
|
|
2047
|
+
z27.object({ type: z27.literal("term.close"), tid: TerminalIdSchema }),
|
|
1965
2048
|
/** Whether the phone's app is in front: a device that is visible gets no push. */
|
|
1966
|
-
|
|
2049
|
+
z27.object({ type: z27.literal("presence"), visible: z27.boolean() }),
|
|
1967
2050
|
/** Installs `version` on the PC, then restarts its daemon; the phone asks for its own build's version. Passkey, purpose `pc`. */
|
|
1968
|
-
|
|
2051
|
+
z27.object({ type: z27.literal("daemon.update"), ...pcOp, version: z27.string().regex(SEMVER) }).strict(),
|
|
1969
2052
|
/** Restarts the PC's daemon without installing anything. Passkey, purpose `pc`. */
|
|
1970
|
-
|
|
2053
|
+
z27.object({ type: z27.literal("daemon.restart"), ...pcOp }).strict()
|
|
1971
2054
|
]);
|
|
1972
|
-
var PhoneModelChoiceSchema =
|
|
2055
|
+
var PhoneModelChoiceSchema = z27.object({
|
|
1973
2056
|
id: ModelChoiceSchema.shape.id.max(120),
|
|
1974
|
-
label:
|
|
1975
|
-
description:
|
|
1976
|
-
efforts:
|
|
2057
|
+
label: z27.string().max(80),
|
|
2058
|
+
description: z27.string().max(200).optional(),
|
|
2059
|
+
efforts: z27.array(EffortSchema).max(8).optional(),
|
|
1977
2060
|
defaultEffort: EffortSchema.optional(),
|
|
1978
|
-
isDefault:
|
|
2061
|
+
isDefault: z27.boolean().optional()
|
|
1979
2062
|
}).strict();
|
|
1980
|
-
var
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
2063
|
+
var PHONE_COMMANDS_MAX = 300;
|
|
2064
|
+
var PhoneSlashCommandSchema = SlashCommandSchema.extend({ description: z27.string().max(200).optional() }).strict();
|
|
2065
|
+
var PhoneServerMessageSchema = z27.discriminatedUnion("type", [
|
|
2066
|
+
z27.object({ type: z27.literal("snapshot"), protocol: z27.literal(PHONE_PROTOCOL), sessions: z27.array(PhoneSessionSchema), capabilities: CapabilitiesByToolSchema, daemon: z27.object({
|
|
2067
|
+
version: z27.string(),
|
|
2068
|
+
name: z27.string().max(40),
|
|
2069
|
+
boot: z27.string().uuid().optional(),
|
|
1985
2070
|
/** The daemon takes `session.model`. */
|
|
1986
|
-
models:
|
|
2071
|
+
models: z27.literal(true).optional(),
|
|
1987
2072
|
/** The daemon sends `session.checklist` and a session's `checklist` summary. */
|
|
1988
|
-
checklist:
|
|
2073
|
+
checklist: z27.literal(true).optional(),
|
|
1989
2074
|
/** `update`: the daemon can install a version and restart (npm, systemd); `restart`: it can restart (systemd). */
|
|
1990
|
-
update:
|
|
1991
|
-
restart:
|
|
2075
|
+
update: z27.literal(true).optional(),
|
|
2076
|
+
restart: z27.literal(true).optional(),
|
|
1992
2077
|
/** The daemon takes `session.close` and `session.resume`. */
|
|
1993
|
-
sessionClose:
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
2078
|
+
sessionClose: z27.literal(true).optional(),
|
|
2079
|
+
/** The daemon streams a session's terminal (`term.open`). */
|
|
2080
|
+
terminal: z27.literal(true).optional(),
|
|
2081
|
+
/** The PC lets a phone type into a terminal (`term.hold`): its setting is on. */
|
|
2082
|
+
terminalInput: z27.literal(true).optional(),
|
|
2083
|
+
/** The daemon answers `session.commands`. */
|
|
2084
|
+
commands: z27.literal(true).optional(),
|
|
2085
|
+
/** The daemon takes `session.broadcast` (« Écrire au groupe »). */
|
|
2086
|
+
broadcast: z27.literal(true).optional()
|
|
2087
|
+
}), device: z27.object({ confirm: z27.boolean(), push: z27.enum(["on", "off", "stale", "unavailable"]).optional(), chat: z27.literal(true).optional(), contextNear: ContextPrefsSchema.shape.near.optional() }).optional() }),
|
|
2088
|
+
z27.object({ type: z27.literal("confirm.challenge"), purpose: ConfirmPurposeSchema, challenge: B64U2.max(64), rpId: z27.string().max(253), credentialId: B64U2.max(1366).optional(), expiresInMs: z27.number().int().positive() }),
|
|
2089
|
+
z27.object({ type: z27.literal("session.updated"), session: PhoneSessionSchema }),
|
|
2090
|
+
z27.object({ type: z27.literal("session.removed"), id: z27.string() }),
|
|
1998
2091
|
/** A session's checklist, sent to the phone that watches it; `null`: it has none (any more). */
|
|
1999
|
-
|
|
2092
|
+
z27.object({ type: z27.literal("session.checklist"), id: z27.string(), checklist: PhoneChecklistSchema.nullable() }),
|
|
2000
2093
|
/** `pending.cut` is set when even this body was shortened. */
|
|
2001
|
-
|
|
2002
|
-
|
|
2094
|
+
z27.object({ type: z27.literal("session.pending"), id: z27.string(), pending: PhonePendingSchema }),
|
|
2095
|
+
z27.object({ type: z27.literal("session.preview"), id: z27.string(), lines: z27.array(z27.string()) }),
|
|
2003
2096
|
/** `cut`: the ids of the items shortened; `more`: older items were left out. */
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
type:
|
|
2097
|
+
z27.object({ type: z27.literal("session.thread"), id: z27.string(), items: z27.array(ThreadItemSchema), cut: z27.array(z27.string()), more: z27.boolean() }),
|
|
2098
|
+
z27.object({ type: z27.literal("session.thread.item"), id: z27.string(), item: ThreadItemSchema, cut: z27.literal(true).optional() }),
|
|
2099
|
+
z27.object({
|
|
2100
|
+
type: z27.literal("operation.result"),
|
|
2008
2101
|
op: OperationIdSchema,
|
|
2009
2102
|
status: OperationStatusSchema,
|
|
2010
2103
|
reason: OperationReasonSchema.optional(),
|
|
2011
2104
|
/** How an applied `session.close` ended the agent: `killed` when it had to be forced. */
|
|
2012
|
-
how: CloseHowSchema.optional()
|
|
2105
|
+
how: CloseHowSchema.optional(),
|
|
2106
|
+
/** An applied `session.broadcast`: the names that got it and those that did not. */
|
|
2107
|
+
sent: z27.array(z27.string().max(100)).max(BROADCAST_SESSIONS_MAX).optional(),
|
|
2108
|
+
refused: z27.array(z27.object({ name: z27.string().max(100), reason: z27.string().max(200) })).max(BROADCAST_SESSIONS_MAX).optional()
|
|
2013
2109
|
}),
|
|
2014
2110
|
/** The models an agent offers; `error`: it could not be asked, `models` is then what Ledge knows without it. */
|
|
2015
|
-
|
|
2111
|
+
z27.object({ type: z27.literal("models.listing"), tool: ToolSchema, models: z27.array(PhoneModelChoiceSchema).max(40), error: z27.literal(true).optional() }),
|
|
2016
2112
|
/** A model change that was accepted and then failed (the agent could not restart). */
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2113
|
+
z27.object({ type: z27.literal("session.model.failed"), id: z27.string(), reason: ModelRefusalSchema }),
|
|
2114
|
+
/** A session's slash commands; `error`: they could not be read (the agent is not listed, or did not answer in time): a command typed by hand still goes. */
|
|
2115
|
+
z27.object({ type: z27.literal("session.commands.listing"), id: z27.string(), commands: z27.array(PhoneSlashCommandSchema).max(PHONE_COMMANDS_MAX), error: z27.literal(true).optional() }),
|
|
2116
|
+
z27.object({ type: z27.literal("chat.history"), turns: z27.array(PhoneChatTurnSchema).max(50) }),
|
|
2117
|
+
z27.object({ type: z27.literal("chat.step"), qid: OperationIdSchema, step: PhoneChatStepSchema }),
|
|
2020
2118
|
/** The whole text so far, not an increment. */
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2119
|
+
z27.object({ type: z27.literal("chat.delta"), qid: OperationIdSchema, text: z27.string().max(THREAD_TEXT_MAX) }),
|
|
2120
|
+
z27.object({ type: z27.literal("chat.done"), qid: OperationIdSchema, turn: PhoneChatTurnSchema }),
|
|
2121
|
+
z27.object({ type: z27.literal("chat.error"), qid: OperationIdSchema, code: ChatErrorCodeSchema }),
|
|
2024
2122
|
/** The daemon updating or restarting itself, whoever asked: npm runs, then the service restarts (the link drops right after). */
|
|
2025
|
-
|
|
2123
|
+
z27.object({ type: z27.literal("daemon.progress"), version: z27.string().max(40), step: z27.enum(["installing", "restarting"]) }),
|
|
2026
2124
|
/** Nothing was changed. Never npm's output nor a command: both hold the PC's paths. */
|
|
2027
|
-
|
|
2125
|
+
z27.object({ type: z27.literal("daemon.failed"), version: z27.string().max(40), reason: UpdateFailureSchema }),
|
|
2028
2126
|
/** The tasks Ledge gave, open or closed lately, after each snapshot; then each change. */
|
|
2029
|
-
|
|
2030
|
-
|
|
2127
|
+
z27.object({ type: z27.literal("tasks"), tasks: z27.array(PhoneTaskSchema).max(200) }),
|
|
2128
|
+
z27.object({ type: z27.literal("task.updated"), task: PhoneTaskSchema }),
|
|
2031
2129
|
AttachmentStoredSchema,
|
|
2032
2130
|
AttachmentDataSchema,
|
|
2033
2131
|
AttachmentErrorSchema,
|
|
2132
|
+
/** A terminal's first screen (also the answer to `term.resync`, then without `op`): the pane's size, the cursor, and the `seq` the next output takes. */
|
|
2133
|
+
z27.object({
|
|
2134
|
+
type: z27.literal("term.opened"),
|
|
2135
|
+
op: OperationIdSchema.optional(),
|
|
2136
|
+
tid: TerminalIdSchema,
|
|
2137
|
+
id: z27.string(),
|
|
2138
|
+
cols: TermDimSchema,
|
|
2139
|
+
rows: TermDimSchema,
|
|
2140
|
+
screen: z27.string().max(TERM_SCREEN_MAX),
|
|
2141
|
+
cursor: z27.object({ x: z27.number().int().nonnegative(), y: z27.number().int().nonnegative() }),
|
|
2142
|
+
seq: z27.number().int().nonnegative(),
|
|
2143
|
+
/** Read-only for good: a subagent's page shows its parent's pane. */
|
|
2144
|
+
readOnly: z27.literal(true).optional()
|
|
2145
|
+
}),
|
|
2146
|
+
/** What the pane printed since the last one; `seq` + 1 each time. */
|
|
2147
|
+
z27.object({ type: z27.literal("term.output"), tid: TerminalIdSchema, seq: z27.number().int().nonnegative(), data: z27.string().min(1).max(TERM_OUTPUT_MAX) }),
|
|
2148
|
+
z27.object({ type: z27.literal("term.size"), tid: TerminalIdSchema, cols: TermDimSchema, rows: TermDimSchema }),
|
|
2149
|
+
/** The phone holds the hand until `until`, pushed back by each key (5 min), never past 30 min from the hold. */
|
|
2150
|
+
z27.object({ type: z27.literal("term.held"), tid: TerminalIdSchema, until: z27.string().datetime() }),
|
|
2151
|
+
z27.object({ type: z27.literal("term.released"), tid: TerminalIdSchema, why: TermReleaseWhySchema }),
|
|
2152
|
+
z27.object({ type: z27.literal("term.exit"), tid: TerminalIdSchema, why: TermExitWhySchema }),
|
|
2034
2153
|
/** Never carries free text. */
|
|
2035
|
-
|
|
2154
|
+
z27.object({ type: z27.literal("error"), code: z27.enum(["invalid", "unknown_session", "too_large"]), request: z27.string().max(40).optional() })
|
|
2036
2155
|
]);
|
|
2037
2156
|
|
|
2038
2157
|
// src/imageInfo.ts
|