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

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 +425 -2
  69. package/dist/fleet-manager.js +2014 -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 +77 -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,11 @@ 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 discordPresenceEagerTimer;
296
+ private discordPresenceEagerPending;
297
+ private discordPresenceInFlight;
298
+ private static readonly DISCORD_PRESENCE_REFRESH_MS;
257
299
  /** Days of event/activity history to keep. */
258
300
  private static readonly EVENT_LOG_RETENTION_DAYS;
259
301
  private watchdogTimer;
@@ -262,7 +304,29 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
262
304
  private mirrorBuffer;
263
305
  private mirrorTimer;
264
306
  private sseClients;
265
- private webToken;
307
+ /**
308
+ * Read from disk on every access rather than cached at startup: `agend
309
+ * web-token rotate` runs in a separate process, and a cached copy would keep
310
+ * authorizing revoked links and cookies until the fleet restarted.
311
+ */
312
+ private get webToken();
313
+ /**
314
+ * Set while a Settings apply job is driving the reconcile. The reconcile
315
+ * stays the single doer; it just says out loud what it is doing to whom, so
316
+ * the job's rows are the work rather than a prediction of it.
317
+ */
318
+ private applyJobStoreCache;
319
+ /** The apply that currently owns the reconcile slot, reserved synchronously
320
+ * so a second request cannot slip in before the first one starts working. */
321
+ private activeApplyJobId;
322
+ /** The fleet-level signature this process actually came up on. */
323
+ private appliedFleetLevel;
324
+ /** The config behind that signature, kept so a "needs restart" log can name
325
+ * which keys moved rather than just asserting that something did. */
326
+ private startupFleetConfig;
327
+ /** Set when the file on disk and the in-memory config disagree on a
328
+ * startup-only key at startup. See checkStartupSignatureConsistency(). */
329
+ private fleetSignatureMismatch;
266
330
  private viewToken;
267
331
  private healthServerListening;
268
332
  constructor(dataDir: string);
@@ -273,6 +337,18 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
273
337
  stormSuppressed(kind: string): boolean;
274
338
  private handleSighup;
275
339
  private scheduleReconcile;
340
+ /**
341
+ * Take the reconcile slot, or refuse.
342
+ *
343
+ * Only one reconcile may touch lifecycle and config at a time — two of them
344
+ * stop and start the same instance in parallel. SIGHUP and a Settings apply
345
+ * are the same operation from two entrances, so they share the one slot: the
346
+ * signal coalesces into a pending replay, the apply is told the fleet is busy.
347
+ *
348
+ * The returned promise is the caller's to handle; the stored one is already
349
+ * handled, so a rejection never escapes as an unhandled rejection.
350
+ */
351
+ private startExclusiveReconcile;
276
352
  /**
277
353
  * Is the fleet going down (or coming back up) on purpose?
278
354
  *
@@ -309,6 +385,13 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
309
385
  getSysInfo(): import("./fleet-context.js").SysInfo;
310
386
  /** Load fleet.yaml and build routing table */
311
387
  loadConfig(configPath: string): FleetConfig;
388
+ /**
389
+ * A channel's configurable bot_token_env is an env-key writer too. Refuse
390
+ * an overlap with a registry API key (or a process-reserved key) before the
391
+ * config becomes live; otherwise a Discord token could be written into
392
+ * GROQ_API_KEY by a perfectly valid-looking rotation request.
393
+ */
394
+ private assertProviderSecretEnvKeys;
312
395
  /** User-authored fleet.yaml, before defaults are merged into instances. */
313
396
  getRawFleetConfig(): RawFleetConfig;
314
397
  /** Build topic routing table: { topicId -> RouteTarget } */
@@ -398,6 +481,11 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
398
481
  * Classic channels use their effective backend merge chain, not the raw row.
399
482
  */
400
483
  getActiveUsageProviderIds(): ReadonlySet<string>;
484
+ /** Subscription providers used by the running/paused instances owned by one adapter. */
485
+ getUsageProviderIdsForAdapter(adapterId: string): ReadonlySet<string>;
486
+ /** `[instance, effective backend, credential profile]` for everything that is
487
+ * running or paused — the one place both usage views agree on who is live. */
488
+ private activeBackendBindings;
401
489
  /** Effective backends with a running or persisted-paused fleet/Classic instance. */
