@nordbyte/nordrelay 0.3.0 → 0.3.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.3.1 - 2026-05-12
4
+
5
+ Commits since `v0.3.0`:
6
+
7
+ - Move runtime home to .nordrelay.
8
+ - Improve dashboard live status handling.
9
+ - Separate dashboard contexts from Telegram sessions.
10
+ - Expand dashboard controls and activity views.
11
+
3
12
  ## v0.3.0 - 2026-05-12
4
13
 
5
14
  Commits since `v0.2.1`:
package/README.md CHANGED
@@ -137,7 +137,7 @@ Operations:
137
137
  - Telegram sends/edits/documents are routed through a rate-limit queue that honors Telegram retry-after responses.
138
138
  - Context metadata, queues, and preferences are written atomically with backup recovery.
139
139
  - Context metadata, queues, preferences, audit events, and locks can use JSON files or the optional SQLite state backend with `NORDRELAY_STATE_BACKEND=sqlite`.
140
- - Runtime state and logs are written under `~/.codex/nordrelay/`.
140
+ - Runtime config, state, and logs are written under `~/.nordrelay/`.
141
141
  - `nordrelay init` creates a private runtime config, `nordrelay doctor` validates host prerequisites, and `nordrelay web` starts a full local WebUI dashboard.
142
142
  - The WebUI has responsive header/sidebar/footer navigation, live chat streaming, session controls, queue/artifact/log/diagnostic views, and settings management.
143
143
  - The WebUI supports light and dark themes, tabbed settings groups, paginated session browsing, and chat uploads for images, documents, and audio transcription.
@@ -161,7 +161,7 @@ nordrelay doctor
161
161
  nordrelay start
162
162
  ```
163
163
 
164
- npm is the fastest install path and is the recommended default for normal use. For package installs, put runtime configuration in a directory-local `.env` before running `nordrelay`, or in `~/.codex/nordrelay/nordrelay.env`.
164
+ npm is the fastest install path and is the recommended default for normal use. `nordrelay init` writes the private runtime config to `~/.nordrelay/nordrelay.env`.
165
165
 
166
166
  Non-interactive setup is also supported:
167
167
 
@@ -176,7 +176,9 @@ Install dependencies and build the runtime:
176
176
  ```bash
177
177
  npm install
178
178
  npm run build
179
- cp .env.example .env
179
+ mkdir -p ~/.nordrelay
180
+ cp .env.example ~/.nordrelay/nordrelay.env
181
+ chmod 600 ~/.nordrelay/nordrelay.env
180
182
  ```
181
183
 
182
184
  Create the Telegram bot:
@@ -184,11 +186,11 @@ Create the Telegram bot:
184
186
  1. Open Telegram and talk to `@BotFather`.
185
187
  2. Run `/newbot`.
186
188
  3. Choose a display name and bot username.
187
- 4. Copy the bot token into `TELEGRAM_BOT_TOKEN` in `.env`.
189
+ 4. Copy the bot token into `TELEGRAM_BOT_TOKEN` in `~/.nordrelay/nordrelay.env`.
188
190
  5. Find your Telegram user id with a trusted id helper bot, for example `@userinfobot`, or from Telegram API tooling.
189
191
  6. Put your user id into `TELEGRAM_ADMIN_USER_IDS`.
190
192
 
191
- Minimal private-bot `.env`:
193
+ Minimal private-bot `~/.nordrelay/nordrelay.env`:
192
194
 
193
195
  ```dotenv
194
196
  TELEGRAM_BOT_TOKEN=123456789:replace-me
@@ -217,7 +219,7 @@ Codex authentication:
217
219
  Pi setup:
218
220
 
219
221
  - Install Pi from https://pi.dev/ and confirm `pi --help` works on the host.
220
- - Set `NORDRELAY_PI_ENABLED=true` in `.env`.
222
+ - Set `NORDRELAY_PI_ENABLED=true` in `~/.nordrelay/nordrelay.env`.
221
223
  - Keep `NORDRELAY_DEFAULT_AGENT=codex` to start chats in Codex, or set `NORDRELAY_DEFAULT_AGENT=pi` to start chats in Pi.
222
224
  - Optional: set `PI_SESSION_DIR` if your Pi sessions are not stored in `~/.pi/agent/sessions/`.
223
225
  - Optional: set `PI_DEFAULT_MODEL=openai-codex/gpt-5.5` and `PI_DEFAULT_THINKING=medium`.
@@ -282,9 +284,9 @@ npm run foreground
282
284
 
283
285
  Runtime files:
284
286
 
285
- - PID file: `~/.codex/nordrelay/nordrelay.pid`
286
- - State file: `~/.codex/nordrelay/state.json`
287
- - Log file: `~/.codex/nordrelay/nordrelay.log`
287
+ - PID file: `~/.nordrelay/nordrelay.pid`
288
+ - State file: `~/.nordrelay/state.json`
289
+ - Log file: `~/.nordrelay/nordrelay.log`
288
290
  - Home override: `NORDRELAY_HOME=/custom/path`
289
291
  - Local dashboard: `nordrelay web --host 127.0.0.1 --port 31878`
