@songsid/agend 2.1.6-beta.1 → 2.1.6-beta.10

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 (184) hide show
  1. package/dist/agent-endpoint.d.ts +18 -0
  2. package/dist/agent-endpoint.js +53 -2
  3. package/dist/agent-endpoint.js.map +1 -1
  4. package/dist/apply-job.d.ts +114 -0
  5. package/dist/apply-job.js +214 -0
  6. package/dist/apply-job.js.map +1 -0
  7. package/dist/backend/claude-code.d.ts +25 -0
  8. package/dist/backend/claude-code.js +127 -0
  9. package/dist/backend/claude-code.js.map +1 -1
  10. package/dist/backend/codex.d.ts +41 -0
  11. package/dist/backend/codex.js +133 -0
  12. package/dist/backend/codex.js.map +1 -1
  13. package/dist/backend/credential-profile.d.ts +159 -0
  14. package/dist/backend/credential-profile.js +340 -0
  15. package/dist/backend/credential-profile.js.map +1 -0
  16. package/dist/backend/factory.js +4 -1
  17. package/dist/backend/factory.js.map +1 -1
  18. package/dist/backend/kiro-auth-store.d.ts +25 -0
  19. package/dist/backend/kiro-auth-store.js +61 -0
  20. package/dist/backend/kiro-auth-store.js.map +1 -0
  21. package/dist/backend/kiro.d.ts +8 -0
  22. package/dist/backend/kiro.js +31 -2
  23. package/dist/backend/kiro.js.map +1 -1
  24. package/dist/backend/muse.d.ts +90 -0
  25. package/dist/backend/muse.js +437 -0
  26. package/dist/backend/muse.js.map +1 -0
  27. package/dist/backend/types.d.ts +41 -0
  28. package/dist/backend/types.js.map +1 -1
  29. package/dist/channel/access-manager.d.ts +20 -0
  30. package/dist/channel/access-manager.js +25 -0
  31. package/dist/channel/access-manager.js.map +1 -1
  32. package/dist/channel/adapters/discord.d.ts +17 -0
  33. package/dist/channel/adapters/discord.js +72 -11
  34. package/dist/channel/adapters/discord.js.map +1 -1
  35. package/dist/channel/adapters/telegram.d.ts +6 -0
  36. package/dist/channel/adapters/telegram.js +36 -0
  37. package/dist/channel/adapters/telegram.js.map +1 -1
  38. package/dist/channel/markdown-chunk.d.ts +8 -3
  39. package/dist/channel/markdown-chunk.js +12 -3
  40. package/dist/channel/markdown-chunk.js.map +1 -1
  41. package/dist/channel/mcp-server.js +9 -12
  42. package/dist/channel/mcp-server.js.map +1 -1
  43. package/dist/channel/mcp-tools.d.ts +6 -2
  44. package/dist/channel/mcp-tools.js +6 -36
  45. package/dist/channel/mcp-tools.js.map +1 -1
  46. package/dist/channel/tool-router.js +32 -3
  47. package/dist/channel/tool-router.js.map +1 -1
  48. package/dist/channel/types.d.ts +18 -0
  49. package/dist/cli.js +113 -0
  50. package/dist/cli.js.map +1 -1
  51. package/dist/config-validator.js +45 -5
  52. package/dist/config-validator.js.map +1 -1
  53. package/dist/connection-secrets.d.ts +96 -0
  54. package/dist/connection-secrets.js +25 -0
  55. package/dist/connection-secrets.js.map +1 -0
  56. package/dist/daemon.d.ts +61 -0
  57. package/dist/daemon.js +359 -88
  58. package/dist/daemon.js.map +1 -1
  59. package/dist/event-log.d.ts +9 -0
  60. package/dist/event-log.js +21 -0
  61. package/dist/event-log.js.map +1 -1
  62. package/dist/fleet-level-config.d.ts +42 -0
  63. package/dist/fleet-level-config.js +78 -0
  64. package/dist/fleet-level-config.js.map +1 -0
  65. package/dist/fleet-lock.d.ts +21 -0
  66. package/dist/fleet-lock.js +42 -8
  67. package/dist/fleet-lock.js.map +1 -1
  68. package/dist/fleet-manager.d.ts +417 -2
  69. package/dist/fleet-manager.js +1981 -182
  70. package/dist/fleet-manager.js.map +1 -1
  71. package/dist/general-knowledge/skills/credential-profiles/SKILL.md +145 -0
  72. package/dist/general-knowledge/skills/worker-collaboration/SKILL.md +11 -1
  73. package/dist/instance-config-impact.d.ts +55 -0
  74. package/dist/instance-config-impact.js +152 -0
  75. package/dist/instance-config-impact.js.map +1 -0
  76. package/dist/instance-lifecycle.js +8 -4
  77. package/dist/instance-lifecycle.js.map +1 -1
  78. package/dist/locale.js +24 -0
  79. package/dist/locale.js.map +1 -1
  80. package/dist/logger.js +42 -25
  81. package/dist/logger.js.map +1 -1
  82. package/dist/muse-usage-relay.d.ts +72 -0
  83. package/dist/muse-usage-relay.js +419 -0
  84. package/dist/muse-usage-relay.js.map +1 -0
  85. package/dist/outbound-handlers.d.ts +5 -1
  86. package/dist/outbound-handlers.js +199 -1
  87. package/dist/outbound-handlers.js.map +1 -1
  88. package/dist/outbound-schemas.d.ts +7 -5
  89. package/dist/outbound-schemas.js +3 -2
  90. package/dist/outbound-schemas.js.map +1 -1
  91. package/dist/provider-probe.d.ts +48 -0
  92. package/dist/provider-probe.js +121 -0
  93. package/dist/provider-probe.js.map +1 -0
  94. package/dist/provider-secret-registry.d.ts +98 -0
  95. package/dist/provider-secret-registry.js +334 -0
  96. package/dist/provider-secret-registry.js.map +1 -0
  97. package/dist/quickstart-api.d.ts +164 -0
  98. package/dist/quickstart-api.js +351 -0
  99. package/dist/quickstart-api.js.map +1 -0
  100. package/dist/quickstart.js +23 -50
  101. package/dist/quickstart.js.map +1 -1
  102. package/dist/scheduler/db.js +17 -5
  103. package/dist/scheduler/db.js.map +1 -1
  104. package/dist/scheduler/db.test.js +34 -1
  105. package/dist/scheduler/db.test.js.map +1 -1
  106. package/dist/scheduler/types.d.ts +4 -0
  107. package/dist/scheduler/types.js.map +1 -1
  108. package/dist/secret-store.d.ts +25 -0
  109. package/dist/secret-store.js +165 -0
  110. package/dist/secret-store.js.map +1 -0
  111. package/dist/self-restart-limit.d.ts +21 -0
  112. package/dist/self-restart-limit.js +129 -0
  113. package/dist/self-restart-limit.js.map +1 -0
  114. package/dist/settings-api.d.ts +116 -0
  115. package/dist/settings-api.js +530 -5
  116. package/dist/settings-api.js.map +1 -1
  117. package/dist/setup-auth.d.ts +113 -0
  118. package/dist/setup-auth.js +181 -0
  119. package/dist/setup-auth.js.map +1 -0
  120. package/dist/setup-form.d.ts +18 -0
  121. package/dist/setup-form.js +315 -0
  122. package/dist/setup-form.js.map +1 -0
  123. package/dist/setup-host.d.ts +162 -0
  124. package/dist/setup-host.js +496 -0
  125. package/dist/setup-host.js.map +1 -0
  126. package/dist/setup-marker.d.ts +8 -0
  127. package/dist/setup-marker.js +39 -0
  128. package/dist/setup-marker.js.map +1 -0
  129. package/dist/setup-tunnel-consent.d.ts +53 -0
  130. package/dist/setup-tunnel-consent.js +82 -0
  131. package/dist/setup-tunnel-consent.js.map +1 -0
  132. package/dist/setup-wizard.js +4 -0
  133. package/dist/setup-wizard.js.map +1 -1
  134. package/dist/steer-capability.js +4 -1
  135. package/dist/steer-capability.js.map +1 -1
  136. package/dist/tips.js +1 -1
  137. package/dist/tips.js.map +1 -1
  138. package/dist/tmux-manager.js +29 -4
  139. package/dist/tmux-manager.js.map +1 -1
  140. package/dist/tool-permissions-notice.d.ts +38 -0
  141. package/dist/tool-permissions-notice.js +92 -0
  142. package/dist/tool-permissions-notice.js.map +1 -0
  143. package/dist/tool-permissions.d.ts +120 -0
  144. package/dist/tool-permissions.js +277 -0
  145. package/dist/tool-permissions.js.map +1 -0
  146. package/dist/topic-commands.js +1 -0
  147. package/dist/topic-commands.js.map +1 -1
  148. package/dist/transcript-sources.d.ts +12 -1
  149. package/dist/transcript-sources.js +19 -3
  150. package/dist/transcript-sources.js.map +1 -1
  151. package/dist/tunnel/cloudflared.d.ts +71 -0
  152. package/dist/tunnel/cloudflared.js +447 -0
  153. package/dist/tunnel/cloudflared.js.map +1 -0
  154. package/dist/tunnel/lease.d.ts +75 -0
  155. package/dist/tunnel/lease.js +209 -0
  156. package/dist/tunnel/lease.js.map +1 -0
  157. package/dist/tunnel/manager.d.ts +56 -0
  158. package/dist/tunnel/manager.js +167 -0
  159. package/dist/tunnel/manager.js.map +1 -0
  160. package/dist/tunnel/types.d.ts +119 -0
  161. package/dist/tunnel/types.js +33 -0
  162. package/dist/tunnel/types.js.map +1 -0
  163. package/dist/types.d.ts +2 -0
  164. package/dist/ui/dashboard.html +4 -3
  165. package/dist/ui/settings.html +808 -156
  166. package/dist/ui/view.html +2 -2
  167. package/dist/usage/i18n-keys.d.ts +1 -1
  168. package/dist/usage/i18n-keys.js +1 -1
  169. package/dist/usage/i18n-keys.js.map +1 -1
  170. package/dist/usage/providers.d.ts +23 -14
  171. package/dist/usage/providers.js +220 -58
  172. package/dist/usage/providers.js.map +1 -1
  173. package/dist/usage/usage-api.d.ts +13 -0
  174. package/dist/usage/usage-api.js +69 -1
  175. package/dist/usage/usage-api.js.map +1 -1
  176. package/dist/web-api.js +8 -5
  177. package/dist/web-api.js.map +1 -1
  178. package/dist/web-auth.d.ts +75 -0
  179. package/dist/web-auth.js +208 -2
  180. package/dist/web-auth.js.map +1 -1
  181. package/dist/web-terminal.d.ts +30 -1
  182. package/dist/web-terminal.js +86 -3
  183. package/dist/web-terminal.js.map +1 -1
  184. package/package.json +2 -1
