@paradow/ledge 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/cli/{attach-3U4A44ZE.js → attach-Y4OMZXAH.js} +7 -7
  2. package/dist/cli/{bridge-7JT6P53L.js → bridge-6K523KUX.js} +2 -2
  3. package/dist/cli/{chunk-FPW7MF5X.js → chunk-2H5FJH4Q.js} +2 -2
  4. package/dist/cli/{chunk-5LVPB3ET.js → chunk-2LQITRTR.js} +178 -39
  5. package/dist/cli/{chunk-D3JQV5AA.js → chunk-4IBQ4PG6.js} +6 -6
  6. package/dist/cli/{chunk-5DDBCJX2.js → chunk-BNKPXSUY.js} +1 -1
  7. package/dist/cli/{chunk-UWANRALT.js → chunk-CU2E3W4L.js} +1 -1
  8. package/dist/cli/{chunk-6A7JPTHV.js → chunk-DXVHFVJI.js} +2 -2
  9. package/dist/cli/chunk-EHHYRQWY.js +6 -0
  10. package/dist/cli/{chunk-2P2SUT7A.js → chunk-IMSPQUFC.js} +2 -2
  11. package/dist/cli/{chunk-ULWVO3TH.js → chunk-KGEF6OIU.js} +2 -2
  12. package/dist/cli/{chunk-IIXALRFM.js → chunk-NKYJF3VT.js} +2 -2
  13. package/dist/cli/{chunk-PFDZ6VYG.js → chunk-PXO4FFJR.js} +1 -1
  14. package/dist/cli/{chunk-QBJEUZYW.js → chunk-R5462SQM.js} +1 -1
  15. package/dist/cli/{daemon-KHGAO6BC.js → daemon-NIEJZDEC.js} +1243 -189
  16. package/dist/cli/{hook-R6OWCFAQ.js → hook-BGIM76EW.js} +8 -8
  17. package/dist/cli/index.js +11 -11
  18. package/dist/cli/{launch-PPTQEWYD.js → launch-JS74JGW6.js} +7 -7
  19. package/dist/cli/send-JX6O7AQR.js +14 -0
  20. package/dist/cli/{setup-FPQK3NA7.js → setup-2GROTY6B.js} +4 -4
  21. package/dist/cli/{status-QLTB6T3U.js → status-Q6TQXVLF.js} +3 -3
  22. package/dist/cli/{uninstall-QC5WEWDH.js → uninstall-JCX7QXU2.js} +4 -4
  23. package/dist/cli/{version-AELAEF6T.js → version-X45HSUBB.js} +1 -1
  24. package/dist/cli/who-KAAEASAA.js +11 -0
  25. package/package.json +1 -1
  26. package/dist/cli/chunk-QUUZSAPI.js +0 -6
  27. package/dist/cli/send-74LTIRSN.js +0 -14
  28. package/dist/cli/who-5F6CHRA3.js +0 -11
@@ -1,19 +1,19 @@
1
1
  import {
2
2
  attachEnv
3
- } from "./chunk-D3JQV5AA.js";
3
+ } from "./chunk-4IBQ4PG6.js";
4
4
  import {
5
5
  connect
6
- } from "./chunk-PFDZ6VYG.js";
7
- import "./chunk-ULWVO3TH.js";
6
+ } from "./chunk-PXO4FFJR.js";
7
+ import "./chunk-KGEF6OIU.js";
8
8
  import {
9
9
  PROTOCOL_PORT,
10
10
  backendOf
11
- } from "./chunk-5LVPB3ET.js";
11
+ } from "./chunk-2LQITRTR.js";
12
12
  import {
13
13
  realTmux
14
- } from "./chunk-FPW7MF5X.js";
15
- import "./chunk-5DDBCJX2.js";
16
- import "./chunk-QBJEUZYW.js";
14
+ } from "./chunk-2H5FJH4Q.js";
15
+ import "./chunk-BNKPXSUY.js";
16
+ import "./chunk-R5462SQM.js";
17
17
 
18
18
  // src/cli/attach.ts
