@yefengr/remote-pi 0.7.4 → 0.7.6

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 (165) hide show
  1. package/README.md +81 -586
  2. package/dist/bin/supervisord.js +4 -5
  3. package/dist/bin/supervisord.js.map +1 -1
  4. package/dist/config.d.ts +1 -1
  5. package/dist/config.js +2 -2
  6. package/dist/daemon/cli-links.d.ts +30 -0
  7. package/dist/daemon/cli-links.js +134 -0
  8. package/dist/daemon/cli-links.js.map +1 -0
  9. package/dist/daemon/commands.d.ts +27 -0
  10. package/dist/daemon/commands.js +295 -0
  11. package/dist/daemon/commands.js.map +1 -0
  12. package/dist/daemon/control_protocol.d.ts +53 -31
  13. package/dist/daemon/control_protocol.js +8 -31
  14. package/dist/daemon/control_protocol.js.map +1 -1
  15. package/dist/daemon/cron_log.d.ts +2 -23
  16. package/dist/daemon/cron_log.js +10 -25
  17. package/dist/daemon/cron_log.js.map +1 -1
  18. package/dist/daemon/cron_registry.d.ts +3 -40
  19. package/dist/daemon/cron_registry.js +58 -103
  20. package/dist/daemon/cron_registry.js.map +1 -1
  21. package/dist/daemon/install-runtime.d.ts +10 -0
  22. package/dist/daemon/install-runtime.js +81 -0
  23. package/dist/daemon/install-runtime.js.map +1 -0
  24. package/dist/daemon/install.d.ts +3 -63
  25. package/dist/daemon/install.js +5 -289
  26. package/dist/daemon/install.js.map +1 -1
  27. package/dist/daemon/preflight.d.ts +51 -0
  28. package/dist/daemon/preflight.js +136 -0
  29. package/dist/daemon/preflight.js.map +1 -0
  30. package/dist/daemon/registry.d.ts +33 -45
  31. package/dist/daemon/registry.js +171 -117
  32. package/dist/daemon/registry.js.map +1 -1
  33. package/dist/daemon/rpc_child.d.ts +92 -146
  34. package/dist/daemon/rpc_child.js +336 -263
  35. package/dist/daemon/rpc_child.js.map +1 -1
  36. package/dist/daemon/status.d.ts +45 -0
  37. package/dist/daemon/status.js +87 -0
  38. package/dist/daemon/status.js.map +1 -0
  39. package/dist/daemon/supervisor-ipc.d.ts +2 -0
  40. package/dist/daemon/supervisor-ipc.js +20 -0
  41. package/dist/daemon/supervisor-ipc.js.map +1 -0
  42. package/dist/daemon/supervisor.d.ts +48 -71
  43. package/dist/daemon/supervisor.js +430 -420
  44. package/dist/daemon/supervisor.js.map +1 -1
  45. package/dist/extension_ui_bridge.d.ts +4 -3
  46. package/dist/extension_ui_bridge.js +10 -0
  47. package/dist/extension_ui_bridge.js.map +1 -1
  48. package/dist/index.d.ts +25 -230
  49. package/dist/index.js +515 -5553
  50. package/dist/index.js.map +1 -1
  51. package/dist/pairing/crypto.d.ts +8 -1
  52. package/dist/pairing/crypto.js +56 -6
  53. package/dist/pairing/crypto.js.map +1 -1
  54. package/dist/pairing/owner_storage.d.ts +42 -0
  55. package/dist/pairing/owner_storage.js +207 -0
  56. package/dist/pairing/owner_storage.js.map +1 -0
  57. package/dist/pairing/qr.d.ts +3 -42
  58. package/dist/pairing/qr.js +9 -59
  59. package/dist/pairing/qr.js.map +1 -1
  60. package/dist/pairing/storage.d.ts +3 -45
  61. package/dist/pairing/storage.js +10 -223
  62. package/dist/pairing/storage.js.map +1 -1
  63. package/dist/protocol/types.d.ts +1 -1
  64. package/dist/protocol/v2/schemas.d.ts +1 -1
  65. package/dist/protocol/v2/schemas.js +1 -1
  66. package/dist/protocol/v2/schemas.js.map +1 -1
  67. package/dist/runtime/owner_router.d.ts +16 -0
  68. package/dist/runtime/owner_router.js +37 -0
  69. package/dist/runtime/owner_router.js.map +1 -0
  70. package/dist/session/ipc.d.ts +1 -22
  71. package/dist/session/ipc.js +4 -11
  72. package/dist/session/ipc.js.map +1 -1
  73. package/dist/session/local_config.d.ts +4 -47
  74. package/dist/session/local_config.js +19 -101
  75. package/dist/session/local_config.js.map +1 -1
  76. package/dist/transport/peer_channel.d.ts +25 -39
  77. package/dist/transport/peer_channel.js +74 -131
  78. package/dist/transport/peer_channel.js.map +1 -1
  79. package/dist/transport/relay_client.d.ts +26 -70
  80. package/dist/transport/relay_client.js +37 -106
  81. package/dist/transport/relay_client.js.map +1 -1
  82. package/docs/daemon.md +91 -207
  83. package/package.json +21 -17
  84. package/dist/daemon/id.d.ts +0 -24
  85. package/dist/daemon/id.js +0 -36
  86. package/dist/daemon/id.js.map +0 -1
  87. package/dist/mcp/mesh_result.d.ts +0 -10
  88. package/dist/mcp/mesh_result.js +0 -42
  89. package/dist/mcp/mesh_result.js.map +0 -1
  90. package/dist/mcp/mesh_server.d.ts +0 -16
  91. package/dist/mcp/mesh_server.js +0 -327
  92. package/dist/mcp/mesh_server.js.map +0 -1
  93. package/dist/mesh/canonical.d.ts +0 -30
  94. package/dist/mesh/canonical.js +0 -61
  95. package/dist/mesh/canonical.js.map +0 -1
  96. package/dist/mesh/client.d.ts +0 -18
  97. package/dist/mesh/client.js +0 -125
  98. package/dist/mesh/client.js.map +0 -1
  99. package/dist/mesh/encoding.d.ts +0 -38
  100. package/dist/mesh/encoding.js +0 -216
  101. package/dist/mesh/encoding.js.map +0 -1
  102. package/dist/mesh/self_revoke.d.ts +0 -73
  103. package/dist/mesh/self_revoke.js +0 -401
  104. package/dist/mesh/self_revoke.js.map +0 -1
  105. package/dist/mesh/siblings.d.ts +0 -49
  106. package/dist/mesh/siblings.js +0 -159
  107. package/dist/mesh/siblings.js.map +0 -1
  108. package/dist/mesh/types.d.ts +0 -34
  109. package/dist/mesh/types.js +0 -11
  110. package/dist/mesh/types.js.map +0 -1
  111. package/dist/mesh/verify.d.ts +0 -17
  112. package/dist/mesh/verify.js +0 -86
  113. package/dist/mesh/verify.js.map +0 -1
  114. package/dist/rooms.d.ts +0 -29
  115. package/dist/rooms.js +0 -57
  116. package/dist/rooms.js.map +0 -1
  117. package/dist/session/bridge.d.ts +0 -37
  118. package/dist/session/bridge.js +0 -130
  119. package/dist/session/bridge.js.map +0 -1
  120. package/dist/session/broker.d.ts +0 -189
  121. package/dist/session/broker.js +0 -507
  122. package/dist/session/broker.js.map +0 -1
  123. package/dist/session/broker_remote.d.ts +0 -74
  124. package/dist/session/broker_remote.js +0 -583
  125. package/dist/session/broker_remote.js.map +0 -1
  126. package/dist/session/cwd_lock.d.ts +0 -33
  127. package/dist/session/cwd_lock.js +0 -126
  128. package/dist/session/cwd_lock.js.map +0 -1
  129. package/dist/session/envelope.d.ts +0 -33
  130. package/dist/session/envelope.js +0 -117
  131. package/dist/session/envelope.js.map +0 -1
  132. package/dist/session/global_config.d.ts +0 -33
  133. package/dist/session/global_config.js +0 -73
  134. package/dist/session/global_config.js.map +0 -1
  135. package/dist/session/leader_election.d.ts +0 -32
  136. package/dist/session/leader_election.js +0 -106
  137. package/dist/session/leader_election.js.map +0 -1
  138. package/dist/session/mesh_node.d.ts +0 -116
  139. package/dist/session/mesh_node.js +0 -573
  140. package/dist/session/mesh_node.js.map +0 -1
  141. package/dist/session/peer.d.ts +0 -139
  142. package/dist/session/peer.js +0 -451
  143. package/dist/session/peer.js.map +0 -1
  144. package/dist/session/peer_inventory.d.ts +0 -13
  145. package/dist/session/peer_inventory.js +0 -48
  146. package/dist/session/peer_inventory.js.map +0 -1
  147. package/dist/session/peer_limits.d.ts +0 -9
  148. package/dist/session/peer_limits.js +0 -21
  149. package/dist/session/peer_limits.js.map +0 -1
  150. package/dist/session/setup_wizard.d.ts +0 -39
  151. package/dist/session/setup_wizard.js +0 -63
  152. package/dist/session/setup_wizard.js.map +0 -1
  153. package/dist/session/tools.d.ts +0 -24
  154. package/dist/session/tools.js +0 -252
  155. package/dist/session/tools.js.map +0 -1
  156. package/dist/session/wizard.d.ts +0 -13
  157. package/dist/session/wizard.js +0 -20
  158. package/dist/session/wizard.js.map +0 -1
  159. package/dist/transport/pi_forward_client.d.ts +0 -29
  160. package/dist/transport/pi_forward_client.js +0 -62
  161. package/dist/transport/pi_forward_client.js.map +0 -1
  162. package/dist/ui/footer.d.ts +0 -32
  163. package/dist/ui/footer.js +0 -34
  164. package/dist/ui/footer.js.map +0 -1
  165. package/skills/agent-network/SKILL.md +0 -310