@@ -21,6 +21,9 @@ import { type AgentEndpointContext } from "./agent-endpoint.js";
21
21
  import { ClassicChannelManager } from "./classic-channel-manager.js";
22
22
  import { type ExplicitInstanceRemoval } from "./instance-removal.js";
23
23
  import type { InstanceState } from "./backend/types.js";
24
+ import { type ConnectionMetadata, type ConnectionBinding, type BindingProbe, type SecretApplyJob, type ProviderSecretApplyJob } from "./connection-secrets.js";
25
+ import { type ProviderSecretStatus } from "./provider-secret-registry.js";
26
+ import { ApplyJobStore, type ApplyJob, type ApplyTargetKind, type SelfRestartResult } from "./apply-job.js";
24
27
  import { StormWindow } from "./storm-window.js";
25
28
  import { SpawnGate } from "./spawn-gate.js";
26
29
  import { BackendOutageTracker } from "./backend-outage.js";
@@ -242,6 +245,40 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
242
245
  private ipcReconnectInFlight;
243
246
  private adapterRestarting;
244
247
  private adapterState;
248
+ /** Web Settings secret rotation is deliberately separate from reconnect
249
+ * recovery: a rotation must build a fresh provider client with the new token,
250
+ * and stale callbacks from the old client must not win. */
251
+ private connectionSecretChallenges;
252
+ private connectionSecretChallengesByKey;
253
+ private connectionSecretJobs;
254
+ private connectionSecretJobSession;
255
+ private connectionSecretInFlight;
256
+ private connectionSecretGenerations;
257
+ /** Local epoch that fences a challenge across adapter replacement and
258
+ * provider reconnect generations. The adapter's own generation can reset
259
+ * when a new adapter object is constructed, so keep an independent epoch. */
260
+ private connectionSecretAdapterRefs;
261
+ private connectionSecretHealthGenerations;
262
+ /** Generic API-key verifier/apply state. The challenge scope contains the
263
+ * resolved spec/env key, so a request can never retarget another provider. */
264
+ private providerSecretChallenges;
265
+ private providerSecretChallengesByKey;
266
+ private providerSecretJobs;
267
+ private providerSecretJobSession;
268
+ private providerSecretInFlight;
269
+ private providerSecretGenerations;
270
+ /** Test seam only; production always uses the fixed HTTPS client. */
271
+ private providerSecretHttpClient?;
272
+ /** Code-owned activation hooks; never populated from a request. */
273
+ private providerSecretReloadHooks;
274
+ /** In-memory snapshots for narrow hot consumers (currently Groq voice). */
275
+ private providerSecretHotSnapshots;
276
+ /** Web Settings connection-binding step-up challenges and apply jobs. */
277
+ private connectionBindingChallenges;
278
+ private connectionBindingChallengesByKey;
279
+ private connectionBindingJobs;
280
+ private connectionBindingJobSession;
281
+ private connectionBindingInFlight;
245
282
  private collabInstances;
