@nordbyte/nordrelay 0.8.0 → 0.8.2

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 (173) hide show
  1. package/.env.example +9 -0
  2. package/README.md +81 -1197
  3. package/dist/{access-control.js → access/access-control.js} +1 -1
  4. package/dist/{audit-log.js → access/audit-log.js} +2 -2
  5. package/dist/{session-locks.js → access/session-locks.js} +1 -1
  6. package/dist/{user-management.js → access/user-management.js} +1 -1
  7. package/dist/{claude-code-cli.js → agents/claude-code/claude-code-cli.js} +2 -2
  8. package/dist/{claude-code-session.js → agents/claude-code/claude-code-session.js} +1 -1
  9. package/dist/{codex-cli.js → agents/codex/codex-cli.js} +14 -5
  10. package/dist/{codex-session.js → agents/codex/codex-session.js} +2 -4
  11. package/dist/{hermes-cli.js → agents/hermes/hermes-cli.js} +2 -2
  12. package/dist/{hermes-launch.js → agents/hermes/hermes-launch.js} +1 -1
  13. package/dist/{hermes-session.js → agents/hermes/hermes-session.js} +1 -1
  14. package/dist/{openclaw-cli.js → agents/openclaw/openclaw-cli.js} +2 -2
  15. package/dist/{openclaw-launch.js → agents/openclaw/openclaw-launch.js} +1 -1
  16. package/dist/{openclaw-session.js → agents/openclaw/openclaw-session.js} +1 -1
  17. package/dist/{pi-cli.js → agents/pi/pi-cli.js} +2 -2
  18. package/dist/{pi-launch.js → agents/pi/pi-launch.js} +1 -1
  19. package/dist/{pi-session.js → agents/pi/pi-session.js} +1 -1
  20. package/dist/{adapter-conformance.js → agents/shared/adapter-conformance.js} +2 -2
  21. package/dist/{agent-activity.js → agents/shared/agent-activity.js} +5 -5
  22. package/dist/agents/shared/agent-auth-commands.js +30 -0
  23. package/dist/{agent-factory.js → agents/shared/agent-factory.js} +5 -5
  24. package/dist/{agent-feature-matrix.js → agents/shared/agent-feature-matrix.js} +2 -2
  25. package/dist/{agent-updates.js → agents/shared/agent-updates.js} +7 -7
  26. package/dist/{discord-artifacts.js → channels/discord/discord-artifacts.js} +4 -4
  27. package/dist/{discord-bot.js → channels/discord/discord-bot.js} +164 -424
  28. package/dist/{discord-channel-runtime.js → channels/discord/discord-channel-runtime.js} +2 -2
  29. package/dist/{discord-command-surface.js → channels/discord/discord-command-surface.js} +3 -3
  30. package/dist/{bot-rendering.js → channels/shared/bot-rendering.js} +6 -6
  31. package/dist/{channel-actions.js → channels/shared/channel-actions.js} +4 -4
  32. package/dist/channels/shared/channel-bridge-controller.js +69 -0
  33. package/dist/channels/shared/channel-cli-artifacts.js +51 -0
  34. package/dist/{channel-command-service.js → channels/shared/channel-command-service.js} +51 -28
  35. package/dist/channels/shared/channel-external-mirror-controller.js +193 -0
  36. package/dist/channels/shared/channel-external-monitor.js +52 -0
  37. package/dist/{channel-mirror-registry.js → channels/shared/channel-mirror-registry.js} +14 -6
  38. package/dist/{channel-peer-prompt.js → channels/shared/channel-peer-prompt.js} +3 -3
  39. package/dist/{channel-turn-service.js → channels/shared/channel-turn-service.js} +2 -2
  40. package/dist/{context-key.js → channels/shared/context-key.js} +1 -1
  41. package/dist/{session-format.js → channels/shared/session-format.js} +2 -2
  42. package/dist/{slack-artifacts.js → channels/slack/slack-artifacts.js} +4 -4
  43. package/dist/{slack-bot.js → channels/slack/slack-bot.js} +159 -294
  44. package/dist/{slack-channel-runtime.js → channels/slack/slack-channel-runtime.js} +2 -2
  45. package/dist/{slack-command-surface.js → channels/slack/slack-command-surface.js} +2 -2
  46. package/dist/{slack-diagnostics.js → channels/slack/slack-diagnostics.js} +2 -2
  47. package/dist/{bot-ui.js → channels/telegram/bot-ui.js} +1 -1
  48. package/dist/{bot.js → channels/telegram/bot.js} +178 -427
  49. package/dist/{telegram-access-commands.js → channels/telegram/telegram-access-commands.js} +3 -3
  50. package/dist/{telegram-access-middleware.js → channels/telegram/telegram-access-middleware.js} +4 -4
  51. package/dist/{telegram-agent-commands.js → channels/telegram/telegram-agent-commands.js} +9 -9
  52. package/dist/{telegram-artifact-commands.js → channels/telegram/telegram-artifact-commands.js} +4 -4
  53. package/dist/{telegram-channel-runtime.js → channels/telegram/telegram-channel-runtime.js} +2 -2
  54. package/dist/{telegram-command-menu.js → channels/telegram/telegram-command-menu.js} +1 -1
  55. package/dist/{telegram-diagnostics-command.js → channels/telegram/telegram-diagnostics-command.js} +7 -7
  56. package/dist/{telegram-general-commands.js → channels/telegram/telegram-general-commands.js} +4 -4
  57. package/dist/{telegram-operational-commands.js → channels/telegram/telegram-operational-commands.js} +5 -5
  58. package/dist/{telegram-output.js → channels/telegram/telegram-output.js} +2 -2
  59. package/dist/{telegram-preference-commands.js → channels/telegram/telegram-preference-commands.js} +3 -3
  60. package/dist/{telegram-queue-commands.js → channels/telegram/telegram-queue-commands.js} +6 -6
  61. package/dist/{telegram-support-command.js → channels/telegram/telegram-support-command.js} +4 -4
  62. package/dist/{telegram-update-commands.js → channels/telegram/telegram-update-commands.js} +5 -5
  63. package/dist/{config-metadata.js → core/config-metadata.js} +8 -0
  64. package/dist/{config.js → core/config.js} +11 -3
  65. package/dist/index.js +27 -23
  66. package/dist/{peer-client.js → peers/peer-client.js} +57 -1
  67. package/dist/peers/peer-discovery-jobs.js +206 -0
  68. package/dist/peers/peer-discovery.js +223 -0
  69. package/dist/peers/peer-health-monitor.js +49 -0
  70. package/dist/{peer-identity.js → peers/peer-identity.js} +50 -1
  71. package/dist/{peer-runtime-service.js → peers/peer-runtime-service.js} +29 -7
  72. package/dist/{peer-server.js → peers/peer-server.js} +23 -6
  73. package/dist/{peer-store.js → peers/peer-store.js} +84 -11
  74. package/dist/{peer-types.js → peers/peer-types.js} +9 -0
  75. package/dist/peers/peer-web-proxy-contract.js +127 -0
  76. package/dist/{metrics.js → runtime/metrics.js} +5 -3
  77. package/dist/{relay-artifact-service.js → runtime/relay-artifact-service.js} +1 -1
  78. package/dist/runtime/relay-auth-service.js +63 -0
  79. package/dist/runtime/relay-dashboard-service.js +139 -0
  80. package/dist/{relay-external-activity-monitor.js → runtime/relay-external-activity-monitor.js} +140 -53
  81. package/dist/runtime/relay-runtime-active-sessions.js +387 -0
  82. package/dist/runtime/relay-runtime-dashboard.js +201 -0
  83. package/dist/runtime/relay-runtime-prompt-queue-artifacts.js +307 -0
  84. package/dist/runtime/relay-runtime-sessions.js +623 -0
  85. package/dist/runtime/relay-runtime-types.js +1 -0
  86. package/dist/runtime/relay-runtime-updates-jobs.js +360 -0
  87. package/dist/runtime/relay-runtime.js +451 -0
  88. package/dist/runtime/runtime-cache.js +117 -0
  89. package/dist/{session-registry.js → state/session-registry.js} +3 -3
  90. package/dist/{operations.js → support/operations.js} +7 -7
  91. package/dist/{support-bundle.js → support/support-bundle.js} +1 -1
  92. package/dist/{web-api-contract.js → web/web-api-contract.js} +17 -3
  93. package/dist/web/web-api-types.js +1 -0
  94. package/dist/{web-dashboard-access-routes.js → web/web-dashboard-access-routes.js} +2 -2
  95. package/dist/{web-dashboard-assets.js → web/web-dashboard-assets.js} +24 -2
  96. package/dist/{web-dashboard-http.js → web/web-dashboard-http.js} +41 -5
  97. package/dist/{web-dashboard-pages.js → web/web-dashboard-pages.js} +37 -10
  98. package/dist/{web-dashboard-peer-routes.js → web/web-dashboard-peer-routes.js} +102 -7
  99. package/dist/web/web-dashboard-security.js +14 -0
  100. package/dist/{web-dashboard-session-routes.js → web/web-dashboard-session-routes.js} +12 -1
  101. package/dist/{web-dashboard.js → web/web-dashboard.js} +132 -48
  102. package/dist/web/web-performance.js +60 -0
  103. package/dist/web/web-rate-limit.js +19 -0
  104. package/dist/{web-state.js → web/web-state.js} +74 -5
  105. package/dist/webui-assets/dashboard.css +171 -10
  106. package/dist/webui-assets/dashboard.js +515 -48
  107. package/dist/webui-assets/favicon.ico +0 -0
  108. package/dist/webui-assets/favicon.png +0 -0
  109. package/dist/webui-assets/logo.png +0 -0
  110. package/package.json +4 -3
  111. package/plugins/nordrelay/scripts/nordrelay.mjs +17 -5
  112. package/{launchd/start.sh → scripts/launchd-start.sh} +1 -1
  113. package/dist/relay-runtime.js +0 -1916
  114. package/dist/runtime-cache.js +0 -57
  115. /package/dist/{user-management-crypto.js → access/user-management-crypto.js} +0 -0
  116. /package/dist/{user-management-normalize.js → access/user-management-normalize.js} +0 -0
  117. /package/dist/{user-management-types.js → access/user-management-types.js} +0 -0
  118. /package/dist/{claude-code-auth.js → agents/claude-code/claude-code-auth.js} +0 -0
  119. /package/dist/{claude-code-launch.js → agents/claude-code/claude-code-launch.js} +0 -0
  120. /package/dist/{claude-code-state.js → agents/claude-code/claude-code-state.js} +0 -0
  121. /package/dist/{codex-auth.js → agents/codex/codex-auth.js} +0 -0
  122. /package/dist/{codex-config.js → agents/codex/codex-config.js} +0 -0
  123. /package/dist/{codex-launch.js → agents/codex/codex-launch.js} +0 -0
  124. /package/dist/{codex-state.js → agents/codex/codex-state.js} +0 -0
  125. /package/dist/{hermes-api.js → agents/hermes/hermes-api.js} +0 -0
  126. /package/dist/{hermes-auth.js → agents/hermes/hermes-auth.js} +0 -0
  127. /package/dist/{hermes-state.js → agents/hermes/hermes-state.js} +0 -0
  128. /package/dist/{openclaw-auth.js → agents/openclaw/openclaw-auth.js} +0 -0
  129. /package/dist/{openclaw-gateway.js → agents/openclaw/openclaw-gateway.js} +0 -0
  130. /package/dist/{openclaw-state.js → agents/openclaw/openclaw-state.js} +0 -0
  131. /package/dist/{pi-auth.js → agents/pi/pi-auth.js} +0 -0
  132. /package/dist/{pi-rpc.js → agents/pi/pi-rpc.js} +0 -0
  133. /package/dist/{pi-state.js → agents/pi/pi-state.js} +0 -0
  134. /package/dist/{agent-adapter.js → agents/shared/agent-adapter.js} +0 -0
  135. /package/dist/{agent.js → agents/shared/agent.js} +0 -0
  136. /package/dist/{artifacts.js → artifacts/artifacts.js} +0 -0
  137. /package/dist/{attachments.js → artifacts/attachments.js} +0 -0
  138. /package/dist/{voice.js → artifacts/voice.js} +0 -0
  139. /package/dist/{discord-rate-limit.js → channels/discord/discord-rate-limit.js} +0 -0
  140. /package/dist/{channel-adapter.js → channels/shared/channel-adapter.js} +0 -0
  141. /package/dist/{relay-runtime-types.js → channels/shared/channel-bridge-state.js} +0 -0
  142. /package/dist/{channel-command-catalog.js → channels/shared/channel-command-catalog.js} +0 -0
  143. /package/dist/{channel-command-core.js → channels/shared/channel-command-core.js} +0 -0
  144. /package/dist/{channel-prompt-engine.js → channels/shared/channel-prompt-engine.js} +0 -0
  145. /package/dist/{channel-runtime.js → channels/shared/channel-runtime.js} +0 -0
  146. /package/dist/{channel-turn-lifecycle.js → channels/shared/channel-turn-lifecycle.js} +0 -0
  147. /package/dist/{slack-rate-limit.js → channels/slack/slack-rate-limit.js} +0 -0
  148. /package/dist/{telegram-command-types.js → channels/telegram/telegram-command-types.js} +0 -0
  149. /package/dist/{telegram-rate-limit.js → channels/telegram/telegram-rate-limit.js} +0 -0
  150. /package/dist/{activity-events.js → core/activity-events.js} +0 -0
  151. /package/dist/{error-messages.js → core/error-messages.js} +0 -0
  152. /package/dist/{format.js → core/format.js} +0 -0
  153. /package/dist/{logger.js → core/logger.js} +0 -0
  154. /package/dist/{redaction.js → core/redaction.js} +0 -0
  155. /package/dist/{settings-service.js → core/settings-service.js} +0 -0
  156. /package/dist/{settings-wizard-test.js → core/settings-wizard-test.js} +0 -0
  157. /package/dist/{workspace-policy.js → core/workspace-policy.js} +0 -0
  158. /package/dist/{peer-auth.js → peers/peer-auth.js} +0 -0
  159. /package/dist/{peer-context.js → peers/peer-context.js} +0 -0
  160. /package/dist/{peer-readiness.js → peers/peer-readiness.js} +0 -0
  161. /package/dist/{relay-queue-service.js → runtime/relay-queue-service.js} +0 -0
  162. /package/dist/{web-api-types.js → runtime/relay-runtime-delegate.js} +0 -0
  163. /package/dist/{relay-runtime-helpers.js → runtime/relay-runtime-helpers.js} +0 -0
  164. /package/dist/{remote-prompt.js → runtime/remote-prompt.js} +0 -0
  165. /package/dist/{bot-preferences.js → state/bot-preferences.js} +0 -0
  166. /package/dist/{job-store.js → state/job-store.js} +0 -0
  167. /package/dist/{persistence.js → state/persistence.js} +0 -0
  168. /package/dist/{prompt-store.js → state/prompt-store.js} +0 -0
  169. /package/dist/{state-backend.js → state/state-backend.js} +0 -0
  170. /package/dist/{zip-writer.js → support/zip-writer.js} +0 -0
  171. /package/dist/{web-dashboard-artifact-routes.js → web/web-dashboard-artifact-routes.js} +0 -0
  172. /package/dist/{web-dashboard-runtime-routes.js → web/web-dashboard-runtime-routes.js} +0 -0
  173. /package/dist/{web-dashboard-ui.js → web/web-dashboard-ui.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { permissionForWebRequestFromContract } from "./web-api-contract.js";
1
+ import { permissionForWebRequestFromContract } from "../web/web-api-contract.js";
2
2
  export const ALL_PERMISSIONS = [
3
3
  "inspect",
4
4
  "sessions.read",
@@ -1,6 +1,6 @@
1
1
  import { randomUUID } from "node:crypto";
2
- import { auditCategoryForAction, } from "./activity-events.js";
3
- import { createDocumentStore } from "./state-backend.js";
2
+ import { auditCategoryForAction, } from "../core/activity-events.js";
3
+ import { createDocumentStore } from "../state/state-backend.js";
4
4
  export class AuditLogStore {
5
5
  store;
6
6
  maxEvents;
@@ -1,4 +1,4 @@
1
- import { createDocumentStore } from "./state-backend.js";
1
+ import { createDocumentStore } from "../state/state-backend.js";
2
2
  export class SessionLockStore {
3
3
  store;
4
4
  constructor(workspace, backend = "json") {
@@ -2,7 +2,7 @@ import { closeSync, mkdirSync, openSync, rmSync, statSync } from "node:fs";
2
2
  import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { ADMIN_GROUP_ID, USER_GROUP_ID, } from "./access-control.js";
5
- import { readJsonFileWithBackup, writeJsonFileAtomic } from "./persistence.js";
5
+ import { readJsonFileWithBackup, writeJsonFileAtomic } from "../state/persistence.js";
6
6
  import { allPermissionsSafe as ALL_PERMISSIONS_SAFE, assertActiveAdminExists, isPathInside, normalizeDiscordId, normalizeEmail, normalizeGroupIds, normalizeNumberList, normalizePayload, normalizePermissions, normalizeSlackId, normalizeStringList, normalizeWorkspacePath, slugify, } from "./user-management-normalize.js";
7
7
  import { constantTimeStringEqual, hashPassword, hashToken, randomId, randomLinkCode, randomSessionToken, sleepSync, verifyPasswordHash, } from "./user-management-crypto.js";
8
8
  const SESSION_TTL_MS = 7 * 24 * 60 * 60 * 1000;
@@ -1,10 +1,10 @@
1
- import { findExecutableOnPath } from "./codex-cli.js";
1
+ import { findExecutableOnPath } from "../codex/codex-cli.js";
2
2
  export function resolveClaudeCodeCli(env = process.env, explicitPath) {
3
3
  const configuredPath = optionalString(explicitPath) ?? optionalString(env.CLAUDE_CODE_CLI_PATH);
4
4
  if (configuredPath) {
5
5
  return { path: configuredPath, source: "env" };
6
6
  }
7
- const pathMatch = findExecutableOnPath("claude", env.PATH);
7
+ const pathMatch = findExecutableOnPath("claude", env.PATH, { pathext: env.PATHEXT });
8
8
  return pathMatch ? { path: pathMatch, source: "path" } : { source: "bundled" };
9
9
  }
10
10
  export function describeClaudeCodeCli(resolution) {
@@ -1,7 +1,7 @@
1
1
  import { query } from "@anthropic-ai/claude-agent-sdk";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
- import { CLAUDE_CODE_AGENT_CAPABILITIES, CLAUDE_CODE_EFFORT_LEVELS, } from "./agent.js";
4
+ import { CLAUDE_CODE_AGENT_CAPABILITIES, CLAUDE_CODE_EFFORT_LEVELS, } from "../shared/agent.js";
5
5
  import { resolveClaudeCodeCli } from "./claude-code-cli.js";
6
6
  import { claudeCodeProfileAsLaunchProfile, findClaudeCodeLaunchProfile, listClaudeCodeLaunchProfiles, } from "./claude-code-launch.js";
7
7
  import { getClaudeCodeSession, listClaudeCodeSessions, listClaudeCodeWorkspaces, } from "./claude-code-state.js";
@@ -12,7 +12,7 @@ export function resolveCodexCli(env = process.env) {
12
12
  if (isEnabled(env.CODEX_USE_BUNDLED_CLI)) {
13
13
  return { source: "bundled" };
14
14
  }
15
- const pathMatch = findExecutableOnPath("codex", env.PATH);
15
+ const pathMatch = findExecutableOnPath("codex", env.PATH, { pathext: env.PATHEXT });
16
16
  return pathMatch ? { path: pathMatch, source: "path" } : { source: "bundled" };
17
17
  }
18
18
  export function describeCodexCli(resolution) {
@@ -21,13 +21,11 @@ export function describeCodexCli(resolution) {
21
21
  }
22
22
  return "bundled @openai/codex";
23
23
  }
24
- export function findExecutableOnPath(command, pathValue) {
24
+ export function findExecutableOnPath(command, pathValue, options = {}) {
25
25
  if (!pathValue) {
26
26
  return undefined;
27
27
  }
28
- const extensions = process.platform === "win32"
29
- ? ["", ...(process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM").split(";")]
30
- : [""];
28
+ const extensions = executableExtensions(options.platform ?? process.platform, options.pathext ?? process.env.PATHEXT);
31
29
  for (const rawDirectory of pathValue.split(path.delimiter)) {
32
30
  const directory = rawDirectory.trim();
33
31
  if (!directory) {
@@ -43,6 +41,17 @@ export function findExecutableOnPath(command, pathValue) {
43
41
  }
44
42
  return undefined;
45
43
  }
44
+ function executableExtensions(platform, pathextValue) {
45
+ if (platform !== "win32") {
46
+ return [""];
47
+ }
48
+ const pathext = (pathextValue || ".COM;.EXE;.BAT;.CMD")
49
+ .split(";")
50
+ .map((extension) => extension.trim())
51
+ .filter(Boolean)
52
+ .map((extension) => extension.startsWith(".") ? extension : `.${extension}`);
53
+ return [...new Set([...pathext, ""])];
54
+ }
46
55
  function isExecutable(filePath) {
47
56
  try {
48
57
  accessSync(filePath, constants.X_OK);
@@ -3,7 +3,7 @@ import { resolveCodexCli } from "./codex-cli.js";
3
3
  import { readCodexFastMode, writeCodexFastMode } from "./codex-config.js";
4
4
  import { getThread, getThreadUsage, listModels, listThreads, listWorkspaces, } from "./codex-state.js";
5
5
  import { createLaunchProfile, findLaunchProfile, formatLaunchProfileBehavior, } from "./codex-launch.js";
6
- import { CODEX_AGENT_CAPABILITIES, } from "./agent.js";
6
+ import { CODEX_AGENT_CAPABILITIES, } from "../shared/agent.js";
7
7
  export class CodexSessionService {
8
8
  config;
9
9
  codex = null;
@@ -47,8 +47,6 @@ 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";
52
50
  const info = {
53
51
  agentId: "codex",
54
52
  agentLabel: "Codex",
@@ -60,7 +58,7 @@ export class CodexSessionService {
60
58
  launchProfileBehavior: formatLaunchProfileBehavior(effectiveLaunchProfile),
61
59
  sandboxMode: effectiveLaunchProfile.sandboxMode,
62
60
  approvalPolicy: effectiveLaunchProfile.approvalPolicy,
63
- fastMode: attachedThreadFastMode || (codexFastMode ?? (effectiveLaunchProfile.approvalPolicy === "never")),
61
+ fastMode: codexFastMode ?? (effectiveLaunchProfile.approvalPolicy === "never"),
64
62
  unsafeLaunch: effectiveLaunchProfile.unsafe,
65
63
  capabilities: CODEX_AGENT_CAPABILITIES,
66
64
  };
@@ -1,10 +1,10 @@
1
- import { findExecutableOnPath } from "./codex-cli.js";
1
+ import { findExecutableOnPath } from "../codex/codex-cli.js";
2
2
  export function resolveHermesCli(env = process.env, explicitPath) {
3
3
  const configuredPath = optionalString(explicitPath) ?? optionalString(env.HERMES_CLI_PATH);
4
4
  if (configuredPath) {
5
5
  return { path: configuredPath, source: "env" };
6
6
  }
7
- const pathMatch = findExecutableOnPath("hermes", env.PATH);
7
+ const pathMatch = findExecutableOnPath("hermes", env.PATH, { pathext: env.PATHEXT });
8
8
  return pathMatch ? { path: pathMatch, source: "path" } : { source: "missing" };
9
9
  }
10
10
  export function describeHermesCli(resolution) {
@@ -1,4 +1,4 @@
1
- import { createLaunchProfile } from "./codex-launch.js";
1
+ import { createLaunchProfile } from "../codex/codex-launch.js";
2
2
  export const HERMES_LAUNCH_PROFILES = [
3
3
  {
4
4
  id: "default",
@@ -1,7 +1,7 @@
1
1
  import { randomUUID } from "node:crypto";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
- import { HERMES_AGENT_CAPABILITIES, HERMES_REASONING_EFFORTS, } from "./agent.js";
4
+ import { HERMES_AGENT_CAPABILITIES, HERMES_REASONING_EFFORTS, } from "../shared/agent.js";
5
5
  import { HermesApiClient } from "./hermes-api.js";
6
6
  import { resolveHermesCli } from "./hermes-cli.js";
7
7
  import { findHermesLaunchProfile, hermesProfileAsLaunchProfile, listHermesLaunchProfiles, } from "./hermes-launch.js";
@@ -1,10 +1,10 @@
1
- import { findExecutableOnPath } from "./codex-cli.js";
1
+ import { findExecutableOnPath } from "../codex/codex-cli.js";
2
2
  export function resolveOpenClawCli(env = process.env, explicitPath) {
3
3
  const configuredPath = optionalString(explicitPath) ?? optionalString(env.OPENCLAW_CLI_PATH);
4
4
  if (configuredPath) {
5
5
  return { path: configuredPath, source: "env" };
6
6
  }
7
- const pathMatch = findExecutableOnPath("openclaw", env.PATH);
7
+ const pathMatch = findExecutableOnPath("openclaw", env.PATH, { pathext: env.PATHEXT });
8
8
  return pathMatch ? { path: pathMatch, source: "path" } : { source: "missing" };
9
9
  }
10
10
  export function describeOpenClawCli(resolution) {
@@ -1,4 +1,4 @@
1
- import { createLaunchProfile } from "./codex-launch.js";
1
+ import { createLaunchProfile } from "../codex/codex-launch.js";
2
2
  export const OPENCLAW_LAUNCH_PROFILES = [
3
3
  {
4
4
  id: "default",
@@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto";
2
2
  import { spawnSync } from "node:child_process";
3
3
  import { readFile } from "node:fs/promises";
4
4
  import path from "node:path";
5
- import { OPENCLAW_AGENT_CAPABILITIES, OPENCLAW_THINKING_LEVELS, } from "./agent.js";
5
+ import { OPENCLAW_AGENT_CAPABILITIES, OPENCLAW_THINKING_LEVELS, } from "../shared/agent.js";
6
6
  import { OpenClawGatewayClient, extractOpenClawOutputText } from "./openclaw-gateway.js";
7
7
  import { findOpenClawLaunchProfile, listOpenClawLaunchProfiles, openClawProfileAsLaunchProfile, } from "./openclaw-launch.js";
8
8
  import { resolveOpenClawCli } from "./openclaw-cli.js";
@@ -1,10 +1,10 @@
1
- import { findExecutableOnPath } from "./codex-cli.js";
1
+ import { findExecutableOnPath } from "../codex/codex-cli.js";
2
2
  export function resolvePiCli(env = process.env, explicitPath) {
3
3
  const configuredPath = optionalString(explicitPath) ?? optionalString(env.PI_CLI_PATH);
4
4
  if (configuredPath) {
5
5
  return { path: configuredPath, source: "env" };
6
6
  }
7
- const pathMatch = findExecutableOnPath("pi", env.PATH);
7
+ const pathMatch = findExecutableOnPath("pi", env.PATH, { pathext: env.PATHEXT });
8
8
  return pathMatch ? { path: pathMatch, source: "path" } : { source: "missing" };
9
9
  }
10
10
  export function describePiCli(resolution) {
@@ -1,4 +1,4 @@
1
- import { createLaunchProfile } from "./codex-launch.js";
1
+ import { createLaunchProfile } from "../codex/codex-launch.js";
2
2
  export const PI_LAUNCH_PROFILES = [
3
3
  {
4
4
  id: "default",
@@ -1,7 +1,7 @@
1
1
  import { spawnSync } from "node:child_process";
2
2
  import { readFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
- import { PI_AGENT_CAPABILITIES, PI_THINKING_LEVELS, } from "./agent.js";
4
+ import { PI_AGENT_CAPABILITIES, PI_THINKING_LEVELS, } from "../shared/agent.js";
5
5
  import { findPiLaunchProfile, listPiLaunchProfiles, piProfileAsLaunchProfile } from "./pi-launch.js";
6
6
  import { resolvePiCli } from "./pi-cli.js";
7
7
  import { PiRpcClient } from "./pi-rpc.js";
@@ -1,7 +1,7 @@
1
1
  import { listAgentAdapterDescriptors } from "./agent-adapter.js";
2
2
  import { agentFeatureStates } from "./agent-feature-matrix.js";
3
- import { listChannelDescriptors, } from "./channel-adapter.js";
4
- import { channelCatalogCommandNames, } from "./channel-command-core.js";
3
+ import { listChannelDescriptors, } from "../../channels/shared/channel-adapter.js";
4
+ import { channelCatalogCommandNames, } from "../../channels/shared/channel-command-core.js";
5
5
  export const CHANNEL_FEATURES = [
6
6
  { key: "text", label: "Text", description: "Send and receive plain text prompts and replies." },
7
7
  { key: "streaming-edits", label: "Streaming edits", description: "Update an in-flight answer instead of sending only a final message." },
@@ -1,9 +1,9 @@
1
1
  import { CODEX_AGENT_CAPABILITIES, } from "./agent.js";
2
- import { getThreadActivity, getThreadActivityLog, getThreadRolloutSnapshot, } from "./codex-state.js";
3
- import { getClaudeCodeSessionActivity, getClaudeCodeSessionActivityLog, getClaudeCodeSessionDiagnostics, getClaudeCodeSessionSnapshot, } from "./claude-code-state.js";
4
- import { getHermesSessionActivity, getHermesSessionActivityLog, getHermesSessionDiagnostics, getHermesSessionSnapshot, } from "./hermes-state.js";
5
- import { getOpenClawSessionActivity, getOpenClawSessionActivityLog, getOpenClawSessionDiagnostics, getOpenClawSessionSnapshot, } from "./openclaw-state.js";
6
- import { getPiSessionActivity, getPiSessionActivityLog, getPiSessionDiagnostics, getPiSessionSnapshot, } from "./pi-state.js";
2
+ import { getThreadActivity, getThreadActivityLog, getThreadRolloutSnapshot, } from "../codex/codex-state.js";
3
+ import { getClaudeCodeSessionActivity, getClaudeCodeSessionActivityLog, getClaudeCodeSessionDiagnostics, getClaudeCodeSessionSnapshot, } from "../claude-code/claude-code-state.js";
4
+ import { getHermesSessionActivity, getHermesSessionActivityLog, getHermesSessionDiagnostics, getHermesSessionSnapshot, } from "../hermes/hermes-state.js";
5
+ import { getOpenClawSessionActivity, getOpenClawSessionActivityLog, getOpenClawSessionDiagnostics, getOpenClawSessionSnapshot, } from "../openclaw/openclaw-state.js";
6
+ import { getPiSessionActivity, getPiSessionActivityLog, getPiSessionDiagnostics, getPiSessionSnapshot, } from "../pi/pi-state.js";
7
7
  export function getExternalActivityForSession(session, config) {
8
8
  const info = session?.getInfo();
9
9
  if (!info || !(info.capabilities ?? CODEX_AGENT_CAPABILITIES).externalActivity) {
@@ -0,0 +1,30 @@
1
+ export function agentIdForAuth(info) {
2
+ return info?.agentId ?? "codex";
3
+ }
4
+ export function agentLabelForAuth(info) {
5
+ return info?.agentLabel ?? "Codex";
6
+ }
7
+ export function hostAgentLoginCommand(config, info) {
8
+ const agentId = agentIdForAuth(info);
9
+ if (agentId === "hermes")
10
+ return `${config.hermesCliPath ?? "hermes"} login --no-browser`;
11
+ if (agentId === "claude-code")
12
+ return `${config.claudeCodeCliPath ?? "claude"} auth login`;
13
+ if (agentId === "pi")
14
+ return `${config.piCliPath ?? "pi"} auth login`;
15
+ if (agentId === "openclaw")
16
+ return `${config.openClawCliPath ?? "openclaw"} login`;
17
+ return "codex login --device-auth";
18
+ }
19
+ export function hostAgentLogoutCommand(config, info) {
20
+ const agentId = agentIdForAuth(info);
21
+ if (agentId === "hermes")
22
+ return `${config.hermesCliPath ?? "hermes"} logout`;
23
+ if (agentId === "claude-code")
24
+ return `${config.claudeCodeCliPath ?? "claude"} auth logout`;
25
+ if (agentId === "pi")
26
+ return `${config.piCliPath ?? "pi"} auth logout`;
27
+ if (agentId === "openclaw")
28
+ return `${config.openClawCliPath ?? "openclaw"} logout`;
29
+ return "codex logout";
30
+ }
@@ -1,8 +1,8 @@
1
- import { CodexSessionService } from "./codex-session.js";
2
- import { ClaudeCodeSessionService } from "./claude-code-session.js";
3
- import { HermesSessionService } from "./hermes-session.js";
4
- import { OpenClawSessionService } from "./openclaw-session.js";
5
- import { PiSessionService } from "./pi-session.js";
1
+ import { CodexSessionService } from "../codex/codex-session.js";
2
+ import { ClaudeCodeSessionService } from "../claude-code/claude-code-session.js";
3
+ import { HermesSessionService } from "../hermes/hermes-session.js";
4
+ import { OpenClawSessionService } from "../openclaw/openclaw-session.js";
5
+ import { PiSessionService } from "../pi/pi-session.js";
6
6
  export async function createAgentSessionService(config, agentId, options) {
7
7
  if (agentId === "pi") {
8
8
  if (config.piEnabled !== true) {
@@ -1,4 +1,4 @@
1
- import { escapeHTML } from "./format.js";
1
+ import { escapeHTML } from "../../core/format.js";
2
2
  export const AGENT_FEATURES = [
3
3
  { key: "modelSelection", label: "Model", description: "Pick the model used for new turns or sessions." },
4
4
  { key: "reasoningSelection", label: "Reasoning", description: "Pick thinking/reasoning effort where the agent exposes it." },
@@ -7,7 +7,7 @@ export const AGENT_FEATURES = [
7
7
  { key: "workspaces", label: "Workspaces", description: "List and switch allowed workspaces." },
8
8
  { key: "attachments", label: "Files/images", description: "Send files, photos, staged attachments, and voice transcripts." },
9
9
  { key: "externalActivity", label: "External busy", description: "Detect active CLI turns started outside NordRelay." },
10
- { key: "cliMirror", label: "CLI mirror", description: "Mirror CLI-started turns back to Telegram/WebUI." },
10
+ { key: "cliMirror", label: "CLI mirror", description: "Mirror CLI-started turns back to chat adapters and the WebUI." },
11
11
  { key: "activityLog", label: "Activity", description: "Read activity timelines for sessions and turns." },
12
12
  { key: "usageStats", label: "Usage stats", description: "Show token/context usage reported by the agent." },
13
13
  { key: "subscriptionLimits", label: "Limits", description: "Show subscription/quota limits when the agent exposes them." },
@@ -3,13 +3,13 @@ import { appendFileSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileS
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
5
  import { agentLabel } from "./agent.js";
6
- import { resolveClaudeCodeCli } from "./claude-code-cli.js";
7
- import { resolveCodexCli } from "./codex-cli.js";
8
- import { resolveHermesCli } from "./hermes-cli.js";
9
- import { resolveOpenClawCli } from "./openclaw-cli.js";
10
- import { getAgentUpdateLogPath, getConnectorHome, resolveNpmSpawnCommand } from "./operations.js";
11
- import { resolvePiCli } from "./pi-cli.js";
12
- import { redactText } from "./redaction.js";
6
+ import { resolveClaudeCodeCli } from "../claude-code/claude-code-cli.js";
7
+ import { resolveCodexCli } from "../codex/codex-cli.js";
8
+ import { resolveHermesCli } from "../hermes/hermes-cli.js";
9
+ import { resolveOpenClawCli } from "../openclaw/openclaw-cli.js";
10
+ import { getAgentUpdateLogPath, getConnectorHome, resolveNpmSpawnCommand } from "../../support/operations.js";
11
+ import { resolvePiCli } from "../pi/pi-cli.js";
12
+ import { redactText } from "../../core/redaction.js";
13
13
  const AGENT_INSTALL_PACKAGES = {
14
14
  codex: "@openai/codex",
15
15
  pi: "@earendil-works/pi-coding-agent",
@@ -1,7 +1,7 @@
1
- import { collectRecentWorkspaceArtifacts, createArtifactZipBundle, formatArtifactSummary, listRecentArtifactReports } from "./artifacts.js";
2
- import { filterArtifactReports as filterArtifactReportsForCommand } from "./bot-rendering.js";
3
- import { renderArtifactReportsAction } from "./channel-actions.js";
4
- import { deliverChannelAction } from "./channel-runtime.js";
1
+ import { collectRecentWorkspaceArtifacts, createArtifactZipBundle, formatArtifactSummary, listRecentArtifactReports } from "../../artifacts/artifacts.js";
2
+ import { filterArtifactReports as filterArtifactReportsForCommand } from "../shared/bot-rendering.js";
3
+ import { renderArtifactReportsAction } from "../shared/channel-actions.js";
4
+ import { deliverChannelAction } from "../shared/channel-runtime.js";
5
5
  export function createDiscordArtifactCommandHandler(deps) {
6
6
  return async (request, argument) => {
7
7
  const session = await deps.getSession(request, { deferThreadStart: true });