@mininglamp-oss/cc-channel-octo 1.0.2 → 1.0.3-dev.1465991

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.
Files changed (51) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/config.example.json +5 -0
  3. package/dist/agent-bridge.js +6 -1
  4. package/dist/agent-bridge.js.map +1 -1
  5. package/dist/bot-manager.d.ts +103 -0
  6. package/dist/bot-manager.js +184 -0
  7. package/dist/bot-manager.js.map +1 -0
  8. package/dist/config-watcher.d.ts +48 -0
  9. package/dist/config-watcher.js +143 -0
  10. package/dist/config-watcher.js.map +1 -0
  11. package/dist/config.d.ts +38 -0
  12. package/dist/config.js +8 -0
  13. package/dist/config.js.map +1 -1
  14. package/dist/group-config.d.ts +18 -9
  15. package/dist/group-config.js +47 -10
  16. package/dist/group-config.js.map +1 -1
  17. package/dist/group-context.js +9 -1
  18. package/dist/group-context.js.map +1 -1
  19. package/dist/group-md-cache.d.ts +69 -0
  20. package/dist/group-md-cache.js +93 -0
  21. package/dist/group-md-cache.js.map +1 -0
  22. package/dist/group-md-events.d.ts +43 -0
  23. package/dist/group-md-events.js +43 -0
  24. package/dist/group-md-events.js.map +1 -0
  25. package/dist/group-md-tool.d.ts +49 -0
  26. package/dist/group-md-tool.js +95 -0
  27. package/dist/group-md-tool.js.map +1 -0
  28. package/dist/group-md-writeback.d.ts +97 -0
  29. package/dist/group-md-writeback.js +118 -0
  30. package/dist/group-md-writeback.js.map +1 -0
  31. package/dist/group-md.d.ts +53 -0
  32. package/dist/group-md.js +98 -0
  33. package/dist/group-md.js.map +1 -0
  34. package/dist/index.d.ts +15 -30
  35. package/dist/index.js +133 -140
  36. package/dist/index.js.map +1 -1
  37. package/dist/octo/api.d.ts +98 -1
  38. package/dist/octo/api.js +142 -2
  39. package/dist/octo/api.js.map +1 -1
  40. package/dist/octo/channel-id.d.ts +36 -0
  41. package/dist/octo/channel-id.js +52 -0
  42. package/dist/octo/channel-id.js.map +1 -0
  43. package/dist/octo/types.d.ts +22 -0
  44. package/dist/octo/types.js.map +1 -1
  45. package/dist/session-router.d.ts +43 -1
  46. package/dist/session-router.js +79 -3
  47. package/dist/session-router.js.map +1 -1
  48. package/dist/session-store.d.ts +26 -0
  49. package/dist/session-store.js +64 -1
  50. package/dist/session-store.js.map +1 -1
  51. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.0.3] - 2026-06-26
11
+
12
+ ### Changed
13
+
14
+ - **Hot-reload bots on config change — no gateway restart** — the gateway now
15
+ watches the global `config.json` and loads or unloads bots in place when its
16
+ bot set changes, instead of requiring a full process restart. A bot added by
17
+ provisioning comes online on its own, and a removed bot is disconnected and
18
+ unregistered, without bouncing the gateway or disturbing the other bots'
19
+ live sessions. This pairs with the daemon no longer restarting the gateway on
20
+ provision: previously, after the daemon stopped restarting, a newly added bot
21
+ stayed offline until the gateway was manually restarted.
22
+
23
+ ### Added
24
+
25
+ - **Bot manager + config watcher** — a serial bot lifecycle manager and a
26
+ debounced config watcher reconcile the running bot set against the on-disk
27
+ config. Batch boot is two-phase (start all, cross-register all, then connect)
28
+ so the cross-bot loop guard is consistent, and removal shuts a bot down before
29
+ unregistering it. A generation guard drops stale reconcile passes when the
30
+ config changes again mid-apply.
31
+
10
32
  ## [1.0.2] - 2026-06-24
11
33
 
12
34
  ### Added
@@ -386,6 +408,7 @@ hardening across the SSRF, prompt-injection, and protocol-DoS surfaces.
386
408
  Initial tagged baseline: text messaging, streaming output, SQLite session
387
409
  persistence, rate limiting, and the core security model.
388
410
 