19
19
  import { spawn } from "child_process";
@@ -7,8 +7,8 @@ import {
7
7
  parseClientMessage,
8
8
  parseServerMessage,
9
9
  readDaemonToken
10
- } from "./chunk-5LVPB3ET.js";
11
- import "./chunk-QBJEUZYW.js";
10
+ } from "./chunk-2LQITRTR.js";
11
+ import "./chunk-R5462SQM.js";
12
12
 
13
13
  // src/cli/bridge.ts
14
14
  import WebSocket from "ws";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  log
3
- } from "./chunk-5DDBCJX2.js";
3
+ } from "./chunk-BNKPXSUY.js";
4
4
  import {
5
5
  paths
6
- } from "./chunk-QBJEUZYW.js";
6
+ } from "./chunk-R5462SQM.js";
7
7
 
8
8
  // src/tmux.ts
9
9
  import { execFile } from "child_process";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  paths
3
- } from "./chunk-QBJEUZYW.js";
3
+ } from "./chunk-R5462SQM.js";
4
4
 
5
5
  // ../protocol/src/session.ts
6
6
  import { z } from "zod";
@@ -458,7 +458,7 @@ function pendingKey(p) {
458
458
 
459
459
  // ../protocol/src/mobile.ts
460
460
  import { z as z14 } from "zod";
461
- var DEFAULT_RELAY_URL = "https://server.ledge.paradow.dev";
461
+ var DEFAULT_RELAY_URL = "https://app.kl-ledge.dev";
462
462
  var RelayUrlSchema = z14.string().transform((v, ctx) => {
463
463
  const bad = () => {
464
464
  ctx.addIssue({ code: z14.ZodIssueCode.custom, message: "invalid relay URL" });
@@ -973,7 +973,53 @@ var MeResponseSchema = z18.object({
973
973
  });
974
974
 
975
975
  // ../protocol/src/phone.ts
976
+ import { z as z20 } from "zod";
977
+
978
+ // ../protocol/src/push.ts
976
979
  import { z as z19 } from "zod";
980
+ var B64U = z19.string().regex(/^[A-Za-z0-9_-]*$/);
981
+ var PUSH_HOSTS = ["*.push.apple.com", "fcm.googleapis.com", "updates.push.services.mozilla.com", "*.notify.windows.com"];
982
+ function pushEndpointAllowed(url) {
983
+ let u;
984
+ try {
985
+ u = new URL(url);
986
+ } catch {
987
+ return false;
988
+ }
989
+ if (u.protocol !== "https:" || u.port !== "" || u.username !== "" || u.password !== "") return false;
990
+ const host = u.hostname.toLowerCase();
991
+ return PUSH_HOSTS.some((h) => {
992
+ if (!h.startsWith("*.")) return host === h;
993
+ const suffix = h.slice(1);
994
+ return host.length > suffix.length && host.endsWith(suffix);
995
+ });
996
+ }
997
+ var PushSendSchema = z19.object({
998
+ endpoint: z19.string().url().max(1024),
999
+ body: B64U.max(5462),
1000
+ ttl: z19.number().int().min(0).max(86400),
1001
+ urgency: z19.enum(["normal", "high"]),
1002
+ topic: z19.string().regex(/^[A-Za-z0-9_-]{1,32}$/)
1003
+ });
1004
+ var PushSendResultSchema = z19.object({
1005
+ result: z19.enum(["sent", "gone", "failed"]),
1006
+ status: z19.number().int().optional()
1007
+ });
1008
+ var PushSubscriptionSchema = z19.object({
1009
+ endpoint: z19.string().url().max(1024).refine(pushEndpointAllowed),
1010
+ keys: z19.object({ p256dh: B64U.length(87), auth: B64U.length(22) })
1011
+ });
1012
+ var PushPayloadSchema = z19.object({
1013
+ v: z19.literal(1),
1014
+ kind: z19.enum(["request", "question", "finished", "chat"]),
1015
+ title: z19.string().max(80),
1016
+ body: z19.string().max(120),
1017
+ url: z19.string().regex(/^\/#\/[A-Za-z0-9/%._~-]*$/).max(300),
1018
+ badge: z19.number().int().min(0).max(999),
1019
+ tag: z19.string().regex(/^[A-Za-z0-9_-]{1,32}$/)
1020
+ });
1021
+
1022
+ // ../protocol/src/phone.ts
977
1023
  var PHONE_PROTOCOL = 1;
978
1024
  var PAD_TIERS = [1024, 4096, 16384, 65536, 262144, 655360];
979
1025
  var PLAIN_MAX = 655360;
@@ -991,18 +1037,22 @@ var THREAD_TEXT_MAX = 8192;
991
1037
  var TOOL_TEXT_MAX = 2048;
992
1038
  var PENDING_BODY_MAX = 65536;
993
1039
  var SNAPSHOT_BODY_MAX = 2048;
994
- var RiskSchema = z19.enum(["low", "high"]);
995
- var RiskReasonSchema = z19.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"]);
996
- var OperationIdSchema = z19.string().uuid();
997
- var OperationStatusSchema = z19.enum(["received", "applied", "rejected", "failed"]);
998
- var OperationReasonSchema = z19.enum([...RefusalCodeSchema.options, "untypable", "confirm_required", "conflict"]);
999
- var CapabilitiesSchema = z19.object({
1040
+ var RiskSchema = z20.enum(["low", "high"]);
1041
+ var RiskReasonSchema = z20.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"]);
1042
+ var OperationIdSchema = z20.string().uuid();
1043
+ var OperationStatusSchema = z20.enum(["received", "applied", "rejected", "failed"]);
1044
+ var OperationReasonSchema = z20.enum([...RefusalCodeSchema.options, "untypable", "confirm_required", "conflict", "assertion_invalid", "assertion_expired"]);
1045
+ var CapabilitiesSchema = z20.object({
1000
1046
  /** A question can be answered in free text. */
1001
- freeTextAnswer: z19.boolean()
1047
+ freeTextAnswer: z20.boolean(),
1048
+ /** The session's accept/deny can be typed; absent = true. */
1049
+ decide: z20.boolean().optional(),
1050
+ /** OMP's dialog questions can be answered from the phone; absent = false. */
1051
+ questions: z20.boolean().optional()
1002
1052
  });
1003
1053
  var UNTYPABLE = /[\u0000-\u001f\u007f-\u009f\u200b\u200e\u200f\u2028-\u202e\u2066-\u2069\ufeff]/;
1004
- var CapabilitiesByToolSchema = z19.object({ claude: CapabilitiesSchema, codex: CapabilitiesSchema, cursor: CapabilitiesSchema, omp: CapabilitiesSchema });
1005
- var PhonePendingSchema = PendingSchema.extend({ key: z19.string().max(64), risk: RiskSchema, riskReason: RiskReasonSchema, cut: z19.literal(true).optional() });
1054
+ var CapabilitiesByToolSchema = z20.object({ claude: CapabilitiesSchema, codex: CapabilitiesSchema, cursor: CapabilitiesSchema, omp: CapabilitiesSchema });
1055
+ var PhonePendingSchema = PendingSchema.extend({ key: z20.string().max(64), risk: RiskSchema, riskReason: RiskReasonSchema, cut: z20.literal(true).optional() });
1006
1056
  var PhoneSessionSchema = SessionSchema.pick({
1007
1057
  id: true,
1008
1058
  name: true,
@@ -1018,49 +1068,133 @@ var PhoneSessionSchema = SessionSchema.pick({
1018
1068
  lastReply: true,
1019
1069
  startedAt: true,
1020
1070
  lastActivityAt: true
1021
- }).extend({ pending: PhonePendingSchema.optional(), unread: z19.boolean() });
1022
- var sessionId = z19.string().min(1).max(100);
1023
- var PhoneExpectSchema = PendingSchema.pick({ kind: true, text: true }).extend({ key: z19.string().min(1).max(64) });
1024
- var PhoneClientMessageSchema = z19.discriminatedUnion("type", [
1025
- z19.object({ type: z19.literal("snapshot.request") }),
1026
- z19.object({ type: z19.literal("session.thread"), id: sessionId }),
1071
+ }).extend({ pending: PhonePendingSchema.optional(), unread: z20.boolean() });
1072
+ var B64U2 = z20.string().regex(/^[A-Za-z0-9_-]*$/);
1073
+ var CredentialSchema = z20.object({
1074
+ id: B64U2.max(1366),
1075
+ publicKey: B64U2.max(2048),
1076
+ alg: z20.union([z20.literal(-7), z20.literal(-257)]),
1077
+ clientDataJSON: B64U2.max(4096),
1078
+ authenticatorData: B64U2.max(4096),
1079
+ transports: z20.array(z20.string().max(20)).max(8).optional()
1080
+ });
1081
+ var AssertionSchema = z20.object({
1082
+ id: B64U2.max(1366),
1083
+ clientDataJSON: B64U2.max(4096),
1084
+ authenticatorData: B64U2.max(4096),
1085
+ signature: B64U2.max(1024)
1086
+ });
1087
+ var ConfirmPurposeSchema = z20.enum(["register", "decide", "launch"]);
1088
+ var PhoneChatStepSchema = ChatStepSchema.pick({ kind: true, id: true, name: true }).strict();
1089
+ var PhoneChatProposalSchema = z20.object({
1090
+ project: z20.string().max(80),
1091
+ tool: ToolSchema,
1092
+ prompt: z20.string().max(TOOL_TEXT_MAX).optional(),
1093
+ launchedId: z20.string().optional(),
1094
+ failed: z20.literal(true).optional()
1095
+ }).strict();
1096
+ var PhoneChatRelaySchema = z20.object({
1097
+ id: z20.string().min(1),
1098
+ name: z20.string(),
1099
+ tool: ToolSchema,
1100
+ text: z20.string().max(TOOL_TEXT_MAX),
1101
+ status: z20.enum(["queued", "sent"]).optional(),
1102
+ sentAt: z20.string().datetime().optional(),
1103
+ failed: z20.literal(true).optional()
1104
+ }).strict();
1105
+ var ChatErrorCodeSchema = z20.enum(["busy", "timeout", "cancelled", "failed"]);
1106
+ var PhoneChatTurnSchema = z20.object({
1107
+ qid: OperationIdSchema,
1108
+ question: z20.string().max(MESSAGE_MAX),
1109
+ askedAt: z20.string().datetime(),
1110
+ steps: z20.array(PhoneChatStepSchema).max(50),
1111
+ answer: z20.string().max(THREAD_TEXT_MAX).optional(),
1112
+ answeredAt: z20.string().datetime().optional(),
1113
+ error: ChatErrorCodeSchema.optional(),
1114
+ proposals: z20.array(PhoneChatProposalSchema).max(MAX_PROPOSALS).optional(),
1115
+ relay: PhoneChatRelaySchema.optional(),
1116
+ cut: z20.literal(true).optional()
1117
+ }).strict();
1118
+ var CHAT_HISTORY_BUDGET = 393216;
1119
+ var sessionId = z20.string().min(1).max(100);
1120
+ var PhoneExpectSchema = PendingSchema.pick({ kind: true, text: true }).extend({ key: z20.string().min(1).max(64) });
1121
+ var PhoneClientMessageSchema = z20.discriminatedUnion("type", [
1122
+ z20.object({ type: z20.literal("snapshot.request") }),
1123
+ z20.object({ type: z20.literal("session.thread"), id: sessionId }),
1027
1124
  /** The session's request with its whole body (up to `PENDING_BODY_MAX`). */
1028
- z19.object({ type: z19.literal("session.pending"), id: sessionId }),
1125
+ z20.object({ type: z20.literal("session.pending"), id: sessionId }),
1029
1126
  /** The session whose terminal the phone shows; null when it shows none. */
1030
- z19.object({ type: z19.literal("session.watch"), id: sessionId.nullable() }),
1031
- z19.object({ type: z19.literal("session.read"), id: sessionId, at: z19.string().datetime() }),
1032
- z19.object({
1033
- type: z19.literal("session.decide"),
1127
+ z20.object({ type: z20.literal("session.watch"), id: sessionId.nullable() }),
1128
+ z20.object({ type: z20.literal("session.read"), id: sessionId, at: z20.string().datetime() }),
1129
+ /** Asks for a challenge. One object for both purposes: the gateway refuses a `decide` without `id` and `expect`. */
1130
+ z20.object({ type: z20.literal("confirm.prepare"), purpose: ConfirmPurposeSchema, id: sessionId.optional(), expect: PhoneExpectSchema.optional(), qid: OperationIdSchema.optional() }),
1131
+ z20.object({ type: z20.literal("credential.register"), op: OperationIdSchema, credential: CredentialSchema }),
1132
+ z20.object({
1133
+ type: z20.literal("session.decide"),
1034
1134
  op: OperationIdSchema,
1035
1135
  id: sessionId,
1036
1136
  decision: DecisionSchema,
1037
- note: z19.string().trim().min(1).max(NOTE_MAX).optional(),
1137
+ note: z20.string().trim().min(1).max(NOTE_MAX).optional(),
1038
1138
  /** The request the phone showed: refused unless it is still the pending one. */
1039
- expect: PhoneExpectSchema
1139
+ expect: PhoneExpectSchema,
1140
+ /** The device check over the challenge of `confirm.prepare`; required by the daemon for a high-risk accept. */
1141
+ assertion: AssertionSchema.optional()
1040
1142
  }),
1041
- z19.object({
1042
- type: z19.literal("session.reply"),
1143
+ z20.object({
1144
+ type: z20.literal("session.reply"),
1043
1145
  op: OperationIdSchema,
1044
1146
  id: sessionId,
1045
- text: z19.string().min(1).max(MESSAGE_MAX),
1147
+ text: z20.string().min(1).max(MESSAGE_MAX),
1046
1148
  /** The request the reply answers, or null when the phone showed none: refused if the session's request is no longer that one. */
1047
- expect: PhoneExpectSchema.nullable()
1149
+ expect: PhoneExpectSchema.nullable(),
1150
+ assertion: AssertionSchema.optional()
1151
+ }),
1152
+ /** OMP's `ask`: the answers to every question of the dialog `requestId`, in order; `cancel` declines it. Bounds as the local `session.answer`. */
1153
+ z20.object({
1154
+ type: z20.literal("session.answer"),
1155
+ op: OperationIdSchema,
1156
+ id: sessionId,
1157
+ requestId: z20.string().min(1).max(200),
1158
+ answers: z20.array(z20.object({ id: z20.string().max(200), selected: z20.array(z20.string().max(2e3)).max(100), text: z20.string().max(2e4).optional() })).max(50),
1159
+ cancel: z20.literal(true).optional(),
1160
+ expect: PhoneExpectSchema
1048
1161
  }),
1049
- z19.object({ type: z19.literal("session.interrupt"), op: OperationIdSchema, id: sessionId })
1162
+ z20.object({ type: z20.literal("session.interrupt"), op: OperationIdSchema, id: sessionId }),
1163
+ /** The phone drops its passkey from the daemon. */
1164
+ z20.object({ type: z20.literal("device.forget"), op: OperationIdSchema }),
1165
+ /** The phone's push subscription, with the VAPID key it was made with (so a key change is seen). */
1166
+ z20.object({ type: z20.literal("push.subscribe"), op: OperationIdSchema, subscription: PushSubscriptionSchema, key: B64U2.length(87) }),
1167
+ z20.object({ type: z20.literal("push.unsubscribe"), op: OperationIdSchema }),
1168
+ /** The phone's own chat with Ledge. */
1169
+ z20.object({ type: z20.literal("chat.ask"), qid: OperationIdSchema, text: z20.string().trim().min(1).max(MESSAGE_MAX) }),
1170
+ z20.object({ type: z20.literal("chat.cancel"), qid: OperationIdSchema }),
1171
+ z20.object({ type: z20.literal("chat.reset") }),
1172
+ z20.object({ type: z20.literal("chat.history") }),
1173
+ z20.object({ type: z20.literal("chat.relay"), op: OperationIdSchema, qid: OperationIdSchema }),
1174
+ z20.object({ type: z20.literal("chat.launch"), op: OperationIdSchema, qid: OperationIdSchema, rows: z20.array(z20.number().int().min(0).max(MAX_PROPOSALS - 1)).min(1).max(MAX_PROPOSALS).refine((r) => new Set(r).size === r.length, "a row twice").optional(), assertion: AssertionSchema.optional() }),
1175
+ /** Whether the phone's app is in front: a device that is visible gets no push. */
1176
+ z20.object({ type: z20.literal("presence"), visible: z20.boolean() })
1050
1177
  ]);
1051
- var PhoneServerMessageSchema = z19.discriminatedUnion("type", [
1052
- z19.object({ type: z19.literal("snapshot"), protocol: z19.literal(PHONE_PROTOCOL), sessions: z19.array(PhoneSessionSchema), capabilities: CapabilitiesByToolSchema, daemon: z19.object({ version: z19.string(), name: z19.string().max(40) }) }),
1053
- z19.object({ type: z19.literal("session.updated"), session: PhoneSessionSchema }),
1054
- z19.object({ type: z19.literal("session.removed"), id: z19.string() }),
1178
+ var PhoneServerMessageSchema = z20.discriminatedUnion("type", [
1179
+ z20.object({ type: z20.literal("snapshot"), protocol: z20.literal(PHONE_PROTOCOL), sessions: z20.array(PhoneSessionSchema), capabilities: CapabilitiesByToolSchema, daemon: z20.object({ version: z20.string(), name: z20.string().max(40), boot: z20.string().uuid().optional() }), device: z20.object({ confirm: z20.boolean(), push: z20.enum(["on", "off", "stale", "unavailable"]).optional(), chat: z20.literal(true).optional() }).optional() }),
1180
+ z20.object({ type: z20.literal("confirm.challenge"), purpose: ConfirmPurposeSchema, challenge: B64U2.max(64), rpId: z20.string().max(253), credentialId: B64U2.max(1366).optional(), expiresInMs: z20.number().int().positive() }),
1181
+ z20.object({ type: z20.literal("session.updated"), session: PhoneSessionSchema }),
1182
+ z20.object({ type: z20.literal("session.removed"), id: z20.string() }),
1055
1183
  /** `pending.cut` is set when even this body was shortened. */
1056
- z19.object({ type: z19.literal("session.pending"), id: z19.string(), pending: PhonePendingSchema }),
1057
- z19.object({ type: z19.literal("session.preview"), id: z19.string(), lines: z19.array(z19.string()) }),
1184
+ z20.object({ type: z20.literal("session.pending"), id: z20.string(), pending: PhonePendingSchema }),
1185
+ z20.object({ type: z20.literal("session.preview"), id: z20.string(), lines: z20.array(z20.string()) }),
1058
1186
  /** `cut`: the ids of the items shortened; `more`: older items were left out. */
1059
- z19.object({ type: z19.literal("session.thread"), id: z19.string(), items: z19.array(ThreadItemSchema), cut: z19.array(z19.string()), more: z19.boolean() }),
1060
- z19.object({ type: z19.literal("session.thread.item"), id: z19.string(), item: ThreadItemSchema, cut: z19.literal(true).optional() }),
1061
- z19.object({ type: z19.literal("operation.result"), op: OperationIdSchema, status: OperationStatusSchema, reason: OperationReasonSchema.optional() }),
1187
+ z20.object({ type: z20.literal("session.thread"), id: z20.string(), items: z20.array(ThreadItemSchema), cut: z20.array(z20.string()), more: z20.boolean() }),
1188
+ z20.object({ type: z20.literal("session.thread.item"), id: z20.string(), item: ThreadItemSchema, cut: z20.literal(true).optional() }),
1189
+ z20.object({ type: z20.literal("operation.result"), op: OperationIdSchema, status: OperationStatusSchema, reason: OperationReasonSchema.optional() }),
1190
+ z20.object({ type: z20.literal("chat.history"), turns: z20.array(PhoneChatTurnSchema).max(50) }),
1191
+ z20.object({ type: z20.literal("chat.step"), qid: OperationIdSchema, step: PhoneChatStepSchema }),
1192
+ /** The whole text so far, not an increment. */
1193
+ z20.object({ type: z20.literal("chat.delta"), qid: OperationIdSchema, text: z20.string().max(THREAD_TEXT_MAX) }),
1194
+ z20.object({ type: z20.literal("chat.done"), qid: OperationIdSchema, turn: PhoneChatTurnSchema }),
1195
+ z20.object({ type: z20.literal("chat.error"), qid: OperationIdSchema, code: ChatErrorCodeSchema }),
1062
1196
  /** Never carries free text. */
1063
- z19.object({ type: z19.literal("error"), code: z19.enum(["invalid", "unknown_session", "too_large"]), request: z19.string().max(40).optional() })
1197
+ z20.object({ type: z20.literal("error"), code: z20.enum(["invalid", "unknown_session", "too_large"]), request: z20.string().max(40).optional() })
1064
1198
  ]);
1065
1199
 
1066
1200
  // src/auth.ts
@@ -1225,6 +1359,9 @@ export {
1225
1359
  RELAY_CLOSE_SIGNED_OUT,
1226
1360
  DeviceStartResponseSchema,
1227
1361
  DevicePollResponseSchema,
1362
+ pushEndpointAllowed,
1363
+ PushSendResultSchema,
1364
+ PushPayloadSchema,
1228
1365
  PHONE_PROTOCOL,
1229
1366
  padPlain,
1230
1367
  THREAD_ITEMS_MAX,
@@ -1233,7 +1370,9 @@ export {
1233
1370
  TOOL_TEXT_MAX,
1234
1371
  PENDING_BODY_MAX,
1235
1372
  SNAPSHOT_BODY_MAX,
1373
+ OperationIdSchema,
1236
1374
  UNTYPABLE,
1375
+ CHAT_HISTORY_BUDGET,
1237
1376
  PhoneClientMessageSchema,
1238
1377
  hostAllowed,
1239
1378
  requestAuthorized,
@@ -1,23 +1,23 @@
1
1
  import {
2
2
  DaemonRefusedError,
3
3
  connect
4
- } from "./chunk-PFDZ6VYG.js";
4
+ } from "./chunk-PXO4FFJR.js";
5
5
  import {
6
6
  exitFile,
7
7
  spawnSession
8
- } from "./chunk-ULWVO3TH.js";
8
+ } from "./chunk-KGEF6OIU.js";
9
9
  import {
10
10
  PROTOCOL_PORT
11
- } from "./chunk-5LVPB3ET.js";
11
+ } from "./chunk-2LQITRTR.js";
12
12
  import {
13
13
  realTmux
14
- } from "./chunk-FPW7MF5X.js";
14
+ } from "./chunk-2H5FJH4Q.js";
15
15
  import {
16
16
  log
17
- } from "./chunk-5DDBCJX2.js";
17
+ } from "./chunk-BNKPXSUY.js";
18
18
  import {
19
19
  ensureLedgeDir
20
- } from "./chunk-QBJEUZYW.js";
20
+ } from "./chunk-R5462SQM.js";
21
21
 
22
22
  // src/cli/launch.ts
23
23
  import { spawn } from "child_process";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  paths
3
- } from "./chunk-QBJEUZYW.js";
3
+ } from "./chunk-R5462SQM.js";
4
4
 
5
5
  // src/log.ts
6
6
  import { appendFileSync } from "fs";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  cleanTopic,
3
3
  sessionTitle
4
- } from "./chunk-5LVPB3ET.js";
4
+ } from "./chunk-2LQITRTR.js";
5
5
 
6
6
  // src/daemon/crossSession.ts
7
7
  var FIRST_LINE = /^Another Claude session sent a message:\s*\n/;
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  run
3
- } from "./chunk-FPW7MF5X.js";
3
+ } from "./chunk-2H5FJH4Q.js";
4
4
  import {
5
5
  ensureLedgeDir,
6
6
  paths
7
- } from "./chunk-QBJEUZYW.js";
7
+ } from "./chunk-R5462SQM.js";
8
8
 
9
9
  // src/cli/setup.ts
10
10
  import { readFile as readFile2, writeFile, mkdir, rename, realpath, rm, stat, lstat, readlink, symlink, unlink } from "fs/promises";
@@ -0,0 +1,6 @@
1
+ // src/version.ts
2
+ var LEDGE_VERSION = true ? "0.15.0" : "0.0.0-dev";
3
+
4
+ export {
5
+ LEDGE_VERSION
6
+ };
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  connect,
3
3
  sendMessageAndAwaitAck
4
- } from "./chunk-PFDZ6VYG.js";
4
+ } from "./chunk-PXO4FFJR.js";
5
5
  import {
6
6
  CODEX_HOOK_VAR
7
- } from "./chunk-ULWVO3TH.js";
7
+ } from "./chunk-KGEF6OIU.js";
8
8
 
9
9
  // src/cli/send.ts
10
10
  import { randomUUID } from "crypto";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  pickName
3
- } from "./chunk-5LVPB3ET.js";
3
+ } from "./chunk-2LQITRTR.js";
4
4
  import {
5
5
  paths
6
- } from "./chunk-QBJEUZYW.js";
6
+ } from "./chunk-R5462SQM.js";
7
7
 