246
283
  private healthServer;
247
284
  private healthPortRetried;
@@ -254,6 +291,9 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
254
291
  private fullRestartLauncher;
255
292
  private eventLogPruneTimer;
256
293
  private logRotateTimer;
294
+ private discordPresenceTimer;
295
+ private discordPresenceInFlight;
296
+ private static readonly DISCORD_PRESENCE_REFRESH_MS;
257
297
  /** Days of event/activity history to keep. */
258
298
  private static readonly EVENT_LOG_RETENTION_DAYS;
259
299
  private watchdogTimer;
@@ -262,7 +302,29 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
262
302
  private mirrorBuffer;
263
303
  private mirrorTimer;
264
304
  private sseClients;
265
- private webToken;
305
+ /**
306
+ * Read from disk on every access rather than cached at startup: `agend
307
+ * web-token rotate` runs in a separate process, and a cached copy would keep
308
+ * authorizing revoked links and cookies until the fleet restarted.
309
+ */
310
+ private get webToken();
311
+ /**
312
+ * Set while a Settings apply job is driving the reconcile. The reconcile
313
+ * stays the single doer; it just says out loud what it is doing to whom, so
314
+ * the job's rows are the work rather than a prediction of it.
315
+ */
316
+ private applyJobStoreCache;
317
+ /** The apply that currently owns the reconcile slot, reserved synchronously
318
+ * so a second request cannot slip in before the first one starts working. */
319
+ private activeApplyJobId;
320
+ /** The fleet-level signature this process actually came up on. */
321
+ private appliedFleetLevel;
322
+ /** The config behind that signature, kept so a "needs restart" log can name
323
+ * which keys moved rather than just asserting that something did. */
324
+ private startupFleetConfig;
325
+ /** Set when the file on disk and the in-memory config disagree on a
326
+ * startup-only key at startup. See checkStartupSignatureConsistency(). */
327
+ private fleetSignatureMismatch;
266
328
  private viewToken;