411
+ [1.0.3]: https://github.com/Mininglamp-OSS/cc-channel-octo/compare/v1.0.2...v1.0.3
389
412
  [1.0.2]: https://github.com/Mininglamp-OSS/cc-channel-octo/compare/v1.0.1...v1.0.2
390
413
  [1.0.1]: https://github.com/Mininglamp-OSS/cc-channel-octo/compare/v1.0.0...v1.0.1
391
414
  [1.0.0]: https://github.com/Mininglamp-OSS/cc-channel-octo/compare/v0.2.0...v1.0.0
@@ -9,6 +9,11 @@
9
9
 
10
10
  "_comment_group_config_dir": "v1.0: optional directory of per-group instruction files (<groupId>.md), injected as trusted custom instructions. Operator-controlled — keep it OUTSIDE every bot's workspace (the agent can write there) AND non-writable by the gateway user. Omit to disable.",
11
11
 
12
+ "_comment_server_md": "P2-A: set serverMd=true to fetch each group's instructions from the server GROUP.md API (GET /v1/bot/groups/{groupNo}/md) first, falling back to the local groupConfigDir file on any failure (404 / network / no content). The fetched copy is cached IN MEMORY ONLY (never on disk — it is injected as a trusted system prompt, and a disk cache the gateway user could write would be a poisoning vector). serverMdTtlMs (default 300000 = 5 min) bounds how stale a cached entry may get before re-fetch. Default serverMd=false = pure local-file behavior (flip off to roll back).",
13
+
14
+ "_comment_md_writeback": "P2-C: set mdWriteback=true to give the agent an in-process MCP tool (mcp__group_md__update_group_md) that writes GROUP.md back to the server (PUT /v1/bot/groups/{groupNo}/md). Invocation is owner-gated (only the bot owner uid may call it); content is capped at 10240 bytes UTF-8 locally; write-backs to the same group are serialized in-process (the server has no compare-and-swap, so this prevents this gateway from racing itself — cross-source last-write-wins still applies). Default false = no write-back tool (GROUP.md is read-only from the gateway). Independent of serverMd.",
15
+
16
+
12
17
  "sdk": {
13
18
  "_comment_anthropic_base_url": "Q1: Optional self-hosted Claude API gateway base URL. Forwarded to the SDK subprocess (scoped). Must be https:// (or http://localhost for dev) — SSRF-validated at boot. Omit to use Anthropic's public endpoint.",
14
19
  "_comment_allowed_tools": "Q2: either '*' (allow every tool the SDK exposes) or an explicit string[] whitelist.",
@@ -269,9 +269,14 @@ export async function* queryAgent(userMessage, config, sessionCtx, onToolUse, op
269
269
  });
270
270
  // Detect the SDK's stale/invalid-resume signal (verified via spike): it throws
271
271
  // an Error whose message names the missing/invalid session id.
272
+ // Also catches Bedrock ValidationException for orphaned tool_use blocks left
273
+ // by an interrupted turn (no corresponding tool_result), which surfaces as:
274
+ // ValidationException: messages.N: `tool_use` ids were found without `tool_result` blocks
275
+ // Matching this here causes onResumeFailed() to clear the corrupt sdk_session_id
276
+ // and the turn to retry with fallbackRetryPrompt — same recovery path as stale sessions.
272
277
  const isResumeError = (err) => {
273
278
  const m = err instanceof Error ? err.message : String(err);
274
- return /No conversation found with session ID|--resume requires a valid session/i.test(m);
279
+ return /No conversation found with session ID|--resume requires a valid session|tool_use.*ids were found without.*tool_result|tool_result.*blocks.*immediately after/i.test(m);
275
280
  };
276
281
  const stream = runStream(opts?.resume, userMessage);
277
282
  // Drain one SDK stream, yielding assistant text. Reports the SDK session id once