402
490
  getActiveBackendIds(): ReadonlySet<string>;
403
491
  isClassicInstance(name: string): boolean;
@@ -535,6 +623,15 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
535
623
  * from restarting the same process twice; backendNameOf defines ownership.
536
624
  */
537
625
  private configuredBackendInstanceNames;
626
+ /**
627
+ * Probe the same executable set exposed by the web backend catalog.
628
+ *
629
+ * This deliberately has no cache: an `/install-cli` completion can add a
630
+ * binary to PATH while the fleet process remains alive, and the next bare
631
+ * `/login` must see it without requiring a restart or an explicit cache
632
+ * invalidation call.
633
+ */
634
+ private probeInstalledBackends;
538
635
  /**
539
636
  * One fleet-level notice per burst, not one per instance: a post-update herd
540
637
  * fails many instances within the same second. Two notices per incident at
@@ -584,6 +681,15 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
584
681
  private startUpdateProgressMonitor;
585
682
  /** Start all instances from fleet config */
586
683
  startAll(configPath: string): Promise<void>;
684
+ /** Keep Discord profile activity aligned with the same cached usage source as /usage. */
685
+ private startDiscordUsagePresence;
686
+ /**
687
+ * Request one prompt presence refresh after an instance/adapter comes online.
688
+ * Startup can bring several instances up together; a short coalescing window
689
+ * keeps that herd on the existing shared refresh path and one usage fetch.
690
+ */
691
+ private requestDiscordUsagePresenceRefresh;
692
+ private refreshDiscordUsagePresence;
587
693
  /**
588
694
  * Delete inbox files older than retentionDays (by mtime). Cleans the shared
589
695
  * inbox (`<dataDir>/inbox`) and every workspace inbox
@@ -719,12 +825,43 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
719
825
  * Pure: callers rely on being able to ask before claiming the dedup key.
720
826
  */
721
827
  private botMessageDropReason;
828
+ /**
829
+ * Say so when an adapter's access mode is coming from its state file rather
830
+ * than from fleet.yaml. The state file wins by design — a pairing done at
831
+ * runtime has to survive a restart — but that also means an edit to
832
+ * `access.mode` silently does nothing, which is indistinguishable from the
833
+ * fleet not having reloaded. Naming the file is what makes it fixable.
834
+ */
835
+ private warnIfAccessModeOverridden;
722
836
  private handleInboundMessage;
723
837
  /** Handle outbound tool calls from a daemon instance */
724
838
  /** Warn (but don't block) when rate limits are high. 30-min debounce per instance. */
725
839
  private rateLimitWarnedAt;
726
840
  private warnIfRateLimited;
727
841
  /** Handle outbound tool calls from a daemon instance */
842
+ /**
843
+ * Would this instance be allowed to use this tool?
844
+ *
845
+ * Stage 1 asks and records; nothing is refused yet. The recording is not only
846
+ * an observation window: `logActivity("tool_call")` sits on the outbound path
847
+ * only, so today the fleet has no idea what the agent endpoint or the typed
848
+ * IPC handlers are being asked to do — the one face with no authorization is
849
+ * also the one face with no telemetry.
850
+ *
851
+ * The profile comes from the instance the socket belongs to. Deliberately not
852
+ * `senderSessionName`, which arrives inside the message: a caller that fills
853
+ * in its own identity has not been identified.
854
+ */
855
+ /**
856
+ * Say once, at startup, what the new default means for this fleet.
857
+ *
858
+ * Nothing is rewritten: an explicit `tool_set: full` is a choice somebody
859
+ * made, and marking an instance as a coordinator is a judgement about how
860
+ * their fleet is organised. Both stay theirs — this only makes sure they are
861
+ * not discovered by an agent failing at three in the morning.
862
+ */
863
+ private announceToolPermissionsChange;
864
+ private checkToolPermission;
728
865
  private handleOutboundFromInstance;
729
866
  /** Side effects of a routed reply: cancel-button lifecycle, logs, SSE, chat log. */
730
867
  private afterReplyRouted;
