niahere 0.2.23 → 0.2.24

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.23",
3
+ "version": "0.2.24",
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": {
package/src/chat/repl.ts CHANGED
@@ -6,16 +6,7 @@ import { getMcpServers, setMcpServers } from "../mcp";
6
6
  import { createNiaMcpServer } from "../mcp/server";
7
7
  import { Session } from "../db/models";
8
8
  import { relativeTime } from "../utils/format";
9
-
10
- // ANSI helpers
11
- const DIM = "\x1b[2m";
12
- const BOLD = "\x1b[1m";
13
- const CYAN = "\x1b[36m";
14
- const RESET = "\x1b[0m";
15
- const CLEAR_LINE = "\x1b[2K\r";
16
-
17
- // Braille spinner frames
18
- const SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
9
+ import { DIM, BOLD, CYAN, RESET, CLEAR_LINE, SPINNER } from "../utils/cli";
19
10
 
20
11
  class StatusLine {
21
12
  private frame = 0;
@@ -1,7 +1,7 @@
1
1
  import { getConfig, updateRawConfig } from "../utils/config";
2
2
  import { getPaths } from "../utils/paths";
3
3
  import { errMsg } from "../utils/errors";
4
- import { fail } from "../utils/cli";
4
+ import { fail, ICON_PASS, ICON_FAIL } from "../utils/cli";
5
5
  import { log } from "../utils/log";
6
6
 
7
7
  export async function sendCommand(): Promise<void> {
@@ -98,7 +98,7 @@ export async function slackCommand(): Promise<void> {
98
98
  });
99
99
  const data = (await resp.json()) as Record<string, unknown>;
100
100
  if (data.ok) {
101
- console.log(` Auth: \u2713 valid`);
101
+ console.log(` Auth: ${ICON_PASS} valid`);
102
102
  // Backfill workspace info if missing
103
103
  if (!config.channels.slack.workspace) {
104
104
  const enriched = await enrichSlackConfig(config.channels.slack.bot_token);
@@ -108,10 +108,10 @@ export async function slackCommand(): Promise<void> {
108
108
  }
109
109
  }
110
110
  } else {
111
- console.log(` Auth: \u2717 ${data.error}`);
111
+ console.log(` Auth: ${ICON_FAIL} ${data.error}`);
112
112
  }
113
113
  } catch (err) {
114
- console.log(` Auth: \u2717 could not reach Slack API`);
114
+ console.log(` Auth: ${ICON_FAIL} could not reach Slack API`);
115
115
  }
116
116
  } else {
117
117
  console.log("Slack: not configured");
package/src/cli/index.ts CHANGED
@@ -8,7 +8,7 @@ import { Message } from "../db/models";
8
8
  import { withDb } from "../db/connection";
9
9
  import { getNiaHome, getPaths } from "../utils/paths";
10
10
  import { errMsg } from "../utils/errors";
11
- import { fail } from "../utils/cli";
11
+ import { fail, ICON_PASS, ICON_WARN } from "../utils/cli";
12
12
  import { jobCommand } from "./job";
13
13
  import { statusCommand } from "./status";
14
14
  import { sendCommand, telegramCommand, slackCommand } from "./channels";
@@ -64,14 +64,14 @@ async function awaitStartup(timeout = 60_000): Promise<void> {
64
64
  if (ready.has(name)) continue;
65
65
  if (content.includes(STARTUP_MARKERS[name])) {
66
66
  ready.add(name);
67
- console.log(` \u2713 ${name}`);
67
+ console.log(` ${ICON_PASS} ${name}`);
68
68
  }
69
69
  }
70
70
  }
71
71
 
72
72
  const pending = [...expecting].filter((e) => !ready.has(e));
73
73
  if (pending.length > 0) {
74
- console.log(` \u26A0 timed out waiting for: ${pending.join(", ")}`);
74
+ console.log(` ${ICON_WARN} timed out waiting for: ${pending.join(", ")}`);
75
75
  }