267
329
  private healthServerListening;
268
330
  constructor(dataDir: string);
@@ -273,6 +335,18 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
273
335
  stormSuppressed(kind: string): boolean;
274
336
  private handleSighup;
275
337
  private scheduleReconcile;
338
+ /**
339
+ * Take the reconcile slot, or refuse.
340
+ *
341
+ * Only one reconcile may touch lifecycle and config at a time — two of them
342
+ * stop and start the same instance in parallel. SIGHUP and a Settings apply
343
+ * are the same operation from two entrances, so they share the one slot: the
344
+ * signal coalesces into a pending replay, the apply is told the fleet is busy.
345
+ *
346
+ * The returned promise is the caller's to handle; the stored one is already
347
+ * handled, so a rejection never escapes as an unhandled rejection.
348
+ */
349
+ private startExclusiveReconcile;
276
350
  /**
277
351
  * Is the fleet going down (or coming back up) on purpose?
278
352
  *
@@ -309,6 +383,13 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
309
383
  getSysInfo(): import("./fleet-context.js").SysInfo;
310
384
  /** Load fleet.yaml and build routing table */
311
385
  loadConfig(configPath: string): FleetConfig;
386
+ /**
387
+ * A channel's configurable bot_token_env is an env-key writer too. Refuse
388
+ * an overlap with a registry API key (or a process-reserved key) before the
389
+ * config becomes live; otherwise a Discord token could be written into
390
+ * GROQ_API_KEY by a perfectly valid-looking rotation request.
391
+ */
392
+ private assertProviderSecretEnvKeys;
312
393
  /** User-authored fleet.yaml, before defaults are merged into instances. */
313
394
  getRawFleetConfig(): RawFleetConfig;
314
395
  /** Build topic routing table: { topicId -> RouteTarget } */
@@ -398,6 +479,11 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
398
479
  * Classic channels use their effective backend merge chain, not the raw row.
399
480
  */
400
481
  getActiveUsageProviderIds(): ReadonlySet<string>;
482
+ /** Subscription providers used by the running/paused instances owned by one adapter. */
483
+ getUsageProviderIdsForAdapter(adapterId: string): ReadonlySet<string>;
484
+ /** `[instance, effective backend, credential profile]` for everything that is
485
+ * running or paused — the one place both usage views agree on who is live. */
486
+ private activeBackendBindings;
401
487
  /** Effective backends with a running or persisted-paused fleet/Classic instance. */
402
488
  getActiveBackendIds(): ReadonlySet<string>;
403
489
  isClassicInstance(name: string): boolean;
@@ -535,6 +621,15 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
535
621
  * from restarting the same process twice; backendNameOf defines ownership.
536
622
  */
537
623
  private configuredBackendInstanceNames;
624
+ /**
625
+ * Probe the same executable set exposed by the web backend catalog.
626
+ *
627
+ * This deliberately has no cache: an `/install-cli` completion can add a
628
+ * binary to PATH while the fleet process remains alive, and the next bare
629
+ * `/login` must see it without requiring a restart or an explicit cache
630
+ * invalidation call.
631
+ */
632
+ private probeInstalledBackends;
538
633
  /**
539
634
  * One fleet-level notice per burst, not one per instance: a post-update herd
540
635
  * fails many instances within the same second. Two notices per incident at
@@ -584,6 +679,9 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
584
679
  private startUpdateProgressMonitor;
585
680
  /** Start all instances from fleet config */
