@nordbyte/nordrelay 0.2.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.
Files changed (45) hide show
  1. package/.env.example +88 -0
  2. package/Dockerfile +19 -0
  3. package/LICENSE +21 -0
  4. package/README.md +749 -0
  5. package/dist/access-control.js +146 -0
  6. package/dist/agent-factory.js +22 -0
  7. package/dist/agent.js +57 -0
  8. package/dist/artifacts.js +515 -0
  9. package/dist/attachments.js +69 -0
  10. package/dist/bot-preferences.js +146 -0
  11. package/dist/bot-ui.js +161 -0
  12. package/dist/bot.js +4520 -0
  13. package/dist/codex-auth.js +150 -0
  14. package/dist/codex-cli.js +79 -0
  15. package/dist/codex-config.js +50 -0
  16. package/dist/codex-launch.js +109 -0
  17. package/dist/codex-session.js +591 -0
  18. package/dist/codex-state.js +573 -0
  19. package/dist/config.js +385 -0
  20. package/dist/context-key.js +23 -0
  21. package/dist/error-messages.js +73 -0
  22. package/dist/format.js +121 -0
  23. package/dist/index.js +140 -0
  24. package/dist/logger.js +27 -0
  25. package/dist/operations.js +133 -0
  26. package/dist/persistence.js +65 -0
  27. package/dist/pi-cli.js +19 -0
  28. package/dist/pi-rpc.js +158 -0
  29. package/dist/pi-session.js +573 -0
  30. package/dist/pi-state.js +226 -0
  31. package/dist/prompt-store.js +241 -0
  32. package/dist/redaction.js +47 -0
  33. package/dist/session-format.js +191 -0
  34. package/dist/session-registry.js +195 -0
  35. package/dist/telegram-rate-limit.js +136 -0
  36. package/dist/voice.js +373 -0
  37. package/dist/workspace-policy.js +41 -0
  38. package/docker-compose.yml +17 -0
  39. package/launchd/start.sh +8 -0
  40. package/package.json +69 -0
  41. package/plugins/nordrelay/.codex-plugin/plugin.json +48 -0
  42. package/plugins/nordrelay/assets/nordrelay.svg +5 -0
  43. package/plugins/nordrelay/commands/remote.md +33 -0
  44. package/plugins/nordrelay/scripts/nordrelay.mjs +396 -0
  45. package/plugins/nordrelay/skills/telegram-remote/SKILL.md +26 -0
