@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,300 @@
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";
7
+ export function getExternalActivityForSession(session, config) {
8
+ const info = session?.getInfo();
9
+ if (!info || !(info.capabilities ?? CODEX_AGENT_CAPABILITIES).externalActivity) {
10
+ return null;
11
+ }
12
+ const threadId = session?.getActiveThreadId();
13
+ if (!threadId) {
14
+ return null;
15
+ }
16
+ if (info.agentId === "pi") {
17
+ return getPiSessionActivity(info.sessionPath ?? threadId, {
18
+ sessionDir: config.piSessionDir,
19
+ staleAfterMs: config.codexExternalBusyStaleMs,
20
+ });
21
+ }
22
+ if (info.agentId === "hermes") {
23
+ return getHermesSessionActivity(threadId, {
24
+ hermesHome: config.hermesHome,
25
+ stateDbPath: config.hermesStateDbPath,
26
+ workspace: info.workspace,
27
+ staleAfterMs: config.codexExternalBusyStaleMs,
28
+ });
29
+ }
30
+ if (info.agentId === "openclaw") {
31
+ return getOpenClawSessionActivity(threadId, {
32
+ cliPath: config.openClawCliPath,
33
+ openClawHome: config.openClawHome,
34
+ stateDir: config.openClawStateDir,
35
+ workspace: info.workspace,
36
+ openClawAgentId: config.openClawAgentId,
37
+ staleAfterMs: config.codexExternalBusyStaleMs,
38
+ });
39
+ }
40
+ if (info.agentId === "claude-code") {
41
+ return getClaudeCodeSessionActivity(threadId, {
42
+ configDir: config.claudeCodeConfigDir,
43
+ workspace: info.workspace,
44
+ staleAfterMs: config.codexExternalBusyStaleMs,
45
+ });
46
+ }
47
+ const activity = getThreadActivity(threadId, {
48
+ staleAfterMs: config.codexExternalBusyStaleMs,
49
+ });
50
+ if (!activity) {
51
+ return null;
52
+ }
53
+ return {
54
+ agentId: "codex",
55
+ agentLabel: "Codex",
56
+ threadId: activity.threadId,
57
+ sourcePath: activity.rolloutPath,
58
+ sourceLabel: "Codex rollout",
59
+ active: activity.active,
60
+ stale: activity.stale,
61
+ turnId: activity.turnId,
62
+ startedAt: activity.startedAt,
63
+ updatedAt: activity.updatedAt,
64
+ };
65
+ }
66
+ export function getExternalSnapshotForSession(session, config, options = {}) {
67
+ const info = session.getInfo();
68
+ const threadId = session.getActiveThreadId();
69
+ if (!(info.capabilities ?? CODEX_AGENT_CAPABILITIES).externalActivity || !threadId) {
70
+ return null;
71
+ }
72
+ if (info.agentId === "pi") {
73
+ return getPiSessionSnapshot(info.sessionPath ?? threadId, {
74
+ sessionDir: config.piSessionDir,
75
+ afterLine: options.afterLine,
76
+ maxEvents: options.maxEvents,
77
+ staleAfterMs: config.codexExternalBusyStaleMs,
78
+ });
79
+ }
80
+ if (info.agentId === "hermes") {
81
+ return getHermesSessionSnapshot(threadId, {
82
+ hermesHome: config.hermesHome,
83
+ stateDbPath: config.hermesStateDbPath,
84
+ workspace: info.workspace,
85
+ afterLine: options.afterLine,
86
+ maxEvents: options.maxEvents,
87
+ staleAfterMs: config.codexExternalBusyStaleMs,
88
+ });
89
+ }
90
+ if (info.agentId === "openclaw") {
91
+ return getOpenClawSessionSnapshot(threadId, {
92
+ cliPath: config.openClawCliPath,
93
+ openClawHome: config.openClawHome,
94
+ stateDir: config.openClawStateDir,
95
+ workspace: info.workspace,
96
+ openClawAgentId: config.openClawAgentId,
97
+ afterLine: options.afterLine,
98
+ maxEvents: options.maxEvents,
99
+ staleAfterMs: config.codexExternalBusyStaleMs,
100
+ });
101
+ }
102
+ if (info.agentId === "claude-code") {
103
+ return getClaudeCodeSessionSnapshot(threadId, {
104
+ configDir: config.claudeCodeConfigDir,
105
+ workspace: info.workspace,
106
+ afterLine: options.afterLine,
107
+ maxEvents: options.maxEvents,
108
+ staleAfterMs: config.codexExternalBusyStaleMs,
109
+ });
110
+ }
111
+ const snapshot = getThreadRolloutSnapshot(threadId, {
112
+ afterLine: options.afterLine,
113
+ maxEvents: options.maxEvents,
114
+ staleAfterMs: config.codexExternalBusyStaleMs,
115
+ });
116
+ return snapshot ? codexSnapshotToAgentSnapshot(snapshot) : null;
117
+ }
118
+ export function getAgentActivityLog(session, config, limit) {
119
+ const info = session.getInfo();
120
+ const threadId = session.getActiveThreadId();
121
+ if (!threadId) {
122
+ return [];
123
+ }
124
+ if (info.agentId === "pi") {
125
+ return getPiSessionActivityLog(info.sessionPath ?? threadId, limit, { sessionDir: config.piSessionDir });
126
+ }
127
+ if (info.agentId === "hermes") {
128
+ return getHermesSessionActivityLog(threadId, limit, {
129
+ hermesHome: config.hermesHome,
130
+ stateDbPath: config.hermesStateDbPath,
131
+ workspace: info.workspace,
132
+ });
133
+ }
134
+ if (info.agentId === "openclaw") {
135
+ return getOpenClawSessionActivityLog(threadId, limit, {
136
+ cliPath: config.openClawCliPath,
137
+ openClawHome: config.openClawHome,
138
+ stateDir: config.openClawStateDir,
139
+ workspace: info.workspace,
140
+ openClawAgentId: config.openClawAgentId,
141
+ });
142
+ }
143
+ if (info.agentId === "claude-code") {
144
+ return getClaudeCodeSessionActivityLog(threadId, limit, {
145
+ configDir: config.claudeCodeConfigDir,
146
+ workspace: info.workspace,
147
+ });
148
+ }
149
+ return getThreadActivityLog(threadId, limit).map(codexEventToAgentEvent);
150
+ }
151
+ export function getAgentDiagnostics(session, config) {
152
+ const info = session.getInfo();
153
+ if (info.agentId === "pi") {
154
+ const diagnostics = getPiSessionDiagnostics(info.sessionPath ?? info.threadId, {
155
+ sessionDir: config.piSessionDir,
156
+ staleAfterMs: config.codexExternalBusyStaleMs,
157
+ });
158
+ return {
159
+ agentId: "pi",
160
+ agentLabel: "Pi",
161
+ lines: [
162
+ { label: "Pi session dir", value: diagnostics.sessionDir },
163
+ { label: "Pi session file", value: diagnostics.sessionPath ?? "-" },
164
+ { label: "Pi session status", value: diagnostics.status },
165
+ { label: "Pi status reason", value: diagnostics.reason },
166
+ { label: "Pi JSONL lines", value: String(diagnostics.lineCount) },
167
+ { label: "Pi updated", value: diagnostics.updatedAt?.toISOString() ?? "-" },
168
+ { label: "Pi RPC active", value: session.isProcessing() ? "yes" : "idle" },
169
+ ],
170
+ };
171
+ }
172
+ if (info.agentId === "hermes") {
173
+ const diagnostics = getHermesSessionDiagnostics(info.threadId, {
174
+ hermesHome: config.hermesHome,
175
+ stateDbPath: config.hermesStateDbPath,
176
+ workspace: info.workspace,
177
+ staleAfterMs: config.codexExternalBusyStaleMs,
178
+ });
179
+ return {
180
+ agentId: "hermes",
181
+ agentLabel: "Hermes",
182
+ lines: [
183
+ { label: "Hermes API", value: config.hermesApiBaseUrl },
184
+ { label: "Hermes state DB", value: diagnostics.stateDbPath },
185
+ { label: "Hermes session status", value: diagnostics.status },
186
+ { label: "Hermes status reason", value: diagnostics.reason },
187
+ { label: "Hermes messages", value: String(diagnostics.lineCount) },
188
+ { label: "Hermes updated", value: diagnostics.updatedAt?.toISOString() ?? "-" },
189
+ { label: "Hermes API run active", value: session.isProcessing() ? "yes" : "idle" },
190
+ ],
191
+ };
192
+ }
193
+ if (info.agentId === "openclaw") {
194
+ const diagnostics = getOpenClawSessionDiagnostics(info.threadId, {
195
+ cliPath: config.openClawCliPath,
196
+ openClawHome: config.openClawHome,
197
+ stateDir: config.openClawStateDir,
198
+ workspace: info.workspace,
199
+ openClawAgentId: config.openClawAgentId,
200
+ staleAfterMs: config.codexExternalBusyStaleMs,
201
+ });
202
+ return {
203
+ agentId: "openclaw",
204
+ agentLabel: "OpenClaw",
205
+ lines: [
206
+ { label: "OpenClaw Gateway", value: config.openClawGatewayUrl },
207
+ { label: "OpenClaw sessions", value: diagnostics.sourcePath },
208
+ { label: "OpenClaw session status", value: diagnostics.status },
209
+ { label: "OpenClaw status reason", value: diagnostics.reason },
210
+ { label: "OpenClaw events", value: String(diagnostics.lineCount) },
211
+ { label: "OpenClaw updated", value: diagnostics.updatedAt?.toISOString() ?? "-" },
212
+ { label: "OpenClaw Gateway run active", value: session.isProcessing() ? "yes" : "idle" },
213
+ ],
214
+ };
215
+ }
216
+ if (info.agentId === "claude-code") {
217
+ const diagnostics = getClaudeCodeSessionDiagnostics(info.threadId, {
218
+ configDir: config.claudeCodeConfigDir,
219
+ workspace: info.workspace,
220
+ staleAfterMs: config.codexExternalBusyStaleMs,
221
+ });
222
+ return {
223
+ agentId: "claude-code",
224
+ agentLabel: "Claude Code",
225
+ lines: [
226
+ { label: "Claude projects dir", value: diagnostics.projectsDir },
227
+ { label: "Claude session file", value: diagnostics.sessionPath ?? "-" },
228
+ { label: "Claude session status", value: diagnostics.status },
229
+ { label: "Claude status reason", value: diagnostics.reason },
230
+ { label: "Claude JSONL lines", value: String(diagnostics.lineCount) },
231
+ { label: "Claude updated", value: diagnostics.updatedAt?.toISOString() ?? "-" },
232
+ { label: "Claude SDK run active", value: session.isProcessing() ? "yes" : "idle" },
233
+ ],
234
+ };
235
+ }
236
+ const snapshot = info.threadId
237
+ ? getThreadRolloutSnapshot(info.threadId, { staleAfterMs: config.codexExternalBusyStaleMs, maxEvents: 0 })
238
+ : null;
239
+ const status = !info.threadId ? "unavailable" : snapshot?.activity.active ? "active" : snapshot?.activity.stale ? "stale" : snapshot ? "idle" : "unavailable";
240
+ const reason = !info.threadId
241
+ ? "no active thread"
242
+ : snapshot?.activity.active
243
+ ? "open task without terminal event"
244
+ : snapshot?.activity.stale
245
+ ? "open task exceeded stale timeout"
246
+ : snapshot
247
+ ? "no open task"
248
+ : "rollout unavailable";
249
+ return {
250
+ agentId: "codex",
251
+ agentLabel: "Codex",
252
+ lines: [
253
+ { label: "Rollout path", value: snapshot?.rolloutPath ?? "-" },
254
+ { label: "Rollout status", value: status },
255
+ { label: "Rollout reason", value: reason },
256
+ { label: "Rollout turn", value: snapshot?.activity.turnId ?? "-" },
257
+ { label: "Rollout lines", value: String(snapshot?.lineCount ?? 0) },
258
+ { label: "Rollout updated", value: snapshot?.activity.updatedAt?.toISOString() ?? "-" },
259
+ ],
260
+ };
261
+ }
262
+ function codexSnapshotToAgentSnapshot(snapshot) {
263
+ return {
264
+ agentId: "codex",
265
+ agentLabel: "Codex",
266
+ threadId: snapshot.threadId,
267
+ sourcePath: snapshot.rolloutPath,
268
+ sourceLabel: "Codex rollout",
269
+ lineCount: snapshot.lineCount,
270
+ activity: {
271
+ agentId: "codex",
272
+ agentLabel: "Codex",
273
+ threadId: snapshot.threadId,
274
+ sourcePath: snapshot.rolloutPath,
275
+ sourceLabel: "Codex rollout",
276
+ active: snapshot.activity.active,
277
+ stale: snapshot.activity.stale,
278
+ turnId: snapshot.activity.turnId,
279
+ startedAt: snapshot.activity.startedAt,
280
+ updatedAt: snapshot.activity.updatedAt,
281
+ },
282
+ events: snapshot.events.map(codexEventToAgentEvent),
283
+ latestAgentMessage: snapshot.latestAgentMessage,
284
+ latestUserMessage: snapshot.latestUserMessage,
285
+ latestToolName: snapshot.latestToolName,
286
+ };
287
+ }
288
+ function codexEventToAgentEvent(event) {
289
+ return {
290
+ lineNumber: event.lineNumber,
291
+ kind: event.kind,
292
+ timestamp: event.timestamp,
293
+ type: event.type,
294
+ turnId: event.turnId,
295
+ status: event.status,
296
+ text: event.text,
297
+ toolName: event.toolName,
298
+ phase: event.phase,
299
+ };
300
+ }
@@ -1,4 +1,4 @@
1
- import { CODEX_AGENT_CAPABILITIES, PI_AGENT_CAPABILITIES, } from "./agent.js";
1
+ import { CLAUDE_CODE_AGENT_CAPABILITIES, CODEX_AGENT_CAPABILITIES, HERMES_AGENT_CAPABILITIES, OPENCLAW_AGENT_CAPABILITIES, PI_AGENT_CAPABILITIES, } from "./agent.js";
2
2
  export const BUILTIN_AGENT_ADAPTERS = [
3
3
  {
4
4
  id: "codex",
@@ -15,23 +15,28 @@ export const BUILTIN_AGENT_ADAPTERS = [
15
15
  envFlag: "NORDRELAY_PI_ENABLED",
16
16
  },
17
17
  {
18
- id: "claude-code",
19
- label: "Claude Code",
20
- status: "planned",
21
- capabilities: plannedCapabilities(),
22
- notes: "Use this descriptor as the target contract for a future Claude Code session service.",
18
+ id: "hermes",
19
+ label: "Hermes",
20
+ status: "available",
21
+ capabilities: HERMES_AGENT_CAPABILITIES,
22
+ envFlag: "NORDRELAY_HERMES_ENABLED",
23
+ notes: "Uses the Hermes API Server for streaming runs, stop, session continuity, and tool lifecycle events.",
23
24
  },
24
25
  {
25
26
  id: "openclaw",
26
27
  label: "OpenClaw",
27
- status: "planned",
28
- capabilities: plannedCapabilities(),
28
+ status: "available",
29
+ capabilities: OPENCLAW_AGENT_CAPABILITIES,
30
+ envFlag: "NORDRELAY_OPENCLAW_ENABLED",
31
+ notes: "Uses the OpenClaw Gateway WebSocket RPC surface for streamed agent runs, session continuity, and tool lifecycle events.",
29
32
  },
30
33
  {
31
- id: "hermes",
32
- label: "Hermes",
33
- status: "planned",
34
- capabilities: plannedCapabilities(),
34
+ id: "claude-code",
35
+ label: "Claude Code",
36
+ status: "available",
37
+ capabilities: CLAUDE_CODE_AGENT_CAPABILITIES,
38
+ envFlag: "NORDRELAY_CLAUDE_CODE_ENABLED",
39
+ notes: "Uses the Claude Agent SDK with host Claude Code sessions, streaming, tool lifecycle events, session continuity, and handback.",
35
40
  },
36
41
  ];
37
42
  export function listAgentAdapterDescriptors() {
@@ -40,21 +45,3 @@ export function listAgentAdapterDescriptors() {
40
45
  capabilities: { ...descriptor.capabilities },
41
46
  }));