586
681
  startAll(configPath: string): Promise<void>;
682
+ /** Keep Discord profile activity aligned with the same cached usage source as /usage. */
683
+ private startDiscordUsagePresence;
684
+ private refreshDiscordUsagePresence;
587
685
  /**
588
686
  * Delete inbox files older than retentionDays (by mtime). Cleans the shared
589
687
  * inbox (`<dataDir>/inbox`) and every workspace inbox
@@ -719,12 +817,43 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
719
817
  * Pure: callers rely on being able to ask before claiming the dedup key.
720
818
  */
721
819
  private botMessageDropReason;
820
+ /**
821
+ * Say so when an adapter's access mode is coming from its state file rather
822
+ * than from fleet.yaml. The state file wins by design — a pairing done at
823
+ * runtime has to survive a restart — but that also means an edit to
824
+ * `access.mode` silently does nothing, which is indistinguishable from the
825
+ * fleet not having reloaded. Naming the file is what makes it fixable.
826
+ */
827
+ private warnIfAccessModeOverridden;
722
828
  private handleInboundMessage;
723
829
  /** Handle outbound tool calls from a daemon instance */
724
830
  /** Warn (but don't block) when rate limits are high. 30-min debounce per instance. */
725
831
  private rateLimitWarnedAt;
726
832
  private warnIfRateLimited;
727
833
  /** Handle outbound tool calls from a daemon instance */
834
+ /**
835
+ * Would this instance be allowed to use this tool?
836
+ *
837
+ * Stage 1 asks and records; nothing is refused yet. The recording is not only
838
+ * an observation window: `logActivity("tool_call")` sits on the outbound path
839
+ * only, so today the fleet has no idea what the agent endpoint or the typed
840
+ * IPC handlers are being asked to do — the one face with no authorization is
841
+ * also the one face with no telemetry.
842
+ *
843
+ * The profile comes from the instance the socket belongs to. Deliberately not
844
+ * `senderSessionName`, which arrives inside the message: a caller that fills
845
+ * in its own identity has not been identified.
846
+ */
847
+ /**
848
+ * Say once, at startup, what the new default means for this fleet.
849
+ *
850
+ * Nothing is rewritten: an explicit `tool_set: full` is a choice somebody
851
+ * made, and marking an instance as a coordinator is a judgement about how
852
+ * their fleet is organised. Both stay theirs — this only makes sure they are
853
+ * not discovered by an agent failing at three in the morning.
854
+ */
855
+ private announceToolPermissionsChange;
856
+ private checkToolPermission;
728
857
  private handleOutboundFromInstance;
729
858
  /** Side effects of a routed reply: cancel-button lifecycle, logs, SSE, chat log. */
730
859
  private afterReplyRouted;
@@ -760,6 +889,24 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
760
889
  private scheduleSourceAdapter;
761
890
  private notifySourceTopic;
762
891
  private notifyScheduleFailure;
892
+ /**
893
+ * The typed IPC messages, all through one door.
894
+ *
895
+ * They used to be five sibling branches on the dispatch, which is why the
896
+ * permission question had five places to be forgotten. Routing them together
897
+ * means the check above happens once and cannot be skipped by adding a
898
+ * sixth — a new type has to appear in `IPC_TYPE_TOOLS` to be dispatched at
899
+ * all.
900
+ */
901
+ /**
902
+ * Answer a refused typed message the way its handler would have.
903
+ *
904
+ * These are request/response over IPC: dropping the message silently leaves
905
+ * the caller waiting for a reply that never comes, and a hung agent is a
906
+ * worse failure than a refused one.
907
+ */
908
+ private refuseTypedIpc;
909
+ private dispatchTypedIpc;
763
910
  private handleScheduleCrud;
764
911
  private handleDecisionCrud;
765
912
  /** Resolve display name for an instance, fallback to instance name. */
@@ -771,6 +918,19 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
771
918
  private handleSetDisplayName;
772
919
  private handleSetDescription;
773
920
  handleScheduleCrudHttp(instance: string, op: string, args: Record<string, unknown>): Promise<unknown>;
921
+ /**
922
+ * The only place an agent's request creates, changes or removes a schedule
923
+ * (#895). The IPC handler (MCP calls, direct channel.sock writes) and the
924
+ * agent endpoint (agent-cli, HTTP agent mode) are adapters over this, so the
925
+ * target check cannot be present on one face and missing on the other — the
926
+ * shape #804 had to close twice.
927
+ *
928
+ * `caller` is the instance the server resolved for the request; any
929
+ * `source` in `args` is ignored, and a schedule's source is always its caller.
930
+ * A refusal is a ToolNotPermittedError: 403 on the agent endpoint, the error
931
+ * of the schedule response on IPC.
932
+ */
933
+ private performScheduleOp;
774
934
  handleDecisionCrudHttp(instance: string, op: string, args: Record<string, unknown>): Promise<unknown>;
