@songsid/agend 2.1.5 → 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 +57 -0
  11. package/dist/backend/codex.js +183 -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 +54 -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 +76 -0
  57. package/dist/daemon.js +489 -103
  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 +2055 -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";
@@ -181,6 +184,10 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
181
184
  private instanceIdleWaiters;
182
185
  private lastInboundUser;
183
186
  private cancelButtons;
187
+ /** Latest publication generation per instance. Late results from older
188
+ * generations are retired without touching the current button. */
189
+ private cancelButtonPublications;
190
+ private nextCancelButtonPublicationGeneration;
184
191
  /** Pending idle-edge retirement, one timer per instance. */
185
192
  private cancelButtonIdleRetireTimers;
186
193
  /** Duplicate-reply suppression across both the MCP and HTTP reply paths. */
@@ -238,6 +245,40 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
238
245
  private ipcReconnectInFlight;
239
246
  private adapterRestarting;
240
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;
241
282
  private collabInstances;
242
283
  private healthServer;
243
284
  private healthPortRetried;
@@ -250,6 +291,9 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
250
291
  private fullRestartLauncher;
251
292
  private eventLogPruneTimer;
252
293
  private logRotateTimer;
294
+ private discordPresenceTimer;
295
+ private discordPresenceInFlight;
296
+ private static readonly DISCORD_PRESENCE_REFRESH_MS;
253
297
  /** Days of event/activity history to keep. */
254
298
  private static readonly EVENT_LOG_RETENTION_DAYS;
255
299
  private watchdogTimer;
@@ -258,7 +302,29 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
258
302
  private mirrorBuffer;
259
303
  private mirrorTimer;
260
304
  private sseClients;
261
- 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;
262
328
  private viewToken;
263
329
  private healthServerListening;
264
330
  constructor(dataDir: string);
@@ -269,6 +335,18 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
269
335
  stormSuppressed(kind: string): boolean;
270
336
  private handleSighup;
271
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;
272
350
  /**
273
351
  * Is the fleet going down (or coming back up) on purpose?
274
352
  *
@@ -305,6 +383,13 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
305
383
  getSysInfo(): import("./fleet-context.js").SysInfo;
306
384
  /** Load fleet.yaml and build routing table */
307
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;
308
393
  /** User-authored fleet.yaml, before defaults are merged into instances. */
309
394
  getRawFleetConfig(): RawFleetConfig;
310
395
  /** Build topic routing table: { topicId -> RouteTarget } */
@@ -394,6 +479,11 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
394
479
  * Classic channels use their effective backend merge chain, not the raw row.
395
480
  */
396
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;
397
487
  /** Effective backends with a running or persisted-paused fleet/Classic instance. */
398
488
  getActiveBackendIds(): ReadonlySet<string>;
399
489
  isClassicInstance(name: string): boolean;
@@ -531,6 +621,15 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
531
621
  * from restarting the same process twice; backendNameOf defines ownership.
532
622
  */
533
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;
534
633
  /**
535
634
  * One fleet-level notice per burst, not one per instance: a post-update herd
536
635
  * fails many instances within the same second. Two notices per incident at
@@ -580,6 +679,9 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
580
679
  private startUpdateProgressMonitor;
581
680
  /** Start all instances from fleet config */
582
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;
583
685
  /**
584
686
  * Delete inbox files older than retentionDays (by mtime). Cleans the shared
585
687
  * inbox (`<dataDir>/inbox`) and every workspace inbox
@@ -715,12 +817,43 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
715
817
  * Pure: callers rely on being able to ask before claiming the dedup key.
716
818
  */
717
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;
718
828
  private handleInboundMessage;
719
829
  /** Handle outbound tool calls from a daemon instance */
720
830
  /** Warn (but don't block) when rate limits are high. 30-min debounce per instance. */
721
831
  private rateLimitWarnedAt;
722
832
  private warnIfRateLimited;
723
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;
724
857
  private handleOutboundFromInstance;
725
858
  /** Side effects of a routed reply: cancel-button lifecycle, logs, SSE, chat log. */
726
859
  private afterReplyRouted;
@@ -756,6 +889,24 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
756
889
  private scheduleSourceAdapter;
757
890
  private notifySourceTopic;
758
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;
759
910
  private handleScheduleCrud;
760
911
  private handleDecisionCrud;
761
912
  /** Resolve display name for an instance, fallback to instance name. */
@@ -767,6 +918,19 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
767
918
  private handleSetDisplayName;
768
919
  private handleSetDescription;
769
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;
770
934
  handleDecisionCrudHttp(instance: string, op: string, args: Record<string, unknown>): Promise<unknown>;
771
935
  handleTaskCrudHttp(instance: string, args: Record<string, unknown>): Promise<unknown>;
772
936
  handleSetDisplayNameHttp(instance: string, name: string): Promise<unknown>;
@@ -1001,6 +1165,21 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1001
1165
  * (or an assist for one they stopped) must not stay clickable for the rest
1002
1166
  * of its 15 minutes.
1003
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;
1004
1183
  clearNoncePromptsForInstance(instanceName: string): void;
1005
1184
  /** A clean exit is intentional from the CLI's perspective, but often not from
1006
1185
  * the operator's. Keep the instance notice passive and put the action in the
@@ -1056,6 +1235,10 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1056
1235
  */
1057
1236
  private handleCancelClick;
1058
1237
  private hasCancelButton;
1238
+ private beginCancelButtonPublication;
1239
+ /** Remember a clear/cancel/idle decision that arrived before notifyAlert
1240
+ * returned a message id. `expected` fences an idle timer to its generation. */
1241
+ private markCancelButtonPublicationForRetirement;
1059
1242
  sendCancelButton(instanceName: string, correlationId?: string, preserveProgress?: boolean): Promise<void>;
1060
1243
  /**
1061
1244
  * The cancel button's text for a given elapsed time.
@@ -1430,12 +1613,35 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1430
1613
  /** Human-readable effective model, e.g. `auto (default)`. Used by /ctx. */
1431
1614
  modelDisplayForInstance(instanceName: string): string;
1432
1615
  private modelChoiceLabel;
1433
- /** 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
+ */
1434
1626
  private probeBackend;
1435
1627
  /** Background-probe every distinct backend in use at startup (non-blocking). */
1436
1628
  private probeCliEnvs;
1437
1629
  /** Best-effort model list for `/model`: cached CLI env first, else live probe. Never throws. */
1438
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;
1439
1645
  /**
1440
1646
  * Model catalog behind the `list_models` tool.
1441
1647
  *
@@ -1485,6 +1691,18 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1485
1691
  private claudeApiModelOptions;
1486
1692
  /** Replace a consumed "/model" menu with the full account catalog tier. */
1487
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;
1488
1706
  /** Consume a `/model` selection callback. Returns true for all model-select ids (incl. stale). */
1489
1707
  private handleModelSelection;
1490
1708
  /** Apply a model to an instance: runtime paste (claude-code) or persist + restart (others). */
@@ -1576,6 +1794,211 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1576
1794
  * fields, plus cold fleet-level settings, retain restart semantics.
1577
1795
  */
1578
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;
1579
2002
  restartInstances(): Promise<void>;
1580
2003
  private checkForUpdates;
1581
2004
  /**