8
8
  // src/daemon/transcript.ts
9
9
  import { closeSync, fstatSync, openSync, readSync } from "fs";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  connect
3
- } from "./chunk-PFDZ6VYG.js";
3
+ } from "./chunk-PXO4FFJR.js";
4
4
  import {
5
5
  isArchived
6
- } from "./chunk-5LVPB3ET.js";
6
+ } from "./chunk-2LQITRTR.js";
7
7
 
8
8
  // src/cli/who.ts
9
9
  import { basename } from "path";
@@ -4,7 +4,7 @@ import {
4
4
  SUMMARY_MAX,
5
5
  parseServerMessage,
6
6
  readDaemonToken
7
- } from "./chunk-5LVPB3ET.js";
7
+ } from "./chunk-2LQITRTR.js";
8
8
 
9
9
  // src/client.ts
10
10
  import WebSocket from "ws";
@@ -17,7 +17,7 @@ function ledgeDir() {
17
17
  }
18
18
  function paths() {
19
19
  const dir = ledgeDir();
20
- return { dir, tmuxConf: join(dir, "tmux.conf"), journal: join(dir, "sessions.json"), log: join(dir, "daemon.log"), pid: join(dir, "daemon.pid"), history: join(dir, "history"), machines: join(dir, "machines.json"), projects: join(dir, "projects.json"), island: join(dir, "island.json"), token: join(dir, "token"), mobile: join(dir, "mobile.json"), mobileSession: join(dir, "mobile-session.json"), mobileKey: join(dir, "mobile-key"), devices: join(dir, "devices.json") };
20
+ return { dir, tmuxConf: join(dir, "tmux.conf"), journal: join(dir, "sessions.json"), log: join(dir, "daemon.log"), pid: join(dir, "daemon.pid"), history: join(dir, "history"), machines: join(dir, "machines.json"), projects: join(dir, "projects.json"), island: join(dir, "island.json"), token: join(dir, "token"), mobile: join(dir, "mobile.json"), mobileSession: join(dir, "mobile-session.json"), mobileKey: join(dir, "mobile-key"), devices: join(dir, "devices.json"), revocations: join(dir, "revocations.json") };
21
21
  }
22
22
  async function ensureLedgeDir() {
23
23
  const p = paths();