@moxxy/sdk 0.21.1 → 0.22.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/dist/channel-control.d.ts +65 -0
- package/dist/channel-control.d.ts.map +1 -0
- package/dist/channel-control.js +139 -0
- package/dist/channel-control.js.map +1 -0
- package/dist/channel-status.d.ts +32 -0
- package/dist/channel-status.d.ts.map +1 -0
- package/dist/channel-status.js +29 -0
- package/dist/channel-status.js.map +1 -0
- package/dist/channel.d.ts +64 -0
- package/dist/channel.d.ts.map +1 -1
- package/dist/channel.js.map +1 -1
- package/dist/event-store.d.ts +1 -1
- package/dist/event-store.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +8 -0
- package/dist/server.js.map +1 -1
- package/package.json +1 -1
- package/src/channel-control.test.ts +141 -0
- package/src/channel-control.ts +144 -0
- package/src/channel-status.ts +55 -0
- package/src/channel.ts +67 -0
- package/src/event-store.ts +1 -1
- package/src/index.ts +3 -0
- package/src/server.ts +19 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-independent control surface for dedicated channel runners.
|
|
3
|
+
*
|
|
4
|
+
* A dedicated channel (Slack, Telegram, …) runs as its OWN isolated runner
|
|
5
|
+
* subprocess that publishes a tiny status file (`channel-<name>.status.json`,
|
|
6
|
+
* see {@link ./channel-status}) on ready and clears it on graceful shutdown. That
|
|
7
|
+
* file — NOT a held child handle — is the source of truth for "is it running",
|
|
8
|
+
* so a channel started from anywhere (the TUI `/channels` panel, `moxxy channels
|
|
9
|
+
* start`, the desktop panel) is visible and stoppable from everywhere, and keeps
|
|
10
|
+
* running after the launcher exits.
|
|
11
|
+
*
|
|
12
|
+
* These helpers are the shared spine for those surfaces:
|
|
13
|
+
* - {@link spawnDedicatedChannel} — start one, detached, on its own runner.
|
|
14
|
+
* - {@link liveChannelStatus}/{@link listLiveChannelStatuses} — discover the
|
|
15
|
+
* running ones (with stale-file self-healing).
|
|
16
|
+
* - {@link stopDedicatedChannel} — signal one to stop.
|
|
17
|
+
*
|
|
18
|
+
* Node-only (`node:child_process`, `node:fs`) — exported from `@moxxy/sdk/server`.
|
|
19
|
+
*/
|
|
20
|
+
import { type ChannelRunStatus } from './channel-status.js';
|
|
21
|
+
/**
|
|
22
|
+
* Start a channel on its own dedicated, detached runner by re-invoking this very
|
|
23
|
+
* moxxy binary as `moxxy <name>` with `MOXXY_DEDICATED_RUNNER=1`. The child is
|
|
24
|
+
* `detached` + `unref`'d with no stdio, so it OUTLIVES the launcher (the user can
|
|
25
|
+
* quit the TUI and the bot keeps serving) and reports itself via its status file.
|
|
26
|
+
*
|
|
27
|
+
* Returns the child pid, or undefined if the spawn produced none. Throws if the
|
|
28
|
+
* moxxy CLI entry can't be resolved (no `process.argv[1]`).
|
|
29
|
+
*
|
|
30
|
+
* Caller's job (this is fire-and-forget): poll {@link liveChannelStatus} to learn
|
|
31
|
+
* when it's ready / failed (no status file within a timeout ⇒ it died on boot —
|
|
32
|
+
* re-run `moxxy <name>` in the foreground to see why).
|
|
33
|
+
*/
|
|
34
|
+
export declare function spawnDedicatedChannel(name: string): number | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Is `pid` a live process? `kill(pid, 0)` sends no signal — it only probes:
|
|
37
|
+
* - resolves ⇒ alive,
|
|
38
|
+
* - `ESRCH` ⇒ gone,
|
|
39
|
+
* - `EPERM` ⇒ alive but owned by another user (treat as alive — it exists).
|
|
40
|
+
*/
|
|
41
|
+
export declare function isPidAlive(pid: number): boolean;
|
|
42
|
+
/**
|
|
43
|
+
* The status of channel `name` IF it is actually running. Reads its status file
|
|
44
|
+
* and verifies the pid is alive; a file whose pid is dead (the runner crashed or
|
|
45
|
+
* was SIGKILL'd without clearing it) is treated as not-running AND removed, so a
|
|
46
|
+
* stale file never masquerades as a live channel.
|
|
47
|
+
*/
|
|
48
|
+
export declare function liveChannelStatus(name: string): ChannelRunStatus | null;
|
|
49
|
+
/**
|
|
50
|
+
* Every currently-running dedicated channel, discovered by scanning the moxxy
|
|
51
|
+
* home for status files and filtering to live pids (self-healing stale ones).
|
|
52
|
+
* Returns [] when the home dir doesn't exist yet.
|
|
53
|
+
*/
|
|
54
|
+
export declare function listLiveChannelStatuses(): ChannelRunStatus[];
|
|
55
|
+
/**
|
|
56
|
+
* Ask channel `name` to stop by SIGTERM-ing its runner. The runner's own signal
|
|
57
|
+
* handler tears down gracefully and clears its status file. Returns `'stopped'`
|
|
58
|
+
* if a live runner was signaled, `'not-running'` if there was nothing to stop.
|
|
59
|
+
*
|
|
60
|
+
* This is a single, synchronous SIGTERM — callers that want a hard backstop poll
|
|
61
|
+
* {@link liveChannelStatus} afterwards and escalate (SIGKILL + {@link clearChannelStatus})
|
|
62
|
+
* if it ignores the term within a grace period.
|
|
63
|
+
*/
|
|
64
|
+
export declare function stopDedicatedChannel(name: string): 'stopped' | 'not-running';
|
|
65
|
+
//# sourceMappingURL=channel-control.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-control.d.ts","sourceRoot":"","sources":["../src/channel-control.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,qBAAqB,CAAC;AAS7B;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAatE;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ/C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAQvE;AAQD;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,gBAAgB,EAAE,CAe5D;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CAU5E"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-independent control surface for dedicated channel runners.
|
|
3
|
+
*
|
|
4
|
+
* A dedicated channel (Slack, Telegram, …) runs as its OWN isolated runner
|
|
5
|
+
* subprocess that publishes a tiny status file (`channel-<name>.status.json`,
|
|
6
|
+
* see {@link ./channel-status}) on ready and clears it on graceful shutdown. That
|
|
7
|
+
* file — NOT a held child handle — is the source of truth for "is it running",
|
|
8
|
+
* so a channel started from anywhere (the TUI `/channels` panel, `moxxy channels
|
|
9
|
+
* start`, the desktop panel) is visible and stoppable from everywhere, and keeps
|
|
10
|
+
* running after the launcher exits.
|
|
11
|
+
*
|
|
12
|
+
* These helpers are the shared spine for those surfaces:
|
|
13
|
+
* - {@link spawnDedicatedChannel} — start one, detached, on its own runner.
|
|
14
|
+
* - {@link liveChannelStatus}/{@link listLiveChannelStatuses} — discover the
|
|
15
|
+
* running ones (with stale-file self-healing).
|
|
16
|
+
* - {@link stopDedicatedChannel} — signal one to stop.
|
|
17
|
+
*
|
|
18
|
+
* Node-only (`node:child_process`, `node:fs`) — exported from `@moxxy/sdk/server`.
|
|
19
|
+
*/
|
|
20
|
+
import { spawn } from 'node:child_process';
|
|
21
|
+
import { readdirSync } from 'node:fs';
|
|
22
|
+
import { clearChannelStatus, readChannelStatus, } from './channel-status.js';
|
|
23
|
+
import { moxxyHome } from './fs-utils.js';
|
|
24
|
+
/** Env vars that ADDRESS a runner (socket + sticky session). We scrub these from
|
|
25
|
+
* a spawned channel's env so `applyDedicatedRunnerEnv` (which only fills UNSET
|
|
26
|
+
* vars) derives the channel's OWN isolated socket/session from its name — rather
|
|
27
|
+
* than the channel silently inheriting and sharing the launcher's runner. */
|
|
28
|
+
const ADDRESSING_ENV = ['MOXXY_RUNNER_SOCKET', 'MOXXY_SESSION_ID', 'MOXXY_SESSION_SOURCE'];
|
|
29
|
+
/**
|
|
30
|
+
* Start a channel on its own dedicated, detached runner by re-invoking this very
|
|
31
|
+
* moxxy binary as `moxxy <name>` with `MOXXY_DEDICATED_RUNNER=1`. The child is
|
|
32
|
+
* `detached` + `unref`'d with no stdio, so it OUTLIVES the launcher (the user can
|
|
33
|
+
* quit the TUI and the bot keeps serving) and reports itself via its status file.
|
|
34
|
+
*
|
|
35
|
+
* Returns the child pid, or undefined if the spawn produced none. Throws if the
|
|
36
|
+
* moxxy CLI entry can't be resolved (no `process.argv[1]`).
|
|
37
|
+
*
|
|
38
|
+
* Caller's job (this is fire-and-forget): poll {@link liveChannelStatus} to learn
|
|
39
|
+
* when it's ready / failed (no status file within a timeout ⇒ it died on boot —
|
|
40
|
+
* re-run `moxxy <name>` in the foreground to see why).
|
|
41
|
+
*/
|
|
42
|
+
export function spawnDedicatedChannel(name) {
|
|
43
|
+
const node = process.execPath; // the running Node binary (pnpm `moxxy` launches via Node)
|
|
44
|
+
const entry = process.argv[1]; // the resolved CLI entry (…/cli/dist/bin.js)
|
|
45
|
+
if (!entry) {
|
|
46
|
+
throw new Error('cannot start a channel: the moxxy CLI entry is unknown (process.argv[1] missing)');
|
|
47
|
+
}
|
|
48
|
+
const env = { ...process.env, MOXXY_DEDICATED_RUNNER: '1' };
|
|
49
|
+
for (const key of ADDRESSING_ENV)
|
|
50
|
+
delete env[key];
|
|
51
|
+
const child = spawn(node, [entry, name], { detached: true, stdio: 'ignore', env });
|
|
52
|
+
child.unref();
|
|
53
|
+
return child.pid;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Is `pid` a live process? `kill(pid, 0)` sends no signal — it only probes:
|
|
57
|
+
* - resolves ⇒ alive,
|
|
58
|
+
* - `ESRCH` ⇒ gone,
|
|
59
|
+
* - `EPERM` ⇒ alive but owned by another user (treat as alive — it exists).
|
|
60
|
+
*/
|
|
61
|
+
export function isPidAlive(pid) {
|
|
62
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
63
|
+
return false;
|
|
64
|
+
try {
|
|
65
|
+
process.kill(pid, 0);
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
return err.code === 'EPERM';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* The status of channel `name` IF it is actually running. Reads its status file
|
|
74
|
+
* and verifies the pid is alive; a file whose pid is dead (the runner crashed or
|
|
75
|
+
* was SIGKILL'd without clearing it) is treated as not-running AND removed, so a
|
|
76
|
+
* stale file never masquerades as a live channel.
|
|
77
|
+
*/
|
|
78
|
+
export function liveChannelStatus(name) {
|
|
79
|
+
const status = readChannelStatus(name);
|
|
80
|
+
if (!status)
|
|
81
|
+
return null;
|
|
82
|
+
if (!isPidAlive(status.pid)) {
|
|
83
|
+
clearChannelStatus(name);
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
return status;
|
|
87
|
+
}
|
|
88
|
+
/** The channel name encoded in a `channel-<name>.status.json` file, or null. */
|
|
89
|
+
function statusFileChannelName(file) {
|
|
90
|
+
const m = /^channel-(.+)\.status\.json$/.exec(file);
|
|
91
|
+
return m ? (m[1] ?? null) : null;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Every currently-running dedicated channel, discovered by scanning the moxxy
|
|
95
|
+
* home for status files and filtering to live pids (self-healing stale ones).
|
|
96
|
+
* Returns [] when the home dir doesn't exist yet.
|
|
97
|
+
*/
|
|
98
|
+
export function listLiveChannelStatuses() {
|
|
99
|
+
let files;
|
|
100
|
+
try {
|
|
101
|
+
files = readdirSync(moxxyHome());
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
return []; // no ~/.moxxy yet ⇒ nothing running
|
|
105
|
+
}
|
|
106
|
+
const live = [];
|
|
107
|
+
for (const file of files) {
|
|
108
|
+
const name = statusFileChannelName(file);
|
|
109
|
+
if (!name)
|
|
110
|
+
continue;
|
|
111
|
+
const status = liveChannelStatus(name);
|
|
112
|
+
if (status)
|
|
113
|
+
live.push(status);
|
|
114
|
+
}
|
|
115
|
+
return live;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Ask channel `name` to stop by SIGTERM-ing its runner. The runner's own signal
|
|
119
|
+
* handler tears down gracefully and clears its status file. Returns `'stopped'`
|
|
120
|
+
* if a live runner was signaled, `'not-running'` if there was nothing to stop.
|
|
121
|
+
*
|
|
122
|
+
* This is a single, synchronous SIGTERM — callers that want a hard backstop poll
|
|
123
|
+
* {@link liveChannelStatus} afterwards and escalate (SIGKILL + {@link clearChannelStatus})
|
|
124
|
+
* if it ignores the term within a grace period.
|
|
125
|
+
*/
|
|
126
|
+
export function stopDedicatedChannel(name) {
|
|
127
|
+
const status = liveChannelStatus(name);
|
|
128
|
+
if (!status)
|
|
129
|
+
return 'not-running';
|
|
130
|
+
try {
|
|
131
|
+
process.kill(status.pid, 'SIGTERM');
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
// Raced us to exit between the liveness check and here — already stopped.
|
|
135
|
+
clearChannelStatus(name);
|
|
136
|
+
}
|
|
137
|
+
return 'stopped';
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=channel-control.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-control.js","sourceRoot":"","sources":["../src/channel-control.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The on-disk status a dedicated channel runner publishes so an out-of-process
|
|
3
|
+
* supervisor (the desktop "Channels" panel) can observe it without the runner
|
|
4
|
+
* protocol. Written by `moxxy <channel>` when it self-hosts a dedicated runner,
|
|
5
|
+
* read by the desktop host; removed on graceful shutdown.
|
|
6
|
+
*
|
|
7
|
+
* It is intentionally tiny — readiness + the public ingest URL — not a mirror of
|
|
8
|
+
* the session. The supervisor owns liveness (it holds the child handle); this
|
|
9
|
+
* file is the channel's own report of "I'm up, and here's the URL to paste".
|
|
10
|
+
*/
|
|
11
|
+
export interface ChannelRunStatus {
|
|
12
|
+
/** Channel name (e.g. `slack`, `telegram`). */
|
|
13
|
+
readonly name: string;
|
|
14
|
+
/** PID of the channel runner process. */
|
|
15
|
+
readonly pid: number;
|
|
16
|
+
/** ISO timestamp the channel reported ready. */
|
|
17
|
+
readonly startedAt: string;
|
|
18
|
+
/** The session source the runner stamped (e.g. `slack`). */
|
|
19
|
+
readonly source?: string;
|
|
20
|
+
/** Public ingest URL (e.g. Slack's Events Request URL) once the tunnel is up;
|
|
21
|
+
* null for channels with no inbound endpoint (Telegram long-polls). */
|
|
22
|
+
readonly requestUrl?: string | null;
|
|
23
|
+
}
|
|
24
|
+
/** `~/.moxxy/channel-<name>.status.json` (honors `$MOXXY_HOME`). */
|
|
25
|
+
export declare function channelStatusPath(name: string): string;
|
|
26
|
+
/** Atomically publish a channel's run status (0600 — it may carry a URL). */
|
|
27
|
+
export declare function writeChannelStatus(status: ChannelRunStatus): void;
|
|
28
|
+
/** Read a channel's published status, or null if absent/unparseable. */
|
|
29
|
+
export declare function readChannelStatus(name: string): ChannelRunStatus | null;
|
|
30
|
+
/** Remove a channel's status file (best-effort; called on graceful shutdown). */
|
|
31
|
+
export declare function clearChannelStatus(name: string): void;
|
|
32
|
+
//# sourceMappingURL=channel-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-status.d.ts","sourceRoot":"","sources":["../src/channel-status.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4DAA4D;IAC5D,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;4EACwE;IACxE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAEjE;AAED,wEAAwE;AACxE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAMvE;AAED,iFAAiF;AACjF,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAMrD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { readFileSync, rmSync } from 'node:fs';
|
|
2
|
+
import { moxxyPath, writeFileAtomicSync } from './fs-utils.js';
|
|
3
|
+
/** `~/.moxxy/channel-<name>.status.json` (honors `$MOXXY_HOME`). */
|
|
4
|
+
export function channelStatusPath(name) {
|
|
5
|
+
return moxxyPath(`channel-${name}.status.json`);
|
|
6
|
+
}
|
|
7
|
+
/** Atomically publish a channel's run status (0600 — it may carry a URL). */
|
|
8
|
+
export function writeChannelStatus(status) {
|
|
9
|
+
writeFileAtomicSync(channelStatusPath(status.name), JSON.stringify(status), { mode: 0o600 });
|
|
10
|
+
}
|
|
11
|
+
/** Read a channel's published status, or null if absent/unparseable. */
|
|
12
|
+
export function readChannelStatus(name) {
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse(readFileSync(channelStatusPath(name), 'utf8'));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** Remove a channel's status file (best-effort; called on graceful shutdown). */
|
|
21
|
+
export function clearChannelStatus(name) {
|
|
22
|
+
try {
|
|
23
|
+
rmSync(channelStatusPath(name), { force: true });
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
/* best-effort */
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=channel-status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-status.js","sourceRoot":"","sources":["../src/channel-status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AA0B/D,oEAAoE;AACpE,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,SAAS,CAAC,WAAW,IAAI,cAAc,CAAC,CAAC;AAClD,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,kBAAkB,CAAC,MAAwB;IACzD,mBAAmB,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC/F,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAqB,CAAC;IACvF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,IAAI,CAAC;QACH,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;AACH,CAAC"}
|
package/dist/channel.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PermissionResolver } from './permission.js';
|
|
2
2
|
import type { ClientSession } from './client-session.js';
|
|
3
|
+
import type { SessionSource } from './event-store.js';
|
|
3
4
|
/**
|
|
4
5
|
* A Channel is a bidirectional surface that drives a Session: it feeds user
|
|
5
6
|
* prompts in, renders assistant chunks + tool activity out, and implements a
|
|
@@ -22,6 +23,14 @@ export interface Channel<TStartOpts = unknown> {
|
|
|
22
23
|
* resolves when the channel exits gracefully.
|
|
23
24
|
*/
|
|
24
25
|
start(opts: TStartOpts): Promise<ChannelHandle>;
|
|
26
|
+
/**
|
|
27
|
+
* The public ingest URL this channel exposes once running — e.g. Slack's
|
|
28
|
+
* Events Request URL after its proxy tunnel opens — or null when it has none
|
|
29
|
+
* (Telegram long-polls). Read by the dedicated-runner host to publish the URL
|
|
30
|
+
* the user must paste into the provider's config. Optional: channels with no
|
|
31
|
+
* inbound endpoint omit it.
|
|
32
|
+
*/
|
|
33
|
+
readonly requestUrl?: string | null;
|
|
25
34
|
}
|
|
26
35
|
export interface ChannelHandle {
|
|
27
36
|
/**
|
|
@@ -121,6 +130,61 @@ export interface ChannelDef<TStartOpts = unknown> {
|
|
|
121
130
|
* starts the channel.
|
|
122
131
|
*/
|
|
123
132
|
readonly interactiveCommand?: string;
|
|
133
|
+
/**
|
|
134
|
+
* Declare that this channel runs on its OWN dedicated, isolated runner: a
|
|
135
|
+
* distinct runner socket (`channel-<name>.sock`) + a stable sticky session id
|
|
136
|
+
* (`moxxy-channel-<name>`), so the channel acts as its own agent thread,
|
|
137
|
+
* separate from whatever runner serves the desktop/TUI. NO runner-protocol
|
|
138
|
+
* change — one dedicated runner is still one Session. Channels that should
|
|
139
|
+
* operate autonomously (slack, telegram) set this; the CLI reads it generically
|
|
140
|
+
* (see `applyDedicatedRunnerEnv`) so no per-channel name list is needed. Any
|
|
141
|
+
* channel can also opt in at runtime via `--dedicated` / `MOXXY_DEDICATED_RUNNER=1`.
|
|
142
|
+
*/
|
|
143
|
+
readonly dedicatedRunner?: boolean;
|
|
144
|
+
/**
|
|
145
|
+
* The {@link SessionSource} to stamp on this channel's sessions when it runs
|
|
146
|
+
* dedicated (persisted into the meta sidecar; surfaces filter history by it).
|
|
147
|
+
* Only honored alongside `dedicatedRunner`. When unset, the source falls back
|
|
148
|
+
* to the usual env/default resolution.
|
|
149
|
+
*/
|
|
150
|
+
readonly sessionSource?: SessionSource;
|
|
151
|
+
/**
|
|
152
|
+
* Declarative config the channel needs to run (its secret fields + where they
|
|
153
|
+
* live in the vault, plus pairing hints). This is what a control surface — the
|
|
154
|
+
* TUI `/channels` panel, `moxxy channels start`, the desktop "Channels" panel —
|
|
155
|
+
* renders to let the user configure + start the channel WITHOUT hardcoding a
|
|
156
|
+
* per-channel table. The channel self-describes here; the vault keys named are
|
|
157
|
+
* the same ones the channel actually reads at boot (its `keys.ts`). Channels
|
|
158
|
+
* with no setup (web/http) omit this.
|
|
159
|
+
*/
|
|
160
|
+
readonly config?: ChannelConfigDescriptor;
|
|
161
|
+
}
|
|
162
|
+
/** One secret/config input a channel exposes for a control surface to collect. */
|
|
163
|
+
export interface ChannelConfigField {
|
|
164
|
+
/** Option key (e.g. `botToken`). Stable identifier within the channel. */
|
|
165
|
+
readonly name: string;
|
|
166
|
+
/** Short human label (e.g. `Bot token`). */
|
|
167
|
+
readonly label: string;
|
|
168
|
+
/** The vault key the channel reads this value from (e.g. `slack_bot_token`). */
|
|
169
|
+
readonly vaultKey: string;
|
|
170
|
+
/** Must be present for the channel to count as "configured". */
|
|
171
|
+
readonly required?: boolean;
|
|
172
|
+
/** Treat as a secret — mask the input and never echo the stored value. */
|
|
173
|
+
readonly secret?: boolean;
|
|
174
|
+
/** Placeholder shown in an empty input (e.g. `xoxb-…`). */
|
|
175
|
+
readonly placeholder?: string;
|
|
176
|
+
/** One-line guidance on where to obtain the value. */
|
|
177
|
+
readonly help?: string;
|
|
178
|
+
}
|
|
179
|
+
/** What a channel declares about being configured + run from a control surface. */
|
|
180
|
+
export interface ChannelConfigDescriptor {
|
|
181
|
+
/** The fields to collect, in display order. */
|
|
182
|
+
readonly fields: ReadonlyArray<ChannelConfigField>;
|
|
183
|
+
/** The channel exposes a public ingest URL (Slack's Request URL) once started,
|
|
184
|
+
* so a control surface should poll for + surface it. */
|
|
185
|
+
readonly hasRequestUrl?: boolean;
|
|
186
|
+
/** Post-start pairing/setup instructions to show the user. */
|
|
187
|
+
readonly runHint?: string;
|
|
124
188
|
}
|
|
125
189
|
export interface ChannelAvailability {
|
|
126
190
|
readonly ok: boolean;
|
package/dist/channel.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"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"}
|
package/dist/channel.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AA0DA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB,EAAE,IAAsB;IACvE,oEAAoE;IACpE,8EAA8E;IAC9E,oEAAoE;IACpE,OAAO,OAAO,CAAC,KAAK,CAAC,IAAa,CAAC,CAAC;AACtC,CAAC"}
|
package/dist/event-store.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type { SessionId } from './ids.js';
|
|
|
11
11
|
* event (prompts, tool I/O), so that explicit opt-in is the trust boundary.
|
|
12
12
|
*/
|
|
13
13
|
/** Originating channel of a session (persisted into the meta sidecar). */
|
|
14
|
-
export type SessionSource = 'cli' | 'tui' | 'desktop' | 'mobile';
|
|
14
|
+
export type SessionSource = 'cli' | 'tui' | 'desktop' | 'mobile' | 'slack' | 'telegram';
|
|
15
15
|
/**
|
|
16
16
|
* The single per-session metadata record (the JSONL impl writes it to
|
|
17
17
|
* `~/.moxxy/sessions/<id>.json`). ONE per session — the unit every surface
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-store.d.ts","sourceRoot":"","sources":["../src/event-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C;;;;;;;;;GASG;AAEH,0EAA0E;AAC1E,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"event-store.d.ts","sourceRoot":"","sources":["../src/event-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAE1C;;;;;;;;;GASG;AAEH,0EAA0E;AAC1E,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,KAAK,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;AAExF;;;;;;;GAOG;AACH,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,uCAAuC;IACvC,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;IAChC,qDAAqD;IACrD,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,wCAAwC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,oEAAoE;AACpE,MAAM,WAAW,SAAS;IACxB,iFAAiF;IACjF,QAAQ,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,WAAW,YAAY;IAC3B,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC;IAC7E,OAAO,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CACrC;AAED,oDAAoD;AACpD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,aAAa,CAAC;CACjC;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,YAAY,GAAG,MAAM,IAAI,CAAC;IACtC,sEAAsE;IACtE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,6EAA6E;IAC7E,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,qEAAqE;IACrE,YAAY,CAAC,KAAK,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACvE,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wDAAwD;IACxD,IAAI,CAAC,KAAK,EAAE,eAAe,GAAG,iBAAiB,CAAC;IAChD,uDAAuD;IACvD,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IAChE,+DAA+D;IAC/D,QAAQ,CACN,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAC9C,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,SAAS,CAAC,CAAC;CACvB"}
|
package/dist/index.d.ts
CHANGED
|
@@ -21,6 +21,7 @@ export type { TunnelProviderDef, TunnelHandle, TunnelOpenOptions } from './tunne
|
|
|
21
21
|
export type { EventStoreDef, EventStoreSession, EventStoreScope, EventLogLike, EventPage, SessionMeta, SessionSource, } from './event-store.js';
|
|
22
22
|
export { isRetryableError, toFriendlyError, zodToJsonSchema, estimateTextTokens, type StopReason } from './provider-utils.js';
|
|
23
23
|
export type { WriteFileAtomicOptions } from './fs-utils.js';
|
|
24
|
+
export type { ChannelRunStatus } from './channel-status.js';
|
|
24
25
|
export type { CrossProcessFireLock, CrossProcessFireLockOptions } from './cross-process-lock.js';
|
|
25
26
|
export { createMutex, type Mutex } from './mutex.js';
|
|
26
27
|
export { createJsonFileStore, type JsonFileStore, type JsonFileStoreOptions, } from './json-file-store.js';
|
|
@@ -46,7 +47,7 @@ export type { AppContext, TurnContext, ToolCallContext, ToolResultContext, ToolC
|
|
|
46
47
|
export type { ServiceRegistry, NamedRegistry } from './services.js';
|
|
47
48
|
export type { PluginKind, PluginSpec, Plugin, PluginManifest, ResolvedPluginManifest, } from './plugin.js';
|
|
48
49
|
export { startChannelWith } from './channel.js';
|
|
49
|
-
export type { Channel, ChannelHandle, ChannelStartArgs, ChannelStartOptsBase, ChannelFactoryDeps, ChannelDef, ChannelAvailability, ChannelRegistry, ChannelSubcommand, ChannelSubcommandContext, ChannelCommandArgs, } from './channel.js';
|
|
50
|
+
export type { Channel, ChannelHandle, ChannelStartArgs, ChannelStartOptsBase, ChannelFactoryDeps, ChannelDef, ChannelConfigField, ChannelConfigDescriptor, ChannelAvailability, ChannelRegistry, ChannelSubcommand, ChannelSubcommandContext, ChannelCommandArgs, } from './channel.js';
|
|
50
51
|
export type { EmbeddingProvider, EmbedderDef } from './embedding.js';
|
|
51
52
|
export { CachedEmbeddingProvider } from './embedding-cache.js';
|
|
52
53
|
export { defineSurface } from './surface.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EACP,MAAM,EACN,UAAU,EACV,SAAS,EACT,QAAQ,EACR,OAAO,GACR,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAEjG,YAAY,EACV,SAAS,EACT,WAAW,EACX,UAAU,EACV,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,qBAAqB,EACrB,mBAAmB,EACnB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,uBAAuB,EACvB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,oBAAoB,EACpB,qBAAqB,EACrB,UAAU,EACV,UAAU,EACV,WAAW,GACZ,MAAM,aAAa,CAAC;AAErB,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,gBAAgB,EAChB,gBAAgB,EAChB,qBAAqB,EACrB,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,aAAa,EACb,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EACV,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,WAAW,EACX,OAAO,EACP,uBAAuB,EACvB,UAAU,EACV,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACrB,YAAY,EACZ,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,WAAW,CAAC;AAEnB,YAAY,EACV,YAAY,EACZ,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,QAAQ,EACR,gBAAgB,GACjB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,YAAY,EACV,YAAY,EACZ,cAAc,EACd,eAAe,EACf,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAGvB,YAAY,EACV,YAAY,EACZ,eAAe,EACf,eAAe,EACf,aAAa,EACb,SAAS,EACT,UAAU,EACV,eAAe,EACf,WAAW,EACX,WAAW,EACX,qBAAqB,EACrB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AACtF,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAClF,YAAY,EACV,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,eAAe,EACf,WAAW,EACX,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,UAAU,GACX,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,QAAQ,EACR,UAAU,EACV,OAAO,EACP,cAAc,EACd,eAAe,EACf,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,eAAe,GAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACpH,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACtF,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,SAAS,EACT,WAAW,EACX,aAAa,GACd,MAAM,kBAAkB,CAAC;AAK1B,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,kBAAkB,EAAE,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAC9H,YAAY,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,YAAY,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACjG,OAAO,EAAE,WAAW,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,EACL,mBAAmB,EACnB,KAAK,aAAa,EAClB,KAAK,oBAAoB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG7D,YAAY,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,gCAAgC,EAChC,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,EAC/B,KAAK,iCAAiC,GACvC,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,UAAU,EACV,kBAAkB,EAClB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,eAAe,EACf,2BAA2B,EAC3B,uBAAuB,EACvB,UAAU,EACV,cAAc,EACd,aAAa,EACb,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,sBAAsB,EAC3B,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,iBAAiB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,0BAA0B,EAC1B,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC;AAE5B,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EACL,qBAAqB,EACrB,qBAAqB,EACrB,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,GAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,KAAK,uBAAuB,GAC7B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,EACf,eAAe,EACf,KAAK,UAAU,GAChB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,sBAAsB,EACtB,gCAAgC,EAChC,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,GACtB,MAAM,uBAAuB,CAAC;AAE/B,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/F,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,kBAAkB,EAClB,eAAe,EACf,qBAAqB,EACrB,uBAAuB,EACvB,iBAAiB,EACjB,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AAEvB,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAE3C,YAAY,EACV,UAAU,EACV,cAAc,EACd,aAAa,EACb,oBAAoB,GACrB,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,OAAO,EACP,SAAS,EACT,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,gBAAgB,EAChB,cAAc,GACf,MAAM,WAAW,CAAC;AAEnB,YAAY,EACV,UAAU,EACV,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,cAAc,EACd,cAAc,GACf,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAEpE,YAAY,EACV,UAAU,EACV,UAAU,EACV,MAAM,EACN,cAAc,EACd,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,YAAY,EACV,OAAO,EACP,aAAa,EACb,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,mBAAmB,EACnB,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAE/D,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,UAAU,EACV,eAAe,EACf,WAAW,EACX,iBAAiB,EACjB,WAAW,GACZ,MAAM,cAAc,CAAC;AAEtB,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EACV,WAAW,EACX,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,YAAY,EACV,WAAW,EACX,cAAc,EACd,wBAAwB,EACxB,eAAe,EACf,iBAAiB,GAClB,MAAM,kBAAkB,CAAC;AAE1B,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,QAAQ,EAAE,OAAO,aAAa,EAAE,sBAAsB,GAAG,OAAO,CAAC,OAAO,aAAa,EAAE,MAAM,CAAC,CAAC;CACrG;AAED,OAAO,EACL,YAAY,EACZ,UAAU,EACV,cAAc,EACd,UAAU,EACV,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,aAAa,EACb,WAAW,EACX,sBAAsB,GACvB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE9D,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,GACvB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,iBAAiB,GACvB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,aAAa,GACnB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AA6GjG,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AA2BhD,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AAWpC,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,UAAU,GACX,MAAM,mBAAmB,CAAC;AAY3B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAWpH,+DAA+D;AAC/D,0EAA0E;AAC1E,yEAAyE;AACzE,iEAAiE;AACjE,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,eAAe,EAAE,kBAAkB,EAAmB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -17,5 +17,7 @@
|
|
|
17
17
|
export { writeFileAtomic, writeFileAtomicSync, moxxyHome, moxxyPath, } from './fs-utils.js';
|
|
18
18
|
export { CrossProcessFireLock } from './cross-process-lock.js';
|
|
19
19
|
export { readRequestBody, bearerTokenMatches } from './http-utils.js';
|
|
20
|
+
export { channelStatusPath, writeChannelStatus, readChannelStatus, clearChannelStatus, } from './channel-status.js';
|
|
21
|
+
export { spawnDedicatedChannel, isPidAlive, liveChannelStatus, listLiveChannelStatuses, stopDedicatedChannel, } from './channel-control.js';
|
|
20
22
|
export { resolveChannelToken, rotateChannelToken, bearerGuard, encodeWsBearerProtocol, tokenFromWsProtocolHeader, MOXXY_WS_SUBPROTOCOL, MOXXY_WS_BEARER_PROTOCOL_PREFIX, } from './channel-auth.js';
|
|
21
23
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,SAAS,EACT,SAAS,GACV,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,SAAS,EACT,SAAS,GACV,MAAM,eAAe,CAAC;AAGvB,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAItE,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAI7B,OAAO,EACL,qBAAqB,EACrB,UAAU,EACV,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,sBAAsB,EACtB,yBAAyB,EACzB,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,mBAAmB,CAAC"}
|
package/dist/server.js
CHANGED
|
@@ -19,5 +19,13 @@ export { writeFileAtomic, writeFileAtomicSync, moxxyHome, moxxyPath, } from './f
|
|
|
19
19
|
// options type is re-exported from the main barrel like other erased types.
|
|
20
20
|
export { CrossProcessFireLock } from './cross-process-lock.js';
|
|
21
21
|
export { readRequestBody, bearerTokenMatches } from './http-utils.js';
|
|
22
|
+
// Dedicated-channel run-status file: a channel publishes readiness + its public
|
|
23
|
+
// ingest URL so the desktop "Channels" supervisor can observe it out-of-process
|
|
24
|
+
// (node:fs). The `ChannelRunStatus` *type* rides the main barrel like the others.
|
|
25
|
+
export { channelStatusPath, writeChannelStatus, readChannelStatus, clearChannelStatus, } from './channel-status.js';
|
|
26
|
+
// Process-independent control of dedicated channel runners (start detached,
|
|
27
|
+
// discover via status files, stop) — shared by the TUI `/channels` panel and the
|
|
28
|
+
// `moxxy channels start|stop|status` subcommands (node:child_process + node:fs).
|
|
29
|
+
export { spawnDedicatedChannel, isPidAlive, liveChannelStatus, listLiveChannelStatuses, stopDedicatedChannel, } from './channel-control.js';
|
|
22
30
|
export { resolveChannelToken, rotateChannelToken, bearerGuard, encodeWsBearerProtocol, tokenFromWsProtocolHeader, MOXXY_WS_SUBPROTOCOL, MOXXY_WS_BEARER_PROTOCOL_PREFIX, } from './channel-auth.js';
|
|
23
31
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,SAAS,EACT,SAAS,GACV,MAAM,eAAe,CAAC;AACvB,0EAA0E;AAC1E,4EAA4E;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,sBAAsB,EACtB,yBAAyB,EACzB,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,SAAS,EACT,SAAS,GACV,MAAM,eAAe,CAAC;AACvB,0EAA0E;AAC1E,4EAA4E;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACtE,gFAAgF;AAChF,gFAAgF;AAChF,kFAAkF;AAClF,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,qBAAqB,CAAC;AAC7B,4EAA4E;AAC5E,iFAAiF;AACjF,iFAAiF;AACjF,OAAO,EACL,qBAAqB,EACrB,UAAU,EACV,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,WAAW,EACX,sBAAsB,EACtB,yBAAyB,EACzB,oBAAoB,EACpB,+BAA+B,GAChC,MAAM,mBAAmB,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
2
|
+
import fs from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
|
|
6
|
+
// `spawnDedicatedChannel` re-invokes the CLI via node:child_process — mock it so
|
|
7
|
+
// the test asserts the spawn shape without launching a real process. `vi.hoisted`
|
|
8
|
+
// makes the mock fn available to the hoisted `vi.mock` factory.
|
|
9
|
+
const { spawnMock } = vi.hoisted(() => ({
|
|
10
|
+
spawnMock: vi.fn(() => ({ pid: 4321, unref: (): void => {} })),
|
|
11
|
+
}));
|
|
12
|
+
vi.mock('node:child_process', () => ({ spawn: spawnMock }));
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
isPidAlive,
|
|
16
|
+
listLiveChannelStatuses,
|
|
17
|
+
liveChannelStatus,
|
|
18
|
+
spawnDedicatedChannel,
|
|
19
|
+
stopDedicatedChannel,
|
|
20
|
+
} from './channel-control.js';
|
|
21
|
+
import { channelStatusPath, writeChannelStatus } from './channel-status.js';
|
|
22
|
+
|
|
23
|
+
// A pid that is essentially never alive (above the platform max) → ESRCH.
|
|
24
|
+
const DEAD_PID = 2_000_000_000;
|
|
25
|
+
|
|
26
|
+
let home: string;
|
|
27
|
+
let prevHome: string | undefined;
|
|
28
|
+
|
|
29
|
+
beforeEach(() => {
|
|
30
|
+
home = fs.mkdtempSync(path.join(os.tmpdir(), 'moxxy-channel-control-'));
|
|
31
|
+
prevHome = process.env.MOXXY_HOME;
|
|
32
|
+
process.env.MOXXY_HOME = home;
|
|
33
|
+
spawnMock.mockClear();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
if (prevHome === undefined) delete process.env.MOXXY_HOME;
|
|
38
|
+
else process.env.MOXXY_HOME = prevHome;
|
|
39
|
+
fs.rmSync(home, { recursive: true, force: true });
|
|
40
|
+
vi.restoreAllMocks();
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
describe('isPidAlive', () => {
|
|
44
|
+
it('is true for the current process, false for a dead/invalid pid', () => {
|
|
45
|
+
expect(isPidAlive(process.pid)).toBe(true);
|
|
46
|
+
expect(isPidAlive(DEAD_PID)).toBe(false);
|
|
47
|
+
expect(isPidAlive(0)).toBe(false);
|
|
48
|
+
expect(isPidAlive(-1)).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('liveChannelStatus', () => {
|
|
53
|
+
it('returns null when no status file exists', () => {
|
|
54
|
+
expect(liveChannelStatus('slack')).toBeNull();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('returns the status when the runner pid is alive', () => {
|
|
58
|
+
writeChannelStatus({
|
|
59
|
+
name: 'slack',
|
|
60
|
+
pid: process.pid,
|
|
61
|
+
startedAt: new Date().toISOString(),
|
|
62
|
+
requestUrl: 'https://example.test/slack',
|
|
63
|
+
});
|
|
64
|
+
const s = liveChannelStatus('slack');
|
|
65
|
+
expect(s?.pid).toBe(process.pid);
|
|
66
|
+
expect(s?.requestUrl).toBe('https://example.test/slack');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('self-heals a stale file (dead pid) — returns null AND removes it', () => {
|
|
70
|
+
writeChannelStatus({ name: 'ghost', pid: DEAD_PID, startedAt: new Date().toISOString() });
|
|
71
|
+
expect(fs.existsSync(channelStatusPath('ghost'))).toBe(true);
|
|
72
|
+
expect(liveChannelStatus('ghost')).toBeNull();
|
|
73
|
+
expect(fs.existsSync(channelStatusPath('ghost'))).toBe(false);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
describe('listLiveChannelStatuses', () => {
|
|
78
|
+
it('returns only live channels, drops stale files, ignores unrelated files', () => {
|
|
79
|
+
writeChannelStatus({ name: 'slack', pid: process.pid, startedAt: new Date().toISOString() });
|
|
80
|
+
writeChannelStatus({ name: 'telegram', pid: process.pid, startedAt: new Date().toISOString() });
|
|
81
|
+
writeChannelStatus({ name: 'ghost', pid: DEAD_PID, startedAt: new Date().toISOString() });
|
|
82
|
+
fs.writeFileSync(path.join(home, 'vault.json'), '{}'); // unrelated file in ~/.moxxy
|
|
83
|
+
|
|
84
|
+
const names = listLiveChannelStatuses()
|
|
85
|
+
.map((s) => s.name)
|
|
86
|
+
.sort();
|
|
87
|
+
expect(names).toEqual(['slack', 'telegram']);
|
|
88
|
+
expect(fs.existsSync(channelStatusPath('ghost'))).toBe(false);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('returns [] when the home dir does not exist', () => {
|
|
92
|
+
process.env.MOXXY_HOME = path.join(home, 'does-not-exist');
|
|
93
|
+
expect(listLiveChannelStatuses()).toEqual([]);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
describe('stopDedicatedChannel', () => {
|
|
98
|
+
it('reports not-running when there is no live status', () => {
|
|
99
|
+
expect(stopDedicatedChannel('slack')).toBe('not-running');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('SIGTERMs the live runner and reports stopped', () => {
|
|
103
|
+
// Intercept kill so the liveness probe (signal 0) reports alive and the
|
|
104
|
+
// SIGTERM is recorded rather than actually delivered.
|
|
105
|
+
const killSpy = vi
|
|
106
|
+
.spyOn(process, 'kill')
|
|
107
|
+
.mockImplementation(((_pid: number, _sig?: string | number) => true) as typeof process.kill);
|
|
108
|
+
writeChannelStatus({ name: 'slack', pid: 999_999, startedAt: new Date().toISOString() });
|
|
109
|
+
|
|
110
|
+
expect(stopDedicatedChannel('slack')).toBe('stopped');
|
|
111
|
+
expect(killSpy).toHaveBeenCalledWith(999_999, 'SIGTERM');
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe('spawnDedicatedChannel', () => {
|
|
116
|
+
it('spawns a detached, dedicated runner with a scrubbed env', () => {
|
|
117
|
+
process.env.MOXXY_RUNNER_SOCKET = '/tmp/should-be-scrubbed.sock';
|
|
118
|
+
process.env.MOXXY_SESSION_ID = 'should-be-scrubbed';
|
|
119
|
+
try {
|
|
120
|
+
const pid = spawnDedicatedChannel('slack');
|
|
121
|
+
expect(pid).toBe(4321);
|
|
122
|
+
expect(spawnMock).toHaveBeenCalledTimes(1);
|
|
123
|
+
const [bin, argsArg, optsArg] = spawnMock.mock.calls[0] as [
|
|
124
|
+
string,
|
|
125
|
+
string[],
|
|
126
|
+
{ detached?: boolean; stdio?: string; env?: NodeJS.ProcessEnv },
|
|
127
|
+
];
|
|
128
|
+
expect(bin).toBe(process.execPath);
|
|
129
|
+
expect(argsArg).toEqual([process.argv[1], 'slack']);
|
|
130
|
+
expect(optsArg.detached).toBe(true);
|
|
131
|
+
expect(optsArg.stdio).toBe('ignore');
|
|
132
|
+
// Dedicated flag set; addressing vars scrubbed so the channel isolates.
|
|
133
|
+
expect(optsArg.env?.MOXXY_DEDICATED_RUNNER).toBe('1');
|
|
134
|
+
expect(optsArg.env?.MOXXY_RUNNER_SOCKET).toBeUndefined();
|
|
135
|
+
expect(optsArg.env?.MOXXY_SESSION_ID).toBeUndefined();
|
|
136
|
+
} finally {
|
|
137
|
+
delete process.env.MOXXY_RUNNER_SOCKET;
|
|
138
|
+
delete process.env.MOXXY_SESSION_ID;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process-independent control surface for dedicated channel runners.
|
|
3
|
+
*
|
|
4
|
+
* A dedicated channel (Slack, Telegram, …) runs as its OWN isolated runner
|
|
5
|
+
* subprocess that publishes a tiny status file (`channel-<name>.status.json`,
|
|
6
|
+
* see {@link ./channel-status}) on ready and clears it on graceful shutdown. That
|
|
7
|
+
* file — NOT a held child handle — is the source of truth for "is it running",
|
|
8
|
+
* so a channel started from anywhere (the TUI `/channels` panel, `moxxy channels
|
|
9
|
+
* start`, the desktop panel) is visible and stoppable from everywhere, and keeps
|
|
10
|
+
* running after the launcher exits.
|
|
11
|
+
*
|
|
12
|
+
* These helpers are the shared spine for those surfaces:
|
|
13
|
+
* - {@link spawnDedicatedChannel} — start one, detached, on its own runner.
|
|
14
|
+
* - {@link liveChannelStatus}/{@link listLiveChannelStatuses} — discover the
|
|
15
|
+
* running ones (with stale-file self-healing).
|
|
16
|
+
* - {@link stopDedicatedChannel} — signal one to stop.
|
|
17
|
+
*
|
|
18
|
+
* Node-only (`node:child_process`, `node:fs`) — exported from `@moxxy/sdk/server`.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { spawn } from 'node:child_process';
|
|
22
|
+
import { readdirSync } from 'node:fs';
|
|
23
|
+
|
|
24
|
+
import {
|
|
25
|
+
type ChannelRunStatus,
|
|
26
|
+
clearChannelStatus,
|
|
27
|
+
readChannelStatus,
|
|
28
|
+
} from './channel-status.js';
|
|
29
|
+
import { moxxyHome } from './fs-utils.js';
|
|
30
|
+
|
|
31
|
+
/** Env vars that ADDRESS a runner (socket + sticky session). We scrub these from
|
|
32
|
+
* a spawned channel's env so `applyDedicatedRunnerEnv` (which only fills UNSET
|
|
33
|
+
* vars) derives the channel's OWN isolated socket/session from its name — rather
|
|
34
|
+
* than the channel silently inheriting and sharing the launcher's runner. */
|
|
35
|
+
const ADDRESSING_ENV = ['MOXXY_RUNNER_SOCKET', 'MOXXY_SESSION_ID', 'MOXXY_SESSION_SOURCE'] as const;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Start a channel on its own dedicated, detached runner by re-invoking this very
|
|
39
|
+
* moxxy binary as `moxxy <name>` with `MOXXY_DEDICATED_RUNNER=1`. The child is
|
|
40
|
+
* `detached` + `unref`'d with no stdio, so it OUTLIVES the launcher (the user can
|
|
41
|
+
* quit the TUI and the bot keeps serving) and reports itself via its status file.
|
|
42
|
+
*
|
|
43
|
+
* Returns the child pid, or undefined if the spawn produced none. Throws if the
|
|
44
|
+
* moxxy CLI entry can't be resolved (no `process.argv[1]`).
|
|
45
|
+
*
|
|
46
|
+
* Caller's job (this is fire-and-forget): poll {@link liveChannelStatus} to learn
|
|
47
|
+
* when it's ready / failed (no status file within a timeout ⇒ it died on boot —
|
|
48
|
+
* re-run `moxxy <name>` in the foreground to see why).
|
|
49
|
+
*/
|
|
50
|
+
export function spawnDedicatedChannel(name: string): number | undefined {
|
|
51
|
+
const node = process.execPath; // the running Node binary (pnpm `moxxy` launches via Node)
|
|
52
|
+
const entry = process.argv[1]; // the resolved CLI entry (…/cli/dist/bin.js)
|
|
53
|
+
if (!entry) {
|
|
54
|
+
throw new Error('cannot start a channel: the moxxy CLI entry is unknown (process.argv[1] missing)');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const env: NodeJS.ProcessEnv = { ...process.env, MOXXY_DEDICATED_RUNNER: '1' };
|
|
58
|
+
for (const key of ADDRESSING_ENV) delete env[key];
|
|
59
|
+
|
|
60
|
+
const child = spawn(node, [entry, name], { detached: true, stdio: 'ignore', env });
|
|
61
|
+
child.unref();
|
|
62
|
+
return child.pid;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Is `pid` a live process? `kill(pid, 0)` sends no signal — it only probes:
|
|
67
|
+
* - resolves ⇒ alive,
|
|
68
|
+
* - `ESRCH` ⇒ gone,
|
|
69
|
+
* - `EPERM` ⇒ alive but owned by another user (treat as alive — it exists).
|
|
70
|
+
*/
|
|
71
|
+
export function isPidAlive(pid: number): boolean {
|
|
72
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
73
|
+
try {
|
|
74
|
+
process.kill(pid, 0);
|
|
75
|
+
return true;
|
|
76
|
+
} catch (err) {
|
|
77
|
+
return (err as NodeJS.ErrnoException).code === 'EPERM';
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The status of channel `name` IF it is actually running. Reads its status file
|
|
83
|
+
* and verifies the pid is alive; a file whose pid is dead (the runner crashed or
|
|
84
|
+
* was SIGKILL'd without clearing it) is treated as not-running AND removed, so a
|
|
85
|
+
* stale file never masquerades as a live channel.
|
|
86
|
+
*/
|
|
87
|
+
export function liveChannelStatus(name: string): ChannelRunStatus | null {
|
|
88
|
+
const status = readChannelStatus(name);
|
|
89
|
+
if (!status) return null;
|
|
90
|
+
if (!isPidAlive(status.pid)) {
|
|
91
|
+
clearChannelStatus(name);
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
return status;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** The channel name encoded in a `channel-<name>.status.json` file, or null. */
|
|
98
|
+
function statusFileChannelName(file: string): string | null {
|
|
99
|
+
const m = /^channel-(.+)\.status\.json$/.exec(file);
|
|
100
|
+
return m ? (m[1] ?? null) : null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Every currently-running dedicated channel, discovered by scanning the moxxy
|
|
105
|
+
* home for status files and filtering to live pids (self-healing stale ones).
|
|
106
|
+
* Returns [] when the home dir doesn't exist yet.
|
|
107
|
+
*/
|
|
108
|
+
export function listLiveChannelStatuses(): ChannelRunStatus[] {
|
|
109
|
+
let files: string[];
|
|
110
|
+
try {
|
|
111
|
+
files = readdirSync(moxxyHome());
|
|
112
|
+
} catch {
|
|
113
|
+
return []; // no ~/.moxxy yet ⇒ nothing running
|
|
114
|
+
}
|
|
115
|
+
const live: ChannelRunStatus[] = [];
|
|
116
|
+
for (const file of files) {
|
|
117
|
+
const name = statusFileChannelName(file);
|
|
118
|
+
if (!name) continue;
|
|
119
|
+
const status = liveChannelStatus(name);
|
|
120
|
+
if (status) live.push(status);
|
|
121
|
+
}
|
|
122
|
+
return live;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Ask channel `name` to stop by SIGTERM-ing its runner. The runner's own signal
|
|
127
|
+
* handler tears down gracefully and clears its status file. Returns `'stopped'`
|
|
128
|
+
* if a live runner was signaled, `'not-running'` if there was nothing to stop.
|
|
129
|
+
*
|
|
130
|
+
* This is a single, synchronous SIGTERM — callers that want a hard backstop poll
|
|
131
|
+
* {@link liveChannelStatus} afterwards and escalate (SIGKILL + {@link clearChannelStatus})
|
|
132
|
+
* if it ignores the term within a grace period.
|
|
133
|
+
*/
|
|
134
|
+
export function stopDedicatedChannel(name: string): 'stopped' | 'not-running' {
|
|
135
|
+
const status = liveChannelStatus(name);
|
|
136
|
+
if (!status) return 'not-running';
|
|
137
|
+
try {
|
|
138
|
+
process.kill(status.pid, 'SIGTERM');
|
|
139
|
+
} catch {
|
|
140
|
+
// Raced us to exit between the liveness check and here — already stopped.
|
|
141
|
+
clearChannelStatus(name);
|
|
142
|
+
}
|
|
143
|
+
return 'stopped';
|
|
144
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { readFileSync, rmSync } from 'node:fs';
|
|
2
|
+
|
|
3
|
+
import { moxxyPath, writeFileAtomicSync } from './fs-utils.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The on-disk status a dedicated channel runner publishes so an out-of-process
|
|
7
|
+
* supervisor (the desktop "Channels" panel) can observe it without the runner
|
|
8
|
+
* protocol. Written by `moxxy <channel>` when it self-hosts a dedicated runner,
|
|
9
|
+
* read by the desktop host; removed on graceful shutdown.
|
|
10
|
+
*
|
|
11
|
+
* It is intentionally tiny — readiness + the public ingest URL — not a mirror of
|
|
12
|
+
* the session. The supervisor owns liveness (it holds the child handle); this
|
|
13
|
+
* file is the channel's own report of "I'm up, and here's the URL to paste".
|
|
14
|
+
*/
|
|
15
|
+
export interface ChannelRunStatus {
|
|
16
|
+
/** Channel name (e.g. `slack`, `telegram`). */
|
|
17
|
+
readonly name: string;
|
|
18
|
+
/** PID of the channel runner process. */
|
|
19
|
+
readonly pid: number;
|
|
20
|
+
/** ISO timestamp the channel reported ready. */
|
|
21
|
+
readonly startedAt: string;
|
|
22
|
+
/** The session source the runner stamped (e.g. `slack`). */
|
|
23
|
+
readonly source?: string;
|
|
24
|
+
/** Public ingest URL (e.g. Slack's Events Request URL) once the tunnel is up;
|
|
25
|
+
* null for channels with no inbound endpoint (Telegram long-polls). */
|
|
26
|
+
readonly requestUrl?: string | null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** `~/.moxxy/channel-<name>.status.json` (honors `$MOXXY_HOME`). */
|
|
30
|
+
export function channelStatusPath(name: string): string {
|
|
31
|
+
return moxxyPath(`channel-${name}.status.json`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Atomically publish a channel's run status (0600 — it may carry a URL). */
|
|
35
|
+
export function writeChannelStatus(status: ChannelRunStatus): void {
|
|
36
|
+
writeFileAtomicSync(channelStatusPath(status.name), JSON.stringify(status), { mode: 0o600 });
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Read a channel's published status, or null if absent/unparseable. */
|
|
40
|
+
export function readChannelStatus(name: string): ChannelRunStatus | null {
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(readFileSync(channelStatusPath(name), 'utf8')) as ChannelRunStatus;
|
|
43
|
+
} catch {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Remove a channel's status file (best-effort; called on graceful shutdown). */
|
|
49
|
+
export function clearChannelStatus(name: string): void {
|
|
50
|
+
try {
|
|
51
|
+
rmSync(channelStatusPath(name), { force: true });
|
|
52
|
+
} catch {
|
|
53
|
+
/* best-effort */
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/channel.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { PermissionResolver } from './permission.js';
|
|
2
2
|
import type { ClientSession } from './client-session.js';
|
|
3
|
+
import type { SessionSource } from './event-store.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* A Channel is a bidirectional surface that drives a Session: it feeds user
|
|
@@ -25,6 +26,15 @@ export interface Channel<TStartOpts = unknown> {
|
|
|
25
26
|
* resolves when the channel exits gracefully.
|
|
26
27
|
*/
|
|
27
28
|
start(opts: TStartOpts): Promise<ChannelHandle>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* The public ingest URL this channel exposes once running — e.g. Slack's
|
|
32
|
+
* Events Request URL after its proxy tunnel opens — or null when it has none
|
|
33
|
+
* (Telegram long-polls). Read by the dedicated-runner host to publish the URL
|
|
34
|
+
* the user must paste into the provider's config. Optional: channels with no
|
|
35
|
+
* inbound endpoint omit it.
|
|
36
|
+
*/
|
|
37
|
+
readonly requestUrl?: string | null;
|
|
28
38
|
}
|
|
29
39
|
|
|
30
40
|
export interface ChannelHandle {
|
|
@@ -134,6 +144,63 @@ export interface ChannelDef<TStartOpts = unknown> {
|
|
|
134
144
|
* starts the channel.
|
|
135
145
|
*/
|
|
136
146
|
readonly interactiveCommand?: string;
|
|
147
|
+
/**
|
|
148
|
+
* Declare that this channel runs on its OWN dedicated, isolated runner: a
|
|
149
|
+
* distinct runner socket (`channel-<name>.sock`) + a stable sticky session id
|
|
150
|
+
* (`moxxy-channel-<name>`), so the channel acts as its own agent thread,
|
|
151
|
+
* separate from whatever runner serves the desktop/TUI. NO runner-protocol
|
|
152
|
+
* change — one dedicated runner is still one Session. Channels that should
|
|
153
|
+
* operate autonomously (slack, telegram) set this; the CLI reads it generically
|
|
154
|
+
* (see `applyDedicatedRunnerEnv`) so no per-channel name list is needed. Any
|
|
155
|
+
* channel can also opt in at runtime via `--dedicated` / `MOXXY_DEDICATED_RUNNER=1`.
|
|
156
|
+
*/
|
|
157
|
+
readonly dedicatedRunner?: boolean;
|
|
158
|
+
/**
|
|
159
|
+
* The {@link SessionSource} to stamp on this channel's sessions when it runs
|
|
160
|
+
* dedicated (persisted into the meta sidecar; surfaces filter history by it).
|
|
161
|
+
* Only honored alongside `dedicatedRunner`. When unset, the source falls back
|
|
162
|
+
* to the usual env/default resolution.
|
|
163
|
+
*/
|
|
164
|
+
readonly sessionSource?: SessionSource;
|
|
165
|
+
/**
|
|
166
|
+
* Declarative config the channel needs to run (its secret fields + where they
|
|
167
|
+
* live in the vault, plus pairing hints). This is what a control surface — the
|
|
168
|
+
* TUI `/channels` panel, `moxxy channels start`, the desktop "Channels" panel —
|
|
169
|
+
* renders to let the user configure + start the channel WITHOUT hardcoding a
|
|
170
|
+
* per-channel table. The channel self-describes here; the vault keys named are
|
|
171
|
+
* the same ones the channel actually reads at boot (its `keys.ts`). Channels
|
|
172
|
+
* with no setup (web/http) omit this.
|
|
173
|
+
*/
|
|
174
|
+
readonly config?: ChannelConfigDescriptor;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/** One secret/config input a channel exposes for a control surface to collect. */
|
|
178
|
+
export interface ChannelConfigField {
|
|
179
|
+
/** Option key (e.g. `botToken`). Stable identifier within the channel. */
|
|
180
|
+
readonly name: string;
|
|
181
|
+
/** Short human label (e.g. `Bot token`). */
|
|
182
|
+
readonly label: string;
|
|
183
|
+
/** The vault key the channel reads this value from (e.g. `slack_bot_token`). */
|
|
184
|
+
readonly vaultKey: string;
|
|
185
|
+
/** Must be present for the channel to count as "configured". */
|
|
186
|
+
readonly required?: boolean;
|
|
187
|
+
/** Treat as a secret — mask the input and never echo the stored value. */
|
|
188
|
+
readonly secret?: boolean;
|
|
189
|
+
/** Placeholder shown in an empty input (e.g. `xoxb-…`). */
|
|
190
|
+
readonly placeholder?: string;
|
|
191
|
+
/** One-line guidance on where to obtain the value. */
|
|
192
|
+
readonly help?: string;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/** What a channel declares about being configured + run from a control surface. */
|
|
196
|
+
export interface ChannelConfigDescriptor {
|
|
197
|
+
/** The fields to collect, in display order. */
|
|
198
|
+
readonly fields: ReadonlyArray<ChannelConfigField>;
|
|
199
|
+
/** The channel exposes a public ingest URL (Slack's Request URL) once started,
|
|
200
|
+
* so a control surface should poll for + surface it. */
|
|
201
|
+
readonly hasRequestUrl?: boolean;
|
|
202
|
+
/** Post-start pairing/setup instructions to show the user. */
|
|
203
|
+
readonly runHint?: string;
|
|
137
204
|
}
|
|
138
205
|
|
|
139
206
|
export interface ChannelAvailability {
|
package/src/event-store.ts
CHANGED
|
@@ -13,7 +13,7 @@ import type { SessionId } from './ids.js';
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
/** Originating channel of a session (persisted into the meta sidecar). */
|
|
16
|
-
export type SessionSource = 'cli' | 'tui' | 'desktop' | 'mobile';
|
|
16
|
+
export type SessionSource = 'cli' | 'tui' | 'desktop' | 'mobile' | 'slack' | 'telegram';
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* The single per-session metadata record (the JSONL impl writes it to
|
package/src/index.ts
CHANGED
|
@@ -194,6 +194,7 @@ export type {
|
|
|
194
194
|
// builtins and would break a browser/RN bundle. See ./server.ts.
|
|
195
195
|
export { isRetryableError, toFriendlyError, zodToJsonSchema, estimateTextTokens, type StopReason } from './provider-utils.js';
|
|
196
196
|
export type { WriteFileAtomicOptions } from './fs-utils.js';
|
|
197
|
+
export type { ChannelRunStatus } from './channel-status.js';
|
|
197
198
|
export type { CrossProcessFireLock, CrossProcessFireLockOptions } from './cross-process-lock.js';
|
|
198
199
|
export { createMutex, type Mutex } from './mutex.js';
|
|
199
200
|
export {
|
|
@@ -372,6 +373,8 @@ export type {
|
|
|
372
373
|
ChannelStartOptsBase,
|
|
373
374
|
ChannelFactoryDeps,
|
|
374
375
|
ChannelDef,
|
|
376
|
+
ChannelConfigField,
|
|
377
|
+
ChannelConfigDescriptor,
|
|
375
378
|
ChannelAvailability,
|
|
376
379
|
ChannelRegistry,
|
|
377
380
|
ChannelSubcommand,
|
package/src/server.ts
CHANGED
|
@@ -25,6 +25,25 @@ export {
|
|
|
25
25
|
// options type is re-exported from the main barrel like other erased types.
|
|
26
26
|
export { CrossProcessFireLock } from './cross-process-lock.js';
|
|
27
27
|
export { readRequestBody, bearerTokenMatches } from './http-utils.js';
|
|
28
|
+
// Dedicated-channel run-status file: a channel publishes readiness + its public
|
|
29
|
+
// ingest URL so the desktop "Channels" supervisor can observe it out-of-process
|
|
30
|
+
// (node:fs). The `ChannelRunStatus` *type* rides the main barrel like the others.
|
|
31
|
+
export {
|
|
32
|
+
channelStatusPath,
|
|
33
|
+
writeChannelStatus,
|
|
34
|
+
readChannelStatus,
|
|
35
|
+
clearChannelStatus,
|
|
36
|
+
} from './channel-status.js';
|
|
37
|
+
// Process-independent control of dedicated channel runners (start detached,
|
|
38
|
+
// discover via status files, stop) — shared by the TUI `/channels` panel and the
|
|
39
|
+
// `moxxy channels start|stop|status` subcommands (node:child_process + node:fs).
|
|
40
|
+
export {
|
|
41
|
+
spawnDedicatedChannel,
|
|
42
|
+
isPidAlive,
|
|
43
|
+
liveChannelStatus,
|
|
44
|
+
listLiveChannelStatuses,
|
|
45
|
+
stopDedicatedChannel,
|
|
46
|
+
} from './channel-control.js';
|
|
28
47
|
export {
|
|
29
48
|
resolveChannelToken,
|
|
30
49
|
rotateChannelToken,
|