@nordbyte/nordrelay 0.3.1 → 0.4.0

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 (48) hide show
  1. package/.env.example +45 -2
  2. package/README.md +204 -30
  3. package/dist/agent-activity.js +300 -0
  4. package/dist/agent-adapter.js +17 -30
  5. package/dist/agent-factory.js +27 -0
  6. package/dist/agent.js +123 -9
  7. package/dist/artifacts.js +1 -1
  8. package/dist/audit-log.js +1 -1
  9. package/dist/bot-ui.js +1 -1
  10. package/dist/bot.js +328 -159
  11. package/dist/claude-code-auth.js +121 -0
  12. package/dist/claude-code-cli.js +19 -0
  13. package/dist/claude-code-launch.js +73 -0
  14. package/dist/claude-code-session.js +660 -0
  15. package/dist/claude-code-state.js +590 -0
  16. package/dist/codex-session.js +12 -1
  17. package/dist/config.js +113 -9
  18. package/dist/hermes-api.js +150 -0
  19. package/dist/hermes-auth.js +96 -0
  20. package/dist/hermes-cli.js +19 -0
  21. package/dist/hermes-launch.js +57 -0
  22. package/dist/hermes-session.js +477 -0
  23. package/dist/hermes-state.js +609 -0
  24. package/dist/index.js +51 -8
  25. package/dist/openclaw-auth.js +27 -0
  26. package/dist/openclaw-cli.js +19 -0
  27. package/dist/openclaw-gateway.js +285 -0
  28. package/dist/openclaw-launch.js +65 -0
  29. package/dist/openclaw-session.js +549 -0
  30. package/dist/openclaw-state.js +409 -0
  31. package/dist/operations.js +83 -2
  32. package/dist/pi-auth.js +59 -0
  33. package/dist/pi-launch.js +61 -0
  34. package/dist/pi-rpc.js +18 -0
  35. package/dist/pi-session.js +103 -15
  36. package/dist/pi-state.js +253 -0
  37. package/dist/relay-runtime.js +673 -51
  38. package/dist/session-format.js +28 -18
  39. package/dist/session-registry.js +40 -15
  40. package/dist/settings-service.js +35 -4
  41. package/dist/web-dashboard-ui.js +18 -0
  42. package/dist/web-dashboard.js +329 -47
  43. package/package.json +8 -3
  44. package/plugins/nordrelay/.codex-plugin/plugin.json +7 -4
  45. package/plugins/nordrelay/commands/remote.md +2 -2
  46. package/plugins/nordrelay/scripts/nordrelay.mjs +131 -3
  47. package/plugins/nordrelay/skills/telegram-remote/SKILL.md +2 -2
  48. package/CHANGELOG.md +0 -26