775
935
  handleTaskCrudHttp(instance: string, args: Record<string, unknown>): Promise<unknown>;
776
936
  handleSetDisplayNameHttp(instance: string, name: string): Promise<unknown>;
@@ -1005,6 +1165,21 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1005
1165
  * (or an assist for one they stopped) must not stay clickable for the rest
1006
1166
  * of its 15 minutes.
1007
1167
  */
1168
+ /**
1169
+ * Collapse every still-armed button prompt, for a fleet that is going away.
1170
+ *
1171
+ * The map is in memory; the buttons are in the chat for up to 24 hours. A
1172
+ * restart therefore leaves them looking live — pressing one takes the stale
1173
+ * branch, which acknowledges the click and drops the dismissal without
1174
+ * saying so. Retiring them here means the user meets a spent prompt instead
1175
+ * of a live-looking dead one.
1176
+ *
1177
+ * Best effort and bounded. Each collapse is a platform call, a day of tips
1178
+ * can be many of them, and shutdown still has instances to stop. Whatever
1179
+ * has not finished by the deadline is abandoned — that is exactly today's
1180
+ * behaviour, so the budget can only leave things no worse than before.
1181
+ */
1182
+ private retirePendingNoncePrompts;
1008
1183
  clearNoncePromptsForInstance(instanceName: string): void;
1009
1184
  /** A clean exit is intentional from the CLI's perspective, but often not from
1010
1185
  * the operator's. Keep the instance notice passive and put the action in the
@@ -1438,12 +1613,35 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1438
1613
  /** Human-readable effective model, e.g. `auto (default)`. Used by /ctx. */
1439
1614
  modelDisplayForInstance(instanceName: string): string;
1440
1615
  private modelChoiceLabel;
1441
- /** Probe one backend's CLI env and cache it. Best-effort; never throws. */
1616
+ /**
1617
+ * Probe one backend's CLI env and cache it. Best-effort; never throws.
1618
+ *
1619
+ * `refreshVendorCatalog` is the "🔄 Refresh models" path only (#886): first
1620
+ * ask the CLI to refetch its own catalog, for backends whose probe merely
1621
+ * reads a file the CLI maintains. Every other caller leaves it off, so the
1622
+ * startup and /model probes behave exactly as before. A failed vendor
1623
+ * refresh fails the probe (null), which the menu reports instead of passing
1624
+ * the old list off as fresh.
1625
+ */
1442
1626
  private probeBackend;
1443
1627
  /** Background-probe every distinct backend in use at startup (non-blocking). */
1444
1628
  private probeCliEnvs;
1445
1629
  /** Best-effort model list for `/model`: cached CLI env first, else live probe. Never throws. */
1446
1630
  private getModelOptions;
1631
+ /**
1632
+ * The model list plus where it came from. `source` is "live" only when a probe
1633
+ * actually ran and answered; a refresh that failed or ran out of time reports
1634
+ * "cache" with the previous list, so a menu can say "could not refresh"
1635
+ * instead of presenting an old list as a fresh one.
1636
+ */
1637
+ private getModelOptionsWithSource;
1638
+ /**
1639
+ * The /model menu's choices, in the one order all three pickers share:
1640
+ * 🔄 Refresh first, then models, then (claude) "More models…". Refresh takes
1641
+ * a slot inside Discord's 25-option select cap, so it is paid for from the
1642
+ * model rows, never from "More models…".
1643
+ */
1644
+ private modelMenuChoices;
1447
1645
  /**
1448
1646
  * Model catalog behind the `list_models` tool.
1449
1647
  *
@@ -1493,6 +1691,18 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1493
1691
  private claudeApiModelOptions;
1494
1692
  /** Replace a consumed "/model" menu with the full account catalog tier. */
1495
1693
  private expandClaudeModelMenu;
1694
+ /**
1695
+ * "🔄 Refresh models" (#886): probe live past both caches and redraw the menu.
1696
+ *
1697
+ * Past AgEnD's cli-env cache (refresh=true) and, where the backend supports
1698
+ * it, past the CLI's own catalog cache too (codex: `codex debug models`).
1699
+ * Without the second half, a codex refresh re-read the same models_cache.json
1700
+ * and showed the old list as new.
1701
+ *
1702
+ * A failed refresh keeps the previous list and says so. It never blanks the
1703
+ * menu, because a picker with no rows cannot even offer another refresh.
1704
+ */
1705
+ private refreshModelMenu;
1496
1706
  /** Consume a `/model` selection callback. Returns true for all model-select ids (incl. stale). */
1497
1707
  private handleModelSelection;
1498
1708
  /** Apply a model to an instance: runtime paste (claude-code) or persist + restart (others). */
@@ -1584,6 +1794,211 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1584
1794
  * fields, plus cold fleet-level settings, retain restart semantics.
1585
1795
  */