@@ -760,6 +897,24 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
760
897
  private scheduleSourceAdapter;
761
898
  private notifySourceTopic;
762
899
  private notifyScheduleFailure;
900
+ /**
901
+ * The typed IPC messages, all through one door.
902
+ *
903
+ * They used to be five sibling branches on the dispatch, which is why the
904
+ * permission question had five places to be forgotten. Routing them together
905
+ * means the check above happens once and cannot be skipped by adding a
906
+ * sixth — a new type has to appear in `IPC_TYPE_TOOLS` to be dispatched at
907
+ * all.
908
+ */
909
+ /**
910
+ * Answer a refused typed message the way its handler would have.
911
+ *
912
+ * These are request/response over IPC: dropping the message silently leaves
913
+ * the caller waiting for a reply that never comes, and a hung agent is a
914
+ * worse failure than a refused one.
915
+ */
916
+ private refuseTypedIpc;
917
+ private dispatchTypedIpc;
763
918
  private handleScheduleCrud;
764
919
  private handleDecisionCrud;
765
920
  /** Resolve display name for an instance, fallback to instance name. */
@@ -771,6 +926,19 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
771
926
  private handleSetDisplayName;
772
927
  private handleSetDescription;
773
928
  handleScheduleCrudHttp(instance: string, op: string, args: Record<string, unknown>): Promise<unknown>;
929
+ /**
930
+ * The only place an agent's request creates, changes or removes a schedule
931
+ * (#895). The IPC handler (MCP calls, direct channel.sock writes) and the
932
+ * agent endpoint (agent-cli, HTTP agent mode) are adapters over this, so the
933
+ * target check cannot be present on one face and missing on the other — the
934
+ * shape #804 had to close twice.
935
+ *
936
+ * `caller` is the instance the server resolved for the request; any
937
+ * `source` in `args` is ignored, and a schedule's source is always its caller.
938
+ * A refusal is a ToolNotPermittedError: 403 on the agent endpoint, the error
939
+ * of the schedule response on IPC.
940
+ */
941
+ private performScheduleOp;
774
942
  handleDecisionCrudHttp(instance: string, op: string, args: Record<string, unknown>): Promise<unknown>;
775
943
  handleTaskCrudHttp(instance: string, args: Record<string, unknown>): Promise<unknown>;
776
944
  handleSetDisplayNameHttp(instance: string, name: string): Promise<unknown>;
@@ -1005,6 +1173,21 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1005
1173
  * (or an assist for one they stopped) must not stay clickable for the rest
1006
1174
  * of its 15 minutes.
1007
1175
  */
1176
+ /**
1177
+ * Collapse every still-armed button prompt, for a fleet that is going away.
1178
+ *
1179
+ * The map is in memory; the buttons are in the chat for up to 24 hours. A
1180
+ * restart therefore leaves them looking live — pressing one takes the stale
1181
+ * branch, which acknowledges the click and drops the dismissal without
1182
+ * saying so. Retiring them here means the user meets a spent prompt instead
1183
+ * of a live-looking dead one.
1184
+ *
1185
+ * Best effort and bounded. Each collapse is a platform call, a day of tips
1186
+ * can be many of them, and shutdown still has instances to stop. Whatever
1187
+ * has not finished by the deadline is abandoned — that is exactly today's
1188
+ * behaviour, so the budget can only leave things no worse than before.
1189
+ */
1190
+ private retirePendingNoncePrompts;
1008
1191
  clearNoncePromptsForInstance(instanceName: string): void;
1009
1192
  /** A clean exit is intentional from the CLI's perspective, but often not from
1010
1193
  * the operator's. Keep the instance notice passive and put the action in the
@@ -1438,12 +1621,35 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1438
1621
  /** Human-readable effective model, e.g. `auto (default)`. Used by /ctx. */
1439
1622
  modelDisplayForInstance(instanceName: string): string;
1440
1623
  private modelChoiceLabel;
