@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/actions/handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAuEH;8EAC8E;AAC9E,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,cAAc,EAAE,KAAK,CAAC,aAAa;QACnC,gEAAgE;QAChE,2EAA2E;QAC3E,wDAAwD;QACxD,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK;KAChD,
|
|
1
|
+
{"version":3,"file":"handlers.js","sourceRoot":"","sources":["../../src/actions/handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAuEH;8EAC8E;AAC9E,MAAM,UAAU,aAAa,CAAC,KAAiB;IAC7C,OAAO;QACL,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,cAAc,EAAE,KAAK,CAAC,aAAa;QACnC,gEAAgE;QAChE,2EAA2E;QAC3E,wDAAwD;QACxD,MAAM,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK;KAChD,CAAA;AACH,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/actions/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AASH,IAAI,iBAAiB,GAA+B,IAAI,
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/actions/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AASH,IAAI,iBAAiB,GAA+B,IAAI,CAAA;AAExD;;;GAGG;AACH,MAAM,aAAa,GAAwB;IACzC,OAAO,KAAI,CAAC;IACZ,YAAY;QACV,OAAO,EAAE,CAAA;IACX,CAAC;IACD,IAAI;QACF,OAAO,SAAS,CAAA;IAClB,CAAC;CACF,CAAA;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CACjC,GAA+B;IAE/B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,GAAG,EAAE,aAAa,CAAA;QAC/B,IAAI,IAAI,EAAE,CAAC;YACT,iBAAiB,GAAG,IAAI,CAAA;YACxB,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;IACvE,CAAC;IACD,OAAO,iBAAiB,IAAI,aAAa,CAAA;AAC3C,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,2BAA2B;IACzC,iBAAiB,GAAG,IAAI,CAAA;AAC1B,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `pi-unbien-launcher` — the regime-2 machine-launcher daemon.
|
|
4
|
+
*
|
|
5
|
+
* A lightweight mesh peer (NOT a pi session) that lets a paired app launch a
|
|
6
|
+
* session on THIS machine even when no pi is running here. Reads the machine's
|
|
7
|
+
* un-bien config for identity + relay + launch backend, joins the machine-level
|
|
8
|
+
* control room, advertises `remote_launch`, and spawns tmux/herdr on request.
|
|
9
|
+
*
|
|
10
|
+
* Run by hand during bring-up:
|
|
11
|
+
* pnpm build && node dist/bin/launcher.js
|
|
12
|
+
* (An OS-service unit for keepalive is a separate install step.)
|
|
13
|
+
*/
|
|
14
|
+
import { startLauncher } from "../launcher/launcher.js";
|
|
15
|
+
async function main() {
|
|
16
|
+
const handle = await startLauncher();
|
|
17
|
+
// eslint-disable-next-line no-console
|
|
18
|
+
console.log(`[un-bien launcher] listening on control room ${handle.roomId} ` +
|
|
19
|
+
`(epk ${handle.epk.slice(0, 16)}…) — Ctrl-C to stop`);
|
|
20
|
+
let shuttingDown = false;
|
|
21
|
+
const shutdown = (signal) => {
|
|
22
|
+
if (shuttingDown)
|
|
23
|
+
return;
|
|
24
|
+
shuttingDown = true;
|
|
25
|
+
// eslint-disable-next-line no-console
|
|
26
|
+
console.log(`[un-bien launcher] ${signal} — shutting down`);
|
|
27
|
+
handle.stop();
|
|
28
|
+
process.exit(0);
|
|
29
|
+
};
|
|
30
|
+
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
31
|
+
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
|
32
|
+
}
|
|
33
|
+
main().catch((err) => {
|
|
34
|
+
// eslint-disable-next-line no-console
|
|
35
|
+
console.error(`[un-bien launcher] fatal: ${err instanceof Error ? err.message : String(err)}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=launcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"launcher.js","sourceRoot":"","sources":["../../src/bin/launcher.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAEvD,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,MAAM,aAAa,EAAE,CAAA;IACpC,sCAAsC;IACtC,OAAO,CAAC,GAAG,CACT,gDAAgD,MAAM,CAAC,MAAM,GAAG;QAC9D,QAAQ,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,qBAAqB,CACvD,CAAA;IAED,IAAI,YAAY,GAAG,KAAK,CAAA;IACxB,MAAM,QAAQ,GAAG,CAAC,MAAc,EAAE,EAAE;QAClC,IAAI,YAAY;YAAE,OAAM;QACxB,YAAY,GAAG,IAAI,CAAA;QACnB,sCAAsC;QACtC,OAAO,CAAC,GAAG,CAAC,sBAAsB,MAAM,kBAAkB,CAAC,CAAA;QAC3D,MAAM,CAAC,IAAI,EAAE,CAAA;QACb,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC,CAAA;IACD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAA;IAC9C,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAA;AAClD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,sCAAsC;IACtC,OAAO,CAAC,KAAK,CACX,6BAA6B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAChF,CAAA;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { Ed25519Keypair } from "../pairing/crypto.js";
|
|
3
|
+
import type { SelfRevoke } from "../mesh/self_revoke.js";
|
|
4
|
+
import type { MeshTopologySnapshot } from "../mesh/siblings.js";
|
|
5
|
+
import type { Envelope } from "../session/envelope.js";
|
|
6
|
+
import type { MeshNode } from "../session/mesh_node.js";
|
|
7
|
+
import type { AcquiredLock } from "../session/cwd_lock.js";
|
|
8
|
+
import type { RelayClient } from "../transport/relay_client.js";
|
|
9
|
+
import type { PlainPeerChannel } from "../transport/peer_channel.js";
|
|
10
|
+
import type { ThinkingLevel } from "../protocol/types.js";
|
|
11
|
+
/** App↔Pi room meta projected by the ROOT session (see index.ts `_myRoomMeta`). */
|
|
12
|
+
export type RoomMeta = {
|
|
13
|
+
name: string;
|
|
14
|
+
cwd: string;
|
|
15
|
+
model?: string;
|
|
16
|
+
thinking?: ThinkingLevel;
|
|
17
|
+
working?: boolean;
|
|
18
|
+
sessionId?: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* The seam between index.ts (composition root) and the `/unbien` command
|
|
22
|
+
* modules.
|
|
23
|
+
*
|
|
24
|
+
* index.ts owns every piece of mutable module state and every lifecycle
|
|
25
|
+
* helper the command handlers touch. Command modules MUST NOT import from
|
|
26
|
+
* `../index.js` (that would be a circular import); instead index.ts builds
|
|
27
|
+
* one `CommandDeps` object (accessor closures over its module state plus
|
|
28
|
+
* direct function references) and passes it to `registerUnbienCommands`,
|
|
29
|
+
* which threads it into every handler that needs it.
|
|
30
|
+
*
|
|
31
|
+
* Members are added exactly as the moved code requires them — nothing
|
|
32
|
+
* speculative. Mutable state that commands write is a get/set pair; state
|
|
33
|
+
* they only read is `readonly`.
|
|
34
|
+
*/
|
|
35
|
+
export interface CommandDeps {
|
|
36
|
+
/** Remote state machine: `idle` → `started` (`paired` is derived). */
|
|
37
|
+
state: "idle" | "started";
|
|
38
|
+
/** Live relay WS connection, null when off. */
|
|
39
|
+
relay: RelayClient | null;
|
|
40
|
+
/** URL used by the current relay connection (http(s):// canonical form). */
|
|
41
|
+
relayUrl: string | null;
|
|
42
|
+
/** Local UDS mesh node, null when not joined. */
|
|
43
|
+
meshNode: MeshNode | null;
|
|
44
|
+
/** Mesh session name (LOCAL_SESSION_NAME once joined). */
|
|
45
|
+
sessionName: string | null;
|
|
46
|
+
/** Authoritative local-mesh peer count (broker `list_peers`). */
|
|
47
|
+
sessionPeerCount: number;
|
|
48
|
+
/** Cached Ed25519 identity of this connect cycle. */
|
|
49
|
+
cachedEd25519: Ed25519Keypair | null;
|
|
50
|
+
/** Last-known model name (root session projection). */
|
|
51
|
+
currentModel: string | undefined;
|
|
52
|
+
/** Last-known thinking level (root session projection). */
|
|
53
|
+
currentThinking: ThinkingLevel | undefined;
|
|
54
|
+
/** THE App↔Pi room id for the current chat session. */
|
|
55
|
+
myRoomId: string | null;
|
|
56
|
+
/** Room meta hello payload persisted for reconnect replay. */
|
|
57
|
+
myRoomMeta: RoomMeta | null;
|
|
58
|
+
/** Shortid of the most recently attached peer (UX hint only). */
|
|
59
|
+
peerShort: string;
|
|
60
|
+
/** Epoch of this Pi process's session (stamped on first start). */
|
|
61
|
+
sessionStartedAt: number | null;
|
|
62
|
+
/** Per-(cwd,name) singleton lock backing the mesh registration. */
|
|
63
|
+
cwdLock: AcquiredLock | null;
|
|
64
|
+
/** Name the cwd-lock actually reserved (`name` or `name#N`). */
|
|
65
|
+
lockedName: string | null;
|
|
66
|
+
/** Relay candidate generation (invalidates in-flight starts/stops). */
|
|
67
|
+
relayLifecycleGeneration: number;
|
|
68
|
+
/** True when a relay start was deferred because no session id existed yet
|
|
69
|
+
* (design 01M1CAW0); the root session_start re-runs the start once the id
|
|
70
|
+
* is available. */
|
|
71
|
+
relayStartDeferred: boolean;
|
|
72
|
+
/** Root replacement authority epoch (session replacements). */
|
|
73
|
+
rootLifecycleGeneration: number;
|
|
74
|
+
/** Mesh join candidate generation. */
|
|
75
|
+
meshJoinGeneration: number;
|
|
76
|
+
/** SelfRevoke topology producer for the relay path. */
|
|
77
|
+
selfRevoke: SelfRevoke | null;
|
|
78
|
+
/** Epoch guarding the SelfRevoke producer identity. */
|
|
79
|
+
selfRevokeEpoch: number;
|
|
80
|
+
/** Producer epoch that last published a verified topology. */
|
|
81
|
+
selfRevokeTopologyReadyEpoch: number;
|
|
82
|
+
/** Last topology snapshot published by the producer. */
|
|
83
|
+
selfRevokeTopology: MeshTopologySnapshot | null;
|
|
84
|
+
/** Auto-listener dispose fn for the current relay connection. */
|
|
85
|
+
stopAutoListener: (() => void) | null;
|
|
86
|
+
/** Cached "any device is paired machine-wide" flag (peers.json). */
|
|
87
|
+
readonly hasGlobalPairings: boolean;
|
|
88
|
+
/** Connected owner channels, keyed by canonical owner pubkey. */
|
|
89
|
+
readonly activePeers: Map<string, PlainPeerChannel>;
|
|
90
|
+
/** Set by session_shutdown; blocks outgoing candidates until rearm. */
|
|
91
|
+
readonly disposed: boolean;
|
|
92
|
+
/** Always-fresh session_start ctx (model/registry fallback). */
|
|
93
|
+
readonly lastEventCtx: Pick<ExtensionContext, "compact" | "abort" | "ui"> | null;
|
|
94
|
+
/** The ROOT session's ExtensionAPI (never a subagent child's). */
|
|
95
|
+
readonly pi: ExtensionAPI | null;
|
|
96
|
+
/** The root session's pi sessionId, null pre-sessionManager. */
|
|
97
|
+
readonly rootSessionId: string | null;
|
|
98
|
+
/** True while `generation` is the current root lifecycle epoch. */
|
|
99
|
+
isCurrentRootLifecycle(generation: number): boolean;
|
|
100
|
+
/** Friendly (configured or derived) agent name for a cwd. */
|
|
101
|
+
displayName(cwd: string): string;
|
|
102
|
+
/** Room id for the current chat session, derived from the stable pi
|
|
103
|
+
* session id — or null when no session id exists yet, in which case the
|
|
104
|
+
* caller must NOT announce/join a room (design 01M1CAW0; the cwd-derived
|
|
105
|
+
* fallback is retired). */
|
|
106
|
+
deriveRoomId(cwd: string, name: string): string | null;
|
|
107
|
+
/** Friendly model name for room_meta. */
|
|
108
|
+
currentModelName(): string | undefined;
|
|
109
|
+
/** The ROOT session's state record (turn/agentRun/sessionManager). */
|
|
110
|
+
rootState(): {
|
|
111
|
+
sessionManager?: {
|
|
112
|
+
getSessionId(): string;
|
|
113
|
+
} | null;
|
|
114
|
+
};
|
|
115
|
+
/** Full teardown of relay-side state (relay off, bridge detached). */
|
|
116
|
+
goIdle(): void;
|
|
117
|
+
/** Reconnect backoff entry for a closed relay. */
|
|
118
|
+
onRelayClose(closedRelay: RelayClient): void;
|
|
119
|
+
/** Attach the pair_request auto-listener to a live relay. */
|
|
120
|
+
installAutoListener(relay: RelayClient): () => void;
|
|
121
|
+
/** Repaint the footer status line from current state. */
|
|
122
|
+
refreshFooter(ctx?: {
|
|
123
|
+
ui?: {
|
|
124
|
+
setStatus?: unknown;
|
|
125
|
+
setTitle?: unknown;
|
|
126
|
+
};
|
|
127
|
+
} | null): void;
|
|
128
|
+
/** Tear down an owner's live channel + report the revocation. */
|
|
129
|
+
revokeActiveOwnerRuntime(canonicalOwnerPubkey: string): void;
|
|
130
|
+
/** Attach the cross-PC bridge once relay + leader are both up. */
|
|
131
|
+
attachBridgeIfReady(): void;
|
|
132
|
+
/** Broadcast relay connectivity state to RPC clients. */
|
|
133
|
+
emitRelayState(force?: boolean): void;
|
|
134
|
+
/** Re-query the broker for the authoritative local peer count. */
|
|
135
|
+
refreshSessionPeerCount(peer: MeshNode, ctx?: Pick<ExtensionContext, "ui"> | null): void;
|
|
136
|
+
/** Queue an inbound mesh message for agent delivery. */
|
|
137
|
+
deliverMeshMessageToAgent(env: Envelope): void;
|
|
138
|
+
/** Reads peers.json and refreshes the global-pairings cache + footer. */
|
|
139
|
+
refreshPairingsCache(): void;
|
|
140
|
+
/** Tear down a connected owner's channel (revoke / disconnect). */
|
|
141
|
+
detachPeerChannel(appPeerId: string): void;
|
|
142
|
+
/** RPC control channel verbs (`relay:toggle` / `relay:on` / `relay:off`). */
|
|
143
|
+
handleControl(cmd: string): Promise<void>;
|
|
144
|
+
/** Relay connectivity label for status output. */
|
|
145
|
+
relayStatus(): "connected" | "reconnecting" | "disconnected";
|
|
146
|
+
/** Test-visible state: `idle` | `started` | derived `paired`. */
|
|
147
|
+
getState(): "idle" | "started" | "paired";
|
|
148
|
+
/** Hidden dev-only e2e UI harness (`/unbien test <scenario>`). */
|
|
149
|
+
runTestScenario(scenario: string): string;
|
|
150
|
+
/** ctx.ui.notify that never throws (stale-ctx safe). */
|
|
151
|
+
safeNotify(message: string, level?: "info" | "warning" | "error", preferred?: {
|
|
152
|
+
ui?: unknown;
|
|
153
|
+
} | null): void;
|
|
154
|
+
/** Rename this agent (mesh + relay room) — `/unbien rename`. */
|
|
155
|
+
renameAgent(newName: string): Promise<void>;
|
|
156
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deps.js","sourceRoot":"","sources":["../../src/commands/deps.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Record that `sessionId` was born from the app fork request `req`. Best-effort. */
|
|
2
|
+
export declare function writeForkLink(sessionDir: string, sessionId: string, req: string): void;
|
|
3
|
+
/** Read + delete the fork request id for `sessionId`, or undefined when none. */
|
|
4
|
+
export declare function takeForkLink(sessionDir: string, sessionId: string): string | undefined;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fork-born linkage: a tiny marker persisted by `_cmdFork`'s `withSession`
|
|
3
|
+
* (running in the NEW forked session) and consumed by that session's FIRST
|
|
4
|
+
* `session_sync_end`, which echoes the app's originating fork request id as
|
|
5
|
+
* `forked_from_req` so the app can auto-navigate to the new session.
|
|
6
|
+
*
|
|
7
|
+
* Why a FILE and not a module variable: `ctx.fork` replaces the AgentSession,
|
|
8
|
+
* and the pi TUI host re-evaluates this extension module fresh for the new
|
|
9
|
+
* session (jiti moduleCache:false), so a module-level stash set in withSession
|
|
10
|
+
* would be lost before the new session handles the app's session_sync. The
|
|
11
|
+
* marker is keyed by the new session id and lives in the session dir, so it
|
|
12
|
+
* survives the re-eval (and a process restart) and is unambiguous.
|
|
13
|
+
*
|
|
14
|
+
* Consumed ONCE (take = read + unlink): the app navigates on the first sync;
|
|
15
|
+
* leaving it would re-fire the jump on every reconnect.
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
|
|
18
|
+
import { join } from "node:path";
|
|
19
|
+
function _linkPath(sessionDir, sessionId) {
|
|
20
|
+
return join(sessionDir, `.unbien-fork-${sessionId}.json`);
|
|
21
|
+
}
|
|
22
|
+
/** Record that `sessionId` was born from the app fork request `req`. Best-effort. */
|
|
23
|
+
export function writeForkLink(sessionDir, sessionId, req) {
|
|
24
|
+
try {
|
|
25
|
+
writeFileSync(_linkPath(sessionDir, sessionId), JSON.stringify({ req, ts: Date.now() }));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
/* best-effort — a missing link just means no auto-nav */
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** Read + delete the fork request id for `sessionId`, or undefined when none. */
|
|
32
|
+
export function takeForkLink(sessionDir, sessionId) {
|
|
33
|
+
const path = _linkPath(sessionDir, sessionId);
|
|
34
|
+
try {
|
|
35
|
+
if (!existsSync(path))
|
|
36
|
+
return undefined;
|
|
37
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
38
|
+
unlinkSync(path);
|
|
39
|
+
return typeof parsed.req === "string" ? parsed.req : undefined;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=fork_link.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fork_link.js","sourceRoot":"","sources":["../../src/commands/fork_link.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,SAAS,SAAS,CAAC,UAAkB,EAAE,SAAiB;IACtD,OAAO,IAAI,CAAC,UAAU,EAAE,gBAAgB,SAAS,OAAO,CAAC,CAAA;AAC3D,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,aAAa,CAC3B,UAAkB,EAClB,SAAiB,EACjB,GAAW;IAEX,IAAI,CAAC;QACH,aAAa,CACX,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,EAChC,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CACxC,CAAA;IACH,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;AACH,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,YAAY,CAC1B,UAAkB,EAClB,SAAiB;IAEjB,MAAM,IAAI,GAAG,SAAS,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;IAC7C,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,SAAS,CAAA;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAsB,CAAA;QAC1E,UAAU,CAAC,IAAI,CAAC,CAAA;QAChB,OAAO,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAA;IAChE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/unbien` housekeeping commands: service install/uninstall, the
|
|
3
|
+
* agent-network skill deploy, extension-dir/skill-path resolution, and the
|
|
4
|
+
* `unbien claude` CLI launcher.
|
|
5
|
+
*
|
|
6
|
+
* None of these touch index.ts module state, so they take no CommandDeps —
|
|
7
|
+
* everything they use is imported from pi-independent modules. Carved out
|
|
8
|
+
* of index.ts (phase 1 of the index.ts carve-up).
|
|
9
|
+
*
|
|
10
|
+
* NOTE: this file lives one directory deeper than index.ts used to, so the
|
|
11
|
+
* import.meta.url-based path math (extension dir, packaged skill, mesh
|
|
12
|
+
* server) climbs one extra level — behavior is otherwise identical.
|
|
13
|
+
*/
|
|
14
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
15
|
+
/**
|
|
16
|
+
* `linkCli` controls whether we symlink `un-bien` into `~/.local/bin/`. The
|
|
17
|
+
* slash-command path passes `true` (user is inside Pi's TUI — they installed
|
|
18
|
+
* via `pi install npm:un-bien` and need us to expose the CLI for them). The
|
|
19
|
+
* standalone-CLI path passes `false` because the user is already running our
|
|
20
|
+
* binary from PATH (they did `npm install -g un-bien`), so re-linking would
|
|
21
|
+
* point their `un-bien` at the Pi-extension copy and diverge on upgrades.
|
|
22
|
+
*/
|
|
23
|
+
/** Returns true on success, false when install failed (so the standalone CLI
|
|
24
|
+
* can exit non-zero — e.g. the Cockpit / CI detect failure by exit code).
|
|
25
|
+
* We do NOT process.exit here: this also runs inside the Pi TUI, where exiting
|
|
26
|
+
* would kill the session. */
|
|
27
|
+
export declare function _cmdInstall(ctx: Pick<ExtensionContext, "ui">, opts?: {
|
|
28
|
+
linkCli?: boolean;
|
|
29
|
+
}): boolean;
|
|
30
|
+
export declare function _cmdUninstall(ctx: Pick<ExtensionContext, "ui">, opts?: {
|
|
31
|
+
linkCli?: boolean;
|
|
32
|
+
}): void;
|
|
33
|
+
export declare function _deployAgentNetworkSkill(): void;
|
|
34
|
+
export declare function _cmdClaudeCli(args: string[]): Promise<void>;
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { installService, uninstallService, linkCliBinaries, unlinkCliBinaries, } from "../daemon/install.js";
|
|
2
|
+
import { defaultAgentName, localConfigExists, saveLocalConfig, } from "../session/local_config.js";
|
|
3
|
+
import { skillsDir } from "../session/global_config.js";
|
|
4
|
+
import { spawnSync } from "node:child_process";
|
|
5
|
+
import { copyFileSync, existsSync, mkdirSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
6
|
+
import { tmpdir } from "node:os";
|
|
7
|
+
import { dirname, join, resolve } from "node:path";
|
|
8
|
+
import { createInterface } from "node:readline";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
// ── Install/uninstall the launcher-daemon service ────────────────────────────
|
|
11
|
+
//
|
|
12
|
+
// Installs the un-bien launcher daemon as a user-level system service (systemd
|
|
13
|
+
// `--user` unit on Linux, launchd LaunchAgent on macOS, Task Scheduler on
|
|
14
|
+
// Windows). Once installed the launcher daemon starts at login + survives
|
|
15
|
+
// reboots. Uninstall is the inverse.
|
|
16
|
+
/**
|
|
17
|
+
* `linkCli` controls whether we symlink `un-bien` into `~/.local/bin/`. The
|
|
18
|
+
* slash-command path passes `true` (user is inside Pi's TUI — they installed
|
|
19
|
+
* via `pi install npm:un-bien` and need us to expose the CLI for them). The
|
|
20
|
+
* standalone-CLI path passes `false` because the user is already running our
|
|
21
|
+
* binary from PATH (they did `npm install -g un-bien`), so re-linking would
|
|
22
|
+
* point their `un-bien` at the Pi-extension copy and diverge on upgrades.
|
|
23
|
+
*/
|
|
24
|
+
/** Returns true on success, false when install failed (so the standalone CLI
|
|
25
|
+
* can exit non-zero — e.g. the Cockpit / CI detect failure by exit code).
|
|
26
|
+
* We do NOT process.exit here: this also runs inside the Pi TUI, where exiting
|
|
27
|
+
* would kill the session. */
|
|
28
|
+
export function _cmdInstall(ctx, opts = {}) {
|
|
29
|
+
const linkCli = opts.linkCli ?? false;
|
|
30
|
+
try {
|
|
31
|
+
const result = installService();
|
|
32
|
+
const sections = [
|
|
33
|
+
`[un-bien] Launcher daemon service installed (${result.platform}).`,
|
|
34
|
+
` Unit: ${result.unitPath}`,
|
|
35
|
+
` Steps:\n${result.log.map((l) => " " + l).join("\n")}`,
|
|
36
|
+
];
|
|
37
|
+
if (linkCli) {
|
|
38
|
+
const link = linkCliBinaries();
|
|
39
|
+
sections.push(` CLI bins linked into ${link.binDir}:`, link.links.map((l) => ` ${l.name} → ${l.target}`).join("\n"), ` Steps:\n${link.log.map((l) => " " + l).join("\n")}`);
|
|
40
|
+
if (!link.onPath) {
|
|
41
|
+
if (process.platform === "win32") {
|
|
42
|
+
sections.push(` ⚠ ${link.binDir} was just added to your user PATH (it wasn't there yet).`, ` Open a NEW terminal and run \`unbien status\` to verify.`);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
sections.push(` ⚠ ${link.binDir} is not on $PATH yet. Add this line to ~/.zshrc / ~/.bashrc:`, ` export PATH="$HOME/.local/bin:$PATH"`, ` Then open a new terminal and run \`unbien status\` to verify.`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
ctx.ui.notify(sections.join("\n"), "info");
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
ctx.ui.notify(`[un-bien] install failed: ${String(err)}`, "error");
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function _cmdUninstall(ctx, opts = {}) {
|
|
58
|
+
const linkCli = opts.linkCli ?? false;
|
|
59
|
+
try {
|
|
60
|
+
const result = uninstallService();
|
|
61
|
+
const sections = [
|
|
62
|
+
`[un-bien] Launcher daemon service uninstalled (${result.platform}).`,
|
|
63
|
+
` Unit: ${result.unitPath} (${result.removed ? "removed" : "not present"})`,
|
|
64
|
+
` Steps:\n${result.log.map((l) => " " + l).join("\n")}`,
|
|
65
|
+
];
|
|
66
|
+
if (linkCli) {
|
|
67
|
+
const unlink = unlinkCliBinaries();
|
|
68
|
+
sections.push(` CLI bins cleanup (${unlink.binDir}):`, unlink.removed
|
|
69
|
+
.map((r) => ` ${r.name} (${r.existed ? "removed" : "not present"})`)
|
|
70
|
+
.join("\n"));
|
|
71
|
+
}
|
|
72
|
+
ctx.ui.notify(sections.join("\n"), "info");
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
ctx.ui.notify(`[un-bien] uninstall failed: ${String(err)}`, "error");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// ── Agent-network commands (plano 19) ─────────────────────────────────────────
|
|
79
|
+
function _resolveExtensionDir() {
|
|
80
|
+
// dist/commands/housekeeping.js → dist/commands; skills sit at
|
|
81
|
+
// <extensionRoot>/skills/. When we run from src/ via tsx (dev), this file
|
|
82
|
+
// is in src/commands/ and skills/ is two levels up. We detect by checking
|
|
83
|
+
// both locations.
|
|
84
|
+
const here = fileURLToPath(import.meta.url);
|
|
85
|
+
// dist/commands/housekeeping.js or src/commands/housekeeping.ts → parent =
|
|
86
|
+
// <dist or src>/commands; sibling = ../../skills (dist) / ../skills (src)
|
|
87
|
+
const parent = here.replace(/\/[^/]+$/, "");
|
|
88
|
+
const candidateA = join(parent, "..", "..", "skills"); // dist/commands → ../../skills
|
|
89
|
+
const candidateB = join(parent, "..", "skills"); // src/commands → ../skills
|
|
90
|
+
if (existsSync(candidateA))
|
|
91
|
+
return parent.replace(/\/(dist\/)?commands$/, "");
|
|
92
|
+
if (existsSync(candidateB))
|
|
93
|
+
return parent.replace(/\/commands$/, "");
|
|
94
|
+
return parent.replace(/\/commands$/, "");
|
|
95
|
+
}
|
|
96
|
+
export function _deployAgentNetworkSkill() {
|
|
97
|
+
// Pi SDK spec (core/skills.js): every skill must live at
|
|
98
|
+
// <skillsRoot>/<skill-name>/SKILL.md
|
|
99
|
+
// The skill `name:` frontmatter must equal the parent directory name. We
|
|
100
|
+
// ship the source pre-arranged that way so deploy is a straight copy into
|
|
101
|
+
// `<state root>/skills/agent-network/SKILL.md`.
|
|
102
|
+
const root = _resolveExtensionDir();
|
|
103
|
+
const src1 = join(root, "skills", "agent-network", "SKILL.md");
|
|
104
|
+
const src2 = join(root, "..", "skills", "agent-network", "SKILL.md");
|
|
105
|
+
const src = existsSync(src1) ? src1 : existsSync(src2) ? src2 : null;
|
|
106
|
+
if (!src)
|
|
107
|
+
return;
|
|
108
|
+
const dstDir = join(skillsDir(), "agent-network");
|
|
109
|
+
const dst = join(dstDir, "SKILL.md");
|
|
110
|
+
try {
|
|
111
|
+
mkdirSync(dstDir, { recursive: true });
|
|
112
|
+
copyFileSync(src, dst);
|
|
113
|
+
// Cleanup legacy flat-layout deploy at `<state root>/skills/agent-network.md`
|
|
114
|
+
// (fails the Pi SDK's name-vs-parent-dir validation).
|
|
115
|
+
const legacy = join(skillsDir(), "agent-network.md");
|
|
116
|
+
if (existsSync(legacy)) {
|
|
117
|
+
try {
|
|
118
|
+
unlinkSync(legacy);
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
/* ignored */
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
/* best-effort */
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// ── `unbien claude` — launch Claude Code connected to the mesh ─────────────
|
|
130
|
+
/**
|
|
131
|
+
* Resolve the packaged agent-network skill path
|
|
132
|
+
* (`<pkgRoot>/skills/agent-network/SKILL.md`). Single source of truth shared
|
|
133
|
+
* by both runtimes: Pi discovers it via `resources_discover`, and the Claude
|
|
134
|
+
* launcher injects it as a system prompt (see `_cmdClaudeCli`). Returns null
|
|
135
|
+
* if the file is missing (e.g. running before `pnpm build`).
|
|
136
|
+
*/
|
|
137
|
+
function _agentNetworkSkillPath() {
|
|
138
|
+
const here = fileURLToPath(import.meta.url); // dist/commands/housekeeping.js (or src/ via tsx)
|
|
139
|
+
const pkgRoot = dirname(dirname(dirname(here))); // package root (dist/commands → ../..; src/commands → ../..)
|
|
140
|
+
const skill = join(pkgRoot, "skills", "agent-network", "SKILL.md");
|
|
141
|
+
return existsSync(skill) ? skill : null;
|
|
142
|
+
}
|
|
143
|
+
export async function _cmdClaudeCli(args) {
|
|
144
|
+
// Contract: `unbien claude [cwd] [claude-flags...]`. The optional cwd is
|
|
145
|
+
// ONLY the leading positional (first token, not a flag); everything after it
|
|
146
|
+
// is forwarded verbatim to the `claude` binary (e.g. `--resume`, `-c`,
|
|
147
|
+
// `-p "prompt"`). Restricting cwd to the leading token avoids mistaking a
|
|
148
|
+
// flag's value (e.g. the id in `--resume <id>`) for the cwd.
|
|
149
|
+
const hasCwdArg = args.length > 0 && !args[0].startsWith("-");
|
|
150
|
+
const targetCwd = hasCwdArg ? args[0] : process.cwd();
|
|
151
|
+
const passthroughArgs = hasCwdArg ? args.slice(1) : args;
|
|
152
|
+
// Wizard when no local config exists
|
|
153
|
+
if (!localConfigExists(targetCwd)) {
|
|
154
|
+
const suggested = defaultAgentName(targetCwd);
|
|
155
|
+
process.stdout.write(`\n[un-bien] No config found for ${targetCwd}\n`);
|
|
156
|
+
process.stdout.write("Let's set up this agent.\n\n");
|
|
157
|
+
const rl = createInterface({
|
|
158
|
+
input: process.stdin,
|
|
159
|
+
output: process.stdout,
|
|
160
|
+
});
|
|
161
|
+
const agentName = await new Promise((res) => rl.question(`Agent name [${suggested}]: `, (ans) => {
|
|
162
|
+
rl.close();
|
|
163
|
+
res(ans.trim() || suggested);
|
|
164
|
+
}));
|
|
165
|
+
saveLocalConfig(targetCwd, {
|
|
166
|
+
agent_name: agentName,
|
|
167
|
+
auto_start_relay: true,
|
|
168
|
+
});
|
|
169
|
+
process.stdout.write(`[un-bien] Config saved: agent="${agentName}"\n\n`);
|
|
170
|
+
}
|
|
171
|
+
// Resolve mesh server script path (dist/mcp/mesh_server.js)
|
|
172
|
+
const here = fileURLToPath(import.meta.url);
|
|
173
|
+
const distRoot = dirname(here); // dist/commands → mesh server at ../mcp/
|
|
174
|
+
const meshServerPath = resolve(distRoot, "..", "mcp/mesh_server.js");
|
|
175
|
+
if (!existsSync(meshServerPath)) {
|
|
176
|
+
console.log(`[un-bien] mesh server not found at ${meshServerPath}. Run pnpm build first.`);
|
|
177
|
+
process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
const absCwd = resolve(targetCwd);
|
|
180
|
+
const SERVER_NAME = "un-bien-mesh";
|
|
181
|
+
// The mesh MCP must be visible ONLY inside a `unbien claude` session — a
|
|
182
|
+
// plain `claude` in the same repo must NOT inherit it (otherwise every
|
|
183
|
+
// ordinary session silently joins the mesh as a stray agent).
|
|
184
|
+
//
|
|
185
|
+
// Older builds registered the server with `claude mcp add -s local`. That
|
|
186
|
+
// scope lives in `~/.claude.json` keyed by the **git repo root** and is
|
|
187
|
+
// inherited by EVERY claude session under that root — which is exactly the
|
|
188
|
+
// leak we're closing. So we no longer write any persistent scope; we load
|
|
189
|
+
// the server through an ephemeral `--mcp-config <tmpfile>` passed on the
|
|
190
|
+
// launch command line (see below). That config is session-only: it is never
|
|
191
|
+
// recorded in any scope `claude mcp list` enumerates, so a normal `claude`
|
|
192
|
+
// sees nothing.
|
|
193
|
+
//
|
|
194
|
+
// Migration: best-effort scrub of the stale `-s local` entry that prior
|
|
195
|
+
// versions left behind (and that is the source of the inherited-mesh bug).
|
|
196
|
+
// Idempotent — a no-op (non-zero, ignored) when the entry is already gone.
|
|
197
|
+
spawnSync("claude", ["mcp", "remove", SERVER_NAME, "-s", "local"], {
|
|
198
|
+
cwd: absCwd,
|
|
199
|
+
stdio: "ignore",
|
|
200
|
+
shell: false,
|
|
201
|
+
});
|
|
202
|
+
// Ephemeral MCP config consumed by `--mcp-config` below. We do NOT bake a
|
|
203
|
+
// `cwd` into it: the server resolves its folder from its own `process.cwd()`,
|
|
204
|
+
// which Claude sets to the directory the session was launched in (verified
|
|
205
|
+
// empirically — NOT the git root, NOT CLAUDE_PROJECT_DIR). We spawn claude
|
|
206
|
+
// with `cwd: absCwd`, the MCP child inherits it, so the server self-identifies
|
|
207
|
+
// as the right agent without leaking that path to any other session.
|
|
208
|
+
// Unique per pid so concurrent `unbien claude` launches don't collide.
|
|
209
|
+
const mcpConfigPath = join(tmpdir(), `un-bien-mesh-mcp-${process.pid}.json`);
|
|
210
|
+
writeFileSync(mcpConfigPath, JSON.stringify({
|
|
211
|
+
mcpServers: {
|
|
212
|
+
[SERVER_NAME]: { command: process.execPath, args: [meshServerPath] },
|
|
213
|
+
},
|
|
214
|
+
}));
|
|
215
|
+
// Inject the agent-network protocol as a system prompt instead of deploying a
|
|
216
|
+
// skill file into ~/.claude. Anyone running `unbien claude` is here to use
|
|
217
|
+
// the mesh, so load the protocol unconditionally — no lazy skill gating, no
|
|
218
|
+
// global skills-dir pollution, and the packaged file is the single source of
|
|
219
|
+
// truth shared with the Pi runtime. Skipped only if the file is missing.
|
|
220
|
+
const skillPath = _agentNetworkSkillPath();
|
|
221
|
+
// Launch flags:
|
|
222
|
+
// --mcp-config <tmpfile> — load the mesh server for
|
|
223
|
+
// THIS session only (never a persistent scope). We intentionally omit
|
|
224
|
+
// `--strict-mcp-config` so the user's own persistent MCP servers stay
|
|
225
|
+
// available alongside the mesh.
|
|
226
|
+
// --dangerously-load-development-channels TAG — enable claude/channel push
|
|
227
|
+
// for our local (non-allowlisted) server, so incoming mesh messages
|
|
228
|
+
// wake Claude instead of waiting for a get_messages poll. Entries must
|
|
229
|
+
// be tagged: `server:<name>` for a manually configured MCP server
|
|
230
|
+
// (`plugin:<name>@<marketplace>` is the plugin form). Shows a one-time
|
|
231
|
+
// confirmation dialog at startup. Works against the `--mcp-config`
|
|
232
|
+
// server in current Claude Code; if a build ever fails to match it, the
|
|
233
|
+
// per-turn `get_messages` poll (mandated by the mesh protocol) still
|
|
234
|
+
// delivers — we lose the wake, not the messages.
|
|
235
|
+
// --dangerously-skip-permissions — auto-approve tool calls
|
|
236
|
+
// --append-system-prompt-file=<skill> — load the mesh protocol
|
|
237
|
+
// `--append-system-prompt-file` uses the glued `--flag=value` form (a SINGLE
|
|
238
|
+
// argv token) on purpose: tools that restore a session by capturing and
|
|
239
|
+
// replaying the live process's argv (e.g. cmux) drop the TRAILING token,
|
|
240
|
+
// which here was the skill path — leaving a dangling `--append-system-prompt-file`
|
|
241
|
+
// → `claude` aborts with "argument missing" and the session never comes back.
|
|
242
|
+
// As one token, the worst case is the whole flag being dropped: claude still
|
|
243
|
+
// starts (just without the injected protocol), which is recoverable instead
|
|
244
|
+
// of fatal. (The other flags stay separate pairs — never last, so unaffected,
|
|
245
|
+
// and we don't risk a parser that may not accept `=`.)
|
|
246
|
+
// Any extra args the user passed (e.g. `--resume`, `-c`) are appended last so
|
|
247
|
+
// they reach the claude binary; ours come first as sensible defaults.
|
|
248
|
+
try {
|
|
249
|
+
spawnSync("claude", [
|
|
250
|
+
"--mcp-config",
|
|
251
|
+
mcpConfigPath,
|
|
252
|
+
"--dangerously-load-development-channels",
|
|
253
|
+
`server:${SERVER_NAME}`,
|
|
254
|
+
"--dangerously-skip-permissions",
|
|
255
|
+
...(skillPath ? [`--append-system-prompt-file=${skillPath}`] : []),
|
|
256
|
+
...passthroughArgs,
|
|
257
|
+
], {
|
|
258
|
+
cwd: absCwd,
|
|
259
|
+
stdio: "inherit",
|
|
260
|
+
shell: false,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
finally {
|
|
264
|
+
// Session over — drop the ephemeral config so it never lingers as a stray
|
|
265
|
+
// file. spawnSync blocks until claude exits, so claude has long since read
|
|
266
|
+
// it. Best-effort: ignore if already gone.
|
|
267
|
+
try {
|
|
268
|
+
unlinkSync(mcpConfigPath);
|
|
269
|
+
}
|
|
270
|
+
catch {
|
|
271
|
+
/* already removed */
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
//# sourceMappingURL=housekeeping.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"housekeeping.js","sourceRoot":"","sources":["../../src/commands/housekeeping.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/unbien` info commands: status, peers, devices/list, config, identity.
|
|
3
|
+
*
|
|
4
|
+
* Read-only views over the composition root's state — everything they need
|
|
5
|
+
* from index.ts's module scope comes through `CommandDeps` (see deps.ts).
|
|
6
|
+
* Carved out of index.ts (phase 1 of the index.ts carve-up).
|
|
7
|
+
*/
|
|
8
|
+
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
9
|
+
import type { CommandDeps } from "./deps.js";
|
|
10
|
+
/**
|
|
11
|
+
* `/unbien status` — full state snapshot. Two lines: local mesh + relay.
|
|
12
|
+
*
|
|
13
|
+
* Always callable; safe when nothing is up (renders the off variants).
|
|
14
|
+
* Reuses the same icons as the footer so terminal + status output stay
|
|
15
|
+
* visually consistent.
|
|
16
|
+
*/
|
|
17
|
+
export declare function _cmdStatus(deps: CommandDeps, ctx: Pick<ExtensionContext, "ui">): void;
|
|
18
|
+
/**
|
|
19
|
+
* Plan/25 Wave D: `/unbien peers`.
|
|
20
|
+
*
|
|
21
|
+
* Queries the local broker for the aggregated peer inventory (`list_peers`
|
|
22
|
+
* returns locals + cross-PC entries prefixed with `<pc_label>:`). Formats
|
|
23
|
+
* the result grouped by source so users can see at a glance who's on
|
|
24
|
+
* their machine vs. on a paired sibling Pi.
|
|
25
|
+
*/
|
|
26
|
+
export declare function _cmdPeers(deps: CommandDeps, ctx: Pick<ExtensionContext, "ui">): Promise<void>;
|
|
27
|
+
export declare function _cmdList(deps: CommandDeps, ctx: Pick<ExtensionContext, "ui">): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* `/unbien config` — print the effective relay URL and where it came from.
|
|
30
|
+
*
|
|
31
|
+
* Documented in the README ("Verify the active URL and its source") and in
|
|
32
|
+
* CLAUDE.md, but like the `relay` family (issue #119) it had no handler and
|
|
33
|
+
* fell through to the status panel, which shows the URL but not the source —
|
|
34
|
+
* so `env` vs `config` vs `default` was unverifiable without a restart.
|
|
35
|
+
*/
|
|
36
|
+
export declare function _cmdConfig(deps: CommandDeps, ctx: Pick<ExtensionContext, "ui">): void;
|
|
37
|
+
/**
|
|
38
|
+
* `/unbien identity` — report NON-SECRET identity state (active EPK, backend,
|
|
39
|
+
* resolved source). The private seed is NEVER shown: command output is
|
|
40
|
+
* LLM-visible, so extraction stays a manual `cat`/keychain op. Read-only
|
|
41
|
+
* (never mints).
|
|
42
|
+
*/
|
|
43
|
+
export declare function _cmdIdentity(ctx: Pick<ExtensionContext, "ui">): Promise<void>;
|