290
292
 
@@ -305,14 +307,18 @@ http://127.0.0.1:31878/
305
307
  The dashboard is a second NordRelay client next to Telegram. It can:
306
308
 
307
309
  - Start a new Codex or Pi session.
308
- - Switch or attach existing sessions.
310
+ - Start a new session from a modal with agent, workspace, model, reasoning/thinking, fast mode, and launch-profile choices.
311
+ - Switch or attach existing sessions, and copy thread IDs from the session list.
309
312
  - Send prompts and receive streamed text/tool/plan updates through Server-Sent Events.
310
313
  - Upload images, documents, and audio files from the chat composer. Images are passed as image inputs, documents are staged for the agent, and audio is transcribed through the configured voice backend.
314
+ - Keep a persistent per-thread WebUI chat history across page reloads.
315
+ - Control the active session model, reasoning/thinking, fast mode, and launch profile directly from the chat view.
311
316
  - Abort turns, hand sessions back to the native CLI, and inspect the active session.
312
- - Manage queued prompts.
313
- - Browse, download, ZIP, and delete artifacts.
314
- - Edit all supported runtime settings from tabbed Settings groups.
315
- - View logs, diagnostics, enabled channels, and agent adapters.
317
+ - Manage queued prompts with pause/resume, run, cancel, reorder buttons, and drag-and-drop prioritization.
318
+ - Browse, preview, download, ZIP, and delete artifacts.
319
+ - Inspect the activity timeline for WebUI and mirrored CLI turns.
320
+ - Edit all supported runtime settings from tabbed Settings groups with option selects, validation feedback, and restart actions.
321
+ - View filtered logs, structured diagnostics, enabled channels, and agent adapters.
316
322
 
317
323
  Dashboard API endpoints are served under `/api/*`. Streaming uses `GET /api/events`.
318
324
 
@@ -612,7 +618,7 @@ Dashboard:
612
618
  - `NORDRELAY_DASHBOARD_TOKEN`: optional dashboard bearer/login token. Required when binding to `0.0.0.0` unless basic auth is configured.
613
619
  - `NORDRELAY_DASHBOARD_USER`: optional dashboard basic-auth user.
614
620
  - `NORDRELAY_DASHBOARD_PASSWORD`: optional dashboard basic-auth password. Required with `NORDRELAY_DASHBOARD_USER`.
615
- - `NORDRELAY_ENV_FILE`: optional env file edited by the dashboard settings page. Defaults to `~/.codex/nordrelay/nordrelay.env` when present, otherwise `.env` in the runtime root.
621
+ - `NORDRELAY_ENV_FILE`: optional explicit env-file path used by the wrapper and edited by the dashboard settings page. Defaults to `~/.nordrelay/nordrelay.env`.
616
622
 
617
623
  Codex:
618
624
 
@@ -671,7 +677,7 @@ Auth and voice:
671
677
 
672
678
  NordRelay wrapper:
673
679
 
674
- - `NORDRELAY_HOME`: state/log directory override. Defaults to `~/.codex/nordrelay`.
680
+ - `NORDRELAY_HOME`: config/state/log directory override. Defaults to `~/.nordrelay`.
675
681
  - `NORDRELAY_SOURCE_ROOT`: runtime source root override. Useful when the plugin is launched from Codex cache.
676
682
  - `NORDRELAY_UPDATE_METHOD`: optional `auto`, `npm`, or `git` self-update method override. Auto uses git when the runtime root has a `.git` directory and npm otherwise.
677
683
  - `NORDRELAY_KEEP_PENDING_UPDATES`: set true to avoid dropping pending Telegram updates on start.
@@ -719,7 +725,7 @@ Unsafe profiles are intentionally gated. Telegram asks for confirmation before a
719
725
  - Do not leave `TELEGRAM_ALLOW_ANY_CHAT=true` enabled after setup.
720
726
  - Treat `danger-full-access` as equivalent to shell access on the host.
721
727
  - Treat uploaded files as untrusted input. They are staged inside the active workspace so the selected sandbox policy still matters.
722
- - Keep `CODEX_API_KEY` and `OPENAI_API_KEY` in `.env` or host secret management; `.env` is gitignored.
728
+ - Keep `CODEX_API_KEY` and `OPENAI_API_KEY` in `~/.nordrelay/nordrelay.env` or host secret management.
723
729
  - In group chats, remember that any allowed user can prompt Codex in that chat context.
724
730
  - Use `TOOL_VERBOSITY=summary` or `errors-only` when command output may include sensitive data.
725
731
  - Review and unsafe launch profiles add a Telegram approve/deny gate before each turn starts.
@@ -777,7 +783,7 @@ Voice not working:
777
783
 
778
784
  - Run `/voice` to list available backends.
779
785
  - Install `ffmpeg` and `faster-whisper` on Linux, install `parakeet-coreml` on macOS Apple Silicon, or set `OPENAI_API_KEY`.
780
- - Check `~/.codex/nordrelay/nordrelay.log` for transcription errors.
786
+ - Check `~/.nordrelay/nordrelay.log` for transcription errors.
781
787
 
782
788
  Files not returned:
