@songsid/agend 2.0.11-beta.4 → 2.0.11-beta.40

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 (54) hide show
  1. package/dist/channel/adapters/discord.d.ts +2 -0
  2. package/dist/channel/adapters/discord.js +45 -36
  3. package/dist/channel/adapters/discord.js.map +1 -1
  4. package/dist/channel/adapters/telegram.js +1 -0
  5. package/dist/channel/adapters/telegram.js.map +1 -1
  6. package/dist/channel/factory.d.ts +4 -0
  7. package/dist/channel/factory.js +1 -0
  8. package/dist/channel/factory.js.map +1 -1
  9. package/dist/channel/mcp-tools.js +3 -0
  10. package/dist/channel/mcp-tools.js.map +1 -1
  11. package/dist/channel/tool-router.js +29 -2
  12. package/dist/channel/tool-router.js.map +1 -1
  13. package/dist/channel/types.d.ts +2 -0
  14. package/dist/classic-channel-manager.d.ts +59 -12
  15. package/dist/classic-channel-manager.js +121 -30
  16. package/dist/classic-channel-manager.js.map +1 -1
  17. package/dist/cli.js +94 -7
  18. package/dist/cli.js.map +1 -1
  19. package/dist/config-validator.d.ts +20 -0
  20. package/dist/config-validator.js +154 -0
  21. package/dist/config-validator.js.map +1 -0
  22. package/dist/fleet-manager.d.ts +29 -6
  23. package/dist/fleet-manager.js +455 -258
  24. package/dist/fleet-manager.js.map +1 -1
  25. package/dist/instance-lifecycle.d.ts +1 -1
  26. package/dist/instance-lifecycle.js +15 -13
  27. package/dist/instance-lifecycle.js.map +1 -1
  28. package/dist/locale.d.ts +19 -0
  29. package/dist/locale.js +179 -0
  30. package/dist/locale.js.map +1 -0
  31. package/dist/outbound-schemas.d.ts +1 -0
  32. package/dist/outbound-schemas.js +1 -0
  33. package/dist/outbound-schemas.js.map +1 -1
  34. package/dist/quickstart.js +252 -16
  35. package/dist/quickstart.js.map +1 -1
  36. package/dist/scheduler/scheduler.js +8 -2
  37. package/dist/scheduler/scheduler.js.map +1 -1
  38. package/dist/service-installer.d.ts +1 -0
  39. package/dist/service-installer.js +2 -1
  40. package/dist/service-installer.js.map +1 -1
  41. package/dist/settings-api.d.ts +33 -0
  42. package/dist/settings-api.js +283 -0
  43. package/dist/settings-api.js.map +1 -0
  44. package/dist/topic-commands.d.ts +14 -0
  45. package/dist/topic-commands.js +78 -16
  46. package/dist/topic-commands.js.map +1 -1
  47. package/dist/types.d.ts +2 -0
  48. package/dist/ui/settings.html +617 -0
  49. package/dist/ui/view.html +295 -39
  50. package/dist/view-api.d.ts +9 -0
  51. package/dist/view-api.js +101 -40
  52. package/dist/view-api.js.map +1 -1
  53. package/package.json +1 -1
  54. package/templates/systemd.service.ejs +2 -1
@@ -1,6 +1,14 @@
1
1
  import type { Logger } from "./logger.js";