@@ -0,0 +1,121 @@
1
+ import { execFile, spawnSync } from "node:child_process";
2
+ const COMMAND_TIMEOUT_MS = 10_000;
3
+ const LOGIN_TIMEOUT_MS = 5 * 60_000;
4
+ const AUTH_CACHE_TTL_MS = 30_000;
5
+ let cachedAuthStatus;
6
+ export async function checkClaudeCodeAuthStatus(cliPath) {
7
+ const command = cliPath ?? "claude";
8
+ const cacheKey = cliPath ?? "bundled-or-path";
9
+ if (cachedAuthStatus?.key === cacheKey && Date.now() < cachedAuthStatus.expiresAt) {
10
+ return cachedAuthStatus.status;
11
+ }
12
+ const status = checkWithCli(command);
13
+ cachedAuthStatus = { key: cacheKey, status, expiresAt: Date.now() + AUTH_CACHE_TTL_MS };
14
+ return status;
15
+ }
16
+ export function clearClaudeCodeAuthCache() {
17
+ cachedAuthStatus = undefined;
18
+ }
19
+ export async function startClaudeCodeLogin(cliPath) {
20
+ clearClaudeCodeAuthCache();
21
+ try {
22
+ const { stdout, stderr } = await runClaudeCodeCommand(cliPath ?? "claude", ["auth", "login"], LOGIN_TIMEOUT_MS);
23
+ const output = [stdout, stderr].filter(Boolean).join("\n").trim();
24
+ return {
25
+ success: true,
26
+ message: output || "Claude Code login completed.",
27
+ };
28
+ }
29
+ catch (error) {
30
+ return {
31
+ success: false,
32
+ message: extractCommandError(error) || "Claude Code login failed. Run 'claude auth login' on the host.",
33
+ };
34
+ }
35
+ }
36
+ export async function startClaudeCodeLogout(cliPath) {
37
+ clearClaudeCodeAuthCache();
38
+ try {
39
+ const { stdout, stderr } = await runClaudeCodeCommand(cliPath ?? "claude", ["auth", "logout"], COMMAND_TIMEOUT_MS);
40
+ const output = [stdout, stderr].filter(Boolean).join("\n").trim();
41
+ return {
42
+ success: true,
43
+ message: output || "Logged out from Claude Code.",
44
+ };
45
+ }
46
+ catch (error) {
47
+ return {
48
+ success: false,
49
+ message: extractCommandError(error) || "Claude Code logout failed. Run 'claude auth logout' on the host.",
50
+ };
51
+ }
52
+ }
53
+ function checkWithCli(command) {
54
+ const result = spawnSync(command, ["auth", "status"], {
55
+ encoding: "utf8",
56
+ timeout: COMMAND_TIMEOUT_MS,
57
+ windowsHide: true,
58
+ env: process.env,
59
+ });
60
+ const output = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
61
+ if (!result.error && result.status === 0) {
62
+ return {
63
+ authenticated: true,
64
+ method: "cli",
65
+ detail: output || "Authenticated via Claude Code CLI.",
66
+ };
67
+ }
68
+ if (result.error && result.error.code === "ENOENT") {
69
+ return {
70
+ authenticated: true,
71
+ method: "cli",
72
+ detail: "Claude Code CLI was not found on PATH; the Claude Agent SDK bundled runtime will perform its own auth check when a turn starts.",
73
+ };
74
+ }
75
+ return {
76
+ authenticated: false,
77
+ method: "none",
78
+ detail: output || result.error?.message || `Claude Code auth status failed with exit ${result.status ?? "unknown"}. Run "claude auth login" on the host.`,
79
+ };
80
+ }
81
+ function runClaudeCodeCommand(command, args, timeout) {
82
+ return new Promise((resolve, reject) => {
83
+ execFile(command, args, {
84
+ encoding: "utf8",
85
+ timeout,
86
+ windowsHide: true,
87
+ env: { ...process.env },
88
+ maxBuffer: 1024 * 1024,
89
+ }, (error, stdout, stderr) => {
90
+ if (error) {
91
+ const enriched = error;
92
+ enriched.stdout = typeof stdout === "string" ? stdout : "";
93
+ enriched.stderr = typeof stderr === "string" ? stderr : "";
94
+ reject(enriched);
95
+ return;
96
+ }
97
+ resolve({
98
+ stdout: typeof stdout === "string" ? stdout : "",
99
+ stderr: typeof stderr === "string" ? stderr : "",
100
+ });
101
+ });
102
+ });
103
+ }
104
+ function extractCommandError(error) {
105
+ if (typeof error === "object" && error !== null) {
106
+ const enriched = error;
107
+ const stderr = enriched.stderr?.trim();
108
+ if (stderr)
109
+ return stderr;
110
+ const stdout = enriched.stdout?.trim();
111
+ if (stdout)
112
+ return stdout;
113
+ if (enriched.code === "ENOENT")
114
+ return "Claude Code CLI not found. Install Claude Code or set CLAUDE_CODE_CLI_PATH.";
115
+ if (enriched.signal)
116
+ return `Command terminated with signal ${enriched.signal}.`;
117
+ if (enriched.message)
118
+ return enriched.message;
119
+ }
120
+ return error instanceof Error ? error.message : String(error);
121
+ }
@@ -0,0 +1,19 @@
1
+ import { findExecutableOnPath } from "./codex-cli.js";
2
+ export function resolveClaudeCodeCli(env = process.env, explicitPath) {
3
+ const configuredPath = optionalString(explicitPath) ?? optionalString(env.CLAUDE_CODE_CLI_PATH);
4
+ if (configuredPath) {
5
+ return { path: configuredPath, source: "env" };
6
+ }
7
+ const pathMatch = findExecutableOnPath("claude", env.PATH);
8
+ return pathMatch ? { path: pathMatch, source: "path" } : { source: "bundled" };
9
+ }
10
+ export function describeClaudeCodeCli(resolution) {
11
+ if (resolution.path) {
12
+ return `${resolution.source} (${resolution.path})`;
13
+ }
14
+ return "bundled @anthropic-ai/claude-agent-sdk";
15
+ }
16
+ function optionalString(value) {
17
+ const trimmed = value?.trim();
18
+ return trimmed ? trimmed : undefined;
19
+ }
@@ -0,0 +1,73 @@
1
+ const CLAUDE_CODE_LAUNCH_PROFILES = [
2
+ {
3
+ id: "default",
4
+ label: "Default",
5
+ behavior: "Claude Code default permissions; ask before risky operations.",
6
+ unsafe: false,
7
+ permissionMode: "default",
8
+ },
9
+ {
10
+ id: "accept-edits",
11
+ label: "Accept Edits",
12
+ behavior: "Auto-accept file edits; keep approval checks for other risky tools.",
13
+ unsafe: false,
14
+ permissionMode: "acceptEdits",
15
+ },
16
+ {
17
+ id: "plan",
18
+ label: "Plan",
19
+ behavior: "Plan mode; no direct implementation tools.",
20
+ unsafe: false,
21
+ permissionMode: "plan",
22
+ },
23
+ {
24
+ id: "readonly",
25
+ label: "Read Only",
26
+ behavior: "Read-only inspection tools only; no file writes or shell execution.",
27
+ unsafe: false,
28
+ permissionMode: "dontAsk",
29
+ tools: ["Read", "Grep", "Glob", "LS"],
30
+ },
31
+ {
32
+ id: "no-tools",
33
+ label: "No Tools",
34
+ behavior: "Conversation only; all built-in tools disabled.",
35
+ unsafe: false,
36
+ permissionMode: "dontAsk",
37
+ tools: [],
38
+ },
39
+ {
40
+ id: "bypass-permissions",
41
+ label: "Bypass Permissions",
42
+ behavior: "Bypass Claude Code permission prompts. Use only in trusted workspaces.",
43
+ unsafe: true,
44
+ permissionMode: "bypassPermissions",
45
+ allowDangerouslySkipPermissions: true,
46
+ },
47
+ ];
48
+ export function listClaudeCodeLaunchProfiles(includeUnsafe = false) {
49
+ return CLAUDE_CODE_LAUNCH_PROFILES
50
+ .filter((profile) => includeUnsafe || !profile.unsafe)
51
+ .map(({ id, label, behavior, unsafe }) => ({ id, label, behavior, unsafe }));
52
+ }
53
+ export function findClaudeCodeLaunchProfile(profileId, includeUnsafe = false) {
54
+ const fallback = CLAUDE_CODE_LAUNCH_PROFILES[0];
55
+ const normalized = profileId?.trim() || fallback.id;
56
+ const profile = CLAUDE_CODE_LAUNCH_PROFILES.find((candidate) => candidate.id === normalized);
57
+ if (!profile || (profile.unsafe && !includeUnsafe)) {
58
+ if (normalized === fallback.id) {
59
+ return fallback;
60
+ }
61
+ throw new Error(`Unknown Claude Code launch profile: ${normalized}`);
62
+ }
63
+ return profile;
64
+ }
65
+ export function claudeCodeProfileAsLaunchProfile(profile) {
66
+ return {
67
+ id: profile.id,
68
+ label: profile.label,
69
+ sandboxMode: "workspace-write",
70
+ approvalPolicy: profile.permissionMode === "bypassPermissions" ? "never" : "on-request",
71
+ unsafe: profile.unsafe,
72
+ };
73
+ }