@songsid/agend 2.1.12-beta.3 → 2.1.12-beta.5

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 (110) hide show
  1. package/README.md +54 -8
  2. package/README.zh-TW.md +104 -11
  3. package/dist/agent-endpoint.d.ts +2 -0
  4. package/dist/agent-endpoint.js +38 -29
  5. package/dist/agent-endpoint.js.map +1 -1
  6. package/dist/backend/factory.js +5 -5
  7. package/dist/backend/factory.js.map +1 -1
  8. package/dist/backend/index.d.ts +0 -1
  9. package/dist/backend/index.js +0 -1
  10. package/dist/backend/index.js.map +1 -1
  11. package/dist/backend/kiro.d.ts +10 -1
  12. package/dist/backend/kiro.js +13 -0
  13. package/dist/backend/kiro.js.map +1 -1
  14. package/dist/backend/mock.d.ts +1 -1
  15. package/dist/backend/mock.js +1 -1
  16. package/dist/backend/muse.d.ts +14 -0
  17. package/dist/backend/muse.js +60 -11
  18. package/dist/backend/muse.js.map +1 -1
  19. package/dist/backend/removed.d.ts +12 -0
  20. package/dist/backend/removed.js +18 -0
  21. package/dist/backend/removed.js.map +1 -0
  22. package/dist/backend/session-signals.js +5 -10
  23. package/dist/backend/session-signals.js.map +1 -1
  24. package/dist/backend/types.d.ts +1 -1
  25. package/dist/backend/types.js +0 -1
  26. package/dist/backend/types.js.map +1 -1
  27. package/dist/channel/adapters/discord.js +9 -0
  28. package/dist/channel/adapters/discord.js.map +1 -1
  29. package/dist/channel/adapters/telegram.d.ts +14 -8
  30. package/dist/channel/adapters/telegram.js +80 -26
  31. package/dist/channel/adapters/telegram.js.map +1 -1
  32. package/dist/channel/mcp-tools.js +2 -2
  33. package/dist/channel/mcp-tools.js.map +1 -1
  34. package/dist/classic-channel-manager.js +2 -2
  35. package/dist/classic-channel-manager.js.map +1 -1
  36. package/dist/cli.js +27 -53
  37. package/dist/cli.js.map +1 -1
  38. package/dist/command-table.d.ts +1 -1
  39. package/dist/command-table.js +4 -2
  40. package/dist/command-table.js.map +1 -1
  41. package/dist/config-validator.js +82 -10
  42. package/dist/config-validator.js.map +1 -1
  43. package/dist/config.js +7 -5
  44. package/dist/config.js.map +1 -1
  45. package/dist/context-guardian.d.ts +1 -1
  46. package/dist/context-guardian.js +1 -1
  47. package/dist/cross-instance-notice.d.ts +39 -0
  48. package/dist/cross-instance-notice.js +84 -0
  49. package/dist/cross-instance-notice.js.map +1 -0
  50. package/dist/daemon.d.ts +6 -0
  51. package/dist/daemon.js +54 -42
  52. package/dist/daemon.js.map +1 -1
  53. package/dist/daily-summary.js +0 -3
  54. package/dist/daily-summary.js.map +1 -1
  55. package/dist/fleet-manager.d.ts +16 -3
  56. package/dist/fleet-manager.js +110 -53
  57. package/dist/fleet-manager.js.map +1 -1
  58. package/dist/general-knowledge/skills/fleet-config/SKILL.md +1 -1
  59. package/dist/instance-config-impact.js +3 -0
  60. package/dist/instance-config-impact.js.map +1 -1
  61. package/dist/instance-lifecycle.d.ts +9 -1
  62. package/dist/instance-lifecycle.js +66 -7
  63. package/dist/instance-lifecycle.js.map +1 -1
  64. package/dist/locale.js +28 -2
  65. package/dist/locale.js.map +1 -1
  66. package/dist/memory-pressure.d.ts +8 -2
  67. package/dist/memory-pressure.js +10 -4
  68. package/dist/memory-pressure.js.map +1 -1
  69. package/dist/outbound-handlers.js +36 -23
  70. package/dist/outbound-handlers.js.map +1 -1
  71. package/dist/outbound-schemas.d.ts +0 -1
  72. package/dist/outbound-schemas.js +4 -4
  73. package/dist/outbound-schemas.js.map +1 -1
  74. package/dist/prompt-file-ref.d.ts +42 -0
  75. package/dist/prompt-file-ref.js +118 -0
  76. package/dist/prompt-file-ref.js.map +1 -0
  77. package/dist/reply-dedup.d.ts +5 -0
  78. package/dist/reply-dedup.js +9 -0
  79. package/dist/reply-dedup.js.map +1 -1
  80. package/dist/settings-api.js +5 -1
  81. package/dist/settings-api.js.map +1 -1
  82. package/dist/setup-wizard.js +0 -4
  83. package/dist/setup-wizard.js.map +1 -1
  84. package/dist/spawn-gate.js +4 -3
  85. package/dist/spawn-gate.js.map +1 -1
  86. package/dist/target-queue-worker.d.ts +1 -1
  87. package/dist/topic-commands.d.ts +64 -5
  88. package/dist/topic-commands.js +172 -14
  89. package/dist/topic-commands.js.map +1 -1
  90. package/dist/transcript-jsonl.d.ts +12 -0
  91. package/dist/transcript-jsonl.js +37 -0
  92. package/dist/transcript-jsonl.js.map +1 -1
  93. package/dist/transcript-monitor.js +10 -7
  94. package/dist/transcript-monitor.js.map +1 -1
  95. package/dist/transcript-sources.d.ts +1 -1
  96. package/dist/transcript-sources.js +29 -11
  97. package/dist/transcript-sources.js.map +1 -1
  98. package/dist/types.d.ts +13 -4
  99. package/dist/ui/dashboard.html +3 -3
  100. package/dist/ui/settings.html +58 -16
  101. package/dist/update-check.d.ts +15 -6
  102. package/dist/update-check.js +20 -7
  103. package/dist/update-check.js.map +1 -1
  104. package/dist/wake-coordinator.js +1 -1
  105. package/dist/web-api.js +1 -2
  106. package/dist/web-api.js.map +1 -1
  107. package/package.json +1 -1
  108. package/dist/backend/gemini-cli.d.ts +0 -20
  109. package/dist/backend/gemini-cli.js +0 -169
  110. package/dist/backend/gemini-cli.js.map +0 -1
