@geohar/un-bien 0.8.0 → 0.14.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 +258 -320
- package/dist/actions/handlers.js.map +1 -1
- package/dist/actions/registry.js.map +1 -1
- package/dist/bin/launcher.js +38 -0
- package/dist/bin/launcher.js.map +1 -0
- package/dist/commands/deps.d.ts +156 -0
- package/dist/commands/deps.js +2 -0
- package/dist/commands/deps.js.map +1 -0
- package/dist/commands/fork_link.d.ts +4 -0
- package/dist/commands/fork_link.js +45 -0
- package/dist/commands/fork_link.js.map +1 -0
- package/dist/commands/housekeeping.d.ts +34 -0
- package/dist/commands/housekeeping.js +275 -0
- package/dist/commands/housekeeping.js.map +1 -0
- package/dist/commands/info.d.ts +43 -0
- package/dist/commands/info.js +127 -0
- package/dist/commands/info.js.map +1 -0
- package/dist/commands/lifecycle.d.ts +45 -0
- package/dist/commands/lifecycle.js +708 -0
- package/dist/commands/lifecycle.js.map +1 -0
- package/dist/commands/pairing.d.ts +26 -0
- package/dist/commands/pairing.js +167 -0
- package/dist/commands/pairing.js.map +1 -0
- package/dist/commands/register.d.ts +12 -0
- package/dist/commands/register.js +255 -0
- package/dist/commands/register.js.map +1 -0
- package/dist/commands/relay.d.ts +28 -0
- package/dist/commands/relay.js +81 -0
- package/dist/commands/relay.js.map +1 -0
- package/dist/commands/session_ops.d.ts +52 -0
- package/dist/commands/session_ops.js +75 -0
- package/dist/commands/session_ops.js.map +1 -0
- package/dist/config.d.ts +30 -2
- package/dist/config.js.map +1 -1
- package/dist/daemon/install.d.ts +36 -37
- package/dist/daemon/install.js +49 -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/extension_ui_bridge.js.map +1 -1
- 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 +32 -127
- package/dist/index.js +957 -4042
- package/dist/index.js.map +1 -1
- package/dist/launch.d.ts +42 -0
- package/dist/launch.js +206 -0
- package/dist/launch.js.map +1 -0
- package/dist/launcher/launcher.d.ts +6 -0
- package/dist/launcher/launcher.js +207 -0
- package/dist/launcher/launcher.js.map +1 -0
- package/dist/mcp/mesh_result.js.map +1 -1
- package/dist/mcp/mesh_server.js.map +1 -1
- package/dist/mesh/canonical.js +1 -1
- package/dist/mesh/canonical.js.map +1 -1
- package/dist/mesh/client.js.map +1 -1
- package/dist/mesh/encoding.js.map +1 -1
- package/dist/mesh/self_revoke.js.map +1 -1
- package/dist/mesh/siblings.js.map +1 -1
- package/dist/mesh/verify.js +1 -1
- package/dist/mesh/verify.js.map +1 -1
- package/dist/pairing/crypto.js +0 -1
- 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/qr.js.map +1 -1
- package/dist/pairing/storage.js +4 -3
- package/dist/pairing/storage.js.map +1 -1
- package/dist/panel_bridge.d.ts +3 -1
- package/dist/panel_bridge.js +11 -10
- package/dist/panel_bridge.js.map +1 -1
- package/dist/paths.d.ts +22 -8
- package/dist/paths.js +37 -10
- package/dist/paths.js.map +1 -1
- package/dist/protocol/codec.js.map +1 -1
- package/dist/rooms.d.ts +16 -0
- package/dist/rooms.js +23 -4
- package/dist/rooms.js.map +1 -1
- package/dist/session/bridge.js.map +1 -1
- package/dist/session/broker.js.map +1 -1
- package/dist/session/broker_remote.js.map +1 -1
- package/dist/session/capabilities.d.ts +11 -0
- package/dist/session/capabilities.js +35 -0
- package/dist/session/capabilities.js.map +1 -0
- package/dist/session/cwd_lock.js +3 -3
- package/dist/session/cwd_lock.js.map +1 -1
- package/dist/session/debug_log.js +15 -5
- package/dist/session/debug_log.js.map +1 -1
- package/dist/session/envelope.js.map +1 -1
- package/dist/session/global_config.d.ts +1 -1
- package/dist/session/global_config.js +1 -1
- package/dist/session/global_config.js.map +1 -1
- package/dist/session/ipc.d.ts +2 -2
- package/dist/session/ipc.js.map +1 -1
- package/dist/session/leader_election.js.map +1 -1
- package/dist/session/local_config.d.ts +37 -0
- package/dist/session/local_config.js +47 -1
- package/dist/session/local_config.js.map +1 -1
- package/dist/session/mesh_node.d.ts +1 -1
- package/dist/session/mesh_node.js +1 -1
- package/dist/session/mesh_node.js.map +1 -1
- package/dist/session/peer.js.map +1 -1
- package/dist/session/peer_inventory.js.map +1 -1
- package/dist/session/peer_limits.js.map +1 -1
- package/dist/session/received_images.d.ts +63 -0
- package/dist/session/received_images.js +273 -0
- package/dist/session/received_images.js.map +1 -0
- package/dist/session/relay_lifecycle.d.ts +219 -0
- package/dist/session/relay_lifecycle.js +764 -0
- package/dist/session/relay_lifecycle.js.map +1 -0
- package/dist/session/rpc_envelope.d.ts +28 -0
- package/dist/session/rpc_envelope.js +10 -1
- package/dist/session/rpc_envelope.js.map +1 -1
- package/dist/session/rpc_handlers.d.ts +53 -0
- package/dist/session/rpc_handlers.js +268 -0
- package/dist/session/rpc_handlers.js.map +1 -0
- package/dist/session/rpc_inbound.d.ts +42 -7
- package/dist/session/rpc_inbound.js +56 -1
- package/dist/session/rpc_inbound.js.map +1 -1
- package/dist/session/setup_wizard.js.map +1 -1
- package/dist/session/tools.js.map +1 -1
- package/dist/session/wizard.js.map +1 -1
- package/dist/state_migration.d.ts +45 -0
- package/dist/state_migration.js +104 -0
- package/dist/state_migration.js.map +1 -0
- package/dist/subagent_rooms.d.ts +68 -0
- package/dist/subagent_rooms.js +919 -0
- package/dist/subagent_rooms.js.map +1 -0
- package/dist/test_hooks.d.ts +180 -0
- package/dist/test_hooks.js +98 -0
- package/dist/test_hooks.js.map +1 -0
- package/dist/transport/peer_channel.d.ts +18 -1
- package/dist/transport/peer_channel.js +42 -12
- package/dist/transport/peer_channel.js.map +1 -1
- package/dist/transport/pi_forward_client.js.map +1 -1
- package/dist/transport/relay_client.d.ts +24 -2
- package/dist/transport/relay_client.js +6 -3
- package/dist/transport/relay_client.js.map +1 -1
- package/dist/ui/footer.js.map +1 -1
- package/docs/daemon.md +170 -179
- package/package.json +13 -11
- package/service-templates/launchd.plist.template +8 -7
- package/service-templates/systemd.service.template +5 -4
- 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
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay.js","sourceRoot":"","sources":["../../src/commands/relay.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/unbien fork | branch | new` — session-replacement / tree ops that exist
|
|
3
|
+
* ONLY on the command ctx (`ctx.fork` / `ctx.navigateTree` / `ctx.newSession`).
|
|
4
|
+
*
|
|
5
|
+
* These commands are INTERNAL plumbing, not a day-to-day surface: the app sends
|
|
6
|
+
* the structured `session_fork` / `session_navigate` / `new_session` frame over
|
|
7
|
+
* the wire, and the extension self-dispatches the matching slash command via
|
|
8
|
+
* `pi.sendUserMessage("/unbien …")` to land in a command ctx — the only context
|
|
9
|
+
* that carries these methods (an event/rpc ctx is the base `ExtensionContext`,
|
|
10
|
+
* which lacks them). See the ub-plane router in index.ts (`session_fork` /
|
|
11
|
+
* `session_navigate`) and the `new_session` rpc handler.
|
|
12
|
+
*
|
|
13
|
+
* The self-dispatched `/unbien …` shows as a user message in the transcript by
|
|
14
|
+
* design (accepted trade-off — there is no non-visible command-dispatch API).
|
|
15
|
+
*/
|
|
16
|
+
import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
17
|
+
import type { CommandDeps } from "./deps.js";
|
|
18
|
+
/**
|
|
19
|
+
* `/unbien fork <entryId> [reqId] [at|before]` — `ctx.fork` creates a NEW
|
|
20
|
+
* session file. pi fires session_shutdown → session_start{reason:"fork"}, and
|
|
21
|
+
* the new session's room announces a NEW app tile.
|
|
22
|
+
*
|
|
23
|
+
* `reqId` (optional) is the app's originating session_fork request id. When
|
|
24
|
+
* present we record a fork-born LINK in the NEW session via `withSession` (the
|
|
25
|
+
* only ctx bound to the replacement session); that session's first
|
|
26
|
+
* session_sync_end echoes it back as `forked_from_req` so the app auto-navigates
|
|
27
|
+
* to the new session. Without a reqId (manual `/unbien fork`) we skip the link.
|
|
28
|
+
*
|
|
29
|
+
* The token after entryId is a position keyword ONLY when it is literally
|
|
30
|
+
* `before`/`at` (manual use); otherwise it is the reqId, and a following
|
|
31
|
+
* `before`/`at` is the position.
|
|
32
|
+
*/
|
|
33
|
+
export declare function _cmdFork(_deps: CommandDeps, args: string, ctx: ExtensionCommandContext): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* `/unbien branch <entryId>` — `ctx.navigateTree` branches IN PLACE (same
|
|
36
|
+
* session file, the leaf moves). Unlike fork it does NOT replace the session.
|
|
37
|
+
*
|
|
38
|
+
* No leaf beacon here: `navigateTree` fires pi's `session_tree` event, and the
|
|
39
|
+
* `session_tree` handler in index.ts pushes the new leaf for EVERY move — TUI
|
|
40
|
+
* `/tree`, edit-resubmit, AND this app-driven branch (marked fromExtension).
|
|
41
|
+
* One source of truth, so a TUI branch reflects live too (it previously only
|
|
42
|
+
* caught up on the next get_entries refetch).
|
|
43
|
+
*/
|
|
44
|
+
export declare function _cmdBranch(_deps: CommandDeps, args: string, ctx: ExtensionCommandContext): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* `/unbien new` — `ctx.newSession` starts a fresh session. Same replacement
|
|
47
|
+
* flow as fork (session_shutdown → session_start{reason:"new"}); the relay
|
|
48
|
+
* lifecycle re-announces + restamps the session clock, and the app drops the
|
|
49
|
+
* old conversation on the new hello (changed sessionId). No `withSession` for
|
|
50
|
+
* the same stale-frame reason as fork.
|
|
51
|
+
*/
|
|
52
|
+
export declare function _cmdNewSession(_deps: CommandDeps, ctx: ExtensionCommandContext): Promise<void>;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { writeForkLink } from "./fork_link.js";
|
|
2
|
+
/**
|
|
3
|
+
* `/unbien fork <entryId> [reqId] [at|before]` — `ctx.fork` creates a NEW
|
|
4
|
+
* session file. pi fires session_shutdown → session_start{reason:"fork"}, and
|
|
5
|
+
* the new session's room announces a NEW app tile.
|
|
6
|
+
*
|
|
7
|
+
* `reqId` (optional) is the app's originating session_fork request id. When
|
|
8
|
+
* present we record a fork-born LINK in the NEW session via `withSession` (the
|
|
9
|
+
* only ctx bound to the replacement session); that session's first
|
|
10
|
+
* session_sync_end echoes it back as `forked_from_req` so the app auto-navigates
|
|
11
|
+
* to the new session. Without a reqId (manual `/unbien fork`) we skip the link.
|
|
12
|
+
*
|
|
13
|
+
* The token after entryId is a position keyword ONLY when it is literally
|
|
14
|
+
* `before`/`at` (manual use); otherwise it is the reqId, and a following
|
|
15
|
+
* `before`/`at` is the position.
|
|
16
|
+
*/
|
|
17
|
+
export async function _cmdFork(_deps, args, ctx) {
|
|
18
|
+
const parts = args.trim().split(/\s+/).filter(Boolean);
|
|
19
|
+
const entryId = parts[0];
|
|
20
|
+
if (!entryId) {
|
|
21
|
+
ctx.ui.notify("[un-bien] fork: missing entry id", "error");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const isPos = (s) => s === "before" || s === "at";
|
|
25
|
+
let reqId;
|
|
26
|
+
let position;
|
|
27
|
+
if (isPos(parts[1])) {
|
|
28
|
+
position = parts[1];
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
reqId = parts[1];
|
|
32
|
+
if (isPos(parts[2]))
|
|
33
|
+
position = parts[2];
|
|
34
|
+
}
|
|
35
|
+
const req = reqId;
|
|
36
|
+
await ctx.fork(entryId, {
|
|
37
|
+
...(position ? { position } : {}),
|
|
38
|
+
...(req
|
|
39
|
+
? {
|
|
40
|
+
withSession: async (fresh) => {
|
|
41
|
+
writeForkLink(fresh.sessionManager.getSessionDir(), fresh.sessionManager.getSessionId(), req);
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
: {}),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* `/unbien branch <entryId>` — `ctx.navigateTree` branches IN PLACE (same
|
|
49
|
+
* session file, the leaf moves). Unlike fork it does NOT replace the session.
|
|
50
|
+
*
|
|
51
|
+
* No leaf beacon here: `navigateTree` fires pi's `session_tree` event, and the
|
|
52
|
+
* `session_tree` handler in index.ts pushes the new leaf for EVERY move — TUI
|
|
53
|
+
* `/tree`, edit-resubmit, AND this app-driven branch (marked fromExtension).
|
|
54
|
+
* One source of truth, so a TUI branch reflects live too (it previously only
|
|
55
|
+
* caught up on the next get_entries refetch).
|
|
56
|
+
*/
|
|
57
|
+
export async function _cmdBranch(_deps, args, ctx) {
|
|
58
|
+
const entryId = args.trim().split(/\s+/).find(Boolean);
|
|
59
|
+
if (!entryId) {
|
|
60
|
+
ctx.ui.notify("[un-bien] branch: missing entry id", "error");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
await ctx.navigateTree(entryId);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* `/unbien new` — `ctx.newSession` starts a fresh session. Same replacement
|
|
67
|
+
* flow as fork (session_shutdown → session_start{reason:"new"}); the relay
|
|
68
|
+
* lifecycle re-announces + restamps the session clock, and the app drops the
|
|
69
|
+
* old conversation on the new hello (changed sessionId). No `withSession` for
|
|
70
|
+
* the same stale-frame reason as fork.
|
|
71
|
+
*/
|
|
72
|
+
export async function _cmdNewSession(_deps, ctx) {
|
|
73
|
+
await ctx.newSession();
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=session_ops.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session_ops.js","sourceRoot":"","sources":["../../src/commands/session_ops.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAE9C;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,KAAkB,EAClB,IAAY,EACZ,GAA4B;IAE5B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACtD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IACxB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,kCAAkC,EAAE,OAAO,CAAC,CAAA;QAC1D,OAAM;IACR,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,CAAqB,EAAwB,EAAE,CAC5D,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI,CAAA;IAC9B,IAAI,KAAyB,CAAA;IAC7B,IAAI,QAAqC,CAAA;IACzC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpB,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IACrB,CAAC;SAAM,CAAC;QACN,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QAChB,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAAE,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;IAC1C,CAAC;IACD,MAAM,GAAG,GAAG,KAAK,CAAA;IACjB,MAAM,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE;QACtB,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACjC,GAAG,CAAC,GAAG;YACL,CAAC,CAAC;gBACE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;oBAC3B,aAAa,CACX,KAAK,CAAC,cAAc,CAAC,aAAa,EAAE,EACpC,KAAK,CAAC,cAAc,CAAC,YAAY,EAAE,EACnC,GAAG,CACJ,CAAA;gBACH,CAAC;aACF;YACH,CAAC,CAAC,EAAE,CAAC;KACR,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,KAAkB,EAClB,IAAY,EACZ,GAA4B;IAE5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACtD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,oCAAoC,EAAE,OAAO,CAAC,CAAA;QAC5D,OAAM;IACR,CAAC;IACD,MAAM,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,CAAA;AACjC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAkB,EAClB,GAA4B;IAE5B,MAAM,GAAG,CAAC,UAAU,EAAE,CAAA;AACxB,CAAC"}
|
package/dist/config.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export type UnBienConfig = {
|
|
|
3
3
|
/**
|
|
4
4
|
* Debug prefs. Fields here gate the file-based diagnostic logs (see
|
|
5
5
|
* `session/debug_log.ts` and `panel_bridge.ts`). Read from config — NOT env —
|
|
6
|
-
* because the
|
|
6
|
+
* because the extension usually runs detached and doesn't inherit a shell's env, so
|
|
7
7
|
* a persisted config field is the only reliable enable switch. Absent/false by
|
|
8
8
|
* default: no logging.
|
|
9
9
|
*/
|
|
@@ -21,13 +21,15 @@ export type UnBienConfig = {
|
|
|
21
21
|
*/
|
|
22
22
|
defaults?: {
|
|
23
23
|
auto_start_relay?: boolean;
|
|
24
|
+
allow_remote_launch?: boolean;
|
|
25
|
+
allow_remote_terminate?: boolean;
|
|
24
26
|
};
|
|
25
27
|
/**
|
|
26
28
|
* Machine-identity storage. `storage` selects the PRIMARY backend for this
|
|
27
29
|
* Pi's long-term Ed25519 seed — `"keychain"` (OS-secured, the default) or
|
|
28
30
|
* `"file"` (a 0600 seed file, the SSH-private-key model: cat-able, portable,
|
|
29
31
|
* works headless). `path` overrides the file-backend location (default
|
|
30
|
-
* `~/.
|
|
32
|
+
* `~/.local/state/un-bien/identity.json`). The unselected backend is still READ (to
|
|
31
33
|
* recover an existing identity) but never written; the resolver mints only on
|
|
32
34
|
* a genuine first run. See `pairing/storage.ts`. Absent ⇒ keychain default.
|
|
33
35
|
*/
|
|
@@ -35,6 +37,32 @@ export type UnBienConfig = {
|
|
|
35
37
|
storage?: "keychain" | "file";
|
|
36
38
|
path?: string;
|
|
37
39
|
};
|
|
40
|
+
/**
|
|
41
|
+
* Remote-launch backend selection (pick-one). Which session backend a
|
|
42
|
+
* honored `session_launch` uses on THIS machine: `tmux` (default) or `herdr`
|
|
43
|
+
* — both PTY-hosted / reattachable. `rpc` is a fast-follow, not yet a choice
|
|
44
|
+
* here. This picks the mechanism machine-wide; whether remote launch is
|
|
45
|
+
* enabled at all stays the per-cwd `allow_remote_launch` LocalConfig flag.
|
|
46
|
+
* See `session_launch` handling in index.ts. Absent ⇒ tmux.
|
|
47
|
+
*
|
|
48
|
+
* `tmux_session` names the ONE shared tmux session that launched pis become
|
|
49
|
+
* WINDOWS of (a window per pi, via clean `new-window`; single `tmux attach`
|
|
50
|
+
* point). Absent ⇒ `"un-bien"`.
|
|
51
|
+
*/
|
|
52
|
+
launch?: {
|
|
53
|
+
backend?: "tmux" | "herdr";
|
|
54
|
+
tmux_session?: string;
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Subagent surfacing. When `rooms` is true, a
|
|
58
|
+
* Pi SUBAGENT is surfaced to the paired app as its OWN session — a distinct
|
|
59
|
+
* relay room (under this machine's identity) that nests under its parent via
|
|
60
|
+
* `room_meta.parent`. Read-only (view-only) for now. Absent/false ⇒ subagents
|
|
61
|
+
* stay hidden from the app (historical behaviour). See `subagent_rooms.ts`.
|
|
62
|
+
*/
|
|
63
|
+
subagents?: {
|
|
64
|
+
rooms?: boolean;
|
|
65
|
+
};
|
|
38
66
|
};
|
|
39
67
|
export declare function loadConfig(): UnBienConfig;
|
|
40
68
|
export declare function saveConfig(patch: Partial<UnBienConfig>): void;
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/daemon/install.d.ts
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates and activates a system service for
|
|
3
|
-
*
|
|
2
|
+
* Generates and activates a system service for the un-bien launcher daemon so
|
|
3
|
+
* it survives reboots.
|
|
4
4
|
*
|
|
5
5
|
* Platform support:
|
|
6
|
-
* - **macOS**: writes `~/Library/LaunchAgents/dev.unbien.
|
|
6
|
+
* - **macOS**: writes `~/Library/LaunchAgents/dev.unbien.launcher.plist`
|
|
7
7
|
* and runs `launchctl bootstrap gui/<uid> <plist>` (modern API) with a
|
|
8
8
|
* fallback to `launchctl load` for older macOS.
|
|
9
|
-
* - **Linux**: writes `~/.config/systemd/user/unbien-
|
|
9
|
+
* - **Linux**: writes `~/.config/systemd/user/unbien-launcher.service`
|
|
10
10
|
* and runs `systemctl --user daemon-reload && systemctl --user enable
|
|
11
|
-
* --now unbien-
|
|
11
|
+
* --now unbien-launcher.service`.
|
|
12
12
|
*
|
|
13
13
|
* Uninstall reverses both. Idempotent — re-running install over an existing
|
|
14
14
|
* unit refreshes it (paths could have changed if user moved node_modules).
|
|
15
15
|
*
|
|
16
16
|
* **What does NOT happen here**: the actual `npm install -g un-bien` step.
|
|
17
|
-
* The user has to make the
|
|
18
|
-
* can wire up the service. The `
|
|
17
|
+
* The user has to make the launcher bin reachable on disk before install
|
|
18
|
+
* can wire up the service. The `findLauncherScript` resolver detects
|
|
19
19
|
* common cases (npm global, pnpm global, local dev clone) and yields a
|
|
20
20
|
* clear error otherwise.
|
|
21
21
|
*/
|
|
22
22
|
export type SupervisorPlatform = "macos" | "linux" | "windows" | "unsupported";
|
|
23
23
|
export declare function detectPlatform(): SupervisorPlatform;
|
|
24
24
|
/**
|
|
25
|
-
* Absolute path to the
|
|
25
|
+
* Absolute path to the launcher daemon's compiled entry. We resolve from
|
|
26
26
|
* `import.meta.url` (this file's location) since wherever the daemon
|
|
27
|
-
* module lives, `bin/
|
|
27
|
+
* module lives, `bin/launcher.js` is a sibling of `daemon/` under
|
|
28
28
|
* `dist/`.
|
|
29
29
|
*
|
|
30
|
-
* After build: `dist/daemon/install.js` → `dist/bin/
|
|
30
|
+
* After build: `dist/daemon/install.js` → `dist/bin/launcher.js`.
|
|
31
31
|
* In dev (`tsx`): same path resolution still lands inside `src/`, which
|
|
32
32
|
* isn't directly runnable by `node` — dev install isn't expected.
|
|
33
33
|
*/
|
|
34
|
-
export declare function
|
|
34
|
+
export declare function findLauncherScript(): string;
|
|
35
35
|
/**
|
|
36
36
|
* Absolute path to the extension's CLI entry (`dist/index.js`). This is
|
|
37
37
|
* the file we symlink to `~/.local/bin/unbien` so the user can run
|
|
38
38
|
* `un-bien <subcommand>` from any shell after installing the extension
|
|
39
39
|
* through Pi (`pi install npm:un-bien`).
|
|
40
40
|
*
|
|
41
|
-
* Same resolution strategy as `
|
|
41
|
+
* Same resolution strategy as `findLauncherScript`: from
|
|
42
42
|
* `dist/daemon/install.js` → `dist/index.js`.
|
|
43
43
|
*/
|
|
44
44
|
export declare function findRemotePiScript(): string;
|
|
@@ -46,43 +46,44 @@ export declare function findNodeBinary(): string;
|
|
|
46
46
|
export declare function findTemplate(name: "systemd" | "launchd" | "taskscheduler" | "vbs-launcher"): string;
|
|
47
47
|
export declare function systemdUnitPath(): string;
|
|
48
48
|
export declare function launchdPlistPath(): string;
|
|
49
|
-
export declare const LAUNCHD_LABEL = "dev.unbien.
|
|
50
|
-
/** systemd --user unit name (with `.service`) for the
|
|
51
|
-
export declare const SYSTEMD_UNIT = "unbien-
|
|
52
|
-
/** Windows Task Scheduler task name
|
|
53
|
-
export declare const WINDOWS_TASK_NAME = "
|
|
49
|
+
export declare const LAUNCHD_LABEL = "dev.unbien.launcher";
|
|
50
|
+
/** systemd --user unit name (with `.service`) for the launcher daemon. */
|
|
51
|
+
export declare const SYSTEMD_UNIT = "unbien-launcher.service";
|
|
52
|
+
/** Windows Task Scheduler task name. */
|
|
53
|
+
export declare const WINDOWS_TASK_NAME = "RemotePiLauncher";
|
|
54
54
|
/** Path of the rendered Task Scheduler XML (input to `schtasks /Create /XML`). */
|
|
55
55
|
export declare function taskXmlPath(): string;
|
|
56
56
|
/**
|
|
57
57
|
* Path of the rendered VBScript launcher the Task Scheduler action invokes
|
|
58
|
-
* via `wscript.exe` (
|
|
59
|
-
*
|
|
58
|
+
* via `wscript.exe` (Windows). Launching node through this hidden wrapper is
|
|
59
|
+
* what keeps the launcher daemon from flashing a console window.
|
|
60
60
|
*/
|
|
61
61
|
export declare function vbsLauncherPath(): string;
|
|
62
62
|
/**
|
|
63
|
-
* Combined stdout/stderr log for the Windows
|
|
64
|
-
* launches it hidden via wscript, so without this redirect its output
|
|
65
|
-
*
|
|
66
|
-
*
|
|
63
|
+
* Combined stdout/stderr log for the Windows launcher daemon. The Task
|
|
64
|
+
* Scheduler launches it hidden via wscript, so without this redirect its output
|
|
65
|
+
* would vanish — mirrors launchd/systemd, which already log to
|
|
66
|
+
* `<state root>/launcher.log` (default `~/.local/state/un-bien/`).
|
|
67
67
|
*/
|
|
68
|
-
export declare function
|
|
68
|
+
export declare function launcherLogPath(): string;
|
|
69
69
|
export interface RenderVars {
|
|
70
70
|
node: string;
|
|
71
|
-
|
|
71
|
+
launcher: string;
|
|
72
72
|
home: string;
|
|
73
73
|
user: string;
|
|
74
|
-
/** PATH inherited so `
|
|
75
|
-
*
|
|
74
|
+
/** PATH inherited so `tmux`/`herdr` (the remote-launch backends) and `pi`
|
|
75
|
+
* resolve the same way they do interactively. We snapshot
|
|
76
|
+
* `process.env.PATH` at install time. */
|
|
76
77
|
path: string;
|
|
77
78
|
/** Windows only: absolute path of the VBScript launcher the Task Scheduler
|
|
78
79
|
* action runs via `wscript.exe`. Empty on POSIX (templates ignore `{VBS}`). */
|
|
79
80
|
vbs: string;
|
|
80
|
-
/** Windows only: combined stdout/stderr log the hidden
|
|
81
|
-
* Empty on POSIX (templates ignore `{LOG}`). */
|
|
81
|
+
/** Windows only: combined stdout/stderr log the hidden launcher daemon
|
|
82
|
+
* appends to. Empty on POSIX (templates ignore `{LOG}`). */
|
|
82
83
|
logPath: string;
|
|
83
84
|
}
|
|
84
85
|
export declare function defaultRenderVars(): RenderVars;
|
|
85
|
-
/** Replace `{NODE}` / `{
|
|
86
|
+
/** Replace `{NODE}` / `{PRESENCE}` / `{USER}` / `{HOME}` / `{PATH}` / `{VBS}` / `{LOG}`. */
|
|
86
87
|
export declare function renderTemplate(template: string, vars: RenderVars): string;
|
|
87
88
|
export interface InstallResult {
|
|
88
89
|
platform: SupervisorPlatform;
|
|
@@ -113,9 +114,9 @@ export declare function uninstallService(): UninstallResult;
|
|
|
113
114
|
*/
|
|
114
115
|
export declare function buildElevatedCmd(lines: string[], logFile: string): string;
|
|
115
116
|
export interface LinkBinariesResult {
|
|
116
|
-
/** `~/.local/bin/`. The
|
|
117
|
+
/** `~/.local/bin/`. The symlink lands here. */
|
|
117
118
|
binDir: string;
|
|
118
|
-
/** Paths of the
|
|
119
|
+
/** Paths of the symlink(s) we created/refreshed. */
|
|
119
120
|
links: Array<{
|
|
120
121
|
name: string;
|
|
121
122
|
path: string;
|
|
@@ -134,10 +135,9 @@ export declare function userLocalBinDir(home?: string): string;
|
|
|
134
135
|
*/
|
|
135
136
|
export declare function isOnPath(dir: string, envPath?: string): boolean;
|
|
136
137
|
/**
|
|
137
|
-
* Create (or refresh) the `un-bien`
|
|
138
|
-
*
|
|
139
|
-
* extension
|
|
140
|
-
* on upgrades, so this MUST overwrite).
|
|
138
|
+
* Create (or refresh) the `un-bien` symlink in `~/.local/bin/`. Idempotent —
|
|
139
|
+
* replaces stale links pointing at old extension paths (Pi can reinstall the
|
|
140
|
+
* extension to a different hash dir on upgrades, so this MUST overwrite).
|
|
141
141
|
*
|
|
142
142
|
* Returns `onPath: false` when `~/.local/bin` isn't in the user's `$PATH`.
|
|
143
143
|
* The caller is responsible for surfacing the shell-rc instruction —
|
|
@@ -145,7 +145,6 @@ export declare function isOnPath(dir: string, envPath?: string): boolean;
|
|
|
145
145
|
*/
|
|
146
146
|
export declare function linkCliBinaries(home?: string, paths?: {
|
|
147
147
|
remotePi?: string;
|
|
148
|
-
supervisord?: string;
|
|
149
148
|
}, opts?: {
|
|
150
149
|
node?: string;
|
|
151
150
|
mutatePath?: boolean;
|
package/dist/daemon/install.js
CHANGED
|
@@ -19,20 +19,20 @@ export function detectPlatform() {
|
|
|
19
19
|
}
|
|
20
20
|
// ── Path resolution ────────────────────────────────────────────────────────
|
|
21
21
|
/**
|
|
22
|
-
* Absolute path to the
|
|
22
|
+
* Absolute path to the launcher daemon's compiled entry. We resolve from
|
|
23
23
|
* `import.meta.url` (this file's location) since wherever the daemon
|
|
24
|
-
* module lives, `bin/
|
|
24
|
+
* module lives, `bin/launcher.js` is a sibling of `daemon/` under
|
|
25
25
|
* `dist/`.
|
|
26
26
|
*
|
|
27
|
-
* After build: `dist/daemon/install.js` → `dist/bin/
|
|
27
|
+
* After build: `dist/daemon/install.js` → `dist/bin/launcher.js`.
|
|
28
28
|
* In dev (`tsx`): same path resolution still lands inside `src/`, which
|
|
29
29
|
* isn't directly runnable by `node` — dev install isn't expected.
|
|
30
30
|
*/
|
|
31
|
-
export function
|
|
31
|
+
export function findLauncherScript() {
|
|
32
32
|
const here = fileURLToPath(import.meta.url); // dist/daemon/install.js
|
|
33
33
|
const daemonDir = dirname(here); // dist/daemon
|
|
34
34
|
const distRoot = dirname(daemonDir); // dist
|
|
35
|
-
return resolve(distRoot, "bin/
|
|
35
|
+
return resolve(distRoot, "bin/launcher.js");
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
38
|
* Absolute path to the extension's CLI entry (`dist/index.js`). This is
|
|
@@ -40,7 +40,7 @@ export function findSupervisorScript() {
|
|
|
40
40
|
* `un-bien <subcommand>` from any shell after installing the extension
|
|
41
41
|
* through Pi (`pi install npm:un-bien`).
|
|
42
42
|
*
|
|
43
|
-
* Same resolution strategy as `
|
|
43
|
+
* Same resolution strategy as `findLauncherScript`: from
|
|
44
44
|
* `dist/daemon/install.js` → `dist/index.js`.
|
|
45
45
|
*/
|
|
46
46
|
export function findRemotePiScript() {
|
|
@@ -74,53 +74,53 @@ export function findTemplate(name) {
|
|
|
74
74
|
}
|
|
75
75
|
// ── Service paths ──────────────────────────────────────────────────────────
|
|
76
76
|
export function systemdUnitPath() {
|
|
77
|
-
return join(homedir(), ".config", "systemd", "user", "unbien-
|
|
77
|
+
return join(homedir(), ".config", "systemd", "user", "unbien-launcher.service");
|
|
78
78
|
}
|
|
79
79
|
export function launchdPlistPath() {
|
|
80
|
-
return join(homedir(), "Library", "LaunchAgents", "dev.unbien.
|
|
80
|
+
return join(homedir(), "Library", "LaunchAgents", "dev.unbien.launcher.plist");
|
|
81
81
|
}
|
|
82
|
-
export const LAUNCHD_LABEL = "dev.unbien.
|
|
83
|
-
/** systemd --user unit name (with `.service`) for the
|
|
84
|
-
export const SYSTEMD_UNIT = "unbien-
|
|
85
|
-
/** Windows Task Scheduler task name
|
|
86
|
-
export const WINDOWS_TASK_NAME = "
|
|
82
|
+
export const LAUNCHD_LABEL = "dev.unbien.launcher";
|
|
83
|
+
/** systemd --user unit name (with `.service`) for the launcher daemon. */
|
|
84
|
+
export const SYSTEMD_UNIT = "unbien-launcher.service";
|
|
85
|
+
/** Windows Task Scheduler task name. */
|
|
86
|
+
export const WINDOWS_TASK_NAME = "RemotePiLauncher";
|
|
87
87
|
/** Path of the rendered Task Scheduler XML (input to `schtasks /Create /XML`). */
|
|
88
88
|
export function taskXmlPath() {
|
|
89
|
-
return join(unbienStateHome(), "
|
|
89
|
+
return join(unbienStateHome(), "RemotePiLauncher.xml");
|
|
90
90
|
}
|
|
91
91
|
/**
|
|
92
92
|
* Path of the rendered VBScript launcher the Task Scheduler action invokes
|
|
93
|
-
* via `wscript.exe` (
|
|
94
|
-
*
|
|
93
|
+
* via `wscript.exe` (Windows). Launching node through this hidden wrapper is
|
|
94
|
+
* what keeps the launcher daemon from flashing a console window.
|
|
95
95
|
*/
|
|
96
96
|
export function vbsLauncherPath() {
|
|
97
|
-
return join(unbienStateHome(), "
|
|
97
|
+
return join(unbienStateHome(), "RemotePiLauncherRun.vbs");
|
|
98
98
|
}
|
|
99
99
|
/**
|
|
100
|
-
* Combined stdout/stderr log for the Windows
|
|
101
|
-
* launches it hidden via wscript, so without this redirect its output
|
|
102
|
-
*
|
|
103
|
-
*
|
|
100
|
+
* Combined stdout/stderr log for the Windows launcher daemon. The Task
|
|
101
|
+
* Scheduler launches it hidden via wscript, so without this redirect its output
|
|
102
|
+
* would vanish — mirrors launchd/systemd, which already log to
|
|
103
|
+
* `<state root>/launcher.log` (default `~/.local/state/un-bien/`).
|
|
104
104
|
*/
|
|
105
|
-
export function
|
|
106
|
-
return join(unbienStateHome(), "
|
|
105
|
+
export function launcherLogPath() {
|
|
106
|
+
return join(unbienStateHome(), "launcher.log");
|
|
107
107
|
}
|
|
108
108
|
export function defaultRenderVars() {
|
|
109
109
|
return {
|
|
110
110
|
node: findNodeBinary(),
|
|
111
|
-
|
|
111
|
+
launcher: findLauncherScript(),
|
|
112
112
|
home: homedir(),
|
|
113
113
|
user: userInfo().username,
|
|
114
114
|
path: process.env["PATH"] ?? "/usr/local/bin:/usr/bin:/bin",
|
|
115
115
|
vbs: vbsLauncherPath(),
|
|
116
|
-
logPath:
|
|
116
|
+
logPath: launcherLogPath(),
|
|
117
117
|
};
|
|
118
118
|
}
|
|
119
|
-
/** Replace `{NODE}` / `{
|
|
119
|
+
/** Replace `{NODE}` / `{PRESENCE}` / `{USER}` / `{HOME}` / `{PATH}` / `{VBS}` / `{LOG}`. */
|
|
120
120
|
export function renderTemplate(template, vars) {
|
|
121
121
|
return template
|
|
122
122
|
.replace(/\{NODE\}/g, vars.node)
|
|
123
|
-
.replace(/\{
|
|
123
|
+
.replace(/\{PRESENCE\}/g, vars.launcher)
|
|
124
124
|
.replace(/\{USER\}/g, vars.user)
|
|
125
125
|
.replace(/\{HOME\}/g, vars.home)
|
|
126
126
|
.replace(/\{PATH\}/g, vars.path)
|
|
@@ -140,9 +140,9 @@ export function installService(vars = defaultRenderVars()) {
|
|
|
140
140
|
if (plat === "unsupported") {
|
|
141
141
|
throw new Error(`unsupported platform: ${platform()}. Only macOS, Linux, and Windows.`);
|
|
142
142
|
}
|
|
143
|
-
// Sanity:
|
|
144
|
-
if (!existsSync(vars.
|
|
145
|
-
throw new Error(`
|
|
143
|
+
// Sanity: launcher script must exist on disk.
|
|
144
|
+
if (!existsSync(vars.launcher)) {
|
|
145
|
+
throw new Error(`launcher script not found at ${vars.launcher}. ` +
|
|
146
146
|
"Run `pnpm build` (dev) or `npm install -g un-bien` (prod) first.");
|
|
147
147
|
}
|
|
148
148
|
const templateName = plat === "macos"
|
|
@@ -173,6 +173,12 @@ export function installService(vars = defaultRenderVars()) {
|
|
|
173
173
|
writeFileSync(unitPath, rendered); // launchd/systemd → UTF-8
|
|
174
174
|
}
|
|
175
175
|
log.push(`wrote ${unitPath}`);
|
|
176
|
+
if (plat === "macos") {
|
|
177
|
+
// launchd creates the plist's Standard{Out,Error}Path file, but not its
|
|
178
|
+
// parent directory — ensure the state root exists so the {LOG} redirect
|
|
179
|
+
// doesn't silently vanish on a machine that never ran the extension.
|
|
180
|
+
mkdirSync(dirname(vars.logPath), { recursive: true });
|
|
181
|
+
}
|
|
176
182
|
if (plat === "macos") {
|
|
177
183
|
// Unload first in case a stale entry exists from a prior install —
|
|
178
184
|
// `launchctl bootstrap` errors out otherwise. `bootout` is the modern
|
|
@@ -185,12 +191,12 @@ export function installService(vars = defaultRenderVars()) {
|
|
|
185
191
|
}
|
|
186
192
|
else if (plat === "linux") {
|
|
187
193
|
_exec("systemctl", ["--user", "daemon-reload"], log);
|
|
188
|
-
_exec("systemctl", ["--user", "enable", "--now",
|
|
194
|
+
_exec("systemctl", ["--user", "enable", "--now", SYSTEMD_UNIT], log);
|
|
189
195
|
log.push("activated via systemctl --user enable --now");
|
|
190
196
|
}
|
|
191
197
|
else {
|
|
192
|
-
// windows — Task Scheduler
|
|
193
|
-
// <launcher.vbs>` (not node directly) so the
|
|
198
|
+
// windows — Task Scheduler. The action runs `wscript.exe
|
|
199
|
+
// <launcher.vbs>` (not node directly) so the launcher daemon starts hidden,
|
|
194
200
|
// with no console window. Render + write that launcher first.
|
|
195
201
|
const vbsTpl = findTemplate("vbs-launcher");
|
|
196
202
|
if (!existsSync(vbsTpl))
|
|
@@ -229,7 +235,7 @@ export function uninstallService() {
|
|
|
229
235
|
log.push("deactivated via launchctl bootout");
|
|
230
236
|
}
|
|
231
237
|
else if (plat === "linux") {
|
|
232
|
-
_tryExec("systemctl", ["--user", "disable", "--now",
|
|
238
|
+
_tryExec("systemctl", ["--user", "disable", "--now", SYSTEMD_UNIT], log);
|
|
233
239
|
log.push("deactivated via systemctl --user disable --now");
|
|
234
240
|
}
|
|
235
241
|
else {
|
|
@@ -397,10 +403,9 @@ export function isOnPath(dir, envPath = process.env["PATH"] ?? "") {
|
|
|
397
403
|
.some((entry) => entry.replace(/\/+$/, "") === target);
|
|
398
404
|
}
|
|
399
405
|
/**
|
|
400
|
-
* Create (or refresh) the `un-bien`
|
|
401
|
-
*
|
|
402
|
-
* extension
|
|
403
|
-
* on upgrades, so this MUST overwrite).
|
|
406
|
+
* Create (or refresh) the `un-bien` symlink in `~/.local/bin/`. Idempotent —
|
|
407
|
+
* replaces stale links pointing at old extension paths (Pi can reinstall the
|
|
408
|
+
* extension to a different hash dir on upgrades, so this MUST overwrite).
|
|
404
409
|
*
|
|
405
410
|
* Returns `onPath: false` when `~/.local/bin` isn't in the user's `$PATH`.
|
|
406
411
|
* The caller is responsible for surfacing the shell-rc instruction —
|
|
@@ -418,38 +423,21 @@ export function linkCliBinaries(home = homedir(), paths = {}, opts = {}) {
|
|
|
418
423
|
mkdirSync(binDir, { recursive: true });
|
|
419
424
|
log.push(`ensured ${binDir}`);
|
|
420
425
|
const remotePi = paths.remotePi ?? findRemotePiScript();
|
|
421
|
-
const supervisord = paths.supervisord ?? findSupervisorScript();
|
|
422
426
|
if (!existsSync(remotePi)) {
|
|
423
427
|
throw new Error(`unbien script not found at ${remotePi}. ` +
|
|
424
428
|
"Run `pnpm build` (dev) or reinstall the extension.");
|
|
425
429
|
}
|
|
426
|
-
if (!existsSync(supervisord)) {
|
|
427
|
-
throw new Error(`supervisor script not found at ${supervisord}. ` +
|
|
428
|
-
"Run `pnpm build` (dev) or reinstall the extension.");
|
|
429
|
-
}
|
|
430
430
|
// tsc strips the executable bit on its outputs; the shebang at the top
|
|
431
431
|
// of dist/index.js means the file IS a valid interpreter target once
|
|
432
|
-
// chmod +x is applied.
|
|
433
|
-
// on `node` resolving via the symlink at exec time).
|
|
432
|
+
// chmod +x is applied.
|
|
434
433
|
try {
|
|
435
434
|
chmodSync(remotePi, 0o755);
|
|
436
435
|
}
|
|
437
436
|
catch {
|
|
438
437
|
/* best-effort */
|
|
439
438
|
}
|
|
440
|
-
try {
|
|
441
|
-
chmodSync(supervisord, 0o755);
|
|
442
|
-
}
|
|
443
|
-
catch {
|
|
444
|
-
/* best-effort */
|
|
445
|
-
}
|
|
446
439
|
const links = [
|
|
447
440
|
{ name: "unbien", path: join(binDir, "unbien"), target: remotePi },
|
|
448
|
-
{
|
|
449
|
-
name: "pi-supervisord",
|
|
450
|
-
path: join(binDir, "pi-supervisord"),
|
|
451
|
-
target: supervisord,
|
|
452
|
-
},
|
|
453
441
|
];
|
|
454
442
|
for (const link of links) {
|
|
455
443
|
_replaceSymlink(link.path, link.target, log);
|
|
@@ -463,10 +451,10 @@ export function linkCliBinaries(home = homedir(), paths = {}, opts = {}) {
|
|
|
463
451
|
return { binDir, links, onPath, log };
|
|
464
452
|
}
|
|
465
453
|
/**
|
|
466
|
-
* Windows variant of `linkCliBinaries`: writes `un-bien.cmd`
|
|
467
|
-
*
|
|
468
|
-
*
|
|
469
|
-
*
|
|
454
|
+
* Windows variant of `linkCliBinaries`: writes an `un-bien.cmd` shim into
|
|
455
|
+
* `~/.local/bin` and ensures that dir is on the user's PATH (User scope — no
|
|
456
|
+
* admin). `opts.node` overrides the node binary (tests); `opts.mutatePath ===
|
|
457
|
+
* false` skips the real PATH mutation (tests).
|
|
470
458
|
*/
|
|
471
459
|
function _linkCliBinariesWindows(home, binDir, paths, opts) {
|
|
472
460
|
void home;
|
|
@@ -475,26 +463,16 @@ function _linkCliBinariesWindows(home, binDir, paths, opts) {
|
|
|
475
463
|
log.push(`ensured ${binDir}`);
|
|
476
464
|
const node = opts.node ?? findNodeBinary();
|
|
477
465
|
const remotePi = paths.remotePi ?? findRemotePiScript();
|
|
478
|
-
const supervisord = paths.supervisord ?? findSupervisorScript();
|
|
479
466
|
if (!existsSync(remotePi)) {
|
|
480
467
|
throw new Error(`unbien script not found at ${remotePi}. ` +
|
|
481
468
|
"Run `pnpm build` (dev) or reinstall the extension.");
|
|
482
469
|
}
|
|
483
|
-
if (!existsSync(supervisord)) {
|
|
484
|
-
throw new Error(`supervisor script not found at ${supervisord}. ` +
|
|
485
|
-
"Run `pnpm build` (dev) or reinstall the extension.");
|
|
486
|
-
}
|
|
487
470
|
const links = [
|
|
488
471
|
{
|
|
489
472
|
name: "un-bien.cmd",
|
|
490
473
|
path: join(binDir, "un-bien.cmd"),
|
|
491
474
|
target: remotePi,
|
|
492
475
|
},
|
|
493
|
-
{
|
|
494
|
-
name: "pi-supervisord.cmd",
|
|
495
|
-
path: join(binDir, "pi-supervisord.cmd"),
|
|
496
|
-
target: supervisord,
|
|
497
|
-
},
|
|
498
476
|
];
|
|
499
477
|
for (const link of links) {
|
|
500
478
|
writeFileSync(link.path, buildCmdShim(node, link.target));
|
|
@@ -542,9 +520,7 @@ export function unlinkCliBinaries(home = homedir()) {
|
|
|
542
520
|
const log = [];
|
|
543
521
|
// Windows shims are `.cmd` files (linkCliBinaries writes those); POSIX uses
|
|
544
522
|
// extensionless symlinks. Match what was actually created on this platform.
|
|
545
|
-
const names = platform() === "win32"
|
|
546
|
-
? ["un-bien.cmd", "pi-supervisord.cmd"]
|
|
547
|
-
: ["unbien", "pi-supervisord"];
|
|
523
|
+
const names = platform() === "win32" ? ["un-bien.cmd"] : ["unbien"];
|
|
548
524
|
const removed = [];
|
|
549
525
|
for (const name of names) {
|
|
550
526
|
const path = join(binDir, name);
|