@@ -0,0 +1,146 @@
1
+ const ALL_PERMISSIONS = [
2
+ "inspect",
3
+ "sessions",
4
+ "prompt",
5
+ "files",
6
+ "settings",
7
+ "auth",
8
+ "admin",
9
+ ];
10
+ const COMMAND_PERMISSIONS = new Map([
11
+ ["start", "inspect"],
12
+ ["help", "inspect"],
13
+ ["status", "inspect"],
14
+ ["health", "inspect"],
15
+ ["version", "inspect"],
16
+ ["diagnostics", "admin"],
17
+ ["tasks", "inspect"],
18
+ ["progress", "inspect"],
19
+ ["activity", "inspect"],
20
+ ["mirror", "settings"],
21
+ ["notify", "settings"],
22
+ ["workspaces", "sessions"],
23
+ ["voice", "inspect"],
24
+ ["agent", "settings"],
25
+ ["session", "sessions"],
26
+ ["sessions", "sessions"],
27
+ ["switch", "sessions"],
28
+ ["pinned", "sessions"],
29
+ ["pin", "sessions"],
30
+ ["unpin", "sessions"],
31
+ ["attach", "sessions"],
32
+ ["handback", "sessions"],
33
+ ["new", "sessions"],
34
+ ["sync", "sessions"],
35
+ ["queue", "inspect"],
36
+ ["cancel", "prompt"],
37
+ ["clearqueue", "prompt"],
38
+ ["retry", "prompt"],
39
+ ["abort", "prompt"],
40
+ ["stop", "prompt"],
41
+ ["artifacts", "files"],
42
+ ["launch", "settings"],
43
+ ["launch_profiles", "settings"],
44
+ ["launch-profiles", "settings"],
45
+ ["fast", "settings"],
46
+ ["model", "settings"],
47
+ ["reasoning", "settings"],
48
+ ["effort", "settings"],
49
+ ["auth", "inspect"],
50
+ ["login", "auth"],
51
+ ["logout", "auth"],
52
+ ["logs", "admin"],
53
+ ["restart", "admin"],
54
+ ["update", "admin"],
55
+ ]);
56
+ export function createDefaultRolePolicies() {
57
+ return {
58
+ admin: new Set(ALL_PERMISSIONS),
59
+ operator: new Set(["inspect", "sessions", "prompt", "files", "settings", "auth"]),
60
+ readonly: new Set(["inspect", "sessions"]),
61
+ };
62
+ }
63
+ export function parseRolePoliciesJson(raw) {
64
+ const policies = createDefaultRolePolicies();
65
+ if (!raw) {
66
+ return policies;
67
+ }
68
+ let parsed;
69
+ try {
70
+ parsed = JSON.parse(raw);
71
+ }
72
+ catch (error) {
73
+ throw new Error(`Invalid TELEGRAM_ROLE_POLICIES_JSON: ${error instanceof Error ? error.message : String(error)}`);
74
+ }
75
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
76
+ throw new Error("TELEGRAM_ROLE_POLICIES_JSON must be an object keyed by role");
77
+ }
78
+ for (const [role, rawPermissions] of Object.entries(parsed)) {
79
+ if (!isTelegramRole(role)) {
80
+ throw new Error(`Invalid TELEGRAM_ROLE_POLICIES_JSON role: ${role}`);
81
+ }
82
+ policies[role] = parsePermissionList(rawPermissions, role);
83
+ }
84
+ if (!policies.admin.has("admin")) {
85
+ policies.admin.add("admin");
86
+ }
87
+ return policies;
88
+ }
89
+ export function hasTelegramPermission(policies, role, permission) {
90
+ return policies[role].has(permission) || policies[role].has("admin");
91
+ }
92
+ export function permissionForCommand(command) {
93
+ if (!command) {
94
+ return "inspect";
95
+ }
96
+ return COMMAND_PERMISSIONS.get(command.toLowerCase()) ?? "inspect";
97
+ }
98
+ export function permissionForCallbackData(callbackData) {
99
+ if (!callbackData) {
100
+ return "inspect";
101
+ }
102
+ if (callbackData === "noop_page") {
103
+ return "inspect";
104
+ }
105
+ if (/^(sess_|ws_)/.test(callbackData)) {
106
+ return "sessions";
107
+ }
108
+ if (/^(launch_|launchconfirm_|model_|effort_|agent_)/.test(callbackData)) {
109
+ return "settings";
110
+ }
111
+ if (callbackData.startsWith("approval_") || callbackData.startsWith("codex_abort:") || callbackData.startsWith("agent_abort:")) {
112
+ return "prompt";
113
+ }
114
+ if (callbackData.startsWith("queue_")) {
115
+ return "prompt";
116
+ }
117
+ if (callbackData.startsWith("artifact_")) {
118
+ return "files";
119
+ }
120
+ return "inspect";
121
+ }
122
+ export function isTelegramRole(value) {
123
+ return value === "admin" || value === "operator" || value === "readonly";
124
+ }
125
+ function parsePermissionList(rawPermissions, role) {
126
+ if (rawPermissions === "*") {
127
+ return new Set(ALL_PERMISSIONS);
128
+ }
129
+ if (!Array.isArray(rawPermissions)) {
130
+ throw new Error(`TELEGRAM_ROLE_POLICIES_JSON.${role} must be an array or "*"`);
131
+ }
132
+ const permissions = new Set();
133
+ for (const rawPermission of rawPermissions) {
134
+ if (rawPermission === "*") {
135
+ return new Set(ALL_PERMISSIONS);
136
+ }
137
+ if (typeof rawPermission !== "string" || !isTelegramPermission(rawPermission)) {
138
+ throw new Error(`Invalid TELEGRAM_ROLE_POLICIES_JSON permission for ${role}: ${String(rawPermission)}`);
139
+ }
140
+ permissions.add(rawPermission);
141
+ }
142
+ return permissions;
143
+ }
144
+ function isTelegramPermission(value) {
145
+ return ALL_PERMISSIONS.includes(value);
146
+ }
@@ -0,0 +1,22 @@
1
+ import { CodexSessionService } from "./codex-session.js";
2
+ import { PiSessionService } from "./pi-session.js";
3
+ export async function createAgentSessionService(config, agentId, options) {
4
+ if (agentId === "pi") {
5
+ if (config.piEnabled !== true) {
6
+ throw new Error("Pi support is disabled. Set NORDRELAY_PI_ENABLED=true.");
7
+ }
8
+ return PiSessionService.create(config, options);
9
+ }
10
+ if (config.codexEnabled === false) {
11
+ throw new Error("Codex support is disabled. Set NORDRELAY_CODEX_ENABLED=true.");
12
+ }
13
+ return CodexSessionService.create(config, options);
14
+ }
15
+ export function enabledAgents(config) {
16
+ const agents = [];
17
+ if (config.codexEnabled !== false)
18
+ agents.push("codex");
19
+ if (config.piEnabled)
20
+ agents.push("pi");
21
+ return agents;
22
+ }
package/dist/agent.js ADDED
@@ -0,0 +1,57 @@
1
+ export const AGENT_IDS = ["codex", "pi"];
2
+ export const CODEX_REASONING_EFFORTS = [
3
+ "minimal",
4
+ "low",
5
+ "medium",
6
+ "high",
7
+ "xhigh",
8
+ ];
9
+ export const PI_THINKING_LEVELS = [
10
+ "off",
11
+ "minimal",
12
+ "low",
13
+ "medium",
14
+ "high",
15
+ "xhigh",
16
+ ];
17
+ export const CODEX_AGENT_CAPABILITIES = {
18
+ launchProfiles: true,
19
+ fastMode: true,
20
+ externalActivity: true,
21
+ cliMirror: true,
22
+ activityLog: true,
23
+ auth: true,
24
+ login: true,
25
+ logout: true,
26
+ usageLimits: true,
27
+ workspaces: true,
28
+ attachments: true,
29
+ modelSelection: true,
30
+ reasoningSelection: true,
31
+ handback: true,
32
+ };
33
+ export const PI_AGENT_CAPABILITIES = {
34
+ launchProfiles: false,
35
+ fastMode: false,
36
+ externalActivity: false,
37
+ cliMirror: false,
38
+ activityLog: false,
39
+ auth: false,
40
+ login: false,
41
+ logout: false,
42
+ usageLimits: false,
43
+ workspaces: true,
44
+ attachments: true,
45
+ modelSelection: true,
46
+ reasoningSelection: true,
47
+ handback: true,
48
+ };
49
+ export function isAgentId(value) {
50
+ return value === "codex" || value === "pi";
51
+ }
52
+ export function agentLabel(agentId) {
53
+ return agentId === "pi" ? "Pi" : "Codex";
54
+ }
55
+ export function agentReasoningLabel(agentId) {
56
+ return agentId === "pi" ? "Thinking" : "Reasoning";
57
+ }