@@ -21,7 +21,7 @@ export class SpawnGate {
21
21
  memoryPressure;
22
22
  stopMemoryUpdates;
23
23
  onMemoryUpdate = (snapshot) => {
24
- if (!this.memoryPressure.allowsUnknown(snapshot))
24
+ if (!this.memoryPressure.advisoryOnly())
25
25
  return;
26
26
  this.pressureHeld = false;
27
27
  this.pressureRetryMs = 5_000;
@@ -84,7 +84,8 @@ export class SpawnGate {
84
84
  if (this.nestedQueue.length === 0 && index < 0)
85
85
  return;
86
86
  // Explicit zero preserves the existing deterministic test/embedding opt-out.
87
- const sample = this.options.lowMemoryBytes === 0 ? null : this.memoryPressure.sampleForAdmission();
87
+ // macOS memory is advisory (#1256): admission neither waits for a sample nor reads one.
88
+ const sample = this.options.lowMemoryBytes === 0 || this.memoryPressure.advisoryOnly() ? null : this.memoryPressure.sampleForAdmission();
88
89
  if (sample instanceof Promise) {
89
90
  this.awaitingMemory = true;
90
91
  void sample.finally(() => {
@@ -94,7 +95,7 @@ export class SpawnGate {
94
95
  });
95
96
  return;
96
97
  }
97
- let pressure = sample === null || this.memoryPressure.allowsUnknown(sample) ? "normal" : sample.level;
98
+ let pressure = sample === null ? "normal" : sample.level;
98
99
  if (this.stopped)
99
100
  return;
100
101
  if (pressure === "critical") {
@@ -1 +1 @@
1
- {"version":3,"file":"spawn-gate.js","sourceRoot":"","sources":["../src/spawn-gate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"spawn-gate.js","sourceRoot":"","sources":["../src/spawn-gate.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Phase 2c (docs/design/phase2-submit-contract.md §1.1, §1.5, §4 2c): the
2
+ * Phase 2c (docs/design/929-durable-outbox.md §4): the
3
3
  * per-target owner of a durable delivery lane when `delivery_worker: on`.
4
4
  *
5
5
  * ENSURE_AWAKE belongs to the WakeCoordinator (2b); this worker only runs
@@ -10,6 +10,61 @@ type ExecutionFleetContext = FleetContext & {
10
10
  };
11
11
  /** Sanitize a directory name into a valid instance name. Keeps Unicode letters (incl. CJK). */
12
12
  export declare function sanitizeInstanceName(name: string): string;
13
+ /** Digits of the topic id kept in a fresh instance-name suffix; lengthened on collision. */
14
+ export declare const INSTANCE_NAME_SUFFIX_DIGITS = 6;
15
+ /**
16
+ * Build `<base>-t<last N digits of topicId>` (#1301): when the full-id form
17
+ * is free, N starts at 6 and lengthens on collision, up to the full id.
18
+ * `exists` must cover fleet.yaml keys and instance dirs (a stale tmux window
19
+ * with no config or dir is an orphan that startup cleanup kills — the
20
+ * `-t<digits>` shape is what its matcher recognises). Every name this
21
+ * allocator emits matches the orphan predicate (`isOrphanInstanceWindowName`),
22
+ * so a deleted instance's leftover window is always reaped.
23
+ *
24
+ * A taken candidate is reused as-is ONLY when `isSameTopic` proves the
25
+ * existing entry belongs to this same topic (retry/rebind of a partially
26
+ * created instance keeps the deterministic old path instead of opening a
27
+ * second entry) — this applies to the full form and to every short or
28
+ * lengthened form, so a rebind never allocates a duplicate entry for one
29
+ * topic (#1305 P2-2). A name owned by a *different* topic — including a
30
+ * short suffix that happens to equal another topic's full id (e.g. Discord
31
+ * `blog-t123456` vs Telegram topic `123456`) — is never reused. When even
32
+ * the full-id form is taken by a different topic, allocation refuses with an
33
+ * error (use a different `topic_name`) instead of inventing a non-`-t<digits>`
34
+ * name, so one topic's bind can never overwrite another topic's
35
+ * `working_directory`/`topic_id` (#1305 P1). When `isSameTopic` is omitted
36
+ * the legacy rule applies (a taken full form is reused, taken short forms
37
+ * are skipped); production callers always pass it. A dir-only collision (no
38
+ * config) can never prove same-topic, so callers must report it as a
39
+ * different topic.
40
+ */
41
+ export declare function uniqueInstanceName(base: string, topicId: number | string, exists: (name: string) => boolean, isSameTopic?: (name: string) => boolean): string;
42
+ /**
43
+ * Base user-facing label for one instance name (#1301): an explicit
44
+ * display_name wins; otherwise only a full snowflake-length `-t<digits>`
45
+ * suffix (19+ digits, the pre-2.1.12 form) is shortened to its last 6,
46
+ * keeping the `-t` shape. Allocator-lengthened suffixes (7–18 digits, #1301
47
+ * collision path) are shown whole. This is only the *base* label — two
48
+ * legacy 19-digit names sharing tail6 still shorten identically, so every
49
+ * fleet renderer must go through `assignDisplayLabels`, which disambiguates
50
+ * against the whole fleet (#1305 P2-1). Agent-facing uses (the `[from:…]`
51
+ * header, logs, lookups) keep the real name — agents address by it.
52
+ */
53
+ export declare function displayInstanceName(name: string, displayName?: string | null): string;
54
+ /**
55
+ * Fleet-wide effective display labels (#1305 P2-1). The base label is
56
+ * shortened only while it stays unique across every entry's effective label
57
+ * — legacy (19-digit), new short, lengthened, and explicit `display_name`
58
+ * entries all compete in one namespace. On collision a `-t<digits>` name
59
+ * lengthens its shown tail just enough to be unique; an explicit
60
+ * `display_name` collision (or an exhausted digit tail) is qualified with the
61
+ * real name. Lookup names are untouched — only the shown label changes.
62
+ * Entries are processed in name order so the result is deterministic.
63
+ */
64
+ export declare function assignDisplayLabels(entries: {
65
+ name: string;
66
+ displayName?: string | null;
67
+ }[]): Map<string, string>;
13
68
  /** Allowed filename for /save and /load (no path separators, no shell/inject chars). */
14
69
  export declare const SAVE_FILENAME_RE: RegExp;
15
70
  /** Backends with a native side-question command that does not steer the active turn. */
@@ -210,11 +265,13 @@ export declare class TopicCommands {
210
265
  private handleLoginCommand;
211
266
  private handleTipsCommand;
212
267
  private handleStatusCommand;
213
- /** Compact label for status/sysinfo tables: prefer display_name, else strip the
214
- * `-t<topicId>` suffix (e.g. doupo-server-t1503381916525793300 → doupo-server).
215
- * Keeps rows short so a large fleet's table fits Discord's 2000-char limit. The
216
- * FULL name is still used for all lookups — only the displayed label changes. */
217
- private shortInstanceName;
268
+ /** Fleet-wide display labels for status/sysinfo tables (#1305 P2-1):
269
+ * display_name first, else a 19+-digit `-t<digits>` suffix shortened to its
270
+ * last 6 — lengthened only while the label stays unique across every
271
+ * instance, so same-tail legacy entries remain distinguishable. Keeps rows
272
+ * short so a large fleet's table fits Discord's 2000-char limit. The FULL
273
+ * name is still used for all lookups — only the displayed label changes. */
274
+ private displayLabels;
218
275
  /** Get fleet status as markdown text (shared by TG + DC) */
219
276
  getStatusText(): Promise<string>;
220
277
  private handleSysInfoCommand;
@@ -240,6 +297,8 @@ export declare class TopicCommands {
240
297
  backendCliVersions?: BackendCliVersionSnapshot;
241
298
  }): string;
242
299
  private handleUpdateCommand;
300
+ /** #1302: `/visibility [full|summary|hidden]` in the General topic. */
301
+ private handleVisibilityCommand;
243
302
  private handleDoctorCommand;
244
303
  /** Reply with redirect when message arrives in an unbound topic */
245
304
  handleUnboundTopic(msg: InboundMessage): Promise<void>;
@@ -11,6 +11,7 @@ import { truncateDisplay, MODEL_DISPLAY_WIDTH_MAX } from "./ls-rows.js";
11
11
  import { getTmuxSocketName, getTmuxSessionName } from "./paths.js";
12
12
  import { t, getLocale } from "./locale.js";
13
13
  import { telegramMenu } from "./command-table.js";
14
+ import { runVisibilityCommand } from "./cross-instance-notice.js";
14
15
  import { clampContextPercent, parseContextPercent, parseTokenContextRatio, } from "./context-percent.js";
15
16
  import { isGeneralInstance } from "./general-instance.js";
16
17
  import { backendSupportsSteer } from "./steer-capability.js";
@@ -25,6 +26,130 @@ export function sanitizeInstanceName(name) {
25
26
  const sanitized = name.toLowerCase().replace(/[^\p{L}\d-]/gu, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
26
27
  return sanitized || "project";
27
28
  }
29
+ /** Digits of the topic id kept in a fresh instance-name suffix; lengthened on collision. */
30
+ export const INSTANCE_NAME_SUFFIX_DIGITS = 6;
31
+ /**
32
+ * Build `<base>-t<last N digits of topicId>` (#1301): when the full-id form
33
+ * is free, N starts at 6 and lengthens on collision, up to the full id.
34
+ * `exists` must cover fleet.yaml keys and instance dirs (a stale tmux window
35
+ * with no config or dir is an orphan that startup cleanup kills — the
36
+ * `-t<digits>` shape is what its matcher recognises). Every name this
37
+ * allocator emits matches the orphan predicate (`isOrphanInstanceWindowName`),
38
+ * so a deleted instance's leftover window is always reaped.
39
+ *
40
+ * A taken candidate is reused as-is ONLY when `isSameTopic` proves the
41
+ * existing entry belongs to this same topic (retry/rebind of a partially
42
+ * created instance keeps the deterministic old path instead of opening a
43
+ * second entry) — this applies to the full form and to every short or
44
+ * lengthened form, so a rebind never allocates a duplicate entry for one
45
+ * topic (#1305 P2-2). A name owned by a *different* topic — including a
46
+ * short suffix that happens to equal another topic's full id (e.g. Discord
47
+ * `blog-t123456` vs Telegram topic `123456`) — is never reused. When even
48
+ * the full-id form is taken by a different topic, allocation refuses with an
49
+ * error (use a different `topic_name`) instead of inventing a non-`-t<digits>`
50
+ * name, so one topic's bind can never overwrite another topic's
51
+ * `working_directory`/`topic_id` (#1305 P1). When `isSameTopic` is omitted
52
+ * the legacy rule applies (a taken full form is reused, taken short forms
53
+ * are skipped); production callers always pass it. A dir-only collision (no
54
+ * config) can never prove same-topic, so callers must report it as a
55
+ * different topic.
56
+ */
57
+ export function uniqueInstanceName(base, topicId, exists, isSameTopic) {
58
+ const clean = sanitizeInstanceName(base);
59
+ const id = String(topicId);
60
+ const full = `${clean}-t${id}`;
61
+ const candidates = [];
62
+ for (let n = Math.min(INSTANCE_NAME_SUFFIX_DIGITS, id.length); n < id.length; n++) {
63
+ candidates.push(`${clean}-t${id.slice(-n)}`);
64
+ }
65
+ candidates.push(full);
66
+ // First pass: reuse any candidate already owned by this same topic
67
+ // (retry/rebind keeps the deterministic old path instead of opening a
68
+ // second entry). Every candidate is scanned before anything is allocated:
69
+ // a freed shorter form must not shadow a longer form this topic still owns.
70
+ // Without a proof function the legacy rule applies (a taken full form is
71
+ // reused, taken short forms are skipped).
72
+ for (const name of candidates) {
73
+ if (exists(name) && (isSameTopic?.(name) ?? name === full))
74
+ return name;
75
+ }
76
+ // Second pass: the first free candidate, short first.
77
+ for (const name of candidates) {
78
+ if (!exists(name))
79
+ return name;
80
+ }
81
+ // Even the full-id form is owned by a different topic: refuse. Callers
82
+ // surface this (handleCreate responds an error and rolls back the topic;
83
+ // bindAndStart throws), so creation fails closed with a clear hint.
84
+ throw new Error(`Instance name "${full}" is already used by a different topic; ` +
85
+ `use a different topic_name for topic "${id}".`);
86
+ }
87
+ /**
88
+ * Base user-facing label for one instance name (#1301): an explicit
89
+ * display_name wins; otherwise only a full snowflake-length `-t<digits>`
90
+ * suffix (19+ digits, the pre-2.1.12 form) is shortened to its last 6,
91
+ * keeping the `-t` shape. Allocator-lengthened suffixes (7–18 digits, #1301
92
+ * collision path) are shown whole. This is only the *base* label — two
93
+ * legacy 19-digit names sharing tail6 still shorten identically, so every
94
+ * fleet renderer must go through `assignDisplayLabels`, which disambiguates
95
+ * against the whole fleet (#1305 P2-1). Agent-facing uses (the `[from:…]`
96
+ * header, logs, lookups) keep the real name — agents address by it.
97
+ */
98
+ export function displayInstanceName(name, displayName) {
99
+ const dn = displayName?.trim();
100
+ if (dn)
101
+ return dn;
102
+ return name.replace(/-t(\d{19,})$/, (_, digits) => `-t${digits.slice(-6)}`);
103
+ }
104
+ /**
105
+ * Fleet-wide effective display labels (#1305 P2-1). The base label is
106
+ * shortened only while it stays unique across every entry's effective label
107
+ * — legacy (19-digit), new short, lengthened, and explicit `display_name`
108
+ * entries all compete in one namespace. On collision a `-t<digits>` name
109
+ * lengthens its shown tail just enough to be unique; an explicit
110
+ * `display_name` collision (or an exhausted digit tail) is qualified with the
111
+ * real name. Lookup names are untouched — only the shown label changes.
112
+ * Entries are processed in name order so the result is deterministic.
113
+ */
114
+ export function assignDisplayLabels(entries) {
115
+ const sorted = [...entries].sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));
116
+ const used = new Set();
117
+ const out = new Map();
118
+ for (const { name, displayName } of sorted) {
119
+ const explicit = displayName?.trim() || undefined;
120
+ let label = explicit ?? displayInstanceName(name);
121
+ if (used.has(label))
122
+ label = disambiguateLabel(name, explicit, label, used);
123
+ used.add(label);
124
+ out.set(name, label);
125
+ }
126
+ return out;
127
+ }
128
+ function disambiguateLabel(name, explicit, base, used) {
129
+ if (!explicit) {
130
+ const m = name.match(/^(.*-t)(\d+)$/);
131
+ if (m) {
132
+ const [, prefix, digits] = m;
133
+ const shown = digits.length >= 19 ? 6 : digits.length;
134
+ for (let len = shown + 1; len <= digits.length; len++) {
135
+ const candidate = `${prefix}${digits.slice(-len)}`;
136
+ if (!used.has(candidate))
137
+ return candidate;
138
+ }
139
+ }
140
+ }
141
+ // Every fallback is checked against the same namespace: real names are
142
+ // unique, but they are NOT unique against arbitrary display_name strings,
143
+ // so even the real-name-shaped fallback must be verified. The numbered
144
+ // loop always terminates (i is unbounded) and is deterministic for a
145
+ // given fleet, since entries are processed in name order.
146
+ const short = displayInstanceName(name);
147
+ let candidate = `${base} (${short})`;
148
+ for (let i = 2; used.has(candidate); i++) {
149
+ candidate = `${base} (${short}) (#${i})`;
150
+ }
151
+ return candidate;
152
+ }
28
153
  /** Allowed filename for /save and /load (no path separators, no shell/inject chars). */
29
154
  export const SAVE_FILENAME_RE = /^[\w.-]+$/;
30
155
  /** Backends with a native side-question command that does not steer the active turn. */
@@ -58,7 +183,7 @@ export function parsePauseWakeCommand(text) {
58
183
  * The in-session compact/context-reset command for a backend NAME (the fleet
59
184
  * process routes /compact via IPC and only has the backend string, not a
60
185
  * CliBackend instance). Keep in sync with each backend's getCompactCommand().
61
- * Most CLIs (claude-code, kiro-cli, codex, opencode, gemini-cli) use "/compact".
186
+ * Most CLIs (claude-code, kiro-cli, codex, opencode) use "/compact".
62
187
  * Antigravity (agy) has NO summarizing compact — its only manual context-reset
63
188
  * is "/clear" (a full reset; it also auto-summarizes at a token threshold).
64
189
  */
@@ -166,7 +291,6 @@ export function clearCommandForBackend(backend) {
166
291
  return "/clear";
167
292
  case "grok":
168
293
  return "/new";
169
- case "gemini-cli":
170
294
  default:
171
295
  return null;
172
296
  }
@@ -393,6 +517,11 @@ export class TopicCommands {
393
517
  await this.handleDashboardCommand(msg);
394
518
  return true;
395
519
  }
520
+ const visibility = text.match(/^\/visibility(?:@\S+)?(?:\s+([\s\S]*))?$/i);
521
+ if (visibility) {
522
+ await this.handleVisibilityCommand(msg, visibility[1] ?? "");
523
+ return true;
524
+ }
396
525
  return false;
397
526
  }
398
527
  /**
@@ -1022,15 +1151,21 @@ export class TopicCommands {
1022
1151
  const text = await this.getStatusText();
1023
1152
  await adapter.sendText(msg.chatId, text, { threadId: msg.threadId });
1024
1153
  }
1025
- /** Compact label for status/sysinfo tables: prefer display_name, else strip the
1026
- * `-t<topicId>` suffix (e.g. doupo-server-t1503381916525793300 → doupo-server).
1027
- * Keeps rows short so a large fleet's table fits Discord's 2000-char limit. The
1028
- * FULL name is still used for all lookups — only the displayed label changes. */
1029
- shortInstanceName(name) {
1030
- const dn = this.ctx.fleetConfig?.instances[name]?.display_name;
1031
- if (dn && dn.trim())
1032
- return dn.trim();
1033
- return name.replace(/-t\d+$/, "");
1154
+ /** Fleet-wide display labels for status/sysinfo tables (#1305 P2-1):
1155
+ * display_name first, else a 19+-digit `-t<digits>` suffix shortened to its
1156
+ * last 6 — lengthened only while the label stays unique across every
1157
+ * instance, so same-tail legacy entries remain distinguishable. Keeps rows
1158
+ * short so a large fleet's table fits Discord's 2000-char limit. The FULL
1159
+ * name is still used for all lookups — only the displayed label changes. */
1160
+ displayLabels() {
1161
+ const instances = this.ctx.fleetConfig?.instances ?? {};
1162
+ const names = new Set(Object.keys(instances));
1163
+ for (const ch of this.ctx.classicChannels?.getAll() ?? [])
1164
+ names.add(ch.instanceName);
1165
+ return assignDisplayLabels([...names].map((name) => ({
1166
+ name,
1167
+ displayName: instances[name]?.display_name,
1168
+ })));
1034
1169
  }
1035
1170
  /** Get fleet status as markdown text (shared by TG + DC) */
1036
1171
  async getStatusText() {
@@ -1045,6 +1180,7 @@ export class TopicCommands {
1045
1180
  .filter(ch => !fleetNames.has(ch.instanceName))
1046
1181
  .map(ch => ({ name: ch.instanceName, classic: true })),
1047
1182
  ];
1183
+ const labels = this.displayLabels();
1048
1184
  for (const { name, classic } of instances) {
1049
1185
  const status = this.ctx.getInstanceStatus(name);
1050
1186
  const executionState = status === "paused" ? "paused"
@@ -1076,7 +1212,7 @@ export class TopicCommands {
1076
1212
  // Running but no execution snapshot yet: the old Status
1077
1213
  // column showed 🟢 here — say running, never idle or "—".
1078
1214
  : `🟢 ${t("state.running")}`;
1079
- const displayName = this.shortInstanceName(name);
1215
+ const displayName = labels.get(name) ?? name;
1080
1216
  // Model: same source as /ctx — live statusline for claude-code, the
1081
1217
  // effective resolver otherwise — capped so one long name cannot blow
1082
1218
  // the table wider.
@@ -1238,6 +1374,19 @@ export class TopicCommands {
1238
1374
  child.once("error", err => this.ctx.failUpdateProgress?.(err.message));
1239
1375
  child.unref();
1240
1376
  }
1377
+ /** #1302: `/visibility [full|summary|hidden]` in the General topic. */
1378
+ async handleVisibilityCommand(msg, arg) {
1379
+ const adapter = this.getReplyAdapter(msg);
1380
+ if (!adapter || !this.ctx.fleetConfig)
1381
+ return;
1382
+ // Same rule as /doctor: this adapter's fleet admins only, and an empty list is "nobody", not "everybody".
1383
+ if (!this.ctx.hasFleetAdmins(msg.adapterId) || !this.ctx.isFleetAdmin(msg.userId, msg.adapterId)) {
1384
+ await adapter.sendText(msg.chatId, t("not_authorized"), { threadId: msg.threadId });
1385
+ return;
1386
+ }
1387
+ const reply = runVisibilityCommand(this.ctx.fleetConfig, arg, () => this.ctx.saveFleetConfig());
1388
+ await adapter.sendText(msg.chatId, reply, { threadId: msg.threadId });
1389
+ }
1241
1390
  async handleDoctorCommand(msg) {
1242
1391
  const adapter = this.getReplyAdapter(msg);
1243
1392
  if (!adapter)
@@ -1296,12 +1445,21 @@ export class TopicCommands {
1296
1445
  async bindAndStart(dirPath, topicId) {
1297
1446
  if (!this.ctx.fleetConfig)
1298
1447
  throw new Error("Fleet config not loaded");
1299
- const instanceName = `${sanitizeInstanceName(basename(dirPath))}-t${topicId}`;
1448
+ // Short unique suffix (#1301), same rule as create_instance. Reuse of a
1449
+ // taken name requires proof it belongs to this same topic (#1305 P1):
1450
+ // full topic_id string equality; a dir-only collision (no config entry)
1451
+ // can never prove that, so it counts as a different topic.
1452
+ const instances = this.ctx.fleetConfig?.instances ?? {};
1453
+ const wanted = String(topicId);
1454
+ const instanceName = uniqueInstanceName(basename(dirPath), topicId, (candidate) => candidate in instances
1455
+ || existsSync(this.ctx.getInstanceDir(candidate)), (candidate) => {
1456
+ const owner = instances[candidate];
1457
+ return owner != null && String(owner.topic_id) === wanted;
1458
+ });
1300
1459
  this.ctx.fleetConfig.instances[instanceName] = {
1301
1460
  working_directory: dirPath,
1302
1461
  topic_id: topicId,
1303
1462
  restart_policy: this.ctx.fleetConfig.defaults.restart_policy ?? DEFAULT_INSTANCE_CONFIG.restart_policy,
1304
- context_guardian: this.ctx.fleetConfig.defaults.context_guardian ?? DEFAULT_INSTANCE_CONFIG.context_guardian,
1305
1463
  log_level: this.ctx.fleetConfig.defaults.log_level ?? DEFAULT_INSTANCE_CONFIG.log_level,
1306
1464
  };
1307
1465
  this.ctx.saveFleetConfig();