@geohar/un-bien 0.7.0 → 0.9.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 +237 -268
- package/dist/bin/launcher.js +38 -0
- package/dist/bin/launcher.js.map +1 -0
- package/dist/config.d.ts +41 -1
- package/dist/config.js.map +1 -1
- package/dist/daemon/install.d.ts +33 -35
- package/dist/daemon/install.js +43 -73
- package/dist/daemon/install.js.map +1 -1
- package/dist/enrich_tool_args.d.ts +9 -0
- package/dist/enrich_tool_args.js +171 -0
- package/dist/enrich_tool_args.js.map +1 -0
- package/dist/image_codec.d.ts +22 -0
- package/dist/image_codec.js +149 -0
- package/dist/image_codec.js.map +1 -0
- package/dist/index.d.ts +0 -26
- package/dist/index.js +235 -1237
- package/dist/index.js.map +1 -1
- package/dist/launch.d.ts +34 -0
- package/dist/launch.js +171 -0
- package/dist/launch.js.map +1 -0
- package/dist/launcher/launcher.d.ts +6 -0
- package/dist/launcher/launcher.js +188 -0
- package/dist/launcher/launcher.js.map +1 -0
- package/dist/pairing/crypto.d.ts +4 -0
- package/dist/pairing/crypto.js +10 -0
- package/dist/pairing/crypto.js.map +1 -1
- package/dist/pairing/peer_trust.d.ts +20 -0
- package/dist/pairing/peer_trust.js +82 -0
- package/dist/pairing/peer_trust.js.map +1 -0
- package/dist/pairing/storage.d.ts +51 -26
- package/dist/pairing/storage.js +346 -136
- package/dist/pairing/storage.js.map +1 -1
- package/dist/panel_bridge.d.ts +3 -1
- package/dist/panel_bridge.js +10 -10
- package/dist/panel_bridge.js.map +1 -1
- package/dist/rooms.d.ts +16 -0
- package/dist/rooms.js +22 -0
- package/dist/rooms.js.map +1 -1
- package/dist/session/debug_log.js +2 -2
- package/dist/session/debug_log.js.map +1 -1
- package/dist/session/local_config.js +2 -0
- package/dist/session/local_config.js.map +1 -1
- package/dist/session/rpc_envelope.d.ts +18 -0
- package/dist/session/rpc_envelope.js +1 -1
- package/dist/session/rpc_envelope.js.map +1 -1
- package/dist/session/rpc_inbound.d.ts +2 -2
- package/dist/session/rpc_inbound.js +1 -1
- package/dist/session/rpc_inbound.js.map +1 -1
- package/dist/subagent_rooms.d.ts +49 -0
- package/dist/subagent_rooms.js +787 -0
- package/dist/subagent_rooms.js.map +1 -0
- package/dist/transport/peer_channel.d.ts +7 -1
- package/dist/transport/peer_channel.js +8 -1
- package/dist/transport/peer_channel.js.map +1 -1
- package/dist/transport/relay_client.d.ts +19 -0
- package/dist/transport/relay_client.js.map +1 -1
- package/docs/daemon.md +65 -64
- package/package.json +13 -11
- package/service-templates/launchd.plist.template +5 -5
- package/service-templates/systemd.service.template +2 -2
- package/service-templates/task-launcher.vbs.template +5 -5
- package/service-templates/task-scheduler.xml.template +1 -1
- package/dist/bin/supervisord.js +0 -86
- package/dist/bin/supervisord.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/control_protocol.d.ts +0 -176
- package/dist/daemon/control_protocol.js +0 -63
- package/dist/daemon/control_protocol.js.map +0 -1
- package/dist/daemon/cron_log.d.ts +0 -45
- package/dist/daemon/cron_log.js +0 -71
- package/dist/daemon/cron_log.js.map +0 -1
- package/dist/daemon/cron_registry.d.ts +0 -80
- package/dist/daemon/cron_registry.js +0 -198
- package/dist/daemon/cron_registry.js.map +0 -1
- 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/daemon/registry.d.ts +0 -63
- package/dist/daemon/registry.js +0 -153
- package/dist/daemon/registry.js.map +0 -1
- package/dist/daemon/rpc_child.d.ts +0 -194
- package/dist/daemon/rpc_child.js +0 -419
- package/dist/daemon/rpc_child.js.map +0 -1
- package/dist/daemon/supervisor.d.ts +0 -93
- package/dist/daemon/supervisor.js +0 -666
- package/dist/daemon/supervisor.js.map +0 -1
- /package/dist/bin/{supervisord.d.ts → launcher.d.ts} +0 -0
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cron registry: scheduled prompts for daemons, persisted at
|
|
3
|
-
* `~/.pi/un-bien/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
|
-
export declare const MIN_INTERVAL_MS = 60000;
|
|
15
|
-
/** A scheduled prompt. */
|
|
16
|
-
export interface CronJob {
|
|
17
|
-
/** `j_<hex>` — random, stable across restarts. */
|
|
18
|
-
id: string;
|
|
19
|
-
/** Target daemon id (`daemonIdForCwd`). */
|
|
20
|
-
daemon_id: string;
|
|
21
|
-
/** Cron expression (croner syntax; optional 6th seconds field supported). */
|
|
22
|
-
schedule: string;
|
|
23
|
-
/** IANA timezone for the schedule (e.g. "America/Sao_Paulo"). */
|
|
24
|
-
tz?: string;
|
|
25
|
-
/** Prompt text injected into the daemon when the job fires. */
|
|
26
|
-
prompt: string;
|
|
27
|
-
enabled: boolean;
|
|
28
|
-
/** Skip the fire when the daemon is mid-turn (default true). */
|
|
29
|
-
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
|
-
catchup: boolean;
|
|
35
|
-
created_at: string;
|
|
36
|
-
last_run?: string;
|
|
37
|
-
/** Last fire result — see cron_log `result` values. Shortcut for `cron list`. */
|
|
38
|
-
last_status?: string;
|
|
39
|
-
}
|
|
40
|
-
export interface CronRegistry {
|
|
41
|
-
jobs: CronJob[];
|
|
42
|
-
}
|
|
43
|
-
/** Test/diag-only: the on-disk path. */
|
|
44
|
-
export declare function cronRegistryPath(): string;
|
|
45
|
-
/** Reads the registry; returns empty on missing/corrupt file. */
|
|
46
|
-
export declare function loadCronRegistry(): CronRegistry;
|
|
47
|
-
export declare function saveCronRegistry(reg: CronRegistry): void;
|
|
48
|
-
export declare function listJobs(): CronJob[];
|
|
49
|
-
export declare function getJob(id: string): CronJob | undefined;
|
|
50
|
-
/** Fields a caller supplies when creating a job. Flags default sensibly. */
|
|
51
|
-
export interface NewJobInput {
|
|
52
|
-
daemon_id: string;
|
|
53
|
-
schedule: string;
|
|
54
|
-
prompt: string;
|
|
55
|
-
tz?: string;
|
|
56
|
-
skip_if_busy?: boolean;
|
|
57
|
-
wake?: boolean;
|
|
58
|
-
catchup?: boolean;
|
|
59
|
-
}
|
|
60
|
-
/** Adds a job with a fresh `j_<hex>` id. Pure persistence — call
|
|
61
|
-
* `validateSchedule` first at the op/CLI boundary. */
|
|
62
|
-
export declare function addJob(input: NewJobInput): CronJob;
|
|
63
|
-
export declare function removeJob(id: string): boolean;
|
|
64
|
-
export declare function setJobEnabled(id: string, enabled: boolean): boolean;
|
|
65
|
-
/** Records the outcome of a fire on the job (the `cron list` shortcut). */
|
|
66
|
-
export declare function recordRun(id: string, at: string, status: string): void;
|
|
67
|
-
export interface ScheduleValidation {
|
|
68
|
-
ok: boolean;
|
|
69
|
-
error?: string;
|
|
70
|
-
/** Interval (ms) between the next two runs, when computable. */
|
|
71
|
-
intervalMs?: number;
|
|
72
|
-
}
|
|
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
|
-
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
|
-
export declare function nextRunFor(job: CronJob): Date | null;
|
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
-
import { randomBytes } from "node:crypto";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
import { Cron } from "croner";
|
|
5
|
-
import { unbienStateHome } from "../paths.js";
|
|
6
|
-
/**
|
|
7
|
-
* Cron registry: scheduled prompts for daemons, persisted at
|
|
8
|
-
* `~/.pi/un-bien/cron.json`. Mirrors `registry.ts` (`daemons.json`) — tolerant
|
|
9
|
-
* load (missing/corrupt → empty), atomic-ish full-file save.
|
|
10
|
-
*
|
|
11
|
-
* Each job targets a daemon by its `daemon_id` (the 8-hex id from
|
|
12
|
-
* `daemonIdForCwd`) and fires `prompt` on `schedule` (a cron expression, run
|
|
13
|
-
* by croner in the supervisor). The scheduler engine + `fireJob` live in
|
|
14
|
-
* `supervisor.ts`; this module only owns persistence + schedule validation.
|
|
15
|
-
*
|
|
16
|
-
* Plan/39. Decisions B (croner), C (min-interval 60s), E (audit via cron_log).
|
|
17
|
-
*/
|
|
18
|
-
/** Minimum allowed interval between two consecutive runs of a schedule. */
|
|
19
|
-
export const MIN_INTERVAL_MS = 60_000;
|
|
20
|
-
function cronPath() {
|
|
21
|
-
return join(unbienStateHome(), "cron.json");
|
|
22
|
-
}
|
|
23
|
-
/** Test/diag-only: the on-disk path. */
|
|
24
|
-
export function cronRegistryPath() {
|
|
25
|
-
return cronPath();
|
|
26
|
-
}
|
|
27
|
-
/** Reads the registry; returns empty on missing/corrupt file. */
|
|
28
|
-
export function loadCronRegistry() {
|
|
29
|
-
if (!existsSync(cronPath()))
|
|
30
|
-
return { jobs: [] };
|
|
31
|
-
try {
|
|
32
|
-
const parsed = JSON.parse(readFileSync(cronPath(), "utf8"));
|
|
33
|
-
if (!parsed || typeof parsed !== "object")
|
|
34
|
-
return { jobs: [] };
|
|
35
|
-
const arr = parsed.jobs;
|
|
36
|
-
if (!Array.isArray(arr))
|
|
37
|
-
return { jobs: [] };
|
|
38
|
-
const jobs = [];
|
|
39
|
-
for (const item of arr) {
|
|
40
|
-
const job = _coerceJob(item);
|
|
41
|
-
if (job)
|
|
42
|
-
jobs.push(job);
|
|
43
|
-
}
|
|
44
|
-
return { jobs };
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
return { jobs: [] };
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
export function saveCronRegistry(reg) {
|
|
51
|
-
mkdirSync(dirname(cronPath()), { recursive: true });
|
|
52
|
-
writeFileSync(cronPath(), JSON.stringify(reg, null, 2) + "\n");
|
|
53
|
-
}
|
|
54
|
-
export function listJobs() {
|
|
55
|
-
return loadCronRegistry().jobs;
|
|
56
|
-
}
|
|
57
|
-
export function getJob(id) {
|
|
58
|
-
return loadCronRegistry().jobs.find((j) => j.id === id);
|
|
59
|
-
}
|
|
60
|
-
/** Adds a job with a fresh `j_<hex>` id. Pure persistence — call
|
|
61
|
-
* `validateSchedule` first at the op/CLI boundary. */
|
|
62
|
-
export function addJob(input) {
|
|
63
|
-
const reg = loadCronRegistry();
|
|
64
|
-
const job = {
|
|
65
|
-
id: _freshId(reg.jobs),
|
|
66
|
-
daemon_id: input.daemon_id,
|
|
67
|
-
schedule: input.schedule,
|
|
68
|
-
prompt: input.prompt,
|
|
69
|
-
enabled: true,
|
|
70
|
-
skip_if_busy: input.skip_if_busy ?? true,
|
|
71
|
-
wake: input.wake ?? false,
|
|
72
|
-
catchup: input.catchup ?? false,
|
|
73
|
-
created_at: new Date().toISOString(),
|
|
74
|
-
};
|
|
75
|
-
if (input.tz)
|
|
76
|
-
job.tz = input.tz;
|
|
77
|
-
reg.jobs.push(job);
|
|
78
|
-
saveCronRegistry(reg);
|
|
79
|
-
return job;
|
|
80
|
-
}
|
|
81
|
-
export function removeJob(id) {
|
|
82
|
-
const reg = loadCronRegistry();
|
|
83
|
-
const idx = reg.jobs.findIndex((j) => j.id === id);
|
|
84
|
-
if (idx === -1)
|
|
85
|
-
return false;
|
|
86
|
-
reg.jobs.splice(idx, 1);
|
|
87
|
-
saveCronRegistry(reg);
|
|
88
|
-
return true;
|
|
89
|
-
}
|
|
90
|
-
export function setJobEnabled(id, enabled) {
|
|
91
|
-
const reg = loadCronRegistry();
|
|
92
|
-
const job = reg.jobs.find((j) => j.id === id);
|
|
93
|
-
if (!job)
|
|
94
|
-
return false;
|
|
95
|
-
job.enabled = enabled;
|
|
96
|
-
saveCronRegistry(reg);
|
|
97
|
-
return true;
|
|
98
|
-
}
|
|
99
|
-
/** Records the outcome of a fire on the job (the `cron list` shortcut). */
|
|
100
|
-
export function recordRun(id, at, status) {
|
|
101
|
-
const reg = loadCronRegistry();
|
|
102
|
-
const job = reg.jobs.find((j) => j.id === id);
|
|
103
|
-
if (!job)
|
|
104
|
-
return;
|
|
105
|
-
job.last_run = at;
|
|
106
|
-
job.last_status = status;
|
|
107
|
-
saveCronRegistry(reg);
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Validates a cron expression via croner and enforces the ≥60s min-interval
|
|
111
|
-
* (decision C — guards against pileup + token burn). Returns `ok:false` with a
|
|
112
|
-
* user-facing message on a bad expression or a too-frequent schedule.
|
|
113
|
-
*/
|
|
114
|
-
export function validateSchedule(schedule, tz) {
|
|
115
|
-
let cron;
|
|
116
|
-
try {
|
|
117
|
-
cron = new Cron(schedule, tz ? { timezone: tz } : {});
|
|
118
|
-
}
|
|
119
|
-
catch (e) {
|
|
120
|
-
return {
|
|
121
|
-
ok: false,
|
|
122
|
-
error: `invalid cron expression: ${e.message}`,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
try {
|
|
126
|
-
const n1 = cron.nextRun();
|
|
127
|
-
const n2 = n1 ? cron.nextRun(n1) : null;
|
|
128
|
-
if (!n1 || !n2)
|
|
129
|
-
return { ok: false, error: "schedule has no upcoming runs" };
|
|
130
|
-
const intervalMs = n2.getTime() - n1.getTime();
|
|
131
|
-
if (intervalMs < MIN_INTERVAL_MS) {
|
|
132
|
-
return {
|
|
133
|
-
ok: false,
|
|
134
|
-
intervalMs,
|
|
135
|
-
error: `schedule too frequent: ~${Math.round(intervalMs / 1000)}s between runs (minimum is 60s)`,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
return { ok: true, intervalMs };
|
|
139
|
-
}
|
|
140
|
-
finally {
|
|
141
|
-
cron.stop();
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
/** Returns the next scheduled run for a job, or null. Used by `cron list`. */
|
|
145
|
-
export function nextRunFor(job) {
|
|
146
|
-
try {
|
|
147
|
-
const cron = new Cron(job.schedule, job.tz ? { timezone: job.tz } : {});
|
|
148
|
-
const n = cron.nextRun();
|
|
149
|
-
cron.stop();
|
|
150
|
-
return n;
|
|
151
|
-
}
|
|
152
|
-
catch {
|
|
153
|
-
return null;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
// ── internals ───────────────────────────────────────────────────────────────
|
|
157
|
-
function _freshId(existing) {
|
|
158
|
-
for (let i = 0; i < 1000; i++) {
|
|
159
|
-
const id = `j_${randomBytes(4).toString("hex")}`;
|
|
160
|
-
if (!existing.some((j) => j.id === id))
|
|
161
|
-
return id;
|
|
162
|
-
}
|
|
163
|
-
throw new Error("cron id space exhausted");
|
|
164
|
-
}
|
|
165
|
-
function _coerceJob(item) {
|
|
166
|
-
if (!item || typeof item !== "object")
|
|
167
|
-
return null;
|
|
168
|
-
const o = item;
|
|
169
|
-
if (typeof o["id"] !== "string")
|
|
170
|
-
return null;
|
|
171
|
-
if (typeof o["daemon_id"] !== "string")
|
|
172
|
-
return null;
|
|
173
|
-
if (typeof o["schedule"] !== "string")
|
|
174
|
-
return null;
|
|
175
|
-
if (typeof o["prompt"] !== "string")
|
|
176
|
-
return null;
|
|
177
|
-
const job = {
|
|
178
|
-
id: o["id"],
|
|
179
|
-
daemon_id: o["daemon_id"],
|
|
180
|
-
schedule: o["schedule"],
|
|
181
|
-
prompt: o["prompt"],
|
|
182
|
-
enabled: o["enabled"] !== false,
|
|
183
|
-
skip_if_busy: o["skip_if_busy"] !== false,
|
|
184
|
-
wake: o["wake"] === true,
|
|
185
|
-
catchup: o["catchup"] === true,
|
|
186
|
-
created_at: typeof o["created_at"] === "string"
|
|
187
|
-
? o["created_at"]
|
|
188
|
-
: new Date(0).toISOString(),
|
|
189
|
-
};
|
|
190
|
-
if (typeof o["tz"] === "string")
|
|
191
|
-
job.tz = o["tz"];
|
|
192
|
-
if (typeof o["last_run"] === "string")
|
|
193
|
-
job.last_run = o["last_run"];
|
|
194
|
-
if (typeof o["last_status"] === "string")
|
|
195
|
-
job.last_status = o["last_status"];
|
|
196
|
-
return job;
|
|
197
|
-
}
|
|
198
|
-
//# 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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"}
|
package/dist/daemon/id.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Stable 8-character hex id for a daemon, derived from the cwd it manages.
|
|
3
|
-
*
|
|
4
|
-
* Derivation: `sha256(realpath(cwd))` truncated to 8 hex chars (32 bits ≈
|
|
5
|
-
* 4 billion). Collision risk is negligible at fleet sizes a single user
|
|
6
|
-
* will ever have (<1000 daemons), and 8 hex characters are short enough
|
|
7
|
-
* to type on the CLI (`/unbien send a1b2c3d4 "..."`).
|
|
8
|
-
*
|
|
9
|
-
* Same scheme as `roomIdForCwd` in `src/rooms.ts` — but we use hex
|
|
10
|
-
* instead of base64url so the id has no `_`/`-` (cleaner double-click
|
|
11
|
-
* selection in terminals).
|
|
12
|
-
*
|
|
13
|
-
* Symlinks resolve to a single canonical id via `realpath`, so
|
|
14
|
-
* `/Users/x/Movies` and `/Users/x/link-to-Movies` map to the same daemon.
|
|
15
|
-
* Falls back to the raw path when realpath fails (cwd doesn't exist —
|
|
16
|
-
* shouldn't happen in production but covers test sandboxes).
|
|
17
|
-
*
|
|
18
|
-
* plan/41 audit (2026-06-08): this stays **per-cwd** (no name axis). The
|
|
19
|
-
* multiagent-per-folder model (plan/38/41) applies to the App↔Pi room and the
|
|
20
|
-
* mesh address; a *supervisor daemon* is **one per cwd** by design — the
|
|
21
|
-
* registry keys exactly one entry per cwd (`registry.ts`), so a daemon id never
|
|
22
|
-
* needs the name to disambiguate. Decision: leave `daemonIdForCwd` cwd-only.
|
|
23
|
-
*/
|
|
24
|
-
export declare function daemonIdForCwd(cwd: string): string;
|
package/dist/daemon/id.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { realpathSync } from "node:fs";
|
|
3
|
-
/**
|
|
4
|
-
* Stable 8-character hex id for a daemon, derived from the cwd it manages.
|
|
5
|
-
*
|
|
6
|
-
* Derivation: `sha256(realpath(cwd))` truncated to 8 hex chars (32 bits ≈
|
|
7
|
-
* 4 billion). Collision risk is negligible at fleet sizes a single user
|
|
8
|
-
* will ever have (<1000 daemons), and 8 hex characters are short enough
|
|
9
|
-
* to type on the CLI (`/unbien send a1b2c3d4 "..."`).
|
|
10
|
-
*
|
|
11
|
-
* Same scheme as `roomIdForCwd` in `src/rooms.ts` — but we use hex
|
|
12
|
-
* instead of base64url so the id has no `_`/`-` (cleaner double-click
|
|
13
|
-
* selection in terminals).
|
|
14
|
-
*
|
|
15
|
-
* Symlinks resolve to a single canonical id via `realpath`, so
|
|
16
|
-
* `/Users/x/Movies` and `/Users/x/link-to-Movies` map to the same daemon.
|
|
17
|
-
* Falls back to the raw path when realpath fails (cwd doesn't exist —
|
|
18
|
-
* shouldn't happen in production but covers test sandboxes).
|
|
19
|
-
*
|
|
20
|
-
* plan/41 audit (2026-06-08): this stays **per-cwd** (no name axis). The
|
|
21
|
-
* multiagent-per-folder model (plan/38/41) applies to the App↔Pi room and the
|
|
22
|
-
* mesh address; a *supervisor daemon* is **one per cwd** by design — the
|
|
23
|
-
* registry keys exactly one entry per cwd (`registry.ts`), so a daemon id never
|
|
24
|
-
* needs the name to disambiguate. Decision: leave `daemonIdForCwd` cwd-only.
|
|
25
|
-
*/
|
|
26
|
-
export function daemonIdForCwd(cwd) {
|
|
27
|
-
let target;
|
|
28
|
-
try {
|
|
29
|
-
target = realpathSync(cwd);
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
target = cwd;
|
|
33
|
-
}
|
|
34
|
-
return createHash("sha256").update(target).digest("hex").slice(0, 8);
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=id.js.map
|
package/dist/daemon/id.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"id.js","sourceRoot":"","sources":["../../src/daemon/id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,IAAI,MAAc,CAAC;IACnB,IAAI,CAAC;QACH,MAAM,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,GAAG,GAAG,CAAC;IACf,CAAC;IACD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AACvE,CAAC"}
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
export interface DaemonEntry {
|
|
2
|
-
/** Absolute realpath of the cwd this daemon manages. */
|
|
3
|
-
cwd: string;
|
|
4
|
-
/**
|
|
5
|
-
* Display name (mesh `agent_name`). Persisted here because the supervisor
|
|
6
|
-
* now injects the daemon's config via `UNBIEN_DIRECT_CONFIG` at spawn
|
|
7
|
-
* instead of reading a per-cwd `.pi/un-bien/config.json`. Legacy entries
|
|
8
|
-
* (cwd only) fall back to `defaultAgentName(cwd)`.
|
|
9
|
-
*/
|
|
10
|
-
name?: string;
|
|
11
|
-
}
|
|
12
|
-
export interface DaemonRegistry {
|
|
13
|
-
daemons: DaemonEntry[];
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Normalizes a user-provided path: expands `~`/`~/...`, resolves relative
|
|
17
|
-
* components against `process.cwd()`, and runs `realpath` to canonicalize
|
|
18
|
-
* symlinks. Throws if the resulting path doesn't exist on disk.
|
|
19
|
-
*
|
|
20
|
-
* `/unbien create` always stores normalized paths so two registrations
|
|
21
|
-
* of the same logical folder via different aliases produce a single entry.
|
|
22
|
-
*/
|
|
23
|
-
export declare function normalizeCwd(input: string): string;
|
|
24
|
-
/** Reads the registry, returning an empty one when the file is absent. */
|
|
25
|
-
export declare function loadRegistry(): DaemonRegistry;
|
|
26
|
-
export declare function saveRegistry(reg: DaemonRegistry): void;
|
|
27
|
-
/**
|
|
28
|
-
* Adds a daemon entry. Refuses duplicates (same normalized cwd already
|
|
29
|
-
* present). Returns the derived id + normalized cwd so the caller can
|
|
30
|
-
* report it back to the user.
|
|
31
|
-
*/
|
|
32
|
-
export declare function addDaemon(rawCwd: string, name?: string): {
|
|
33
|
-
id: string;
|
|
34
|
-
cwd: string;
|
|
35
|
-
name: string;
|
|
36
|
-
};
|
|
37
|
-
/**
|
|
38
|
-
* Removes the daemon entry whose derived id matches `id`. Returns the
|
|
39
|
-
* removed cwd (if any). Does NOT touch the cwd's local config — `create`
|
|
40
|
-
* the same cwd later restores the registration idempotently.
|
|
41
|
-
*/
|
|
42
|
-
export declare function removeDaemon(id: string): {
|
|
43
|
-
removed: boolean;
|
|
44
|
-
cwd?: string;
|
|
45
|
-
};
|
|
46
|
-
/** Snapshot of all registered daemons with derived ids. Order matches the
|
|
47
|
-
* file's insertion order — first-registered first. */
|
|
48
|
-
export declare function listDaemons(): Array<{
|
|
49
|
-
id: string;
|
|
50
|
-
cwd: string;
|
|
51
|
-
name: string;
|
|
52
|
-
}>;
|
|
53
|
-
/**
|
|
54
|
-
* One-shot migration: backfill `name` (folder-derived) into legacy entries
|
|
55
|
-
* that predate the name field, persisting the change to `daemons.json`.
|
|
56
|
-
* Idempotent — writes only when something was missing. Returns how many
|
|
57
|
-
* entries were backfilled. The supervisor runs this on start.
|
|
58
|
-
*/
|
|
59
|
-
export declare function migrateRegistryNames(): number;
|
|
60
|
-
/** Test/diag-only: returns the on-disk path. Exported so tests can poke
|
|
61
|
-
* at it (e.g. tmpdir override is done via env, but for now the path is
|
|
62
|
-
* hardcoded to ~/.pi/un-bien/daemons.json). */
|
|
63
|
-
export declare function registryPath(): string;
|
package/dist/daemon/registry.js
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, realpathSync, writeFileSync, } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { dirname, isAbsolute, join, resolve as resolvePath } from "node:path";
|
|
4
|
-
import { daemonIdForCwd } from "./id.js";
|
|
5
|
-
import { defaultAgentName } from "../session/local_config.js";
|
|
6
|
-
import { unbienStateHome } from "../paths.js";
|
|
7
|
-
/**
|
|
8
|
-
* The global daemon registry: which working directories are promoted to
|
|
9
|
-
* always-on daemons under the supervisor.
|
|
10
|
-
*
|
|
11
|
-
* Schema rationale (decision Q in plan/26): the registry stores **only**
|
|
12
|
-
* `cwd` per entry. Everything else (agent_name, auto_start_relay, etc.)
|
|
13
|
-
* is the cwd's local config at `<cwd>/.pi/un-bien/config.json` — single
|
|
14
|
-
* source of truth, no duplication. The daemon `id` is *derived* from cwd
|
|
15
|
-
* via `daemonIdForCwd`, never persisted.
|
|
16
|
-
*
|
|
17
|
-
* Cwds are always normalized to an **absolute realpath** before storage.
|
|
18
|
-
* A user typing `/unbien create ~/Movies` or `/unbien create .`
|
|
19
|
-
* results in the same entry as `/unbien create /Users/x/Movies` — no
|
|
20
|
-
* surprise duplicates, symlinks collapse correctly.
|
|
21
|
-
*/
|
|
22
|
-
/** Resolved at call time so tests can override via `UNBIEN_HOME`. The
|
|
23
|
-
* prod path is always `~/.pi/un-bien/daemons.json`. */
|
|
24
|
-
function registryPathInternal() {
|
|
25
|
-
return join(unbienStateHome(), "daemons.json");
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Normalizes a user-provided path: expands `~`/`~/...`, resolves relative
|
|
29
|
-
* components against `process.cwd()`, and runs `realpath` to canonicalize
|
|
30
|
-
* symlinks. Throws if the resulting path doesn't exist on disk.
|
|
31
|
-
*
|
|
32
|
-
* `/unbien create` always stores normalized paths so two registrations
|
|
33
|
-
* of the same logical folder via different aliases produce a single entry.
|
|
34
|
-
*/
|
|
35
|
-
export function normalizeCwd(input) {
|
|
36
|
-
if (!input || !input.trim()) {
|
|
37
|
-
throw new Error("cwd is required");
|
|
38
|
-
}
|
|
39
|
-
let p = input.trim();
|
|
40
|
-
// Expand `~` / `~/relative`. Shell wouldn't expand inside slash command args.
|
|
41
|
-
if (p === "~")
|
|
42
|
-
p = homedir();
|
|
43
|
-
else if (p.startsWith("~/"))
|
|
44
|
-
p = join(homedir(), p.slice(2));
|
|
45
|
-
if (!isAbsolute(p))
|
|
46
|
-
p = resolvePath(process.cwd(), p);
|
|
47
|
-
// realpath canonicalizes symlinks + throws if path doesn't exist.
|
|
48
|
-
return realpathSync(p);
|
|
49
|
-
}
|
|
50
|
-
/** Reads the registry, returning an empty one when the file is absent. */
|
|
51
|
-
export function loadRegistry() {
|
|
52
|
-
if (!existsSync(registryPathInternal()))
|
|
53
|
-
return { daemons: [] };
|
|
54
|
-
try {
|
|
55
|
-
const raw = readFileSync(registryPathInternal(), "utf8");
|
|
56
|
-
const parsed = JSON.parse(raw);
|
|
57
|
-
if (!parsed || typeof parsed !== "object")
|
|
58
|
-
return { daemons: [] };
|
|
59
|
-
const arr = parsed.daemons;
|
|
60
|
-
if (!Array.isArray(arr))
|
|
61
|
-
return { daemons: [] };
|
|
62
|
-
const daemons = [];
|
|
63
|
-
for (const item of arr) {
|
|
64
|
-
if (!item || typeof item !== "object")
|
|
65
|
-
continue;
|
|
66
|
-
const cwd = item.cwd;
|
|
67
|
-
if (typeof cwd === "string" && cwd.length > 0) {
|
|
68
|
-
const rawName = item.name;
|
|
69
|
-
const entry = { cwd };
|
|
70
|
-
if (typeof rawName === "string" && rawName.length > 0)
|
|
71
|
-
entry.name = rawName;
|
|
72
|
-
daemons.push(entry);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return { daemons };
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
return { daemons: [] };
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
export function saveRegistry(reg) {
|
|
82
|
-
mkdirSync(dirname(registryPathInternal()), { recursive: true });
|
|
83
|
-
writeFileSync(registryPathInternal(), JSON.stringify(reg, null, 2) + "\n");
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Adds a daemon entry. Refuses duplicates (same normalized cwd already
|
|
87
|
-
* present). Returns the derived id + normalized cwd so the caller can
|
|
88
|
-
* report it back to the user.
|
|
89
|
-
*/
|
|
90
|
-
export function addDaemon(rawCwd, name) {
|
|
91
|
-
const cwd = normalizeCwd(rawCwd);
|
|
92
|
-
const reg = loadRegistry();
|
|
93
|
-
if (reg.daemons.some((d) => d.cwd === cwd)) {
|
|
94
|
-
throw new Error(`Daemon already registered for cwd: ${cwd}`);
|
|
95
|
-
}
|
|
96
|
-
// Always persist a name (the registry is the source of truth now that the
|
|
97
|
-
// supervisor injects config via env instead of a local config file).
|
|
98
|
-
const resolvedName = name?.trim() || defaultAgentName(cwd);
|
|
99
|
-
reg.daemons.push({ cwd, name: resolvedName });
|
|
100
|
-
saveRegistry(reg);
|
|
101
|
-
return { id: daemonIdForCwd(cwd), cwd, name: resolvedName };
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Removes the daemon entry whose derived id matches `id`. Returns the
|
|
105
|
-
* removed cwd (if any). Does NOT touch the cwd's local config — `create`
|
|
106
|
-
* the same cwd later restores the registration idempotently.
|
|
107
|
-
*/
|
|
108
|
-
export function removeDaemon(id) {
|
|
109
|
-
const reg = loadRegistry();
|
|
110
|
-
const idx = reg.daemons.findIndex((d) => daemonIdForCwd(d.cwd) === id);
|
|
111
|
-
if (idx === -1)
|
|
112
|
-
return { removed: false };
|
|
113
|
-
const [removed] = reg.daemons.splice(idx, 1);
|
|
114
|
-
saveRegistry(reg);
|
|
115
|
-
return { removed: true, cwd: removed.cwd };
|
|
116
|
-
}
|
|
117
|
-
/** Snapshot of all registered daemons with derived ids. Order matches the
|
|
118
|
-
* file's insertion order — first-registered first. */
|
|
119
|
-
export function listDaemons() {
|
|
120
|
-
return loadRegistry().daemons.map((d) => ({
|
|
121
|
-
id: daemonIdForCwd(d.cwd),
|
|
122
|
-
cwd: d.cwd,
|
|
123
|
-
// Legacy entries (cwd only) fall back to the folder-derived name so a
|
|
124
|
-
// daemon is never nameless. New entries already carry an explicit name.
|
|
125
|
-
name: d.name ?? defaultAgentName(d.cwd),
|
|
126
|
-
}));
|
|
127
|
-
}
|
|
128
|
-
/**
|
|
129
|
-
* One-shot migration: backfill `name` (folder-derived) into legacy entries
|
|
130
|
-
* that predate the name field, persisting the change to `daemons.json`.
|
|
131
|
-
* Idempotent — writes only when something was missing. Returns how many
|
|
132
|
-
* entries were backfilled. The supervisor runs this on start.
|
|
133
|
-
*/
|
|
134
|
-
export function migrateRegistryNames() {
|
|
135
|
-
const reg = loadRegistry();
|
|
136
|
-
let changed = 0;
|
|
137
|
-
for (const d of reg.daemons) {
|
|
138
|
-
if (!d.name) {
|
|
139
|
-
d.name = defaultAgentName(d.cwd);
|
|
140
|
-
changed++;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (changed > 0)
|
|
144
|
-
saveRegistry(reg);
|
|
145
|
-
return changed;
|
|
146
|
-
}
|
|
147
|
-
/** Test/diag-only: returns the on-disk path. Exported so tests can poke
|
|
148
|
-
* at it (e.g. tmpdir override is done via env, but for now the path is
|
|
149
|
-
* hardcoded to ~/.pi/un-bien/daemons.json). */
|
|
150
|
-
export function registryPath() {
|
|
151
|
-
return registryPathInternal();
|
|
152
|
-
}
|
|
153
|
-
//# sourceMappingURL=registry.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/daemon/registry.ts"],"names":[],"mappings":"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"}
|