1441
- /** Probe one backend's CLI env and cache it. Best-effort; never throws. */
1624
+ /**
1625
+ * Probe one backend's CLI env and cache it. Best-effort; never throws.
1626
+ *
1627
+ * `refreshVendorCatalog` is the "🔄 Refresh models" path only (#886): first
1628
+ * ask the CLI to refetch its own catalog, for backends whose probe merely
1629
+ * reads a file the CLI maintains. Every other caller leaves it off, so the
1630
+ * startup and /model probes behave exactly as before. A failed vendor
1631
+ * refresh fails the probe (null), which the menu reports instead of passing
1632
+ * the old list off as fresh.
1633
+ */
1442
1634
  private probeBackend;
1443
1635
  /** Background-probe every distinct backend in use at startup (non-blocking). */
1444
1636
  private probeCliEnvs;
1445
1637
  /** Best-effort model list for `/model`: cached CLI env first, else live probe. Never throws. */
1446
1638
  private getModelOptions;
1639
+ /**
1640
+ * The model list plus where it came from. `source` is "live" only when a probe
1641
+ * actually ran and answered; a refresh that failed or ran out of time reports
1642
+ * "cache" with the previous list, so a menu can say "could not refresh"
1643
+ * instead of presenting an old list as a fresh one.
1644
+ */
1645
+ private getModelOptionsWithSource;
1646
+ /**
1647
+ * The /model menu's choices, in the one order all three pickers share:
1648
+ * 🔄 Refresh first, then models, then (claude) "More models…". Refresh takes
1649
+ * a slot inside Discord's 25-option select cap, so it is paid for from the
1650
+ * model rows, never from "More models…".
1651
+ */
1652
+ private modelMenuChoices;
1447
1653
  /**
1448
1654
  * Model catalog behind the `list_models` tool.
1449
1655
  *
@@ -1493,6 +1699,18 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1493
1699
  private claudeApiModelOptions;
1494
1700
  /** Replace a consumed "/model" menu with the full account catalog tier. */
1495
1701
  private expandClaudeModelMenu;
1702
+ /**
1703
+ * "🔄 Refresh models" (#886): probe live past both caches and redraw the menu.
1704
+ *
1705
+ * Past AgEnD's cli-env cache (refresh=true) and, where the backend supports
1706
+ * it, past the CLI's own catalog cache too (codex: `codex debug models`).
1707
+ * Without the second half, a codex refresh re-read the same models_cache.json
1708
+ * and showed the old list as new.
1709
+ *
1710
+ * A failed refresh keeps the previous list and says so. It never blanks the
1711
+ * menu, because a picker with no rows cannot even offer another refresh.
1712
+ */
1713
+ private refreshModelMenu;
1496
1714
  /** Consume a `/model` selection callback. Returns true for all model-select ids (incl. stale). */
1497
1715
  private handleModelSelection;
1498
1716
  /** Apply a model to an instance: runtime paste (claude-code) or persist + restart (others). */
@@ -1584,6 +1802,211 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1584
1802
  * fields, plus cold fleet-level settings, retain restart semantics.
1585
1803
  */
1586
1804
  private reconcileInstances;