@@ -1,30 +1,50 @@
1
- /**
2
- * CLI ↔ supervisor IPC contract for `~/.pi/remote/supervisor.sock`.
3
- *
4
- * Framing: one JSON object per line, newline-terminated. The CLI sends a
5
- * single `ControlRequest`, the supervisor sends a single `ControlReply`,
6
- * both close the connection. No multiplexing, no streaming — each command
7
- * is a short round-trip.
8
- *
9
- * Plan/26 W2. The Pi RPC protocol (`pi --mode rpc`) used by the daemon
10
- * children themselves is a separate contract — see
11
- * `node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts`.
12
- * This file is strictly the supervisor's own control plane.
13
- */
14
1
  import type { CronJob } from "./cron_registry.js";
15
2
  import type { CronLogEntry } from "./cron_log.js";
16
- /** Per-daemon runtime state observable through the supervisor. */
17
- export type DaemonState = "running" | "stopped" | "starting" | "crashed";
3
+ /** Legacy CLI summary; new callers should use the orthogonal fields on DaemonInfo. */
4
+ export type DaemonState = "stopped" | "starting" | "running" | "crashed" | "blocked";
5
+ export type RegistrationState = "registered" | "missing";
6
+ export type DesiredState = "running" | "stopped";
7
+ export type ProcessState = "absent" | "spawning" | "running" | "exited";
8
+ export type RuntimeState = "pending" | "ready" | "failed";
9
+ export type RelayState = "disconnected" | "connecting" | "connected" | "reconnecting";
10
+ export type HealthState = "stopped" | "starting" | "healthy" | "degraded" | "failed" | "blocked";
11
+ /**
12
+ * Status output keeps registration, desired lifecycle, OS process, RPC runtime,
13
+ * relay connectivity and derived health separate. `id` / `state` are retained
14
+ * only for the current CLI consumers while they are migrated.
15
+ */
18
16
  export interface DaemonInfo {
17
+ daemon_id: string;
18
+ /** Compatibility alias for daemon_id. */
19
19
  id: string;
20
+ endpoint_id: string;
21
+ runtime_instance_id?: string;
22
+ registration: RegistrationState;
23
+ desired: DesiredState;
24
+ process: ProcessState;
25
+ runtime: RuntimeState;
26
+ relay: RelayState;
27
+ health: HealthState;
28
+ /** Compatibility summary; never use it to infer health. */
29
+ state: DaemonState;
20
30
  cwd: string;
21
31
  name: string;
22
- state: DaemonState;
32
+ kind: "daemon";
23
33
  pid?: number;
34
+ started_at?: number;
35
+ uptime?: number;
36
+ /** Compatibility alias for uptime (seconds). */
24
37
  uptime_s?: number;
25
- restart_count?: number;
38
+ restart_count: number;
39
+ startup_stage: string;
40
+ last_error_code?: string;
41
+ last_error_message?: string;
42
+ last_error_at?: number;
43
+ retrying: boolean;
44
+ next_retry_at?: number;
45
+ /** Compatibility alias for relay. */
46
+ relay_state: RelayState;
26
47
  }