42
47
  }
43
- function plannedCapabilities() {
44
- return {
45
- launchProfiles: false,
46
- fastMode: false,
47
- externalActivity: false,
48
- cliMirror: false,
49
- activityLog: false,
50
- auth: false,
51
- login: false,
52
- logout: false,
53
- usageLimits: false,
54
- workspaces: true,
55
- attachments: true,
56
- modelSelection: true,
57
- reasoningSelection: true,
58
- handback: true,
59
- };
60
- }
@@ -1,4 +1,7 @@
1
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";
2
5
  import { PiSessionService } from "./pi-session.js";
3
6
  export async function createAgentSessionService(config, agentId, options) {
4
7
  if (agentId === "pi") {
@@ -7,6 +10,24 @@ export async function createAgentSessionService(config, agentId, options) {
7
10
  }
8
11
  return PiSessionService.create(config, options);
9
12
  }
13
+ if (agentId === "hermes") {
14
+ if (config.hermesEnabled !== true) {
15
+ throw new Error("Hermes support is disabled. Set NORDRELAY_HERMES_ENABLED=true.");
16
+ }
17
+ return HermesSessionService.create(config, options);
18
+ }
19
+ if (agentId === "openclaw") {
20
+ if (config.openClawEnabled !== true) {
21
+ throw new Error("OpenClaw support is disabled. Set NORDRELAY_OPENCLAW_ENABLED=true.");
22
+ }
23
+ return OpenClawSessionService.create(config, options);
24
+ }
25
+ if (agentId === "claude-code") {
26
+ if (config.claudeCodeEnabled !== true) {
27
+ throw new Error("Claude Code support is disabled. Set NORDRELAY_CLAUDE_CODE_ENABLED=true.");
28
+ }
29
+ return ClaudeCodeSessionService.create(config, options);
30
+ }
10
31
  if (config.codexEnabled === false) {
11
32
  throw new Error("Codex support is disabled. Set NORDRELAY_CODEX_ENABLED=true.");
12
33
  }
@@ -18,5 +39,11 @@ export function enabledAgents(config) {
18
39
  agents.push("codex");
19
40
  if (config.piEnabled)
20
41
  agents.push("pi");
42
+ if (config.hermesEnabled)
43
+ agents.push("hermes");
44
+ if (config.openClawEnabled)
45
+ agents.push("openclaw");
46
+ if (config.claudeCodeEnabled)
47
+ agents.push("claude-code");
21
48
  return agents;
22
49
  }
package/dist/agent.js CHANGED
@@ -1,4 +1,4 @@
1
- export const AGENT_IDS = ["codex", "pi"];
1
+ export const AGENT_IDS = ["codex", "pi", "hermes", "openclaw", "claude-code"];
2
2
  export const CODEX_REASONING_EFFORTS = [
3
3
  "minimal",
4
4
  "low",
@@ -14,6 +14,29 @@ export const PI_THINKING_LEVELS = [
14
14
  "high",
15
15
  "xhigh",
16
16
  ];
17
+ export const HERMES_REASONING_EFFORTS = [
18
+ "none",
19
+ "minimal",
20
+ "low",
21
+ "medium",
22
+ "high",
23
+ "xhigh",
24
+ ];
25
+ export const OPENCLAW_THINKING_LEVELS = [
26
+ "off",
27
+ "minimal",
28
+ "low",
29
+ "medium",
30
+ "high",
31
+ "xhigh",
32
+ ];
33
+ export const CLAUDE_CODE_EFFORT_LEVELS = [
34
+ "off",
35
+ "low",
36
+ "medium",
37
+ "high",
38
+ "xhigh",
39
+ ];
17
40
  export const CODEX_AGENT_CAPABILITIES = {
18
41
  launchProfiles: true,
19
42
  fastMode: true,
@@ -23,6 +46,8 @@ export const CODEX_AGENT_CAPABILITIES = {
23
46
  auth: true,
24
47
  login: true,
25
48
  logout: true,
49
+ usageStats: true,
50
+ subscriptionLimits: true,
26
51
  usageLimits: true,
27
52
  workspaces: true,
28
53
  attachments: true,
@@ -31,14 +56,70 @@ export const CODEX_AGENT_CAPABILITIES = {
31
56
  handback: true,
32
57
  };
33
58
  export const PI_AGENT_CAPABILITIES = {
34
- launchProfiles: false,
59
+ launchProfiles: true,
60
+ fastMode: false,
61
+ externalActivity: true,
62
+ cliMirror: true,
63
+ activityLog: true,
64
+ auth: true,
65
+ login: false,
66
+ logout: false,
67
+ usageStats: true,
68
+ subscriptionLimits: false,
69
+ usageLimits: false,
70
+ workspaces: true,
71
+ attachments: true,
72
+ modelSelection: true,
73
+ reasoningSelection: true,
74
+ handback: true,
75
+ };
76
+ export const HERMES_AGENT_CAPABILITIES = {
77
+ launchProfiles: true,
35
78
  fastMode: false,
36
- externalActivity: false,
37
- cliMirror: false,
38
- activityLog: false,
39
- auth: false,
79
+ externalActivity: true,
80
+ cliMirror: true,
81
+ activityLog: true,
82
+ auth: true,
83
+ login: true,
84
+ logout: true,
85
+ usageStats: true,
86
+ subscriptionLimits: false,
87
+ usageLimits: false,
88
+ workspaces: true,
89
+ attachments: true,
90
+ modelSelection: true,
91
+ reasoningSelection: true,
92
+ handback: true,
93
+ };
94
+ export const OPENCLAW_AGENT_CAPABILITIES = {
95
+ launchProfiles: true,
96
+ fastMode: false,
97
+ externalActivity: true,
98
+ cliMirror: true,
99
+ activityLog: true,
100
+ auth: true,
40
101
  login: false,
41
102
  logout: false,
103
+ usageStats: true,
104
+ subscriptionLimits: false,
105
+ usageLimits: false,
106
+ workspaces: true,
107
+ attachments: true,
108
+ modelSelection: true,
109
+ reasoningSelection: true,
110
+ handback: true,
111
+ };
112
+ export const CLAUDE_CODE_AGENT_CAPABILITIES = {
113
+ launchProfiles: true,
114
+ fastMode: false,
115
+ externalActivity: true,
116
+ cliMirror: true,
117
+ activityLog: true,
118
+ auth: true,
119
+ login: true,
120
+ logout: true,
121
+ usageStats: true,
122
+ subscriptionLimits: false,
42
123
  usageLimits: false,
43
124
  workspaces: true,
44
125
  attachments: true,
@@ -47,11 +128,44 @@ export const PI_AGENT_CAPABILITIES = {
47
128
  handback: true,
48
129
  };
49
130
  export function isAgentId(value) {
50
- return value === "codex" || value === "pi";
131
+ return AGENT_IDS.includes(value);
51
132
  }
52
133
  export function agentLabel(agentId) {
53
- return agentId === "pi" ? "Pi" : "Codex";
134
+ if (agentId === "pi") {
135
+ return "Pi";
136
+ }
137
+ if (agentId === "hermes") {
138
+ return "Hermes";
139
+ }
140
+ if (agentId === "openclaw") {
141
+ return "OpenClaw";
142
+ }
143
+ if (agentId === "claude-code") {
144
+ return "Claude Code";
145
+ }
146
+ return "Codex";
54
147
  }
55
148
  export function agentReasoningLabel(agentId) {
56
- return agentId === "pi" ? "Thinking" : "Reasoning";
149
+ if (agentId === "pi" || agentId === "openclaw") {
150
+ return "Thinking";
151
+ }
152
+ if (agentId === "claude-code") {
153
+ return "Effort";
154
+ }
155
+ return "Reasoning";
156
+ }
157
+ export function agentReasoningOptions(agentId) {
158
+ if (agentId === "pi") {
159
+ return PI_THINKING_LEVELS;
160
+ }
161
+ if (agentId === "hermes") {
162
+ return HERMES_REASONING_EFFORTS;
163
+ }
164
+ if (agentId === "openclaw") {
165
+ return OPENCLAW_THINKING_LEVELS;
166
+ }
167
+ if (agentId === "claude-code") {
168
+ return CLAUDE_CODE_EFFORT_LEVELS;
169
+ }
170
+ return CODEX_REASONING_EFFORTS;
57
171
  }
package/dist/artifacts.js CHANGED
@@ -178,7 +178,7 @@ export async function createArtifactZipBundle(artifacts, outDir, options = {}) {
178
178
  }
179
179
  const bundleDir = path.join(outDir, ".telegram-artifacts");
180
180
  await mkdir(bundleDir, { recursive: true });
181
- const bundleName = options.bundleName ?? `codex-artifacts-${sanitizeZipStem(path.basename(path.dirname(outDir)))}.zip`;
181
+ const bundleName = options.bundleName ?? `nordrelay-artifacts-${sanitizeZipStem(path.basename(path.dirname(outDir)))}.zip`;
182
182
  const bundlePath = path.join(bundleDir, bundleName);
183
183
  await rm(bundlePath, { force: true }).catch(() => { });
184
184
  try {
package/dist/audit-log.js CHANGED
@@ -17,8 +17,8 @@ export class AuditLogStore {
17
17
  const next = {
18
18
  id: randomUUID().replace(/-/g, "").slice(0, 12),
19
19
  timestamp: new Date().toISOString(),
20
- channelId: "telegram",
21
20
  ...event,
21
+ channelId: event.channelId ?? "telegram",
22
22
  };
23
23
  payload.events.push(next);
24
24
  if (payload.events.length > this.maxEvents) {
package/dist/bot-ui.js CHANGED
@@ -8,7 +8,7 @@ export function renderHelpMessage() {
8
8
  title: "💬 Session",
9
9
  commands: [
10
10
  ["/new", "Start a new thread"],
11
- ["/agent", "Select Codex or Pi"],
11
+ ["/agent", "Select agent"],
12
12
  ["/session", "Current thread details"],
13
13
  ["/sessions", "Browse & switch threads"],
14
14
  ["/sync", "Sync active sessions from CLI state"],