1805
+ /**
1806
+ * `{channel, cold defaults}` as one comparable string — the part of the config
1807
+ * a running fleet process cannot adopt without restarting.
1808
+ */
1809
+ private fleetLevelSignature;
1810
+ /**
1811
+ * The config a reconcile is about to load, not the one held in memory.
1812
+ *
1813
+ * Settings mutates the in-memory object and writes the file; only the file
1814
+ * goes back through defaults expansion. Forecasting from memory therefore
1815
+ * misses every instance that a changed fleet default will restart — the user
1816
+ * is told "restart AgEnD" and not told that five agents are about to go down.
1817
+ */
1818
+ private nextFleetConfig;
1819
+ /**
1820
+ * Does the config this process is running match the one a reconcile would
1821
+ * load off disk?
1822
+ *
1823
+ * If not, every apply reports a fleet-level change that a restart cannot
1824
+ * clear — restart, recompute, disagree again — a self-sustaining loop that
1825
+ * the rate limit can only slow to three naggings an hour. Startup rewrites
1826
+ * the file in three places before this point (slimFleetConfigAtStartup, the
1827
+ * general auto-create, the general fixup), so the two can genuinely diverge.
1828
+ *
1829
+ * An offer to restart that cannot possibly succeed is worse than no offer, so
1830
+ * the panel shows the mismatch instead of a button.
1831
+ */
1832
+ private checkStartupSignatureConsistency;
1833
+ /**
1834
+ * Is a live adapter already long-polling this bot token?
1835
+ *
1836
+ * Telegram's `getUpdates` has exactly one consumer: a second poller takes
1837
+ * turns with the first and both miss messages. The setup wizard's "post in
1838
+ * the group and I'll detect it" step is a second poller, so it has to know
1839
+ * when the answer is "not against this token, not while I'm running".
1840
+ */
1841
+ isBotTokenInUse(token: string): boolean;
1842
+ /** Non-null when startup found the running config and fleet.yaml disagreeing. */
1843
+ fleetSignatureMismatchKeys(): string[] | null;
1844
+ /**
1845
+ * Restart AgEnD itself on behalf of a Settings apply.
1846
+ *
1847
+ * Deliberately a separate action from Apply: the panel is reachable from
1848
+ * outside the LAN, and "restart the whole fleet" must never be something a
1849
+ * single Apply click can carry along with it.
1850
+ *
1851
+ * The order below is the safety envelope, and the order matters:
1852
+ * concurrency and consistency first (cheap, and a restart during a reconcile
1853
+ * is the dangerous one), then the state checks, then the rate limit, then the
1854
+ * audit notice — and only once all of that holds is the attempt written to
1855
+ * disk and fsynced, before anything spawns.
1856
+ */
1857
+ requestSettingsSelfRestart(jobId: string, key: string): Promise<SelfRestartResult>;
1858
+ /** The audit notice, and the message the restart progress will edit. */
1859
+ private postSelfRestartNotice;
1860
+ /** Jobs outlive this process on purpose; see apply-job.ts. */
1861
+ get applyJobs(): ApplyJobStore;
1862
+ /** The only channel metadata exposed to the Settings secret UI. */
1863
+ listSecureConnections(): ConnectionMetadata[];
1864
+ private secureConnectionChannel;
1865
+ private secureConnectionGeneration;
1866
+ /** Provider API-key rows exposed to Settings (never the env key or secret). */
1867
+ providerSecretsEnabled(): boolean;
1868
+ listProviderSecrets(): ProviderSecretStatus[];
1869
+ private providerSecretStaleConsumers;
1870
+ private providerSecretGeneration;
1871
+ private providerSecretEnvAllowed;
1872
+ verifyProviderSecret(input: {
1873
+ specId: string;
1874
+ secret: string;
1875
+ sessionBinding: string;
1876
+ idempotencyKey: string;
1877
+ }): Promise<{
1878
+ ok: true;
1879
+ verification_id: string;
1880
+ expires_at: number;
1881
+ spec_id: string;
1882
+ activation: "next_use" | "reload_hook";
1883
+ } | {
1884
+ ok: false;
1885
+ status: "unsupported_verifier" | "provider_rejected" | "provider_unavailable" | "invalid";
1886
+ error: string;
1887
+ }>;
1888
+ /** Naming aliases used by integrations that call this an API-key operation. */
1889
+ verifyProviderApiKey(input: Parameters<FleetManager["verifyProviderSecret"]>[0]): ReturnType<FleetManager["verifyProviderSecret"]>;
1890
+ startProviderSecretApply(input: {
1891
+ specId: string;
1892
+ verificationId: string;
1893
+ sessionBinding: string;
1894
+ idempotencyKey: string;
1895
+ }): {
1896
+ job: ProviderSecretApplyJob;
1897
+ reused: boolean;
1898
+ } | {
1899
+ busy: ProviderSecretApplyJob | null;
1900
+ } | {
1901
+ error: string;
1902
+ };
1903
+ startProviderApiKeyApply(input: Parameters<FleetManager["startProviderSecretApply"]>[0]): ReturnType<FleetManager["startProviderSecretApply"]>;
1904
+ getProviderSecretApply(jobId: string, sessionBinding: string): ProviderSecretApplyJob | null;
1905
+ getProviderApiKeyApply(jobId: string, sessionBinding: string): ProviderSecretApplyJob | null;
1906
+ private runProviderSecretApply;
1907
+ /** Groq is currently read from process.env per voice request, so the hook is
1908
+ * intentionally a no-op. Keeping it as a named code-owned hook makes the
1909
+ * hot activation contract explicit and gives tests a failure seam; no generic
1910
+ * SIGHUP or caller-provided hook is ever executed. */
1911
+ private runProviderSecretReloadHook;
1912
+ private normalizeConnectionBinding;
1913
+ private connectionBindingChannelConfig;
1914
+ /** Verify a prospective group/guild binding without mutating fleet state. */
1915
+ verifyConnectionBinding(input: {
1916
+ connectionId: string;
1917
+ binding: {
1918
+ group_id?: unknown;
1919
+ general_channel_id?: unknown;
1920
+ };
1921
+ sessionBinding: string;
1922
+ idempotencyKey: string;
1923
+ }): Promise<{
1924
+ ok: true;
1925
+ verification_id: string;
1926
+ expires_at: number;
1927
+ binding: ConnectionBinding;
1928
+ probe: BindingProbe;
1929
+ } | {
1930
+ ok: false;
1931
+ error: string;
1932
+ }>;
1933
+ startConnectionBindingApply(input: {
1934
+ connectionId: string;
1935
+ verificationId: string;
1936
+ sessionBinding: string;
1937
+ idempotencyKey: string;
1938
+ }): {
1939
+ job: SecretApplyJob;
1940
+ reused: boolean;
1941
+ } | {
1942
+ busy: SecretApplyJob | null;
1943
+ } | {
1944
+ error: string;
1945
+ };
1946
+ getConnectionBindingApply(jobId: string, sessionBinding: string): SecretApplyJob | null;
1947
+ private runConnectionBindingApply;
1948
+ /** Stop, rebuild and wait for a new adapter before committing YAML binding. */
1949
+ private rebuildAdapterForBinding;
1950
+ verifyConnectionSecret(input: {
1951
+ connectionId: string;
1952
+ secret: string;
1953
+ sessionBinding: string;
1954
+ idempotencyKey: string;
1955
+ }): Promise<{
1956
+ ok: true;
1957
+ verification_id: string;
1958
+ expires_at: number;
1959
+ identity?: {
1960
+ id: string | null;
1961
+ username: string | null;
1962
+ };
1963
+ } | {
1964
+ ok: false;
1965
+ error: string;
1966
+ }>;
1967
+ startConnectionSecretApply(input: {
1968
+ connectionId: string;
1969
+ verificationId: string;
1970
+ sessionBinding: string;
1971
+ idempotencyKey: string;
1972
+ }): {
1973
+ job: SecretApplyJob;
1974
+ reused: boolean;
1975
+ } | {
1976
+ busy: SecretApplyJob | null;
1977
+ } | {
1978
+ error: string;
1979
+ };
1980
+ getConnectionSecretApply(jobId: string, sessionBinding: string): SecretApplyJob | null;
1981
+ private runConnectionSecretApply;
1982
+ /** Stop the old provider client and construct a new one from process.env. */
1983
+ private rebuildAdapterForSecret;
1984
+ /**
1985
+ * What a reconcile is about to do, per target.
1986
+ *
1987
+ * A forecast, not the record: it is built from the same `classifyInstanceChange`
1988
+ * the reconcile decides with, but the rows that end up in the job are the ones
1989
+ * the reconcile reports as it works. A target the forecast missed (a Classic
1990
+ * instance inheriting a changed default) is added when it is first touched.
1991
+ */
1992
+ planConfigApply(): Array<{
1993
+ target: string;
1994
+ kind: ApplyTargetKind;
1995
+ }>;
1996
+ /**
1997
+ * Start (or re-join) a Settings apply.
1998
+ *
1999
+ * The key is the client's. Handing back the existing job for a repeated key is
2000
+ * the whole point: the retry after a lost response must not apply everything a
2001
+ * second time.
2002
+ */
2003
+ startSettingsApply(key: string): {
2004
+ job: ApplyJob;
2005
+ reused: boolean;
2006
+ } | {
2007
+ busy: ApplyJob | null;
2008
+ };
2009
+ private runSettingsApply;
1587
2010
  restartInstances(): Promise<void>;
1588
2011
  private checkForUpdates;
1589
2012
  /**