76
76
  }
77
77
 
@@ -143,9 +143,7 @@ switch (command) {
143
143
  if (prompt) {
144
144
  const { createChatEngine } = await import("../chat/engine");
145
145
  const { getMcpServers } = await import("../mcp");
146
- const DIM = "\x1b[2m";
147
- const RST = "\x1b[0m";
148
- const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
146
+ const { DIM, RESET: RST, CLEAR_LINE, SPINNER: FRAMES } = await import("../utils/cli");
149
147
  let frame = 0;
150
148
  let statusText = "thinking";
151
149
  let spinTimer: ReturnType<typeof setInterval> | null = null;
@@ -153,7 +151,7 @@ switch (command) {
153
151
  let streaming = false;
154
152
 
155
153
  const renderSpinner = () => {
156
- process.stderr.write(`\x1b[2K\r${DIM} ${FRAMES[frame]} ${statusText}${RST}`);
154
+ process.stderr.write(`${CLEAR_LINE}${DIM} ${FRAMES[frame]} ${statusText}${RST}`);
157
155
  frame = (frame + 1) % FRAMES.length;
158
156
  };
159
157
 
package/src/cli/job.ts CHANGED
@@ -8,7 +8,7 @@ import { Job } from "../db/models";
8
8
  import { withDb } from "../db/connection";
9
9
  import type { ScheduleType } from "../types";
10
10
  import { errMsg } from "../utils/errors";
11
- import { fail, pickFromList } from "../utils/cli";
11
+ import { fail, pickFromList, ICON_PASS, ICON_FAIL } from "../utils/cli";
12
12
  import { computeInitialNextRun } from "../core/scheduler";
13
13
 
14
14
  async function pickJob(prompt = "Pick a job"): Promise<string> {
@@ -164,7 +164,7 @@ export async function jobCommand(): Promise<void> {
164
164
  for (const e of entries) {
165
165
  const time = localTime(new Date(e.timestamp));
166
166
  const dur = `${e.duration_ms}ms`;
167
- const icon = e.status === "ok" ? "\u2713" : "\u2717";
167
+ const icon = e.status === "ok" ? ICON_PASS : ICON_FAIL;
168
168
  const summary = e.error || e.result.slice(0, 60).replace(/\n/g, " ") || "-";
169
169
  console.log(` ${icon} ${time} ${dur.padStart(8)} ${summary}`);
170
170
  }
@@ -230,7 +230,7 @@ export async function jobCommand(): Promise<void> {
230
230
  for (const e of entries) {
231
231
  const time = localTime(new Date(e.timestamp));
232
232
  const dur = `${e.duration_ms}ms`;
233
- const status = e.status === "ok" ? "\u2713" : "\u2717";
233
+ const status = e.status === "ok" ? ICON_PASS : ICON_FAIL;
234
234
  const summary = e.error || e.result.slice(0, 80).replace(/\n/g, " ") || "-";
235
235
  console.log(` ${status} ${time} ${dur.padStart(8)} ${e.job} ${summary}`);
236
236
  }
package/src/cli/status.ts CHANGED
@@ -8,6 +8,7 @@ import type { ScheduleType, JobStateStatus, RoomStats } from "../types";
8
8
  import { withDb } from "../db/connection";
9
9
  import { errMsg } from "../utils/errors";
10
10
  import { checkForUpdate } from "../utils/update";
11
+ import { ICON_PASS, ICON_FAIL, ICON_RUNNING } from "../utils/cli";
11
12
 
12
13
  type StatusOptions = {
13
14
  json: boolean;
@@ -245,7 +246,7 @@ export async function statusCommand(argv: string[] = []): Promise<void> {
245
246
  safeDate(nextRun)!.getTime() <= now.getTime() &&
246
247
  !stateInfo;
247
248
 
248
- const statusIcon = status === "ok" ? "\u2713" : status === "error" ? "\u2717" : status === "running" ? "\u21bb" : "\u2217";
249
+ const statusIcon = status === "ok" ? ICON_PASS : status === "error" ? ICON_FAIL : status === "running" ? ICON_RUNNING : "\u2217";
249
250
  const durationText = stateInfo?.duration_ms === undefined ? "n/a" : `${stateInfo.duration_ms}ms`;
250
251
  const nextText = nextRun ? formatTimeLine(nextRun, now) : "unknown";
251
252
  const lastText = lastRun ? formatTimeLine(lastRun, now) : "never";
@@ -292,7 +293,7 @@ export async function statusCommand(argv: string[] = []): Promise<void> {
292
293
  console.log("\nJobs (from state file):");
293
294
  for (const [name, info] of fallbackEntries) {
294
295
  const last = formatTimeLine(info.lastRun, now);
295
- const icon = info.status === "ok" ? "\u2713" : info.status === "error" ? "\u2717" : "\u2217";
296
+ const icon = info.status === "ok" ? ICON_PASS : info.status === "error" ? ICON_FAIL : "\u2217";
296
297
  console.log(` ${icon} ${name}: ${info.status} (last: ${last}, ${info.duration_ms}ms)`);
297
298
  }
298
299
  } else if (dbError) {
@@ -98,14 +98,11 @@ export async function healthCommand(): Promise<void> {
98
98
  push(checks, "bun", "ok", "v" + bunVersion);
99
99
 
100
100
  // Output
101
- const GREEN = "\x1b[32m";
102
- const YELLOW = "\x1b[33m";
103
- const RED = "\x1b[31m";
104
- const RST = "\x1b[0m";
101
+ const { GREEN, YELLOW, RED, RESET, ICON_PASS, ICON_FAIL, ICON_WARN } = await import("../utils/cli");
105
102
  const icons: Record<string, string> = {
106
- ok: GREEN + "\u2713" + RST,
107
- warn: YELLOW + "!" + RST,
108
- fail: RED + "\u2717" + RST,
103
+ ok: GREEN + ICON_PASS + RESET,
104
+ warn: YELLOW + ICON_WARN + RESET,
105
+ fail: RED + ICON_FAIL + RESET,
109
106
  };
110
107
 
111
108
  console.log();
@@ -1,10 +1,7 @@
1
1
  import { existsSync, readFileSync } from "fs";
2
2
  import yaml from "js-yaml";
3
3
  import { getPaths } from "../utils/paths";
4
-
5
- const PASS = "\u2713";
6
- const FAIL = "\u2717";
7
- const WARN = "\u26A0";
4
+ import { ICON_PASS as PASS, ICON_FAIL as FAIL, ICON_WARN as WARN } from "../utils/cli";
8
5
 
9
6
  interface Result {
10
7
  ok: boolean;
package/src/utils/cli.ts CHANGED
@@ -1,5 +1,24 @@
1
1
  import * as readline from "readline";
2
2
 
3
+ // ANSI colors
4
+ export const DIM = "\x1b[2m";
5
+ export const BOLD = "\x1b[1m";
6
+ export const RESET = "\x1b[0m";
7
+ export const RED = "\x1b[31m";
8
+ export const GREEN = "\x1b[32m";
9
+ export const YELLOW = "\x1b[33m";
10
+ export const CYAN = "\x1b[36m";
11
+ export const CLEAR_LINE = "\x1b[2K\r";
12
+
13
+ // Icons
14
+ export const ICON_PASS = "\u2713";
15
+ export const ICON_FAIL = "\u2717";
16
+ export const ICON_WARN = "\u26A0";
17
+ export const ICON_RUNNING = "\u21bb";
18
+
19
+ // Spinner frames
20
+ export const SPINNER = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
21
+
3
22
  export function fail(msg: string): never {
4
23
  console.log(msg);
5
24
  process.exit(1);