niahere 0.2.41 → 0.2.42

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "niahere",
3
- "version": "0.2.41",
3
+ "version": "0.2.42",
4
4
  "description": "A personal AI assistant daemon — scheduled jobs, chat across Telegram and Slack, persona system, and visual identity.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -4,7 +4,7 @@ import { log } from "../utils/log";
4
4
  import { createTelegramChannel } from "./telegram";
5
5
  import { createSlackChannel } from "./slack";
6
6
 
7
- export { getChannel } from "./registry";
7
+ export { getChannel, getStarted } from "./registry";
8
8
 
9
9
  /** Register all built-in channel factories. Call once at startup. */
10
10
  export function registerAllChannels(): void {
@@ -19,6 +19,10 @@ export function getChannel(name: string): Channel | undefined {
19
19
  return started.get(name);
20
20
  }
21
21
 
22
+ export function getStarted(): Channel[] {
23
+ return [...started.values()];
24
+ }
25
+
22
26
  export function clearStarted(): void {
23
27
  started.clear();
24
28
  }
package/src/chat/repl.ts CHANGED
@@ -2,7 +2,7 @@ import * as readline from "readline";
2
2
  import { createChatEngine } from "./engine";
3
3
  import { runMigrations } from "../db/migrate";
4
4
  import { closeDb } from "../db/connection";
5
- import { getMcpServers, setMcpServers } from "../mcp";
5
+ import { getMcpServers, setMcpFactory } from "../mcp";
6
6
  import { createNiaMcpServer } from "../mcp/server";
7
7
  import { Session } from "../db/models";
8
8
  import { relativeTime } from "../utils/format";
@@ -113,12 +113,9 @@ export async function startRepl(mode: ChatMode = "continue", simulateChannel?: s
113
113
  process.exit(1);
114
114
  }
115
115
 
116
- // Initialize MCP server if not already set (standalone chat mode)
116
+ // Initialize MCP server factory if not already set (standalone chat mode)
117
117
  if (!getMcpServers()) {
118
- try {
119
- const mcpConfig = createNiaMcpServer();
120
- setMcpServers({ nia: mcpConfig });
121
- } catch {}
118
+ setMcpFactory(() => ({ nia: createNiaMcpServer() }));
122
119
  }
123
120
 
124
121
  // Determine session to use
package/src/cli/index.ts CHANGED
@@ -381,12 +381,16 @@ switch (command) {
381
381
  case "channels": {
382
382
  const sub = process.argv[3];
383
383
  const { updateRawConfig } = await import("../utils/config");
384
- if (sub === "on") {
385
- updateRawConfig({ channels: { enabled: true } });
386
- console.log("channels enabled restart to apply");
387
- } else if (sub === "off") {
388
- updateRawConfig({ channels: { enabled: false } });
389
- console.log("channels disabled — restart to apply");
384
+ if (sub === "on" || sub === "off") {
385
+ const enabled = sub === "on";
386
+ updateRawConfig({ channels: { enabled } });
387
+ const pid = readPid();
388
+ if (pid && isRunning()) {
389
+ process.kill(pid, "SIGHUP");
390
+ console.log(`channels ${enabled ? "enabled" : "disabled"}`);
391
+ } else {
392
+ console.log(`channels ${enabled ? "enabled" : "disabled"} — start nia to apply`);
393
+ }
390
394
  } else {
391
395
  console.log(`channels: ${getConfig().channels.enabled ? "on" : "off"}`);
392
396
  }
@@ -1,17 +1,17 @@
1
1
  import { closeSync, existsSync, mkdirSync, openSync, readFileSync, unlinkSync, writeFileSync } from "fs";
2
2
  import { dirname } from "path";
3
3
  import { getPaths } from "../utils/paths";
4
- import { getConfig } from "../utils/config";
4
+ import { getConfig, resetConfig } from "../utils/config";
5
5
  import { log } from "../utils/log";
6
6
  import { ActiveEngine } from "../db/models";
7
7
  import { runMigrations } from "../db/migrate";
8
8
  import { closeDb, getSql } from "../db/connection";
9
- import { registerAllChannels, startChannels, stopChannels } from "../channels";
9
+ import { registerAllChannels, startChannels, stopChannels, getStarted } from "../channels";
10
10
  import type { Channel } from "../types";
11
11
  import { startScheduler, stopScheduler, recomputeAllNextRuns } from "./scheduler";
12
12
  import { startAlive, stopAlive } from "./alive";
13
13
  import { createNiaMcpServer } from "../mcp/server";
14
- import { setMcpServers } from "../mcp";
14
+ import { setMcpFactory } from "../mcp";
15
15
 
16
16
  export function writePid(pid: number): void {
17
17
  const { pid: pidPath } = getPaths();
@@ -218,14 +218,9 @@ export async function runDaemon(): Promise<void> {
218
218
  log.info({ recovered }, "recovered stale running jobs");
219
219
  }
220
220
 
221
- // Initialize MCP server (in-process, no HTTP needed)
222
- try {
223
- const mcpConfig = createNiaMcpServer();
224
- setMcpServers({ nia: mcpConfig });
225
- log.info("MCP server initialized");
226
- } catch (err) {
227
- log.error({ err }, "failed to initialize MCP server");
228
- }
221
+ // Initialize MCP server factory (each query gets its own Protocol instance)
222
+ setMcpFactory(() => ({ nia: createNiaMcpServer() }));
223
+ log.info("MCP server factory initialized");
229
224
 
230
225
  // Register and start channels
231
226
  registerAllChannels();
@@ -265,9 +260,26 @@ export async function runDaemon(): Promise<void> {
265
260
  log.warn({ err }, "could not subscribe to nia_jobs, falling back to SIGHUP only");
266
261
  }
267
262
 
268
- // SIGHUP as manual fallback
263
+ // SIGHUP: reload config, reconcile channels, recompute jobs
269
264
  process.on("SIGHUP", async () => {
270
- log.info("received SIGHUP, recomputing job schedules");
265
+ log.info("received SIGHUP, reloading config");
266
+ resetConfig();
267
+ const fresh = getConfig();
268
+
269
+ const running = getStarted();
270
+ const wantChannels = fresh.channels.enabled;
271
+ const haveChannels = running.length > 0;
272
+
273
+ if (wantChannels && !haveChannels) {
274
+ log.info("SIGHUP: starting channels");
275
+ const result = await startChannels();
276
+ channels = result.started;
277
+ } else if (!wantChannels && haveChannels) {
278
+ log.info("SIGHUP: stopping channels");
279
+ await stopChannels(running);
280
+ channels = [];
281
+ }
282
+
271
283
  await recomputeAllNextRuns().catch(() => {});
272
284
  });
273
285
 
package/src/mcp/index.ts CHANGED
@@ -1,10 +1,10 @@
1
- /** Shared MCP server config set by daemon, read by chat engine creators. */
2
- let _mcpServers: Record<string, unknown> | null = null;
1
+ /** Factory for per-query MCP serverseach query gets its own Protocol instance. */
2
+ let _mcpFactory: (() => Record<string, unknown>) | null = null;
3
3
 
4
- export function setMcpServers(servers: Record<string, unknown>): void {
5
- _mcpServers = servers;
4
+ export function setMcpFactory(factory: () => Record<string, unknown>): void {
5
+ _mcpFactory = factory;
6
6
  }
7
7
 
8
8
  export function getMcpServers(): Record<string, unknown> | undefined {
9
- return _mcpServers ?? undefined;
9
+ return _mcpFactory?.() ?? undefined;
10
10
  }