@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.
- package/README.md +81 -586
- package/dist/bin/supervisord.js +4 -5
- package/dist/bin/supervisord.js.map +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +2 -2
- package/dist/daemon/cli-links.d.ts +30 -0
- package/dist/daemon/cli-links.js +134 -0
- package/dist/daemon/cli-links.js.map +1 -0
- package/dist/daemon/commands.d.ts +27 -0
- package/dist/daemon/commands.js +295 -0
- package/dist/daemon/commands.js.map +1 -0
- package/dist/daemon/control_protocol.d.ts +53 -31
- package/dist/daemon/control_protocol.js +8 -31
- package/dist/daemon/control_protocol.js.map +1 -1
- package/dist/daemon/cron_log.d.ts +2 -23
- package/dist/daemon/cron_log.js +10 -25
- package/dist/daemon/cron_log.js.map +1 -1
- package/dist/daemon/cron_registry.d.ts +3 -40
- package/dist/daemon/cron_registry.js +58 -103
- package/dist/daemon/cron_registry.js.map +1 -1
- package/dist/daemon/install-runtime.d.ts +10 -0
- package/dist/daemon/install-runtime.js +81 -0
- package/dist/daemon/install-runtime.js.map +1 -0
- package/dist/daemon/install.d.ts +3 -63
- package/dist/daemon/install.js +5 -289
- package/dist/daemon/install.js.map +1 -1
- package/dist/daemon/preflight.d.ts +51 -0
- package/dist/daemon/preflight.js +136 -0
- package/dist/daemon/preflight.js.map +1 -0
- package/dist/daemon/registry.d.ts +33 -45
- package/dist/daemon/registry.js +171 -117
- package/dist/daemon/registry.js.map +1 -1
- package/dist/daemon/rpc_child.d.ts +92 -146
- package/dist/daemon/rpc_child.js +336 -263
- package/dist/daemon/rpc_child.js.map +1 -1
- package/dist/daemon/status.d.ts +45 -0
- package/dist/daemon/status.js +87 -0
- package/dist/daemon/status.js.map +1 -0
- package/dist/daemon/supervisor-ipc.d.ts +2 -0
- package/dist/daemon/supervisor-ipc.js +20 -0
- package/dist/daemon/supervisor-ipc.js.map +1 -0
- package/dist/daemon/supervisor.d.ts +48 -71
- package/dist/daemon/supervisor.js +430 -420
- package/dist/daemon/supervisor.js.map +1 -1
- package/dist/extension_ui_bridge.d.ts +4 -3
- package/dist/extension_ui_bridge.js +10 -0
- package/dist/extension_ui_bridge.js.map +1 -1
- package/dist/index.d.ts +25 -230
- package/dist/index.js +515 -5553
- package/dist/index.js.map +1 -1
- package/dist/pairing/crypto.d.ts +8 -1
- package/dist/pairing/crypto.js +56 -6
- package/dist/pairing/crypto.js.map +1 -1
- package/dist/pairing/owner_storage.d.ts +42 -0
- package/dist/pairing/owner_storage.js +207 -0
- package/dist/pairing/owner_storage.js.map +1 -0
- package/dist/pairing/qr.d.ts +3 -42
- package/dist/pairing/qr.js +9 -59
- package/dist/pairing/qr.js.map +1 -1
- package/dist/pairing/storage.d.ts +3 -45
- package/dist/pairing/storage.js +10 -223
- package/dist/pairing/storage.js.map +1 -1
- package/dist/protocol/types.d.ts +1 -1
- package/dist/protocol/v2/schemas.d.ts +1 -1
- package/dist/protocol/v2/schemas.js +1 -1
- package/dist/protocol/v2/schemas.js.map +1 -1
- package/dist/runtime/owner_router.d.ts +16 -0
- package/dist/runtime/owner_router.js +37 -0
- package/dist/runtime/owner_router.js.map +1 -0
- package/dist/session/ipc.d.ts +1 -22
- package/dist/session/ipc.js +4 -11
- package/dist/session/ipc.js.map +1 -1
- package/dist/session/local_config.d.ts +4 -47
- package/dist/session/local_config.js +19 -101
- package/dist/session/local_config.js.map +1 -1
- package/dist/transport/peer_channel.d.ts +25 -39
- package/dist/transport/peer_channel.js +74 -131
- package/dist/transport/peer_channel.js.map +1 -1
- package/dist/transport/relay_client.d.ts +26 -70
- package/dist/transport/relay_client.js +37 -106
- package/dist/transport/relay_client.js.map +1 -1
- package/docs/daemon.md +91 -207
- package/package.json +21 -17
- package/dist/daemon/id.d.ts +0 -24
- package/dist/daemon/id.js +0 -36
- package/dist/daemon/id.js.map +0 -1
- package/dist/mcp/mesh_result.d.ts +0 -10
- package/dist/mcp/mesh_result.js +0 -42
- package/dist/mcp/mesh_result.js.map +0 -1
- package/dist/mcp/mesh_server.d.ts +0 -16
- package/dist/mcp/mesh_server.js +0 -327
- package/dist/mcp/mesh_server.js.map +0 -1
- package/dist/mesh/canonical.d.ts +0 -30
- package/dist/mesh/canonical.js +0 -61
- package/dist/mesh/canonical.js.map +0 -1
- package/dist/mesh/client.d.ts +0 -18
- package/dist/mesh/client.js +0 -125
- package/dist/mesh/client.js.map +0 -1
- package/dist/mesh/encoding.d.ts +0 -38
- package/dist/mesh/encoding.js +0 -216
- package/dist/mesh/encoding.js.map +0 -1
- package/dist/mesh/self_revoke.d.ts +0 -73
- package/dist/mesh/self_revoke.js +0 -401
- package/dist/mesh/self_revoke.js.map +0 -1
- package/dist/mesh/siblings.d.ts +0 -49
- package/dist/mesh/siblings.js +0 -159
- package/dist/mesh/siblings.js.map +0 -1
- package/dist/mesh/types.d.ts +0 -34
- package/dist/mesh/types.js +0 -11
- package/dist/mesh/types.js.map +0 -1
- package/dist/mesh/verify.d.ts +0 -17
- package/dist/mesh/verify.js +0 -86
- package/dist/mesh/verify.js.map +0 -1
- package/dist/rooms.d.ts +0 -29
- package/dist/rooms.js +0 -57
- package/dist/rooms.js.map +0 -1
- package/dist/session/bridge.d.ts +0 -37
- package/dist/session/bridge.js +0 -130
- package/dist/session/bridge.js.map +0 -1
- package/dist/session/broker.d.ts +0 -189
- package/dist/session/broker.js +0 -507
- package/dist/session/broker.js.map +0 -1
- package/dist/session/broker_remote.d.ts +0 -74
- package/dist/session/broker_remote.js +0 -583
- package/dist/session/broker_remote.js.map +0 -1
- package/dist/session/cwd_lock.d.ts +0 -33
- package/dist/session/cwd_lock.js +0 -126
- package/dist/session/cwd_lock.js.map +0 -1
- package/dist/session/envelope.d.ts +0 -33
- package/dist/session/envelope.js +0 -117
- package/dist/session/envelope.js.map +0 -1
- package/dist/session/global_config.d.ts +0 -33
- package/dist/session/global_config.js +0 -73
- package/dist/session/global_config.js.map +0 -1
- package/dist/session/leader_election.d.ts +0 -32
- package/dist/session/leader_election.js +0 -106
- package/dist/session/leader_election.js.map +0 -1
- package/dist/session/mesh_node.d.ts +0 -116
- package/dist/session/mesh_node.js +0 -573
- package/dist/session/mesh_node.js.map +0 -1
- package/dist/session/peer.d.ts +0 -139
- package/dist/session/peer.js +0 -451
- package/dist/session/peer.js.map +0 -1
- package/dist/session/peer_inventory.d.ts +0 -13
- package/dist/session/peer_inventory.js +0 -48
- package/dist/session/peer_inventory.js.map +0 -1
- package/dist/session/peer_limits.d.ts +0 -9
- package/dist/session/peer_limits.js +0 -21
- package/dist/session/peer_limits.js.map +0 -1
- package/dist/session/setup_wizard.d.ts +0 -39
- package/dist/session/setup_wizard.js +0 -63
- package/dist/session/setup_wizard.js.map +0 -1
- package/dist/session/tools.d.ts +0 -24
- package/dist/session/tools.js +0 -252
- package/dist/session/tools.js.map +0 -1
- package/dist/session/wizard.d.ts +0 -13
- package/dist/session/wizard.js +0 -20
- package/dist/session/wizard.js.map +0 -1
- package/dist/transport/pi_forward_client.d.ts +0 -29
- package/dist/transport/pi_forward_client.js +0 -62
- package/dist/transport/pi_forward_client.js.map +0 -1
- package/dist/ui/footer.d.ts +0 -32
- package/dist/ui/footer.js +0 -34
- package/dist/ui/footer.js.map +0 -1
- 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
|
-
/**
|
|
17
|
-
export type DaemonState = "
|
|
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
|
-
|
|
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
|
|
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 (
|
|
33
|
-
throw new Error(`malformed control request: ${
|
|
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
|
-
|
|
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 (
|
|
52
|
-
throw new Error(`malformed control reply: ${
|
|
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
|
-
|
|
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":"
|
|
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
|
-
|
|
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;
|
package/dist/daemon/cron_log.js
CHANGED
|
@@ -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
|
-
|
|
10
|
-
export function
|
|
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
|
-
|
|
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
|
|
59
|
-
if (opts.jobId &&
|
|
44
|
+
const entry = JSON.parse(line);
|
|
45
|
+
if (opts.jobId && entry.job_id !== opts.jobId)
|
|
60
46
|
continue;
|
|
61
|
-
entries.push(
|
|
47
|
+
entries.push(entry);
|
|
62
48
|
}
|
|
63
49
|
catch {
|
|
64
|
-
|
|
50
|
+
// Skip malformed historical lines.
|
|
65
51
|
}
|
|
66
52
|
}
|
|
67
|
-
|
|
68
|
-
|
|
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":"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;
|
|
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
|
-
/**
|
|
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(
|
|
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;
|