@@ -1 +1 @@
1
- {"version":3,"file":"agent-bridge.js","sourceRoot":"","sources":["../src/agent-bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-bridge.js","sourceRoot":"","sources":["../src/agent-bridge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * BotManager — runtime registry of live bots for hot-reload (#157).
3
+ *
4
+ * Owns a long-lived `Map<configId, BotStack>` so the gateway can add/remove a
5
+ * single bot at runtime (driven by a config.json watcher) instead of a full
6
+ * process restart. Holds the two-identity discipline (plan B2): the Map is
7
+ * keyed by configId (config.json `bots[].id`), while the SessionRouter loop
8
+ * guard is keyed by robotUid (Octo register id) — never mixed.
9
+ *
10
+ * Concurrency (plan C/C6): all mutations funnel through a single serial queue
11
+ * (`enqueue`), so a watcher burst can never run two add/remove against the same
12
+ * set concurrently. The diff is computed INSIDE the queued task against the
13
+ * freshly-loaded desired set, never precomputed in the watcher callback.
14
+ */
15
+ import type { SessionRouter } from './session-router.js';
16
+ /**
17
+ * The subset of a started bot the manager needs to track and tear down. The
18
+ * manager keys bots by the configId passed to addBot (not a field here), and the
19
+ * loop-guard uses robotUid — so configId is intentionally NOT carried on the
20
+ * stack (it would be a write-only field; see plan B2 for the identity split).
21
+ */
22
+ export interface ManagedBot {
23
+ robotUid: string;
24
+ router: SessionRouter;
25
+ connect: () => Promise<void>;
26
+ shutdown: () => Promise<void>;
27
+ }
28
+ /**
29
+ * Diff a desired config-id set against the currently-running config-id set.
30
+ *
31
+ * Returns the configIds to add (in desired, not running) and to remove (running,
32
+ * not in desired). Order within each list is the input order of `desired` /
33
+ * `running` respectively.
34
+ */
35
+ export declare function diffBotSets(desired: readonly string[], running: readonly string[]): {
36
+ toAdd: string[];
37
+ toRemove: string[];
38
+ };
39
+ /**
40
+ * Cross-register the loop-guard known-bot uids for a newly-added bot:
41
+ * - the new bot's router learns every existing bot's robotUid, AND
42
+ * - every existing bot's router learns the new bot's robotUid.
43
+ * Bidirectional — a one-way register would let one side treat the other's
44
+ * messages as user input in a mention-free group (plan B). Pure over the
45
+ * passed collections (no I/O), so it is unit-testable.
46
+ */
47
+ export declare function crossRegisterOnAdd(newBot: ManagedBot, existing: readonly ManagedBot[]): void;
48
+ /** Symmetric teardown: every remaining bot's router forgets the removed bot. */
49
+ export declare function crossUnregisterOnRemove(removed: ManagedBot, remaining: readonly ManagedBot[]): void;
50
+ /** How a managed bot is brought up from a config entry (injected for tests). */
51
+ export type StartFn = (configId: string) => Promise<ManagedBot>;
52
+ /**
53
+ * Runtime registry + serial mutation queue for live bots.
54
+ *
55
+ * The manager never opens sockets itself — `StartFn` (wired to startBot in
56
+ * index.ts) does the register+handler work and returns a ManagedBot whose
57
+ * `connect()` opens the socket. addBot enforces the plan-B ordering:
58
+ * start (register+handler, no socket) → cross-register known bots → connect,
59
+ * with rollback if connect throws.
60
+ */
61
+ export declare class BotManager {
62
+ private readonly start;
63
+ private readonly bots;
64
+ private queue;
65
+ private shuttingDown;
66
+ constructor(start: StartFn);
67
+ /** Snapshot of currently-running config keys (Map keys). */
68
+ runningKeys(): string[];
69
+ size(): number;
70
+ has(key: string): boolean;
71
+ /** Run a mutation on the serial queue so add/remove never interleave. */
72
+ private enqueue;
73
+ /**
74
+ * Add one bot by configId: start → cross-register → connect, rolling back all
75
+ * three on any failure so a half-added bot never lingers in the Map or in
76
+ * sibling routers' known-bot sets.
77
+ */
78
+ addBot(configId: string): Promise<void>;
79
+ /** Remove one bot by configId: shutdown + symmetric unregister + drop. */
80
+ removeBot(configId: string): Promise<void>;
81
+ /**
82
+ * Bring up several bots as ONE two-phase batch: start every bot (register +
83
+ * handler, NO socket) → cross-register the whole set's loop-guard uids
84
+ * pairwise → connect them all. This preserves the "no bot opens its socket
85
+ * before every sibling knows its robotUid" invariant ACROSS the initial set —
86
+ * adding bots one-by-one via addBot would let the first bot connect before
87
+ * later bots exist, so it would never learn them. A bot that fails to start or
88
+ * connect is rolled back and skipped (resilience); the rest still come up.
89
+ * Returns the configIds that failed.
90
+ */
91
+ addBotsBatch(configIds: readonly string[]): Promise<{
92
+ failed: {
93
+ configId: string;
94
+ error: unknown;
95
+ }[];
96
+ }>;
97
+ /**
98
+ * Shut down every running bot (process exit). Drains them concurrently — order
99
+ * doesn't matter at teardown — and clears the Map. Runs on the serial queue so
100
+ * it can't interleave with an in-flight add/remove.
101
+ */
102
+ shutdownAll(): Promise<void>;
103
+ }
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Diff a desired config-id set against the currently-running config-id set.
3
+ *
4
+ * Returns the configIds to add (in desired, not running) and to remove (running,
5
+ * not in desired). Order within each list is the input order of `desired` /
6
+ * `running` respectively.
7
+ */
8
+ export function diffBotSets(desired, running) {
9
+ const runningSet = new Set(running);
10
+ const desiredSet = new Set(desired);
11
+ const toAdd = desired.filter((id) => !runningSet.has(id));
12
+ const toRemove = running.filter((id) => !desiredSet.has(id));
13
+ return { toAdd, toRemove };
14
+ }
15
+ /**
16
+ * Cross-register the loop-guard known-bot uids for a newly-added bot:
17
+ * - the new bot's router learns every existing bot's robotUid, AND
18
+ * - every existing bot's router learns the new bot's robotUid.
19
+ * Bidirectional — a one-way register would let one side treat the other's
20
+ * messages as user input in a mention-free group (plan B). Pure over the
21
+ * passed collections (no I/O), so it is unit-testable.
22
+ */
23
+ export function crossRegisterOnAdd(newBot, existing) {
24
+ for (const e of existing) {
25
+ if (e.robotUid === newBot.robotUid)
26
+ continue;
27
+ newBot.router.registerKnownBot(e.robotUid);
28
+ e.router.registerKnownBot(newBot.robotUid);
29
+ }
30
+ }
31
+ /** Symmetric teardown: every remaining bot's router forgets the removed bot. */
32
+ export function crossUnregisterOnRemove(removed, remaining) {
33
+ for (const r of remaining) {
34
+ r.router.unregisterKnownBot(removed.robotUid);
35
+ }
36
+ }
37
+ /**
38
+ * Runtime registry + serial mutation queue for live bots.
39
+ *
40
+ * The manager never opens sockets itself — `StartFn` (wired to startBot in
41
+ * index.ts) does the register+handler work and returns a ManagedBot whose
42
+ * `connect()` opens the socket. addBot enforces the plan-B ordering:
43
+ * start (register+handler, no socket) → cross-register known bots → connect,
44
+ * with rollback if connect throws.
45
+ */
46
+ export class BotManager {
47
+ start;
48
+ bots = new Map();
49
+ queue = Promise.resolve();
50
+ // Set by shutdownAll() so any apply task that was already past the watcher's
51
+ // `closed` guard can't re-add a bot after teardown has begun (plan E / N4
52
+ // shutdown race). Once true, addBot is a permanent no-op.
53
+ shuttingDown = false;
54
+ constructor(start) {
55
+ this.start = start;
56
+ }
57
+ /** Snapshot of currently-running config keys (Map keys). */
58
+ runningKeys() {
59
+ return [...this.bots.keys()];
60
+ }
61
+ size() {
62
+ return this.bots.size;
63
+ }
64
+ has(key) {
65
+ return this.bots.has(key);
66
+ }
67
+ /** Run a mutation on the serial queue so add/remove never interleave. */
68
+ enqueue(task) {
69
+ const run = this.queue.then(task, task);
70
+ // Keep the chain alive even if a task rejects (so later tasks still run),
71
+ // but propagate the result/rejection to this call's awaiter.
72
+ this.queue = run.then(() => undefined, () => undefined);
73
+ return run;
74
+ }
75
+ /**
76
+ * Add one bot by configId: start → cross-register → connect, rolling back all
77
+ * three on any failure so a half-added bot never lingers in the Map or in
78
+ * sibling routers' known-bot sets.
79
+ */
80
+ addBot(configId) {
81
+ return this.enqueue(async () => {
82
+ if (this.shuttingDown)
83
+ return; // teardown started — don't resurrect bots
84
+ if (this.bots.has(configId))
85
+ return; // idempotent — already running
86
+ const bot = await this.start(configId);
87
+ const existing = [...this.bots.values()];
88
+ crossRegisterOnAdd(bot, existing);
89
+ try {
90
+ await bot.connect();
91
+ }
92
+ catch (err) {
93
+ // Roll back: undo the cross-registration, tear the bot down, leave the
94
+ // set exactly as it was before this addBot.
95
+ crossUnregisterOnRemove(bot, existing);
96
+ await bot.shutdown().catch(() => { });
97
+ throw err;
98
+ }
99
+ this.bots.set(configId, bot);
100
+ });
101
+ }
102
+ /** Remove one bot by configId: shutdown + symmetric unregister + drop. */
103
+ removeBot(configId) {
104
+ return this.enqueue(async () => {
105
+ const bot = this.bots.get(configId);
106
+ if (!bot)
107
+ return; // idempotent — already gone
108
+ this.bots.delete(configId);
109
+ const remaining = [...this.bots.values()];
110
+ // Symmetric inverse of addBot's ordering: close the socket FIRST, then let
111
+ // siblings forget this bot. If we unregistered before shutdown, the bot's
112
+ // in-flight handlers (still draining for up to the gateway drain timeout)
113
+ // could emit replies that siblings — having already dropped its robotUid —
114
+ // would treat as user input, reopening the very loop the guard prevents.
115
+ await bot.shutdown().catch(() => { });
116
+ crossUnregisterOnRemove(bot, remaining);
117
+ });
118
+ }
119
+ /**
120
+ * Bring up several bots as ONE two-phase batch: start every bot (register +
121
+ * handler, NO socket) → cross-register the whole set's loop-guard uids
122
+ * pairwise → connect them all. This preserves the "no bot opens its socket
123
+ * before every sibling knows its robotUid" invariant ACROSS the initial set —
124
+ * adding bots one-by-one via addBot would let the first bot connect before
125
+ * later bots exist, so it would never learn them. A bot that fails to start or
126
+ * connect is rolled back and skipped (resilience); the rest still come up.
127
+ * Returns the configIds that failed.
128
+ */
129
+ addBotsBatch(configIds) {
130
+ return this.enqueue(async () => {
131
+ const failed = [];
132
+ if (this.shuttingDown) {
133
+ return { failed: configIds.map((configId) => ({ configId, error: new Error('shutting down') })) };
134
+ }
135
+ // Phase 1: start (register + handler, no socket) every not-yet-running bot.
136
+ const started = [];
137
+ for (const configId of configIds) {
138
+ if (this.bots.has(configId))
139
+ continue; // already running — skip
140
+ try {
141
+ started.push({ configId, bot: await this.start(configId) });
142
+ }
143
+ catch (error) {
144
+ failed.push({ configId, error });
145
+ }
146
+ }
147
+ // Phase 2: cross-register loop-guard uids across the existing set AND the
148
+ // whole freshly-started batch, BEFORE any socket opens.
149
+ const existing = [...this.bots.values()];
150
+ const batch = started.map((s) => s.bot);
151
+ for (const s of started) {
152
+ crossRegisterOnAdd(s.bot, [...existing, ...batch]);
153
+ }
154
+ // Phase 3: connect every started bot. A connect failure rolls back just
155
+ // that bot (unregister from everyone + shutdown) and is reported.
156
+ for (const s of started) {
157
+ try {
158
+ await s.bot.connect();
159
+ this.bots.set(s.configId, s.bot);
160
+ }
161
+ catch (error) {
162
+ crossUnregisterOnRemove(s.bot, [...existing, ...batch.filter((b) => b !== s.bot)]);
163
+ await s.bot.shutdown().catch(() => { });
164
+ failed.push({ configId: s.configId, error });
165
+ }
166
+ }
167
+ return { failed };
168
+ });
169
+ }
170
+ /**
171
+ * Shut down every running bot (process exit). Drains them concurrently — order
172
+ * doesn't matter at teardown — and clears the Map. Runs on the serial queue so
173
+ * it can't interleave with an in-flight add/remove.
174
+ */
175
+ shutdownAll() {
176
+ this.shuttingDown = true;
177
+ return this.enqueue(async () => {
178
+ const all = [...this.bots.values()];
179
+ this.bots.clear();
180
+ await Promise.allSettled(all.map((b) => b.shutdown()));
181
+ });
182
+ }
183
+ }
184
+ //# sourceMappingURL=bot-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bot-manager.js","sourceRoot":"","sources":["../src/bot-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /** Minimal manager surface the watcher needs (eases testing). */
2
+ export interface Reconcilable {
3
+ runningKeys(): string[];
4
+ addBot(configId: string): Promise<void>;
5
+ removeBot(configId: string): Promise<void>;
6
+ }
7
+ /**
8
+ * Reconcile the running set toward `desiredConfigIds` once. Removes first, then
9
+ * adds, so a config that swaps a bot for another with an overlapping resource
10
+ * (lock/dir) frees it before the replacement claims it. Add/remove failures are
11
+ * logged and swallowed so one bad bot doesn't abort the whole reconcile; the
12
+ * BotManager queue keeps the set consistent. Pure-ish (no fs) for unit testing.
13
+ *
14
+ * `isStale` is checked before each add/remove: a newer config event makes the
15
+ * in-flight reconcile abandon its remaining (now outdated) actions, so a bot
16
+ * removed by a later edit is never started by an earlier, slower reconcile
17
+ * (plan C6 generation guard).
18
+ */
19
+ export declare function reconcile(manager: Reconcilable, desiredConfigIds: readonly string[], log?: (msg: string) => void, isStale?: () => boolean): Promise<void>;
20
+ export interface WatcherHandle {
21
+ /** Force an immediate reconcile (bypasses debounce). For tests / initial sync. */
22
+ applyNow(): Promise<void>;
23
+ close(): void;
24
+ }
25
+ export interface WatchOptions {
26
+ /** Absolute path to the global config.json. */
27
+ configPath: string;
28
+ manager: Reconcilable;
29
+ /**
30
+ * Produce the desired configId list from disk. MUST throw on any invalid
31
+ * config so the watcher can keep the current set (plan D). Typically wraps
32
+ * loadConfig + resolveBotConfigs and maps to `bots[].id`.
33
+ */
34
+ loadDesired: () => readonly string[];
35
+ /** Debounce window in ms (coalesce a burst of writes). Default 200. */
36
+ debounceMs?: number;
37
+ log?: (msg: string) => void;
38
+ }
39
+ /**
40
+ * Start watching `configPath`'s directory and reconcile on change.
41
+ *
42
+ * Serialization & staleness: a single `chain` promise serializes apply runs,
43
+ * and each run re-reads the latest config at execution time, so a burst of
44
+ * events collapses to "apply the newest state" rather than replaying each
45
+ * intermediate edit. The BotManager's own queue further serializes the
46
+ * resulting add/remove calls.
47
+ */
48
+ export declare function watchConfig(opts: WatchOptions): WatcherHandle;
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Config watcher — drives BotManager from config.json changes (#157).
3
+ *
4
+ * Watches the global config's directory (not the file directly: an atomic
5
+ * temp+rename swaps the inode, and a file-targeted fs.watch would stop firing
6
+ * after the first rename). On any change it schedules a debounced, serialized
7
+ * `applyLatestConfig`, which RE-READS the latest config inside the task (never
8
+ * a precomputed diff — plan C6) and reconciles the running set toward it.
9
+ *
10
+ * Robustness (plan D): the desired set is produced by a single `loadDesired`
11
+ * call; if it throws for ANY reason (half-written file, JSON error, missing
12
+ * token, duplicate id, unsafe apiUrl, broken per-bot config), the current
13
+ * running set is left untouched — a bad edit never tears down healthy bots.
14
+ */
15
+ import { watch } from 'node:fs';
16
+ import { dirname, basename } from 'node:path';
17
+ import { diffBotSets } from './bot-manager.js';
18
+ /**
19
+ * Reconcile the running set toward `desiredConfigIds` once. Removes first, then
20
+ * adds, so a config that swaps a bot for another with an overlapping resource
21
+ * (lock/dir) frees it before the replacement claims it. Add/remove failures are
22
+ * logged and swallowed so one bad bot doesn't abort the whole reconcile; the
23
+ * BotManager queue keeps the set consistent. Pure-ish (no fs) for unit testing.
24
+ *
25
+ * `isStale` is checked before each add/remove: a newer config event makes the
26
+ * in-flight reconcile abandon its remaining (now outdated) actions, so a bot
27
+ * removed by a later edit is never started by an earlier, slower reconcile
28
+ * (plan C6 generation guard).
29
+ */
30
+ export async function reconcile(manager, desiredConfigIds, log = () => { }, isStale = () => false) {
31
+ const { toAdd, toRemove } = diffBotSets(desiredConfigIds, manager.runningKeys());
32
+ for (const id of toRemove) {
33
+ if (isStale()) {
34
+ log(`[hot-reload] reconcile superseded by a newer config, stopping`);
35
+ return;
36
+ }
37
+ try {
38
+ await manager.removeBot(id);
39
+ log(`[hot-reload] removed bot ${id}`);
40
+ }
41
+ catch (err) {
42
+ log(`[hot-reload] removeBot ${id} failed: ${errMsg(err)}`);
43
+ }
44
+ }
45
+ for (const id of toAdd) {
46
+ if (isStale()) {
47
+ log(`[hot-reload] reconcile superseded by a newer config, stopping`);
48
+ return;
49
+ }
50
+ try {
51
+ await manager.addBot(id);
52
+ log(`[hot-reload] added bot ${id}`);
53
+ }
54
+ catch (err) {
55
+ log(`[hot-reload] addBot ${id} failed: ${errMsg(err)}`);
56
+ }
57
+ }
58
+ }
59
+ function errMsg(err) {
60
+ return err instanceof Error ? err.message : String(err);
61
+ }
62
+ /**
63
+ * Start watching `configPath`'s directory and reconcile on change.
64
+ *
65
+ * Serialization & staleness: a single `chain` promise serializes apply runs,
66
+ * and each run re-reads the latest config at execution time, so a burst of
67
+ * events collapses to "apply the newest state" rather than replaying each
68
+ * intermediate edit. The BotManager's own queue further serializes the
69
+ * resulting add/remove calls.
70
+ */
71
+ export function watchConfig(opts) {
72
+ const { configPath, manager, loadDesired } = opts;
73
+ const debounceMs = opts.debounceMs ?? 200;
74
+ const log = opts.log ?? (() => { });
75
+ const dir = dirname(configPath);
76
+ const file = basename(configPath);
77
+ let chain = Promise.resolve();
78
+ let timer;
79
+ let closed = false;
80
+ // Generation guard (plan C6). `latestGen` is bumped the moment a file event is
81
+ // observed (in schedule), NOT when the debounced apply finally runs — so an
82
+ // in-flight reconcile is invalidated immediately on a new event, even during
83
+ // the debounce window, instead of continuing to add/connect a bot a later
84
+ // edit already removed. Each apply captures the gen current when it starts and
85
+ // bails (isStale) as soon as a newer event has bumped past it.
86
+ let latestGen = 0;
87
+ const apply = () => {
88
+ const myGen = latestGen;
89
+ // Re-read latest desired set INSIDE the serialized task (plan C6). Any
90
+ // failure (half-write / invalid config) leaves the running set untouched.
91
+ chain = chain.then(async () => {
92
+ if (closed)
93
+ return;
94
+ let desired;
95
+ try {
96
+ desired = loadDesired();
97
+ }
98
+ catch (err) {
99
+ log(`[hot-reload] config invalid, keeping current bots: ${errMsg(err)}`);
100
+ return;
101
+ }
102
+ await reconcile(manager, desired, log, () => closed || myGen !== latestGen);
103
+ });
104
+ return chain;
105
+ };
106
+ const schedule = () => {
107
+ if (closed)
108
+ return;
109
+ // Invalidate any in-flight reconcile right now (not at debounce expiry): a
110
+ // slow reconcile must see this newer event before it acts on stale desired.
111
+ latestGen++;
112
+ if (timer)
113
+ clearTimeout(timer);
114
+ timer = setTimeout(() => {
115
+ timer = undefined;
116
+ void apply();
117
+ }, debounceMs);
118
+ timer.unref?.();
119
+ };
120
+ let watcher;
121
+ try {
122
+ watcher = watch(dir, (_event, changed) => {
123
+ // Only react to our config file (the dir may hold per-bot subdirs etc.).
124
+ // changed is null on some platforms — be permissive and reconcile then.
125
+ if (changed === null || changed === file)
126
+ schedule();
127
+ });
128
+ watcher.on('error', (err) => log(`[hot-reload] watcher error: ${errMsg(err)}`));
129
+ }
130
+ catch (err) {
131
+ log(`[hot-reload] failed to start watcher on ${dir}: ${errMsg(err)}`);
132
+ }
133
+ return {
134
+ applyNow: apply,
135
+ close: () => {
136
+ closed = true;
137
+ if (timer)
138
+ clearTimeout(timer);
139
+ watcher?.close();
140
+ },
141
+ };
142
+ }
143
+ //# sourceMappingURL=config-watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-watcher.js","sourceRoot":"","sources":["../src/config-watcher.ts"],"names":[],"mappings":"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"}