@yefengr/remote-pi 0.7.15 → 0.8.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/README.md +44 -95
- package/dist/actions/handlers.js +1 -1
- package/dist/actions/handlers.js.map +1 -1
- package/dist/actions/registry.d.ts +1 -1
- package/dist/actions/registry.js +1 -1
- package/dist/{daemon/commands.d.ts → commands.d.ts} +4 -5
- package/dist/commands.js +169 -0
- package/dist/commands.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +44 -39
- package/dist/index.js.map +1 -1
- package/dist/pairing/qr.d.ts +22 -21
- package/dist/pairing/qr.js +40 -65
- package/dist/pairing/qr.js.map +1 -1
- package/dist/pairing/storage.js +4 -4
- package/dist/pairing/storage.js.map +1 -1
- package/dist/protocol/types.d.ts +1 -1
- package/dist/protocol/v2/schemas.d.ts +5 -5
- package/dist/protocol/v2/schemas.js +2 -1
- package/dist/protocol/v2/schemas.js.map +1 -1
- package/dist/runtime/pairing_coordinator.js +6 -6
- package/dist/runtime/pairing_coordinator.js.map +1 -1
- package/dist/session/local_config.d.ts +0 -5
- package/dist/session/local_config.js +6 -29
- package/dist/session/local_config.js.map +1 -1
- package/dist/transport/relay_client.js.map +1 -1
- package/package.json +1 -8
- package/dist/bin/supervisord.d.ts +0 -2
- package/dist/bin/supervisord.js +0 -78
- package/dist/bin/supervisord.js.map +0 -1
- package/dist/daemon/cli-links.d.ts +0 -30
- package/dist/daemon/cli-links.js +0 -134
- package/dist/daemon/cli-links.js.map +0 -1
- package/dist/daemon/client.d.ts +0 -20
- package/dist/daemon/client.js +0 -131
- package/dist/daemon/client.js.map +0 -1
- package/dist/daemon/commands.js +0 -311
- package/dist/daemon/commands.js.map +0 -1
- package/dist/daemon/control_protocol.d.ts +0 -198
- package/dist/daemon/control_protocol.js +0 -40
- package/dist/daemon/control_protocol.js.map +0 -1
- package/dist/daemon/cron_log.d.ts +0 -24
- package/dist/daemon/cron_log.js +0 -57
- package/dist/daemon/cron_log.js.map +0 -1
- package/dist/daemon/cron_registry.d.ts +0 -43
- package/dist/daemon/cron_registry.js +0 -149
- package/dist/daemon/cron_registry.js.map +0 -1
- package/dist/daemon/install-runtime.d.ts +0 -10
- package/dist/daemon/install-runtime.js +0 -81
- package/dist/daemon/install-runtime.js.map +0 -1
- package/dist/daemon/install.d.ts +0 -110
- package/dist/daemon/install.js +0 -263
- package/dist/daemon/install.js.map +0 -1
- package/dist/daemon/registry.d.ts +0 -51
- package/dist/daemon/registry.js +0 -207
- package/dist/daemon/registry.js.map +0 -1
- package/dist/daemon/rpc_child.d.ts +0 -135
- package/dist/daemon/rpc_child.js +0 -472
- package/dist/daemon/rpc_child.js.map +0 -1
- package/dist/daemon/status.d.ts +0 -45
- package/dist/daemon/status.js +0 -87
- package/dist/daemon/status.js.map +0 -1
- package/dist/daemon/supervisor-ipc.d.ts +0 -2
- package/dist/daemon/supervisor-ipc.js +0 -20
- package/dist/daemon/supervisor-ipc.js.map +0 -1
- package/dist/daemon/supervisor.d.ts +0 -70
- package/dist/daemon/supervisor.js +0 -637
- package/dist/daemon/supervisor.js.map +0 -1
- package/dist/session/ipc.d.ts +0 -6
- package/dist/session/ipc.js +0 -15
- package/dist/session/ipc.js.map +0 -1
- package/docs/daemon.md +0 -175
- package/service-templates/launchd.plist.template +0 -35
- package/service-templates/systemd.service.template +0 -19
- package/service-templates/task-launcher.vbs.template +0 -10
- package/service-templates/task-scheduler.xml.template +0 -38
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import type { CronJob } from "./cron_registry.js";
|
|
2
|
-
import type { CronLogEntry } from "./cron_log.js";
|
|
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
|
-
*/
|
|
16
|
-
export interface DaemonInfo {
|
|
17
|
-
daemon_id: string;
|
|
18
|
-
/** Compatibility alias for daemon_id. */
|
|
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;
|
|
30
|
-
cwd: string;
|
|
31
|
-
name: string;
|
|
32
|
-
kind: "daemon";
|
|
33
|
-
pid?: number;
|
|
34
|
-
started_at?: number;
|
|
35
|
-
uptime?: number;
|
|
36
|
-
/** Compatibility alias for uptime (seconds). */
|
|
37
|
-
uptime_s?: 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;
|
|
47
|
-
}
|
|
48
|
-
export type ControlRequest = {
|
|
49
|
-
op: "list";
|
|
50
|
-
} | {
|
|
51
|
-
op: "status";
|
|
52
|
-
} | {
|
|
53
|
-
op: "start_all";
|
|
54
|
-
} | {
|
|
55
|
-
op: "start";
|
|
56
|
-
id: string;
|
|
57
|
-
} | {
|
|
58
|
-
op: "stop_all";
|
|
59
|
-
} | {
|
|
60
|
-
op: "stop";
|
|
61
|
-
id: string;
|
|
62
|
-
} | {
|
|
63
|
-
op: "restart_all";
|
|
64
|
-
} | {
|
|
65
|
-
op: "restart";
|
|
66
|
-
id: string;
|
|
67
|
-
} | {
|
|
68
|
-
op: "send";
|
|
69
|
-
id: string;
|
|
70
|
-
text: string;
|
|
71
|
-
} | {
|
|
72
|
-
op: "register";
|
|
73
|
-
cwd: string;
|
|
74
|
-
} | {
|
|
75
|
-
op: "unregister";
|
|
76
|
-
id: string;
|
|
77
|
-
} | {
|
|
78
|
-
op: "unregister_cwd";
|
|
79
|
-
cwd: string;
|
|
80
|
-
} | {
|
|
81
|
-
op: "cron_add";
|
|
82
|
-
daemon_id: string;
|
|
83
|
-
schedule: string;
|
|
84
|
-
prompt: string;
|
|
85
|
-
tz?: string;
|
|
86
|
-
skip_if_busy?: boolean;
|
|
87
|
-
catchup?: boolean;
|
|
88
|
-
} | {
|
|
89
|
-
op: "cron_list";
|
|
90
|
-
} | {
|
|
91
|
-
op: "cron_remove";
|
|
92
|
-
job_id: string;
|
|
93
|
-
} | {
|
|
94
|
-
op: "cron_enable";
|
|
95
|
-
job_id: string;
|
|
96
|
-
enabled: boolean;
|
|
97
|
-
} | {
|
|
98
|
-
op: "cron_run";
|
|
99
|
-
job_id: string;
|
|
100
|
-
} | {
|
|
101
|
-
op: "cron_log";
|
|
102
|
-
job_id?: string;
|
|
103
|
-
tail?: number;
|
|
104
|
-
};
|
|
105
|
-
export type ControlReply<T = unknown> = {
|
|
106
|
-
ok: true;
|
|
107
|
-
data?: T;
|
|
108
|
-
} | {
|
|
109
|
-
ok: false;
|
|
110
|
-
error: string;
|
|
111
|
-
};
|
|
112
|
-
export interface ControlReplyShapes {
|
|
113
|
-
list: {
|
|
114
|
-
daemons: DaemonInfo[];
|
|
115
|
-
};
|
|
116
|
-
status: {
|
|
117
|
-
daemons: DaemonInfo[];
|
|
118
|
-
};
|
|
119
|
-
start_all: {
|
|
120
|
-
started: string[];
|
|
121
|
-
already_running: string[];
|
|
122
|
-
};
|
|
123
|
-
start: {
|
|
124
|
-
id: string;
|
|
125
|
-
state: DaemonState;
|
|
126
|
-
started: boolean;
|
|
127
|
-
desired_state: DesiredState;
|
|
128
|
-
};
|
|
129
|
-
stop_all: {
|
|
130
|
-
stopped: string[];
|
|
131
|
-
already_stopped: string[];
|
|
132
|
-
};
|
|
133
|
-
stop: {
|
|
134
|
-
id: string;
|
|
135
|
-
state: DaemonState;
|
|
136
|
-
stopped: boolean;
|
|
137
|
-
desired_state: DesiredState;
|
|
138
|
-
};
|
|
139
|
-
restart_all: {
|
|
140
|
-
restarted: string[];
|
|
141
|
-
};
|
|
142
|
-
restart: {
|
|
143
|
-
id: string;
|
|
144
|
-
state: DaemonState;
|
|
145
|
-
restarted: boolean;
|
|
146
|
-
desired_state: DesiredState;
|
|
147
|
-
};
|
|
148
|
-
send: {
|
|
149
|
-
id: string;
|
|
150
|
-
accepted: boolean;
|
|
151
|
-
delivered: boolean;
|
|
152
|
-
code?: string;
|
|
153
|
-
error?: string;
|
|
154
|
-
};
|
|
155
|
-
register: {
|
|
156
|
-
id: string;
|
|
157
|
-
cwd: string;
|
|
158
|
-
name: string;
|
|
159
|
-
desired_state: DesiredState;
|
|
160
|
-
};
|
|
161
|
-
unregister: {
|
|
162
|
-
removed: boolean;
|
|
163
|
-
cwd?: string;
|
|
164
|
-
};
|
|
165
|
-
unregister_cwd: {
|
|
166
|
-
removed: boolean;
|
|
167
|
-
cwd?: string;
|
|
168
|
-
};
|
|
169
|
-
cron_add: {
|
|
170
|
-
job: CronJobView;
|
|
171
|
-
};
|
|
172
|
-
cron_list: {
|
|
173
|
-
jobs: CronJobView[];
|
|
174
|
-
};
|
|
175
|
-
cron_remove: {
|
|
176
|
-
removed: boolean;
|
|
177
|
-
};
|
|
178
|
-
cron_enable: {
|
|
179
|
-
job_id: string;
|
|
180
|
-
enabled: boolean;
|
|
181
|
-
updated: boolean;
|
|
182
|
-
};
|
|
183
|
-
cron_run: {
|
|
184
|
-
job_id: string;
|
|
185
|
-
result: string;
|
|
186
|
-
};
|
|
187
|
-
cron_log: {
|
|
188
|
-
entries: CronLogEntry[];
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
export type CronJobView = CronJob & {
|
|
192
|
-
next_run?: string | null;
|
|
193
|
-
};
|
|
194
|
-
export type ControlReplyFor<Op extends ControlRequest["op"]> = Op extends keyof ControlReplyShapes ? ControlReplyShapes[Op] : never;
|
|
195
|
-
export declare function encodeRequest(req: ControlRequest): string;
|
|
196
|
-
export declare function encodeReply<T>(reply: ControlReply<T>): string;
|
|
197
|
-
export declare function parseRequest(line: string): ControlRequest;
|
|
198
|
-
export declare function parseReply(line: string): ControlReply<unknown>;
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
const TRAILING_NEWLINE = "\n";
|
|
2
|
-
export function encodeRequest(req) {
|
|
3
|
-
return JSON.stringify(req) + TRAILING_NEWLINE;
|
|
4
|
-
}
|
|
5
|
-
export function encodeReply(reply) {
|
|
6
|
-
return JSON.stringify(reply) + TRAILING_NEWLINE;
|
|
7
|
-
}
|
|
8
|
-
export function parseRequest(line) {
|
|
9
|
-
let obj;
|
|
10
|
-
try {
|
|
11
|
-
obj = JSON.parse(line);
|
|
12
|
-
}
|
|
13
|
-
catch (error) {
|
|
14
|
-
throw new Error(`malformed control request: ${error.message}`);
|
|
15
|
-
}
|
|
16
|
-
if (!obj || typeof obj !== "object" || Array.isArray(obj)) {
|
|
17
|
-
throw new Error("control request must be a JSON object");
|
|
18
|
-
}
|
|
19
|
-
if (typeof obj.op !== "string") {
|
|
20
|
-
throw new Error("control request missing string `op` field");
|
|
21
|
-
}
|
|
22
|
-
return obj;
|
|
23
|
-
}
|
|
24
|
-
export function parseReply(line) {
|
|
25
|
-
let obj;
|
|
26
|
-
try {
|
|
27
|
-
obj = JSON.parse(line);
|
|
28
|
-
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
throw new Error(`malformed control reply: ${error.message}`);
|
|
31
|
-
}
|
|
32
|
-
if (!obj || typeof obj !== "object" || Array.isArray(obj)) {
|
|
33
|
-
throw new Error("control reply must be a JSON object");
|
|
34
|
-
}
|
|
35
|
-
if (typeof obj.ok !== "boolean") {
|
|
36
|
-
throw new Error("control reply missing boolean `ok` field");
|
|
37
|
-
}
|
|
38
|
-
return obj;
|
|
39
|
-
}
|
|
40
|
-
//# sourceMappingURL=control_protocol.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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,24 +0,0 @@
|
|
|
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";
|
|
3
|
-
export interface CronLogEntry {
|
|
4
|
-
ts: number;
|
|
5
|
-
job_id: string;
|
|
6
|
-
daemon_id: string;
|
|
7
|
-
schedule: string;
|
|
8
|
-
fired: boolean;
|
|
9
|
-
result: CronResult;
|
|
10
|
-
prompt_preview: string;
|
|
11
|
-
}
|
|
12
|
-
export declare function cronLogPath(): string;
|
|
13
|
-
export declare function firedFor(result: CronResult): boolean;
|
|
14
|
-
export declare function appendCronLog(entry: {
|
|
15
|
-
job_id: string;
|
|
16
|
-
daemon_id: string;
|
|
17
|
-
schedule: string;
|
|
18
|
-
result: CronResult;
|
|
19
|
-
prompt: string;
|
|
20
|
-
}): void;
|
|
21
|
-
export declare function readCronLog(opts?: {
|
|
22
|
-
jobId?: string;
|
|
23
|
-
tail?: number;
|
|
24
|
-
}): CronLogEntry[];
|
package/dist/daemon/cron_log.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
const PREVIEW_LEN = 80;
|
|
5
|
-
function logPath() {
|
|
6
|
-
const root = process.env["REMOTE_PI_HOME"] || homedir();
|
|
7
|
-
return join(root, ".pi", "remote", "cron.jsonl");
|
|
8
|
-
}
|
|
9
|
-
export function cronLogPath() { return logPath(); }
|
|
10
|
-
export function firedFor(result) { return result === "accepted"; }
|
|
11
|
-
export function appendCronLog(entry) {
|
|
12
|
-
const line = JSON.stringify({
|
|
13
|
-
ts: Date.now(),
|
|
14
|
-
job_id: entry.job_id,
|
|
15
|
-
daemon_id: entry.daemon_id,
|
|
16
|
-
schedule: entry.schedule,
|
|
17
|
-
fired: firedFor(entry.result),
|
|
18
|
-
result: entry.result,
|
|
19
|
-
prompt_preview: entry.prompt.slice(0, PREVIEW_LEN),
|
|
20
|
-
}) + "\n";
|
|
21
|
-
try {
|
|
22
|
-
mkdirSync(dirname(logPath()), { recursive: true });
|
|
23
|
-
appendFileSync(logPath(), line, "utf8");
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
// Auditing must not turn an already-completed scheduler decision into a retry.
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
export function readCronLog(opts = {}) {
|
|
30
|
-
if (!existsSync(logPath()))
|
|
31
|
-
return [];
|
|
32
|
-
let raw;
|
|
33
|
-
try {
|
|
34
|
-
raw = readFileSync(logPath(), "utf8");
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
return [];
|
|
38
|
-
}
|
|
39
|
-
const entries = [];
|
|
40
|
-
for (const line of raw.split("\n")) {
|
|
41
|
-
if (!line.trim())
|
|
42
|
-
continue;
|
|
43
|
-
try {
|
|
44
|
-
const entry = JSON.parse(line);
|
|
45
|
-
if (opts.jobId && entry.job_id !== opts.jobId)
|
|
46
|
-
continue;
|
|
47
|
-
entries.push(entry);
|
|
48
|
-
}
|
|
49
|
-
catch {
|
|
50
|
-
// Skip malformed historical lines.
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return opts.tail !== undefined && opts.tail >= 0 && entries.length > opts.tail
|
|
54
|
-
? entries.slice(entries.length - opts.tail)
|
|
55
|
-
: entries;
|
|
56
|
-
}
|
|
57
|
-
//# sourceMappingURL=cron_log.js.map
|
|
@@ -1 +0,0 @@
|
|
|
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,43 +0,0 @@
|
|
|
1
|
-
export declare const MIN_INTERVAL_MS = 60000;
|
|
2
|
-
/** A scheduled prompt. Cron never owns a daemon's lifecycle. */
|
|
3
|
-
export interface CronJob {
|
|
4
|
-
id: string;
|
|
5
|
-
daemon_id: string;
|
|
6
|
-
schedule: string;
|
|
7
|
-
tz?: string;
|
|
8
|
-
prompt: string;
|
|
9
|
-
enabled: boolean;
|
|
10
|
-
skip_if_busy: boolean;
|
|
11
|
-
catchup: boolean;
|
|
12
|
-
created_at: string;
|
|
13
|
-
last_run?: string;
|
|
14
|
-
last_status?: string;
|
|
15
|
-
}
|
|
16
|
-
export interface CronRegistry {
|
|
17
|
-
jobs: CronJob[];
|
|
18
|
-
}
|
|
19
|
-
export declare function cronRegistryPath(): string;
|
|
20
|
-
/** Old wake-bearing jobs are intentionally not carried into the new contract. */
|
|
21
|
-
export declare function loadCronRegistry(): CronRegistry;
|
|
22
|
-
export declare function saveCronRegistry(registry: CronRegistry): void;
|
|
23
|
-
export declare function listJobs(): CronJob[];
|
|
24
|
-
export declare function getJob(id: string): CronJob | undefined;
|
|
25
|
-
export interface NewJobInput {
|
|
26
|
-
daemon_id: string;
|
|
27
|
-
schedule: string;
|
|
28
|
-
prompt: string;
|
|
29
|
-
tz?: string;
|
|
30
|
-
skip_if_busy?: boolean;
|
|
31
|
-
catchup?: boolean;
|
|
32
|
-
}
|
|
33
|
-
export declare function addJob(input: NewJobInput): CronJob;
|
|
34
|
-
export declare function removeJob(id: string): boolean;
|
|
35
|
-
export declare function setJobEnabled(id: string, enabled: boolean): boolean;
|
|
36
|
-
export declare function recordRun(id: string, at: string, status: string): void;
|
|
37
|
-
export interface ScheduleValidation {
|
|
38
|
-
ok: boolean;
|
|
39
|
-
error?: string;
|
|
40
|
-
intervalMs?: number;
|
|
41
|
-
}
|
|
42
|
-
export declare function validateSchedule(schedule: string, tz?: string): ScheduleValidation;
|
|
43
|
-
export declare function nextRunFor(job: CronJob): Date | null;
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { randomBytes } from "node:crypto";
|
|
4
|
-
import { dirname, join } from "node:path";
|
|
5
|
-
import { Cron } from "croner";
|
|
6
|
-
export const MIN_INTERVAL_MS = 60_000;
|
|
7
|
-
function cronPath() {
|
|
8
|
-
const root = process.env["REMOTE_PI_HOME"] || homedir();
|
|
9
|
-
return join(root, ".pi", "remote", "cron.json");
|
|
10
|
-
}
|
|
11
|
-
export function cronRegistryPath() { return cronPath(); }
|
|
12
|
-
/** Old wake-bearing jobs are intentionally not carried into the new contract. */
|
|
13
|
-
export function loadCronRegistry() {
|
|
14
|
-
if (!existsSync(cronPath()))
|
|
15
|
-
return { jobs: [] };
|
|
16
|
-
try {
|
|
17
|
-
const parsed = JSON.parse(readFileSync(cronPath(), "utf8"));
|
|
18
|
-
if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.jobs))
|
|
19
|
-
return { jobs: [] };
|
|
20
|
-
return { jobs: parsed.jobs.flatMap((item) => {
|
|
21
|
-
const job = coerceJob(item);
|
|
22
|
-
return job ? [job] : [];
|
|
23
|
-
}) };
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
return { jobs: [] };
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
export function saveCronRegistry(registry) {
|
|
30
|
-
mkdirSync(dirname(cronPath()), { recursive: true });
|
|
31
|
-
writeFileSync(cronPath(), JSON.stringify(registry, null, 2) + "\n");
|
|
32
|
-
}
|
|
33
|
-
export function listJobs() { return loadCronRegistry().jobs; }
|
|
34
|
-
export function getJob(id) { return listJobs().find((job) => job.id === id); }
|
|
35
|
-
export function addJob(input) {
|
|
36
|
-
const registry = loadCronRegistry();
|
|
37
|
-
const job = {
|
|
38
|
-
id: freshId(registry.jobs),
|
|
39
|
-
daemon_id: input.daemon_id,
|
|
40
|
-
schedule: input.schedule,
|
|
41
|
-
prompt: input.prompt,
|
|
42
|
-
enabled: true,
|
|
43
|
-
skip_if_busy: input.skip_if_busy ?? true,
|
|
44
|
-
catchup: input.catchup ?? false,
|
|
45
|
-
created_at: new Date().toISOString(),
|
|
46
|
-
};
|
|
47
|
-
if (input.tz)
|
|
48
|
-
job.tz = input.tz;
|
|
49
|
-
registry.jobs.push(job);
|
|
50
|
-
saveCronRegistry(registry);
|
|
51
|
-
return job;
|
|
52
|
-
}
|
|
53
|
-
export function removeJob(id) {
|
|
54
|
-
const registry = loadCronRegistry();
|
|
55
|
-
const index = registry.jobs.findIndex((job) => job.id === id);
|
|
56
|
-
if (index < 0)
|
|
57
|
-
return false;
|
|
58
|
-
registry.jobs.splice(index, 1);
|
|
59
|
-
saveCronRegistry(registry);
|
|
60
|
-
return true;
|
|
61
|
-
}
|
|
62
|
-
export function setJobEnabled(id, enabled) {
|
|
63
|
-
const registry = loadCronRegistry();
|
|
64
|
-
const job = registry.jobs.find((item) => item.id === id);
|
|
65
|
-
if (!job)
|
|
66
|
-
return false;
|
|
67
|
-
job.enabled = enabled;
|
|
68
|
-
saveCronRegistry(registry);
|
|
69
|
-
return true;
|
|
70
|
-
}
|
|
71
|
-
export function recordRun(id, at, status) {
|
|
72
|
-
const registry = loadCronRegistry();
|
|
73
|
-
const job = registry.jobs.find((item) => item.id === id);
|
|
74
|
-
if (!job)
|
|
75
|
-
return;
|
|
76
|
-
job.last_run = at;
|
|
77
|
-
job.last_status = status;
|
|
78
|
-
saveCronRegistry(registry);
|
|
79
|
-
}
|
|
80
|
-
export function validateSchedule(schedule, tz) {
|
|
81
|
-
let cron;
|
|
82
|
-
try {
|
|
83
|
-
cron = new Cron(schedule, tz ? { timezone: tz } : {});
|
|
84
|
-
}
|
|
85
|
-
catch (error) {
|
|
86
|
-
return { ok: false, error: `invalid cron expression: ${error.message}` };
|
|
87
|
-
}
|
|
88
|
-
try {
|
|
89
|
-
const first = cron.nextRun();
|
|
90
|
-
const second = first ? cron.nextRun(first) : null;
|
|
91
|
-
if (!first || !second)
|
|
92
|
-
return { ok: false, error: "schedule has no upcoming runs" };
|
|
93
|
-
const intervalMs = second.getTime() - first.getTime();
|
|
94
|
-
if (intervalMs < MIN_INTERVAL_MS) {
|
|
95
|
-
return { ok: false, intervalMs, error: `schedule too frequent: ~${Math.round(intervalMs / 1000)}s between runs (minimum is 60s)` };
|
|
96
|
-
}
|
|
97
|
-
return { ok: true, intervalMs };
|
|
98
|
-
}
|
|
99
|
-
finally {
|
|
100
|
-
cron.stop();
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
export function nextRunFor(job) {
|
|
104
|
-
try {
|
|
105
|
-
const cron = new Cron(job.schedule, job.tz ? { timezone: job.tz } : {});
|
|
106
|
-
const next = cron.nextRun();
|
|
107
|
-
cron.stop();
|
|
108
|
-
return next;
|
|
109
|
-
}
|
|
110
|
-
catch {
|
|
111
|
-
return null;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
function freshId(existing) {
|
|
115
|
-
for (let attempt = 0; attempt < 1000; attempt += 1) {
|
|
116
|
-
const id = `j_${randomBytes(4).toString("hex")}`;
|
|
117
|
-
if (!existing.some((job) => job.id === id))
|
|
118
|
-
return id;
|
|
119
|
-
}
|
|
120
|
-
throw new Error("cron id space exhausted");
|
|
121
|
-
}
|
|
122
|
-
function coerceJob(value) {
|
|
123
|
-
if (!value || typeof value !== "object")
|
|
124
|
-
return null;
|
|
125
|
-
const raw = value;
|
|
126
|
-
// No dual-read/migration of wake: old records are deliberately excluded.
|
|
127
|
-
if (Object.hasOwn(raw, "wake"))
|
|
128
|
-
return null;
|
|
129
|
-
if (typeof raw["id"] !== "string" || typeof raw["daemon_id"] !== "string" || typeof raw["schedule"] !== "string" || typeof raw["prompt"] !== "string")
|
|
130
|
-
return null;
|
|
131
|
-
const job = {
|
|
132
|
-
id: raw["id"],
|
|
133
|
-
daemon_id: raw["daemon_id"],
|
|
134
|
-
schedule: raw["schedule"],
|
|
135
|
-
prompt: raw["prompt"],
|
|
136
|
-
enabled: raw["enabled"] !== false,
|
|
137
|
-
skip_if_busy: raw["skip_if_busy"] !== false,
|
|
138
|
-
catchup: raw["catchup"] === true,
|
|
139
|
-
created_at: typeof raw["created_at"] === "string" ? raw["created_at"] : new Date(0).toISOString(),
|
|
140
|
-
};
|
|
141
|
-
if (typeof raw["tz"] === "string")
|
|
142
|
-
job.tz = raw["tz"];
|
|
143
|
-
if (typeof raw["last_run"] === "string")
|
|
144
|
-
job.last_run = raw["last_run"];
|
|
145
|
-
if (typeof raw["last_status"] === "string")
|
|
146
|
-
job.last_status = raw["last_status"];
|
|
147
|
-
return job;
|
|
148
|
-
}
|
|
149
|
-
//# sourceMappingURL=cron_registry.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cron_registry.js","sourceRoot":"","sources":["../../src/daemon/cron_registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export declare function execCommand(cmd: string, args: string[], log: string[]): void;
|
|
2
|
-
/** Cleanup commands may fail when the service is not currently installed. */
|
|
3
|
-
export declare function tryExecCommand(cmd: string, args: string[], log: string[]): void;
|
|
4
|
-
/** Build the elevated Windows batch script. Kept pure for cross-platform tests. */
|
|
5
|
-
export declare function buildElevatedCmd(lines: string[], logFile: string): string;
|
|
6
|
-
/** Run a schtasks sequence through one UAC prompt and surface its output. */
|
|
7
|
-
export declare function execElevatedWindows(lines: string[], log: string[]): void;
|
|
8
|
-
export declare const _exec: typeof execCommand;
|
|
9
|
-
export declare const _tryExec: typeof tryExecCommand;
|
|
10
|
-
export declare const _execElevatedWindows: typeof execElevatedWindows;
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { execFileSync } from "node:child_process";
|
|
2
|
-
import { readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { tmpdir } from "node:os";
|
|
5
|
-
export function execCommand(cmd, args, log) {
|
|
6
|
-
try {
|
|
7
|
-
const out = execFileSync(cmd, args, { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
8
|
-
if (out.trim())
|
|
9
|
-
log.push(`$ ${cmd} ${args.join(" ")}\n${out.trim()}`);
|
|
10
|
-
else
|
|
11
|
-
log.push(`$ ${cmd} ${args.join(" ")}`);
|
|
12
|
-
}
|
|
13
|
-
catch (error) {
|
|
14
|
-
const err = error;
|
|
15
|
-
const stderr = typeof err.stderr === "string" ? err.stderr : err.stderr?.toString() ?? "";
|
|
16
|
-
throw new Error(`\`${cmd} ${args.join(" ")}\` exited ${err.status ?? "?"}\n${stderr.trim() || err.message}`);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
/** Cleanup commands may fail when the service is not currently installed. */
|
|
20
|
-
export function tryExecCommand(cmd, args, log) {
|
|
21
|
-
try {
|
|
22
|
-
execCommand(cmd, args, log);
|
|
23
|
-
}
|
|
24
|
-
catch { /* expected cleanup failure */ }
|
|
25
|
-
}
|
|
26
|
-
/** Build the elevated Windows batch script. Kept pure for cross-platform tests. */
|
|
27
|
-
export function buildElevatedCmd(lines, logFile) {
|
|
28
|
-
const redirect = ` >> "${logFile}" 2>&1`;
|
|
29
|
-
const body = lines.map((line) => /^\s*(if|exit|rem|@)/i.test(line) ? line : line + redirect);
|
|
30
|
-
return ["@echo off", ...body].join("\r\n") + "\r\n";
|
|
31
|
-
}
|
|
32
|
-
function readIfExists(path) {
|
|
33
|
-
try {
|
|
34
|
-
return readFileSync(path, "utf8");
|
|
35
|
-
}
|
|
36
|
-
catch {
|
|
37
|
-
return "";
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
/** Run a schtasks sequence through one UAC prompt and surface its output. */
|
|
41
|
-
export function execElevatedWindows(lines, log) {
|
|
42
|
-
const base = join(tmpdir(), `remote-pi-elevate-${process.pid}`);
|
|
43
|
-
const cmdPath = `${base}.cmd`;
|
|
44
|
-
const logFile = `${base}.log`;
|
|
45
|
-
writeFileSync(cmdPath, buildElevatedCmd(lines, logFile));
|
|
46
|
-
try {
|
|
47
|
-
unlinkSync(logFile);
|
|
48
|
-
}
|
|
49
|
-
catch { /* none yet */ }
|
|
50
|
-
let thrown = null;
|
|
51
|
-
try {
|
|
52
|
-
execFileSync("powershell", [
|
|
53
|
-
"-NoProfile", "-NonInteractive", "-Command",
|
|
54
|
-
`$p = Start-Process -FilePath cmd.exe -ArgumentList '/c','"${cmdPath}"' ` +
|
|
55
|
-
"-Verb RunAs -Wait -PassThru -WindowStyle Hidden; exit $p.ExitCode",
|
|
56
|
-
], { stdio: ["ignore", "pipe", "pipe"] });
|
|
57
|
-
}
|
|
58
|
-
catch (error) {
|
|
59
|
-
thrown = error;
|
|
60
|
-
}
|
|
61
|
-
const output = readIfExists(logFile).trim();
|
|
62
|
-
if (output)
|
|
63
|
-
log.push(output);
|
|
64
|
-
try {
|
|
65
|
-
unlinkSync(cmdPath);
|
|
66
|
-
}
|
|
67
|
-
catch { /* best-effort */ }
|
|
68
|
-
try {
|
|
69
|
-
unlinkSync(logFile);
|
|
70
|
-
}
|
|
71
|
-
catch { /* best-effort */ }
|
|
72
|
-
if (thrown) {
|
|
73
|
-
throw new Error("administrator privileges required — the UAC prompt was declined or the " +
|
|
74
|
-
"schtasks operation failed. Run the command again and accept the Windows " +
|
|
75
|
-
`elevation prompt.${output ? `\n${output}` : ""}`);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
export const _exec = execCommand;
|
|
79
|
-
export const _tryExec = tryExecCommand;
|
|
80
|
-
export const _execElevatedWindows = execElevatedWindows;
|
|
81
|
-
//# sourceMappingURL=install-runtime.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"install-runtime.js","sourceRoot":"","sources":["../../src/daemon/install-runtime.ts"],"names":[],"mappings":"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"}
|