2
2
  export interface ClassicChannel {
3
3
  channelId: string;
4
+ /**
5
+ * Which bot adapter owns this channel's agent. `undefined` only transiently
6
+ * for legacy (pre-multi-bot) entries loaded before the primary adapter id is
7
+ * known — {@link ClassicChannelManager.setPrimaryAdapterId} migrates those to
8
+ * the primary. Enables same-channel multi-bot: two bots in one channel are
9
+ * distinct entries keyed by (channelId, adapterId).
10
+ */
11
+ adapterId?: string;
4
12
  name: string;
5
13
  instanceName: string;
6
14
  backend?: string;
@@ -11,8 +19,14 @@ export interface ClassicChannel {
11
19
  createdAt: string;
12
20
  createdBy: string;
13
21
  }
14
- /** Derive instance name from channel name + last 4 digits of channelId */
15
- export declare function classicInstanceName(sanitizedName: string, channelId: string): string;
22
+ /**
23
+ * Derive instance name from channel name + last 4 digits of channelId.
24
+ * When `adapterId` is given (a non-primary bot in the same channel), append a
25
+ * sanitized adapter suffix so two bots in one channel get distinct instance
26
+ * names (dirs / tmux windows / IPC). The primary bot passes `undefined` to keep
27
+ * the historical name — single-bot users see no change across the upgrade.
28
+ */
29
+ export declare function classicInstanceName(sanitizedName: string, channelId: string, adapterId?: string): string;
16
30
  /**
17
31
  * Manages classic bot channel lifecycle — register/unregister/persist.
18
32
  * Persists to ~/.agend/classicBot.yaml with per-channel backend override.
@@ -21,11 +35,31 @@ export declare function classicInstanceName(sanitizedName: string, channelId: st
21
35
  export declare class ClassicChannelManager {
22
36
  private dataDir;
23
37
  private logger;
38
+ /** Keyed by compositeKey(channelId, adapterId) — see {@link ClassicChannel.adapterId}. */
24
39
  private channels;
40
+ /** Distinct channelIds across all adapters — makes hasChannel() O(1) (hot path: every inbound). */
41
+ private channelIds;
25
42
  private defaults;
26
43
  private readonly configPath;
27
44
  private lastMtime;
45
+ /** The primary (channels[0]) adapter id. Legacy entries migrate to it; it also names without a suffix. */
46
+ private primaryAdapterId?;
28
47
  constructor(dataDir: string, logger: Logger);
48
+ /**
49
+ * Record which adapter is primary. Migrates any legacy (adapterId-less)
50
+ * entries onto it and rewrites the file in the new format. Idempotent.
51
+ */
52
+ setPrimaryAdapterId(adapterId: string): void;
53
+ /** Map key for a (channelId, adapterId) pair. adapterId-less = legacy entry (pre-migration). */
54
+ private compositeKey;
55
+ /** Rebuild the channelId presence set from the entry map (call after any mutation). */
56
+ private rebuildChannelIds;
57
+ /**
58
+ * Resolve the entry for a channel as seen by a specific bot. Exact
59
+ * (channelId, adapterId) match wins; the primary adapter also matches a
60
+ * not-yet-migrated legacy entry as a defensive fallback.
61
+ */
62
+ private find;
29
63
  private load;
30
64
  private save;
31
65
  /** Poll for external file changes (call periodically, e.g. every 30s) */
@@ -42,23 +76,36 @@ export declare class ClassicChannelManager {
42
76
  /** Check if a user is admin. Empty/unset admin_users = no admins (secure default). */
43
77
  isAdmin(userId: string): boolean;
44
78
  /** Toggle collab mode for a channel. Returns new state. */
45
- toggleCollab(channelId: string): boolean;
46
- isCollab(channelId: string): boolean;
47
- getPreTaskCommand(channelId: string): string | undefined;
79
+ toggleCollab(channelId: string, adapterId?: string): boolean;
80
+ isCollab(channelId: string, adapterId?: string): boolean;
81
+ getPreTaskCommand(channelId: string, adapterId?: string): string | undefined;
48
82
  /** Context lines fallback: per-channel → defaults → 5 */
49
- getContextLines(channelId: string): number;
83
+ getContextLines(channelId: string, adapterId?: string): number;
50
84
  /** Backend fallback: per-channel → classic defaults → fleetDefault → "claude-code" */
51
- getBackend(channelId: string, fleetDefault?: string): string;
85
+ getBackend(channelId: string, adapterId?: string, fleetDefault?: string): string;
52
86
  /** Get model for a channel — channel override → defaults → fleet default */
53
- getModel(channelId: string, fleetDefault?: string): string | undefined;
87
+ getModel(channelId: string, adapterId?: string, fleetDefault?: string): string | undefined;
54
88
  /** Get backend for an instance by name */
55
89
  getBackendByInstance(instanceName: string, fleetDefault?: string): string;
56
90
  getChannelIdByInstance(instanceName: string): string | undefined;
57
- isClassicChannel(channelId: string): boolean;
58
- get(channelId: string): ClassicChannel | undefined;
91
+ /** The bot adapter that owns an instance's channel (for restart rebind). */
92
+ getAdapterIdByInstance(instanceName: string): string | undefined;
93
+ /**
94
+ * Resolve the instance a given bot should route to in a channel. Returns
95
+ * undefined if this adapter has no agent here (e.g. a sibling same-guild bot
96
+ * that never ran /start) — callers must NOT fall back to another bot's agent.
97
+ */
98
+ getInstanceByChannel(channelId: string, adapterId?: string): string | undefined;
99
+ /** Instance name for a new registration, applying the primary-adapter naming rule. */
100
+ deriveInstanceName(channelName: string, channelId: string, adapterId?: string): string;
101
+ /** Whether ANY bot has an agent in this channel (adapter-independent). O(1). */
102
+ hasChannel(channelId: string): boolean;
103
+ /** Exact per-bot check. adapterId omitted matches only a legacy entry. */
104
+ isClassicChannel(channelId: string, adapterId?: string): boolean;
105
+ get(channelId: string, adapterId?: string): ClassicChannel | undefined;
59
106
  getAll(): ClassicChannel[];
60
- register(channelId: string, instanceName: string, channelName: string, userId: string): ClassicChannel;
61
- unregister(channelId: string): ClassicChannel | undefined;
107
+ register(channelId: string, adapterId: string | undefined, instanceName: string, channelName: string, userId: string): ClassicChannel;
108
+ unregister(channelId: string, adapterId?: string): ClassicChannel | undefined;
62
109
  static chatLogDir(instanceName: string): string;
63
110
  static logMessage(instanceName: string, username: string, text: string, timestamp: Date, replyToText?: string): void;
64
111
  /** Delete chat log files older than retentionDays. Dates parsed as local to avoid UTC off-by-one. */
@@ -6,10 +6,17 @@ import { sanitizeInstanceName } from "./topic-commands.js";
6
6
  const YAML_HEADER = `# ClassicBot Configuration
7
7
  # Available backends: claude-code, gemini-cli, codex, opencode, kiro-cli
8
8
  `;
9
- /** Derive instance name from channel name + last 4 digits of channelId */
10
- export function classicInstanceName(sanitizedName, channelId) {
9
+ /**
10
+ * Derive instance name from channel name + last 4 digits of channelId.
11
+ * When `adapterId` is given (a non-primary bot in the same channel), append a
12
+ * sanitized adapter suffix so two bots in one channel get distinct instance
13
+ * names (dirs / tmux windows / IPC). The primary bot passes `undefined` to keep
14
+ * the historical name — single-bot users see no change across the upgrade.
15
+ */
16
+ export function classicInstanceName(sanitizedName, channelId, adapterId) {
11
17
  const suffix = channelId.slice(-4);
12
- return `classic-${sanitizedName}-${suffix}`;
18
+ const base = `classic-${sanitizedName}-${suffix}`;
19
+ return adapterId ? `${base}-${sanitizeInstanceName(adapterId)}` : base;
13
20
  }
14
21
  /**
15
22
  * Manages classic bot channel lifecycle — register/unregister/persist.
@@ -19,16 +26,56 @@ export function classicInstanceName(sanitizedName, channelId) {
19
26
  export class ClassicChannelManager {
20
27
  dataDir;
21
28
  logger;
29
+ /** Keyed by compositeKey(channelId, adapterId) — see {@link ClassicChannel.adapterId}. */
22
30
  channels = new Map();
31
+ /** Distinct channelIds across all adapters — makes hasChannel() O(1) (hot path: every inbound). */
32
+ channelIds = new Set();
23
33
  defaults = {};
24
34
  configPath;
25
35
  lastMtime = 0;
36
+ /** The primary (channels[0]) adapter id. Legacy entries migrate to it; it also names without a suffix. */
37
+ primaryAdapterId;
26
38
  constructor(dataDir, logger) {
27
39
  this.dataDir = dataDir;
28
40
  this.logger = logger;
29
41
  this.configPath = join(dataDir, "classicBot.yaml");
30
42
  this.load();
31
43
  }
44
+ /**
45
+ * Record which adapter is primary. Migrates any legacy (adapterId-less)
46
+ * entries onto it and rewrites the file in the new format. Idempotent.
47
+ */
48
+ setPrimaryAdapterId(adapterId) {
49
+ if (this.primaryAdapterId === adapterId)
50
+ return;
51
+ this.primaryAdapterId = adapterId;
52
+ const hadLegacy = [...this.channels.values()].some(ch => ch.adapterId === undefined);
53
+ this.load(); // re-derive keys/names now that the primary id is known
54
+ if (hadLegacy)
55
+ this.save(); // persist the upgraded format once
56
+ }
57
+ /** Map key for a (channelId, adapterId) pair. adapterId-less = legacy entry (pre-migration). */
58
+ compositeKey(channelId, adapterId) {
59
+ return adapterId ? `${channelId}#${adapterId}` : channelId;
60
+ }
61
+ /** Rebuild the channelId presence set from the entry map (call after any mutation). */
62
+ rebuildChannelIds() {
63
+ this.channelIds = new Set([...this.channels.values()].map(ch => ch.channelId));
64
+ }
65
+ /**
66
+ * Resolve the entry for a channel as seen by a specific bot. Exact
67
+ * (channelId, adapterId) match wins; the primary adapter also matches a
68
+ * not-yet-migrated legacy entry as a defensive fallback.
69
+ */
70
+ find(channelId, adapterId) {
71
+ const exact = this.channels.get(this.compositeKey(channelId, adapterId));
72
+ if (exact)
73
+ return exact;
74
+ if (adapterId && adapterId === this.primaryAdapterId) {
75
+ return this.channels.get(this.compositeKey(channelId, undefined));
76
+ }
77
+ return undefined;
78
+ }
32
79
  load() {
33
80
  if (!existsSync(this.configPath))
34
81
  return;
@@ -39,12 +86,19 @@ export class ClassicChannelManager {
39
86
  this.defaults = raw.defaults ?? {};
40
87
  this.channels.clear();
41
88
  if (raw.channels) {
42
- for (const [channelId, val] of Object.entries(raw.channels)) {
89
+ for (const [key, val] of Object.entries(raw.channels)) {
90
+ // Old format: key IS the channelId, no adapterId/instanceName fields.
91
+ const channelId = val.channelId ?? key;
92
+ const adapterId = val.adapterId ?? this.primaryAdapterId; // migrate legacy → primary
43
93
  const name = val.name ?? channelId;
44
- this.channels.set(channelId, {
94
+ // Non-primary adapters carry a suffix; primary/legacy keep the historical name.
95
+ const suffixAdapter = adapterId && adapterId !== this.primaryAdapterId ? adapterId : undefined;
96
+ const instanceName = val.instanceName ?? classicInstanceName(sanitizeInstanceName(name), channelId, suffixAdapter);
97
+ this.channels.set(this.compositeKey(channelId, adapterId), {
45
98
  channelId,
99
+ adapterId,
46
100
  name,
47
- instanceName: classicInstanceName(sanitizeInstanceName(name), channelId),
101
+ instanceName,
48
102
  backend: val.backend,
49
103
  model: val.model,
50
104
  collab: val.collab,
@@ -55,6 +109,7 @@ export class ClassicChannelManager {
55
109
  });
56
110
  }
57
111
  }
112
+ this.rebuildChannelIds();
58
113
  this.lastMtime = statSync(this.configPath).mtimeMs;
59
114
  this.logger.info({ count: this.channels.size }, "Loaded classic channels");
60
115
  }
@@ -66,7 +121,15 @@ export class ClassicChannelManager {
66
121
  mkdirSync(this.dataDir, { recursive: true });
67
122
  const obj = { defaults: this.defaults, channels: {} };
68
123
  for (const ch of this.channels.values()) {
69
- const entry = { name: ch.name, createdBy: ch.createdBy, createdAt: ch.createdAt };
124
+ const entry = {
125
+ channelId: ch.channelId,
126
+ instanceName: ch.instanceName,
127
+ name: ch.name,
128
+ createdBy: ch.createdBy,
129
+ createdAt: ch.createdAt,
130
+ };
131
+ if (ch.adapterId)
132
+ entry.adapterId = ch.adapterId;
70
133
  if (ch.backend)
71
134
  entry.backend = ch.backend;
72
135
  if (ch.model)
@@ -77,7 +140,7 @@ export class ClassicChannelManager {
77
140
  entry.collab = ch.collab;
78
141
  if (ch.preTaskCommand)
79
142
  entry.pre_task_command = ch.preTaskCommand;
80
- obj.channels[ch.channelId] = entry;
143
+ obj.channels[this.compositeKey(ch.channelId, ch.adapterId)] = entry;
81
144
  }
82
145
  writeFileSync(this.configPath, YAML_HEADER + yaml.dump(obj, { lineWidth: -1 }));
83
146
  this.lastMtime = existsSync(this.configPath) ? statSync(this.configPath).mtimeMs : 0;
@@ -121,23 +184,23 @@ export class ClassicChannelManager {
121
184
  return !!list && list.length > 0 && list.includes(userId);
122
185
  }
123
186
  /** Toggle collab mode for a channel. Returns new state. */
124
- toggleCollab(channelId) {
125
- const ch = this.channels.get(channelId);
187
+ toggleCollab(channelId, adapterId) {
188
+ const ch = this.find(channelId, adapterId);
126
189
  if (!ch)
127
190
  return false;
128
191
  ch.collab = !ch.collab;
129
192
  this.save();
130
193
  return ch.collab;
131
194
  }
132
- isCollab(channelId) {
133
- return this.channels.get(channelId)?.collab ?? false;
195
+ isCollab(channelId, adapterId) {
196
+ return this.find(channelId, adapterId)?.collab ?? false;
134
197
  }
135
- getPreTaskCommand(channelId) {
136
- return this.channels.get(channelId)?.preTaskCommand;
198
+ getPreTaskCommand(channelId, adapterId) {
199
+ return this.find(channelId, adapterId)?.preTaskCommand;
137
200
  }
138
201
  /** Context lines fallback: per-channel → defaults → 5 */
139
- getContextLines(channelId) {
140
- const ch = this.channels.get(channelId);
202
+ getContextLines(channelId, adapterId) {
203
+ const ch = this.find(channelId, adapterId);
141
204
  if (ch?.contextLines != null)
142
205
  return ch.contextLines;
143
206
  if (this.defaults.context_lines != null)
@@ -145,13 +208,13 @@ export class ClassicChannelManager {
145
208
  return 5;
146
209
  }
147
210
  /** Backend fallback: per-channel → classic defaults → fleetDefault → "claude-code" */
148
- getBackend(channelId, fleetDefault) {
149
- const ch = this.channels.get(channelId);
211
+ getBackend(channelId, adapterId, fleetDefault) {
212
+ const ch = this.find(channelId, adapterId);
150
213
  return ch?.backend || this.defaults.backend || fleetDefault || "claude-code";
151
214
  }
152
215
  /** Get model for a channel — channel override → defaults → fleet default */
153
- getModel(channelId, fleetDefault) {
154
- const ch = this.channels.get(channelId);
216
+ getModel(channelId, adapterId, fleetDefault) {
217
+ const ch = this.find(channelId, adapterId);
155
218
  return ch?.model || this.defaults.model || fleetDefault;
156
219
  }
157
220
  /** Get backend for an instance by name */
@@ -169,23 +232,51 @@ export class ClassicChannelManager {
169
232
  }
170
233
  return undefined;
171
234
  }
172
- isClassicChannel(channelId) { return this.channels.has(channelId); }
173
- get(channelId) { return this.channels.get(channelId); }
235
+ /** The bot adapter that owns an instance's channel (for restart rebind). */
236
+ getAdapterIdByInstance(instanceName) {
237
+ for (const ch of this.channels.values()) {
238
+ if (ch.instanceName === instanceName)
239
+ return ch.adapterId;
240
+ }
241
+ return undefined;
242
+ }
243
+ /**
244
+ * Resolve the instance a given bot should route to in a channel. Returns
245
+ * undefined if this adapter has no agent here (e.g. a sibling same-guild bot
246
+ * that never ran /start) — callers must NOT fall back to another bot's agent.
247
+ */
248
+ getInstanceByChannel(channelId, adapterId) {
249
+ return this.find(channelId, adapterId)?.instanceName;
250
+ }
251
+ /** Instance name for a new registration, applying the primary-adapter naming rule. */
252
+ deriveInstanceName(channelName, channelId, adapterId) {
253
+ const suffixAdapter = adapterId && adapterId !== this.primaryAdapterId ? adapterId : undefined;
254
+ return classicInstanceName(sanitizeInstanceName(channelName || channelId), channelId, suffixAdapter);
255
+ }
256
+ /** Whether ANY bot has an agent in this channel (adapter-independent). O(1). */
257
+ hasChannel(channelId) {
258
+ return this.channelIds.has(channelId);
259
+ }
260
+ /** Exact per-bot check. adapterId omitted matches only a legacy entry. */
261
+ isClassicChannel(channelId, adapterId) { return !!this.find(channelId, adapterId); }
262
+ get(channelId, adapterId) { return this.find(channelId, adapterId); }
174
263
  getAll() { return [...this.channels.values()]; }
175
- register(channelId, instanceName, channelName, userId) {
176
- const ch = { channelId, name: channelName, instanceName, createdAt: new Date().toISOString(), createdBy: userId };
177
- this.channels.set(channelId, ch);
264
+ register(channelId, adapterId, instanceName, channelName, userId) {
265
+ const ch = { channelId, adapterId, name: channelName, instanceName, createdAt: new Date().toISOString(), createdBy: userId };
266
+ this.channels.set(this.compositeKey(channelId, adapterId), ch);
267
+ this.rebuildChannelIds();
178
268
  this.save();
179
- this.logger.info({ channelId, instanceName }, "Registered classic channel");
269
+ this.logger.info({ channelId, adapterId, instanceName }, "Registered classic channel");
180
270
  return ch;
181
271
  }
182
- unregister(channelId) {
183
- const ch = this.channels.get(channelId);
272
+ unregister(channelId, adapterId) {
273
+ const ch = this.find(channelId, adapterId);
184
274
  if (!ch)
185
275
  return undefined;
186
- this.channels.delete(channelId);
276
+ this.channels.delete(this.compositeKey(ch.channelId, ch.adapterId));
277
+ this.rebuildChannelIds();
187
278
  this.save();
188
- this.logger.info({ channelId, instanceName: ch.instanceName }, "Unregistered classic channel");
279
+ this.logger.info({ channelId, adapterId: ch.adapterId, instanceName: ch.instanceName }, "Unregistered classic channel");
189
280
  return ch;
190
281
  }
191
282
  static chatLogDir(instanceName) {
@@ -1 +1 @@
1
- {"version":3,"file":"classic-channel-manager.js","sourceRoot":"","sources":["../src/classic-channel-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"classic-channel-manager.js","sourceRoot":"","sources":["../src/classic-channel-manager.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -53,6 +53,11 @@ fleet
53
53
  .description("Start fleet or specific instance")
54
54
  .argument("[instance]", "Specific instance to start")
55
55
  .action(async (instance) => {
56
+ // Root running fleet = sandbox environment (e.g. Docker, WSL root service)
57
+ // Set IS_SANDBOX so child processes (claude-code) don't refuse to run
58
+ if (process.getuid?.() === 0 && !process.env.IS_SANDBOX) {
59
+ process.env.IS_SANDBOX = "1";
60
+ }
56
61
  if (instance) {
57
62
  // If fleet daemon is already running, delegate via HTTP API
58
63
  const { loadFleetConfig } = await import("./config.js");
@@ -1373,6 +1378,10 @@ program
1373
1378
  console.log("Service restarted (system).");
1374
1379
  return;
1375
1380
  }
1381
+ // Service exists → systemd will auto-retry via Restart=on-failure. Don't spawn fallback.
1382
+ console.log(" ⚠ systemd restart reported failure, but the service exists — systemd will auto-retry.");
1383
+ console.log(" Check: systemctl status agend");
1384
+ return;
1376
1385
  }
1377
1386
  // 2. User-level systemd service "com.agend.fleet"
1378
1387
  if (plat !== "macos" && isActive("systemctl --user is-active com.agend.fleet 2>/dev/null")) {
@@ -1385,6 +1394,10 @@ program
1385
1394
  console.log("Service restarted (user).");
1386
1395
  return;
1387
1396
  }
1397
+ // Service exists → systemd will auto-retry. Don't fall through to detached spawn.
1398
+ console.log(" ⚠ systemd user service restart reported failure, but the service exists — systemd will auto-retry.");
1399
+ console.log(" Check: systemctl --user status com.agend.fleet");
1400
+ return;
1388
1401
  }
1389
1402
  // 3. launchd (macOS)
1390
1403
  if (plat === "macos") {
@@ -1490,6 +1503,71 @@ program
1490
1503
  const child = spawn(cmd, [htmlPath], { detached: true, stdio: "ignore" });
1491
1504
  child.unref();
1492
1505
  });
1506
+ program
1507
+ .command("view")
1508
+ .description("Open the read-only View dashboard in your browser")
1509
+ .action(async () => {
1510
+ // The View dashboard is open (read-only, no token) — open it directly.
1511
+ const { loadFleetConfig } = await import("./config.js");
1512
+ const fleet = loadFleetConfig(FLEET_CONFIG_PATH);
1513
+ const port = fleet.health_port ?? 19280;
1514
+ const url = `http://localhost:${port}/view`;
1515
+ console.log(`Opening ${url}`);
1516
+ const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "explorer" : "xdg-open";
1517
+ const child = spawn(cmd, [url], { detached: true, stdio: "ignore" });
1518
+ child.unref();
1519
+ });
1520
+ program
1521
+ .command("validate")
1522
+ .description("Validate fleet.yaml and classicBot.yaml")
1523
+ .action(async () => {
1524
+ const { validateFleetConfig, validateClassicBotConfig } = await import("./config-validator.js");
1525
+ const yaml = (await import("js-yaml")).default;
1526
+ const red = (s) => `\x1b[31m${s}\x1b[0m`;
1527
+ const green = (s) => `\x1b[32m${s}\x1b[0m`;
1528
+ const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
1529
+ const dim = (s) => `\x1b[90m${s}\x1b[0m`;
1530
+ let totalErrors = 0, totalWarnings = 0;
1531
+ const check = (label, path, validator) => {
1532
+ console.log(`\n${label} ${dim(path)}`);
1533
+ if (!existsSync(path)) {
1534
+ console.log(` ${dim("(not found — skipped)")}`);
1535
+ return;
1536
+ }
1537
+ let parsed;
1538
+ try {
1539
+ parsed = yaml.load(readFileSync(path, "utf-8"));
1540
+ }
1541
+ catch (e) {
1542
+ totalErrors++;
1543
+ console.log(` ${red("✗")} YAML parse error: ${e.message}`);
1544
+ return;
1545
+ }
1546
+ const r = validator(parsed);
1547
+ for (const err of r.errors) {
1548
+ totalErrors++;
1549
+ console.log(` ${red("✗")} ${err.path ? dim(err.path + ": ") : ""}${err.message}`);
1550
+ }
1551
+ for (const w of r.warnings) {
1552
+ totalWarnings++;
1553
+ console.log(` ${yellow("⚠")} ${w.path ? dim(w.path + ": ") : ""}${w.message}`);
1554
+ }
1555
+ if (r.errors.length === 0 && r.warnings.length === 0)
1556
+ console.log(` ${green("✓ OK")}`);
1557
+ };
1558
+ check("Fleet", FLEET_CONFIG_PATH, validateFleetConfig);
1559
+ check("ClassicBot", join(DATA_DIR, "classicBot.yaml"), validateClassicBotConfig);
1560
+ console.log();
1561
+ if (totalErrors > 0) {
1562
+ console.log(red(`${totalErrors} error(s)`) + (totalWarnings ? `, ${yellow(`${totalWarnings} warning(s)`)}` : ""));
1563
+ process.exit(1);
1564
+ }
1565
+ if (totalWarnings > 0) {
1566
+ console.log(yellow(`${totalWarnings} warning(s)`));
1567
+ return;
1568
+ }
1569
+ console.log(green("✓ All configs valid"));
1570
+ });
1493
1571
  // === Schedule commands ===
1494
1572
  const schedule = program.command("schedule").description("Manage scheduled tasks");
1495
1573
  schedule
@@ -1749,7 +1827,13 @@ async function resolveInstance(query, config) {
1749
1827
  const yamlMod = (await import("js-yaml")).default;
1750
1828
  const classic = yamlMod.load(readFileSync(classicPath, "utf-8"));
1751
1829
  if (classic?.channels) {
1752
- for (const [channelId, val] of Object.entries(classic.channels)) {
1830
+ for (const [key, val] of Object.entries(classic.channels)) {
1831
+ // New format persists instanceName; old format keyed by channelId.
1832
+ if (val.instanceName) {
1833
+ names.push(val.instanceName);
1834
+ continue;
1835
+ }
1836
+ const channelId = val.channelId ?? key;
1753
1837
  const chName = (val.name ?? channelId).toLowerCase().replace(/[^\p{L}\d-]/gu, "-").replace(/-+/g, "-").replace(/^-|-$/g, "") || "project";
1754
1838
  names.push(`classic-${chName}-${channelId.slice(-4)}`);
1755
1839
  }
@@ -1868,16 +1952,20 @@ async function lsAction(opts) {
1868
1952
  const allNames = [...names];
1869
1953
  const classicNames = new Set();
1870
1954
  const classicBackends = new Map();
1955
+ const classicChannelIdByName = new Map();
1871
1956
  if (classicConfig?.channels) {
1872
1957
  const classicDefault = classicConfig.defaults?.backend || config.defaults?.backend || "claude-code";
1873
- for (const [channelId, val] of Object.entries(classicConfig.channels)) {
1958
+ for (const [key, val] of Object.entries(classicConfig.channels)) {
1959
+ // New format stores channelId + instanceName explicitly; old format used
1960
+ // the map key as the channelId and had no adapter suffix.
1961
+ const channelId = val.channelId ?? key;
1874
1962
  const chName = (val.name ?? channelId).toLowerCase().replace(/[^\p{L}\d-]/gu, "-").replace(/-+/g, "-").replace(/^-|-$/g, "") || "project";
1875
- const suffix = channelId.slice(-4);
1876
- const iName = `classic-${chName}-${suffix}`;
1963
+ const iName = val.instanceName ?? `classic-${chName}-${channelId.slice(-4)}`;
1877
1964
  if (!allNames.includes(iName)) {
1878
1965
  allNames.push(iName);
1879
1966
  classicNames.add(iName);
1880
1967
  classicBackends.set(iName, val.backend || classicDefault);
1968
+ classicChannelIdByName.set(iName, channelId);
1881
1969
  }
1882
1970
  }
1883
1971
  }
@@ -1915,9 +2003,8 @@ async function lsAction(opts) {
1915
2003
  if (singleSource)
1916
2004
  return singleSource;
1917
2005
  if (classicNames.has(name)) {
1918
- // Match channelId by suffix: Telegram IDs are short/negative, Discord snowflakes are 17+ digits
1919
- const suffix = name.slice(-4);
1920
- const matchedChId = Object.keys(classicConfig?.channels ?? {}).find(id => id.slice(-4) === suffix) ?? "";
2006
+ // Telegram IDs are short/negative, Discord snowflakes are 17+ digits.
2007
+ const matchedChId = classicChannelIdByName.get(name) ?? "";
1921
2008
  return matchedChId.startsWith("-") || matchedChId.length < 17 ? "TG" : "DC";
1922
2009
  }
1923
2010
  const topicId = String(inst?.topic_id ?? "");