783
789
 
package/dist/bot.js CHANGED
@@ -17,7 +17,7 @@ import { enabledAgents } from "./agent-factory.js";
17
17
  import { checkAuthStatus, clearAuthCache, startLogin, startLogout } from "./codex-auth.js";
18
18
  import { findLaunchProfile, formatLaunchProfileBehavior, formatLaunchProfileLabel, } from "./codex-launch.js";
19
19
  import { getThreadActivity, getThreadActivityLog, getThreadRolloutSnapshot, } from "./codex-state.js";
20
- import { contextKeyFromCtx, isTopicContextKey, parseContextKey } from "./context-key.js";
20
+ import { contextKeyFromCtx, isTelegramContextKey, isTopicContextKey, parseContextKey } from "./context-key.js";
21
21
  import { friendlyErrorText } from "./error-messages.js";
22
22
  import { escapeHTML, formatTelegramHTML } from "./format.js";
23
23
  import { getConnectorHealth, getUpdateLogPath, getVersionChecks, readConnectorState, readFormattedLogTail, spawnConnectorRestart, spawnSelfUpdate, } from "./operations.js";
@@ -331,12 +331,15 @@ export function createBot(config, registry) {
331
331
  const contextKeys = new Set([
332
332
  ...registry.listContexts().map((context) => context.contextKey),
333
333
  ...promptStore.listContextKeys(),
334
- ]);
334
+ ].filter(isTelegramContextKey));
335
335
  for (const contextKey of contextKeys) {
336
336
  await monitorExternalContext(contextKey);
337
337
  }
338
338
  };
339
339
  const monitorExternalContext = async (contextKey) => {
340
+ if (!isTelegramContextKey(contextKey)) {
341
+ return;
342
+ }
340
343
  const session = await registry.getOrCreate(contextKey, { deferThreadStart: true }).catch(() => null);
341
344
  if (!session) {
342
345
  return;
@@ -47,6 +47,8 @@ export class CodexSessionService {
47
47
  const effectiveLaunchProfile = this.activeThreadLaunchProfile ?? this.currentLaunchProfile;
48
48
  const codexFastMode = readCodexFastMode();
49
49
  this.lastObservedFastMode = codexFastMode;
50
+ const attachedThreadFastMode = effectiveLaunchProfile.id === "attached-thread" &&
51
+ effectiveLaunchProfile.approvalPolicy === "never";
50
52
  const info = {
51
53
  agentId: "codex",
52
54
  agentLabel: "Codex",
@@ -58,7 +60,7 @@ export class CodexSessionService {
58
60
  launchProfileBehavior: formatLaunchProfileBehavior(effectiveLaunchProfile),
59
61
  sandboxMode: effectiveLaunchProfile.sandboxMode,
60
62
  approvalPolicy: effectiveLaunchProfile.approvalPolicy,
61
- fastMode: codexFastMode ?? (effectiveLaunchProfile.approvalPolicy === "never"),
63
+ fastMode: attachedThreadFastMode || (codexFastMode ?? (effectiveLaunchProfile.approvalPolicy === "never")),
62
64
  unsafeLaunch: effectiveLaunchProfile.unsafe,
63
65
  capabilities: CODEX_AGENT_CAPABILITIES,
64
66
  };
@@ -21,3 +21,26 @@ export function parseContextKey(key) {
21
21
  export function isTopicContextKey(key) {
22
22
  return key.includes(":");
23
23
  }
24
+ export function isTelegramContextKey(key) {
25
+ const parts = key.split(":");
26
+ if (parts.length < 1 || parts.length > 2) {
27
+ return false;
28
+ }
29
+ const chatIdText = parts[0];
30
+ if (!chatIdText || !/^-?\d+$/.test(chatIdText)) {
31
+ return false;
32
+ }
33
+ const chatId = Number(chatIdText);
34
+ if (!Number.isSafeInteger(chatId) || chatId === 0) {
35
+ return false;
36
+ }
37
+ const threadIdText = parts[1];
38
+ if (threadIdText === undefined) {
39
+ return true;
40
+ }
41
+ if (!/^\d+$/.test(threadIdText)) {
42
+ return false;
43
+ }
44
+ const threadId = Number(threadIdText);
45
+ return Number.isSafeInteger(threadId) && threadId > 0;
46
+ }
@@ -10,7 +10,7 @@ const APP_NAME = "nordrelay";
10
10
  const PACKAGE_NAME = "@nordbyte/nordrelay";
11
11
  const CODEX_PACKAGE_NAME = "@openai/codex";
12
12
  const PI_PACKAGE_NAME = "@mariozechner/pi-coding-agent";
13
- const DEFAULT_HOME = path.join(os.homedir(), ".codex", "nordrelay");
13
+ const DEFAULT_HOME = path.join(os.homedir(), ".nordrelay");
14
14
  const SECRET_RE = /(bot|token|api[_-]?key|authorization|bearer|password|secret)(["'=: ]+)([^\s"',]+)/gi;
15
15
  const DEFAULT_VERSION_CACHE_TTL_MS = 60 * 60 * 1000;
16
16
  export function getConnectorHome() {