27
- /** Requests sent CLI → supervisor. */
28
48
  export type ControlRequest = {
29
49
  op: "list";
30
50
  } | {
@@ -54,6 +74,9 @@ export type ControlRequest = {
54
74
  } | {
55
75
  op: "unregister";
56
76
  id: string;
77
+ } | {
78
+ op: "unregister_cwd";
79
+ cwd: string;
57
80
  } | {
58
81
  op: "cron_add";
59
82
  daemon_id: string;
@@ -61,7 +84,6 @@ export type ControlRequest = {
61
84
  prompt: string;
62
85
  tz?: string;
63
86
  skip_if_busy?: boolean;
64
- wake?: boolean;
65
87
  catchup?: boolean;
66
88
  } | {
67
89
  op: "cron_list";
@@ -80,7 +102,6 @@ export type ControlRequest = {
80
102
  job_id?: string;
81
103
  tail?: number;
82
104
  };
83
- /** Replies sent supervisor → CLI. Tagged by `ok` boolean. */
84
105
  export type ControlReply<T = unknown> = {
85
106
  ok: true;
86
107
  data?: T;
@@ -88,10 +109,6 @@ export type ControlReply<T = unknown> = {
88
109
  ok: false;
89
110
  error: string;
90
111
  };
91
- /**
92
- * Response shapes per op. Keep in sync with the supervisor handlers in
93
- * `daemon/supervisor.ts`. Used for typed client calls.
94
- */
95
112
  export interface ControlReplyShapes {
96
113
  list: {
97
114
  daemons: DaemonInfo[];
@@ -107,6 +124,7 @@ export interface ControlReplyShapes {
107
124
  id: string;
108
125
  state: DaemonState;
109
126
  started: boolean;
127
+ desired_state: DesiredState;
110
128
  };
111
129
  stop_all: {
112
130
  stopped: string[];
@@ -116,6 +134,7 @@ export interface ControlReplyShapes {
116
134
  id: string;
117
135
  state: DaemonState;
118
136
  stopped: boolean;
137
+ desired_state: DesiredState;
119
138
  };
120
139
  restart_all: {
121
140
  restarted: string[];
@@ -124,19 +143,29 @@ export interface ControlReplyShapes {
124
143
  id: string;
125
144
  state: DaemonState;
126
145
  restarted: boolean;
146
+ desired_state: DesiredState;
127
147
  };
128
148
  send: {
129
149
  id: string;
150
+ accepted: boolean;
130
151
  delivered: boolean;
152
+ code?: string;
153
+ error?: string;
131
154
  };
132
155
  register: {
133
156
  id: string;
134
157
  cwd: string;
158
+ name: string;
159
+ desired_state: DesiredState;
135
160
  };
136
161
  unregister: {
137
162
  removed: boolean;
138
163
  cwd?: string;
139
164
  };
165
+ unregister_cwd: {
166
+ removed: boolean;
167
+ cwd?: string;
168
+ };
140
169
  cron_add: {
141
170
  job: CronJobView;
142
171
  };
@@ -159,18 +188,11 @@ export interface ControlReplyShapes {
159
188
  entries: CronLogEntry[];
160
189
  };
161
190
  }
162
- /** A cron job plus its computed `next_run` (ISO), for `cron list`. */
163
191
  export type CronJobView = CronJob & {
164
192
  next_run?: string | null;
165
193
  };
166
- /** Convenience for typed `Client.request<...>("op")` calls. */
167
194
  export type ControlReplyFor<Op extends ControlRequest["op"]> = Op extends keyof ControlReplyShapes ? ControlReplyShapes[Op] : never;
168
195
  export declare function encodeRequest(req: ControlRequest): string;
169
196
  export declare function encodeReply<T>(reply: ControlReply<T>): string;
170
- /**
171
- * Parses a single JSON line into a request. Throws on malformed input —
172
- * the supervisor catches and replies `{ok:false, error}` so the client
173
- * gets a clean error rather than an unframed disconnect.
174
- */
175
197
  export declare function parseRequest(line: string): ControlRequest;
176
198
  export declare function parseReply(line: string): ControlReply<unknown>;
@@ -1,17 +1,3 @@
1
- /**
2
- * CLI ↔ supervisor IPC contract for `~/.pi/remote/supervisor.sock`.
3
- *
4
- * Framing: one JSON object per line, newline-terminated. The CLI sends a
5
- * single `ControlRequest`, the supervisor sends a single `ControlReply`,
6
- * both close the connection. No multiplexing, no streaming — each command
7
- * is a short round-trip.
8
- *
9
- * Plan/26 W2. The Pi RPC protocol (`pi --mode rpc`) used by the daemon
10
- * children themselves is a separate contract — see
11
- * `node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts`.
12
- * This file is strictly the supervisor's own control plane.
13
- */
14
- // ── Serialization helpers ────────────────────────────────────────────────────
15
1
  const TRAILING_NEWLINE = "\n";
16
2
  export function encodeRequest(req) {
17
3
  return JSON.stringify(req) + TRAILING_NEWLINE;
@@ -19,28 +5,20 @@ export function encodeRequest(req) {
19
5
  export function encodeReply(reply) {
20
6
  return JSON.stringify(reply) + TRAILING_NEWLINE;
21
7
  }
22
- /**
23
- * Parses a single JSON line into a request. Throws on malformed input —
24
- * the supervisor catches and replies `{ok:false, error}` so the client
25
- * gets a clean error rather than an unframed disconnect.
26
- */
27
8
  export function parseRequest(line) {
28
9
  let obj;
29
10
  try {
30
11
  obj = JSON.parse(line);
31
12
  }
32
- catch (e) {
33
- throw new Error(`malformed control request: ${e.message}`);
13
+ catch (error) {
14
+ throw new Error(`malformed control request: ${error.message}`);
34
15
  }
35
- if (!obj || typeof obj !== "object") {
16
+ if (!obj || typeof obj !== "object" || Array.isArray(obj)) {
36
17
  throw new Error("control request must be a JSON object");
37
18
  }
38
- const op = obj.op;
39
- if (typeof op !== "string") {
19
+ if (typeof obj.op !== "string") {
40
20
  throw new Error("control request missing string `op` field");
41
21
  }
42
- // We don't validate every field shape here — supervisor handlers do it
43
- // per-op since the error messages are more specific that way.
44
22
  return obj;
45
23
  }
46
24
  export function parseReply(line) {
@@ -48,14 +26,13 @@ export function parseReply(line) {
48
26
  try {
49
27
  obj = JSON.parse(line);
50
28
  }
51
- catch (e) {
52
- throw new Error(`malformed control reply: ${e.message}`);
29
+ catch (error) {
30
+ throw new Error(`malformed control reply: ${error.message}`);
53
31
  }
54
- if (!obj || typeof obj !== "object") {
32
+ if (!obj || typeof obj !== "object" || Array.isArray(obj)) {
55
33
  throw new Error("control reply must be a JSON object");
56
34
  }
57
- const ok = obj.ok;
58
- if (typeof ok !== "boolean") {
35
+ if (typeof obj.ok !== "boolean") {
59
36
  throw new Error("control reply missing boolean `ok` field");
60
37
  }
61
38
  return obj;
@@ -1 +1 @@
1
- {"version":3,"file":"control_protocol.js","sourceRoot":"","sources":["../../src/daemon/control_protocol.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA4EH,gFAAgF;AAEhF,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,MAAM,UAAU,aAAa,CAAC,GAAmB;IAC/C,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,WAAW,CAAI,KAAsB;IACnD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,gBAAgB,CAAC;AAClD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,8BAA+B,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAAC,CAAC;IACpF,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,EAAE,GAAI,GAAwB,CAAC,EAAE,CAAC;IACxC,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,uEAAuE;IACvE,8DAA8D;IAC9D,OAAO,GAAqB,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,4BAA6B,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IAAC,CAAC;IAClF,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACpC,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IACD,MAAM,EAAE,GAAI,GAAwB,CAAC,EAAE,CAAC;IACxC,IAAI,OAAO,EAAE,KAAK,SAAS,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,GAA4B,CAAC;AACtC,CAAC"}
1
+ {"version":3,"file":"control_protocol.js","sourceRoot":"","sources":["../../src/daemon/control_protocol.ts"],"names":[],"mappings":"AAmGA,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAE9B,MAAM,UAAU,aAAa,CAAC,GAAmB;IAC/C,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,gBAAgB,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,WAAW,CAAI,KAAsB;IACnD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,gBAAgB,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAAC,CAAC;IAC/B,OAAO,KAAK,EAAE,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,8BAA+B,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IAAC,CAAC;IAC5F,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,OAAQ,GAAwB,CAAC,EAAE,KAAK,QAAQ,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,GAAqB,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QAAC,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAAC,CAAC;IAC/B,OAAO,KAAK,EAAE,CAAC;QAAC,MAAM,IAAI,KAAK,CAAC,4BAA6B,KAAe,CAAC,OAAO,EAAE,CAAC,CAAC;IAAC,CAAC;IAC1F,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IACD,IAAI,OAAQ,GAAwB,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,GAA4B,CAAC;AACtC,CAAC"}
@@ -1,33 +1,16 @@
1
- /**
2
- * Append-only audit trail for cron fires at `~/.pi/remote/cron.jsonl`.
3
- *
4
- * One JSON line per scheduler decision — **every fire AND every skip** — so an
5
- * operator can see exactly what ran and what didn't (the agent's output goes
6
- * fire-and-forget to the relay/mesh, so the dispatch itself needs its own
7
- * trail). Plan/39 decision E.
8
- */
9
- /** Outcome of a single `fireJob` decision. */
10
- export type CronResult = "delivered" | "deliver_failed" | "woke_and_delivered" | "skipped_busy" | "skipped_down" | "skipped_disabled";
1
+ /** Every result documents a gate decision or the RPC acceptance outcome. */
2
+ export type CronResult = "accepted" | "rejected" | "skipped_busy" | "skipped_disabled" | "skipped_missing" | "skipped_desired_stopped" | "skipped_starting" | "skipped_retrying" | "skipped_failed" | "skipped_blocked";
11
3
  export interface CronLogEntry {
12
- /** epoch ms */
13
4
  ts: number;
14
5
  job_id: string;
15
6
  daemon_id: string;
16
7
  schedule: string;
17
- /** true when a prompt was actually sent (delivered / woke_and_delivered). */
18
8
  fired: boolean;
19
9
  result: CronResult;
20
- /** First chars of the prompt, for at-a-glance log reading. */
21
10
  prompt_preview: string;
22
11
  }
23
- /** Test/diag-only: the on-disk path. */
24
12
  export declare function cronLogPath(): string;
25
- /** Maps a result to whether a prompt was actually delivered. */
26
13
  export declare function firedFor(result: CronResult): boolean;
27
- /**
28
- * Appends one entry. Best-effort: creates the parent dir + file when absent;
29
- * never throws into the scheduler (a logging failure must not abort a fire).
30
- */
31
14
  export declare function appendCronLog(entry: {
32
15
  job_id: string;
33
16
  daemon_id: string;
@@ -35,10 +18,6 @@ export declare function appendCronLog(entry: {
35
18
  result: CronResult;
36
19
  prompt: string;
37
20
  }): void;
38
- /**
39
- * Reads the log, newest-last. Optional `jobId` filter and `tail` (last N).
40
- * Missing file → []. Malformed lines are skipped.
41
- */
42
21
  export declare function readCronLog(opts?: {
43
22
  jobId?: string;
44
23
  tail?: number;
@@ -6,18 +6,8 @@ function logPath() {
6
6
  const root = process.env["REMOTE_PI_HOME"] || homedir();
7
7
  return join(root, ".pi", "remote", "cron.jsonl");
8
8
  }
9
- /** Test/diag-only: the on-disk path. */
10
- export function cronLogPath() {
11
- return logPath();
12
- }
13
- /** Maps a result to whether a prompt was actually delivered. */
14
- export function firedFor(result) {
15
- return result === "delivered" || result === "woke_and_delivered";
16
- }
17
- /**
18
- * Appends one entry. Best-effort: creates the parent dir + file when absent;
19
- * never throws into the scheduler (a logging failure must not abort a fire).
20
- */
9
+ export function cronLogPath() { return logPath(); }
10
+ export function firedFor(result) { return result === "accepted"; }
21
11
  export function appendCronLog(entry) {
22
12
  const line = JSON.stringify({
23
13
  ts: Date.now(),
@@ -33,13 +23,9 @@ export function appendCronLog(entry) {
33
23
  appendFileSync(logPath(), line, "utf8");
34
24
  }
35
25
  catch {
36
- /* audit is best-effort don't break the scheduler on a write error */
26
+ // Auditing must not turn an already-completed scheduler decision into a retry.
37
27
  }
38
28
  }
39
- /**
40
- * Reads the log, newest-last. Optional `jobId` filter and `tail` (last N).
41
- * Missing file → []. Malformed lines are skipped.
42
- */
43
29
  export function readCronLog(opts = {}) {
44
30
  if (!existsSync(logPath()))
45
31
  return [];
@@ -55,18 +41,17 @@ export function readCronLog(opts = {}) {
55
41
  if (!line.trim())
56
42
  continue;
57
43
  try {
58
- const e = JSON.parse(line);
59
- if (opts.jobId && e.job_id !== opts.jobId)
44
+ const entry = JSON.parse(line);
45
+ if (opts.jobId && entry.job_id !== opts.jobId)
60
46
  continue;
61
- entries.push(e);
47
+ entries.push(entry);
62
48
  }
63
49
  catch {
64
- /* skip malformed */
50
+ // Skip malformed historical lines.
65
51
  }
66
52
  }
67
- if (opts.tail !== undefined && opts.tail >= 0 && entries.length > opts.tail) {
68
- return entries.slice(entries.length - opts.tail);
69
- }
70
- return entries;
53
+ return opts.tail !== undefined && opts.tail >= 0 && entries.length > opts.tail
54
+ ? entries.slice(entries.length - opts.tail)
55
+ : entries;
71
56
  }
72
57
  //# sourceMappingURL=cron_log.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"cron_log.js","sourceRoot":"","sources":["../../src/daemon/cron_log.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cron_log.js","sourceRoot":"","sources":["../../src/daemon/cron_log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAyB1C,MAAM,WAAW,GAAG,EAAE,CAAC;AAEvB,SAAS,OAAO;IACd,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,OAAO,EAAE,CAAC;IACxD,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,WAAW,KAAa,OAAO,OAAO,EAAE,CAAC,CAAC,CAAC;AAC3D,MAAM,UAAU,QAAQ,CAAC,MAAkB,IAAa,OAAO,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC;AAEvF,MAAM,UAAU,aAAa,CAAC,KAM7B;IACC,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC;QAC1B,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE;QACd,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;QAC7B,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC;KAC5B,CAAC,GAAG,IAAI,CAAC;IACjC,IAAI,CAAC;QACH,SAAS,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,cAAc,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,+EAA+E;IACjF,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAA0C,EAAE;IACtE,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QAAC,GAAG,GAAG,YAAY,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;IACnE,MAAM,OAAO,GAAmB,EAAE,CAAC;IACnC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE;YAAE,SAAS;QAC3B,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAiB,CAAC;YAC/C,IAAI,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK;gBAAE,SAAS;YACxD,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,mCAAmC;QACrC,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI;QAC5E,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC;QAC3C,CAAC,CAAC,OAAO,CAAC;AACd,CAAC"}
@@ -1,80 +1,43 @@
1
- /**
2
- * Cron registry: scheduled prompts for daemons, persisted at
3
- * `~/.pi/remote/cron.json`. Mirrors `registry.ts` (`daemons.json`) — tolerant
4
- * load (missing/corrupt → empty), atomic-ish full-file save.
5
- *
6
- * Each job targets a daemon by its `daemon_id` (the 8-hex id from
7
- * `daemonIdForCwd`) and fires `prompt` on `schedule` (a cron expression, run
8
- * by croner in the supervisor). The scheduler engine + `fireJob` live in
9
- * `supervisor.ts`; this module only owns persistence + schedule validation.
10
- *
11
- * Plan/39. Decisions B (croner), C (min-interval 60s), E (audit via cron_log).
12
- */
13
- /** Minimum allowed interval between two consecutive runs of a schedule. */
14
1
  export declare const MIN_INTERVAL_MS = 60000;
15
- /** A scheduled prompt. */
2
+ /** A scheduled prompt. Cron never owns a daemon's lifecycle. */
16
3
  export interface CronJob {
17
- /** `j_<hex>` — random, stable across restarts. */
18
4
  id: string;
19
- /** Target daemon id (`daemonIdForCwd`). */
20
5
  daemon_id: string;
21
- /** Cron expression (croner syntax; optional 6th seconds field supported). */
22
6
  schedule: string;
23
- /** IANA timezone for the schedule (e.g. "America/Sao_Paulo"). */
24
7
  tz?: string;
25
- /** Prompt text injected into the daemon when the job fires. */
26
8
  prompt: string;
27
9
  enabled: boolean;
28
- /** Skip the fire when the daemon is mid-turn (default true). */
29
10
  skip_if_busy: boolean;
30
- /** Start the daemon if it's down, then fire (default false). */
31
- wake: boolean;
32
- /** On supervisor start, run once if the previous scheduled run was missed
33
- * while it was down (default false; at most 1×). */
34
11
  catchup: boolean;
35
12
  created_at: string;
36
13
  last_run?: string;
37
- /** Last fire result — see cron_log `result` values. Shortcut for `cron list`. */
38
14
  last_status?: string;
39
15
  }
40
16
  export interface CronRegistry {
41
17
  jobs: CronJob[];
42
18
  }
43
- /** Test/diag-only: the on-disk path. */
44
19
  export declare function cronRegistryPath(): string;
45
- /** Reads the registry; returns empty on missing/corrupt file. */
20
+ /** Old wake-bearing jobs are intentionally not carried into the new contract. */
46
21
  export declare function loadCronRegistry(): CronRegistry;
47
- export declare function saveCronRegistry(reg: CronRegistry): void;
22
+ export declare function saveCronRegistry(registry: CronRegistry): void;
48
23
  export declare function listJobs(): CronJob[];
49
24
  export declare function getJob(id: string): CronJob | undefined;
50
- /** Fields a caller supplies when creating a job. Flags default sensibly. */
51
25
  export interface NewJobInput {
52
26
  daemon_id: string;
53
27
  schedule: string;
54
28
  prompt: string;
55
29
  tz?: string;
56
30
  skip_if_busy?: boolean;
57
- wake?: boolean;
58
31
  catchup?: boolean;
59
32
  }
60
- /** Adds a job with a fresh `j_<hex>` id. Pure persistence — call
61
- * `validateSchedule` first at the op/CLI boundary. */
62
33
  export declare function addJob(input: NewJobInput): CronJob;
63
34
  export declare function removeJob(id: string): boolean;
64
35
  export declare function setJobEnabled(id: string, enabled: boolean): boolean;
65
- /** Records the outcome of a fire on the job (the `cron list` shortcut). */
66
36
  export declare function recordRun(id: string, at: string, status: string): void;
67
37
  export interface ScheduleValidation {
68
38
  ok: boolean;
69
39
  error?: string;
70
- /** Interval (ms) between the next two runs, when computable. */
71
40
  intervalMs?: number;
72
41
  }
73
- /**
74
- * Validates a cron expression via croner and enforces the ≥60s min-interval
75
- * (decision C — guards against pileup + token burn). Returns `ok:false` with a
76
- * user-facing message on a bad expression or a too-frequent schedule.
77
- */
78
42
  export declare function validateSchedule(schedule: string, tz?: string): ScheduleValidation;
79
- /** Returns the next scheduled run for a job, or null. Used by `cron list`. */
80
43
  export declare function nextRunFor(job: CronJob): Date | null;