1586
1796
  private reconcileInstances;
1797
+ /**
1798
+ * `{channel, cold defaults}` as one comparable string — the part of the config
1799
+ * a running fleet process cannot adopt without restarting.
1800
+ */
1801
+ private fleetLevelSignature;
1802
+ /**
1803
+ * The config a reconcile is about to load, not the one held in memory.
1804
+ *
1805
+ * Settings mutates the in-memory object and writes the file; only the file
1806
+ * goes back through defaults expansion. Forecasting from memory therefore
1807
+ * misses every instance that a changed fleet default will restart — the user
1808
+ * is told "restart AgEnD" and not told that five agents are about to go down.
1809
+ */
1810
+ private nextFleetConfig;
1811
+ /**
1812
+ * Does the config this process is running match the one a reconcile would
1813
+ * load off disk?
1814
+ *
1815
+ * If not, every apply reports a fleet-level change that a restart cannot
1816
+ * clear — restart, recompute, disagree again — a self-sustaining loop that
1817
+ * the rate limit can only slow to three naggings an hour. Startup rewrites
1818
+ * the file in three places before this point (slimFleetConfigAtStartup, the
1819
+ * general auto-create, the general fixup), so the two can genuinely diverge.
1820
+ *
1821
+ * An offer to restart that cannot possibly succeed is worse than no offer, so
1822
+ * the panel shows the mismatch instead of a button.
1823
+ */
1824
+ private checkStartupSignatureConsistency;
1825
+ /**
1826
+ * Is a live adapter already long-polling this bot token?
1827
+ *
1828
+ * Telegram's `getUpdates` has exactly one consumer: a second poller takes
1829
+ * turns with the first and both miss messages. The setup wizard's "post in
1830
+ * the group and I'll detect it" step is a second poller, so it has to know
1831
+ * when the answer is "not against this token, not while I'm running".
1832
+ */
1833
+ isBotTokenInUse(token: string): boolean;
1834
+ /** Non-null when startup found the running config and fleet.yaml disagreeing. */
1835
+ fleetSignatureMismatchKeys(): string[] | null;
1836
+ /**
1837
+ * Restart AgEnD itself on behalf of a Settings apply.
1838
+ *
1839
+ * Deliberately a separate action from Apply: the panel is reachable from
1840
+ * outside the LAN, and "restart the whole fleet" must never be something a
1841
+ * single Apply click can carry along with it.
1842
+ *
1843
+ * The order below is the safety envelope, and the order matters:
1844
+ * concurrency and consistency first (cheap, and a restart during a reconcile
1845
+ * is the dangerous one), then the state checks, then the rate limit, then the
1846
+ * audit notice — and only once all of that holds is the attempt written to
1847
+ * disk and fsynced, before anything spawns.
1848
+ */
1849
+ requestSettingsSelfRestart(jobId: string, key: string): Promise<SelfRestartResult>;
1850
+ /** The audit notice, and the message the restart progress will edit. */
1851
+ private postSelfRestartNotice;
1852
+ /** Jobs outlive this process on purpose; see apply-job.ts. */
1853
+ get applyJobs(): ApplyJobStore;
1854
+ /** The only channel metadata exposed to the Settings secret UI. */
1855
+ listSecureConnections(): ConnectionMetadata[];
1856
+ private secureConnectionChannel;
1857
+ private secureConnectionGeneration;
1858
+ /** Provider API-key rows exposed to Settings (never the env key or secret). */
1859
+ providerSecretsEnabled(): boolean;
1860
+ listProviderSecrets(): ProviderSecretStatus[];
1861
+ private providerSecretStaleConsumers;
1862
+ private providerSecretGeneration;
1863
+ private providerSecretEnvAllowed;
1864
+ verifyProviderSecret(input: {
1865
+ specId: string;
1866
+ secret: string;
1867
+ sessionBinding: string;
1868
+ idempotencyKey: string;
1869
+ }): Promise<{
1870
+ ok: true;
1871
+ verification_id: string;
1872
+ expires_at: number;
1873
+ spec_id: string;
1874
+ activation: "next_use" | "reload_hook";
1875
+ } | {
1876
+ ok: false;
1877
+ status: "unsupported_verifier" | "provider_rejected" | "provider_unavailable" | "invalid";
1878
+ error: string;
1879
+ }>;
1880
+ /** Naming aliases used by integrations that call this an API-key operation. */
1881
+ verifyProviderApiKey(input: Parameters<FleetManager["verifyProviderSecret"]>[0]): ReturnType<FleetManager["verifyProviderSecret"]>;
1882
+ startProviderSecretApply(input: {
1883
+ specId: string;
1884
+ verificationId: string;
1885
+ sessionBinding: string;
1886
+ idempotencyKey: string;
1887
+ }): {
1888
+ job: ProviderSecretApplyJob;
1889
+ reused: boolean;
1890
+ } | {
1891
+ busy: ProviderSecretApplyJob | null;
1892
+ } | {
1893
+ error: string;
1894
+ };
1895
+ startProviderApiKeyApply(input: Parameters<FleetManager["startProviderSecretApply"]>[0]): ReturnType<FleetManager["startProviderSecretApply"]>;
1896
+ getProviderSecretApply(jobId: string, sessionBinding: string): ProviderSecretApplyJob | null;
1897
+ getProviderApiKeyApply(jobId: string, sessionBinding: string): ProviderSecretApplyJob | null;
1898
+ private runProviderSecretApply;
1899
+ /** Groq is currently read from process.env per voice request, so the hook is
1900
+ * intentionally a no-op. Keeping it as a named code-owned hook makes the
1901
+ * hot activation contract explicit and gives tests a failure seam; no generic
1902
+ * SIGHUP or caller-provided hook is ever executed. */
1903
+ private runProviderSecretReloadHook;
1904
+ private normalizeConnectionBinding;
1905
+ private connectionBindingChannelConfig;
1906
+ /** Verify a prospective group/guild binding without mutating fleet state. */
1907
+ verifyConnectionBinding(input: {
1908
+ connectionId: string;
1909
+ binding: {
1910
+ group_id?: unknown;
1911
+ general_channel_id?: unknown;
1912
+ };
1913
+ sessionBinding: string;
1914
+ idempotencyKey: string;
1915
+ }): Promise<{
1916
+ ok: true;
1917
+ verification_id: string;
1918
+ expires_at: number;
1919
+ binding: ConnectionBinding;
1920
+ probe: BindingProbe;
1921
+ } | {
1922
+ ok: false;
1923
+ error: string;
1924
+ }>;
1925
+ startConnectionBindingApply(input: {
1926
+ connectionId: string;
1927
+ verificationId: string;
1928
+ sessionBinding: string;
1929
+ idempotencyKey: string;
1930
+ }): {
1931
+ job: SecretApplyJob;
1932
+ reused: boolean;
1933
+ } | {
1934
+ busy: SecretApplyJob | null;
1935
+ } | {
1936
+ error: string;
1937
+ };
1938
+ getConnectionBindingApply(jobId: string, sessionBinding: string): SecretApplyJob | null;
1939
+ private runConnectionBindingApply;
1940
+ /** Stop, rebuild and wait for a new adapter before committing YAML binding. */
1941
+ private rebuildAdapterForBinding;
1942
+ verifyConnectionSecret(input: {
1943
+ connectionId: string;
1944
+ secret: string;
1945
+ sessionBinding: string;
1946
+ idempotencyKey: string;
1947
+ }): Promise<{
1948
+ ok: true;
1949
+ verification_id: string;
1950
+ expires_at: number;
1951
+ identity?: {
1952
+ id: string | null;
1953
+ username: string | null;
1954
+ };
1955
+ } | {
1956
+ ok: false;
1957
+ error: string;
1958
+ }>;
1959
+ startConnectionSecretApply(input: {
1960
+ connectionId: string;
1961
+ verificationId: string;
1962
+ sessionBinding: string;
1963
+ idempotencyKey: string;
1964
+ }): {
1965
+ job: SecretApplyJob;
1966
+ reused: boolean;
1967
+ } | {
1968
+ busy: SecretApplyJob | null;
1969
+ } | {
1970
+ error: string;
1971
+ };
1972
+ getConnectionSecretApply(jobId: string, sessionBinding: string): SecretApplyJob | null;
1973
+ private runConnectionSecretApply;
1974
+ /** Stop the old provider client and construct a new one from process.env. */
1975
+ private rebuildAdapterForSecret;
1976
+ /**
1977
+ * What a reconcile is about to do, per target.
1978
+ *
1979
+ * A forecast, not the record: it is built from the same `classifyInstanceChange`
1980
+ * the reconcile decides with, but the rows that end up in the job are the ones
1981
+ * the reconcile reports as it works. A target the forecast missed (a Classic
1982
+ * instance inheriting a changed default) is added when it is first touched.
1983
+ */
1984
+ planConfigApply(): Array<{
1985
+ target: string;
1986
+ kind: ApplyTargetKind;
1987
+ }>;
1988
+ /**
1989
+ * Start (or re-join) a Settings apply.
1990
+ *
1991
+ * The key is the client's. Handing back the existing job for a repeated key is
1992
+ * the whole point: the retry after a lost response must not apply everything a
1993
+ * second time.
1994
+ */
1995
+ startSettingsApply(key: string): {
1996
+ job: ApplyJob;
1997
+ reused: boolean;
1998
+ } | {
1999
+ busy: ApplyJob | null;
2000
+ };
2001
+ private runSettingsApply;
1587
2002
  restartInstances(): Promise<void>;
1588
2003
  private checkForUpdates;
1589
2004
  /**