@songsid/agend 2.1.8-beta.1 → 2.1.8-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 (119) hide show
  1. package/dist/agent-cli.js +14 -0
  2. package/dist/agent-cli.js.map +1 -1
  3. package/dist/agent-endpoint.d.ts +4 -1
  4. package/dist/agent-endpoint.js +10 -1
  5. package/dist/agent-endpoint.js.map +1 -1
  6. package/dist/backend/claude-code.d.ts +35 -5
  7. package/dist/backend/claude-code.js +288 -17
  8. package/dist/backend/claude-code.js.map +1 -1
  9. package/dist/backend/cli-env-probe-worker.d.ts +1 -0
  10. package/dist/backend/cli-env-probe-worker.js +25 -0
  11. package/dist/backend/cli-env-probe-worker.js.map +1 -0
  12. package/dist/backend/codex-session-lookup.d.ts +16 -0
  13. package/dist/backend/codex-session-lookup.js +76 -2
  14. package/dist/backend/codex-session-lookup.js.map +1 -1
  15. package/dist/backend/codex.d.ts +3 -4
  16. package/dist/backend/codex.js +44 -6
  17. package/dist/backend/codex.js.map +1 -1
  18. package/dist/backend/credential-profile.d.ts +9 -0
  19. package/dist/backend/credential-profile.js +20 -0
  20. package/dist/backend/credential-profile.js.map +1 -1
  21. package/dist/backend/grok.js +19 -0
  22. package/dist/backend/grok.js.map +1 -1
  23. package/dist/backend/muse.d.ts +6 -0
  24. package/dist/backend/muse.js +37 -3
  25. package/dist/backend/muse.js.map +1 -1
  26. package/dist/backend/types.d.ts +13 -2
  27. package/dist/backend/types.js +14 -3
  28. package/dist/backend/types.js.map +1 -1
  29. package/dist/channel/adapters/discord.d.ts +16 -4
  30. package/dist/channel/adapters/discord.js +20 -5
  31. package/dist/channel/adapters/discord.js.map +1 -1
  32. package/dist/channel/mcp-tools.js +6 -0
  33. package/dist/channel/mcp-tools.js.map +1 -1
  34. package/dist/cli.js +138 -48
  35. package/dist/cli.js.map +1 -1
  36. package/dist/config-validator.js +11 -0
  37. package/dist/config-validator.js.map +1 -1
  38. package/dist/config.d.ts +1 -0
  39. package/dist/config.js +1 -1
  40. package/dist/config.js.map +1 -1
  41. package/dist/cross-instance-envelope.d.ts +7 -0
  42. package/dist/cross-instance-envelope.js +19 -1
  43. package/dist/cross-instance-envelope.js.map +1 -1
  44. package/dist/daemon.d.ts +130 -6
  45. package/dist/daemon.js +486 -69
  46. package/dist/daemon.js.map +1 -1
  47. package/dist/delivery-outbox.d.ts +9 -1
  48. package/dist/delivery-outbox.js +25 -4
  49. package/dist/delivery-outbox.js.map +1 -1
  50. package/dist/fleet-context.d.ts +5 -0
  51. package/dist/fleet-context.js.map +1 -1
  52. package/dist/fleet-manager.d.ts +165 -18
  53. package/dist/fleet-manager.js +821 -121
  54. package/dist/fleet-manager.js.map +1 -1
  55. package/dist/forged-envelope-scan.d.ts +160 -0
  56. package/dist/forged-envelope-scan.js +312 -0
  57. package/dist/forged-envelope-scan.js.map +1 -0
  58. package/dist/general-knowledge/skills/persona-emoji/SKILL.md +55 -0
  59. package/dist/instance-lifecycle.d.ts +81 -6
  60. package/dist/instance-lifecycle.js +201 -17
  61. package/dist/instance-lifecycle.js.map +1 -1
  62. package/dist/locale.js +34 -4
  63. package/dist/locale.js.map +1 -1
  64. package/dist/login-controller.js +11 -4
  65. package/dist/login-controller.js.map +1 -1
  66. package/dist/login-flows.d.ts +18 -1
  67. package/dist/login-flows.js +9 -2
  68. package/dist/login-flows.js.map +1 -1
  69. package/dist/ls-rows.d.ts +17 -0
  70. package/dist/ls-rows.js +73 -0
  71. package/dist/ls-rows.js.map +1 -1
  72. package/dist/outbound-handlers.d.ts +3 -0
  73. package/dist/outbound-handlers.js +3 -3
  74. package/dist/outbound-handlers.js.map +1 -1
  75. package/dist/outbound-schemas.d.ts +23 -4
  76. package/dist/outbound-schemas.js +12 -0
  77. package/dist/outbound-schemas.js.map +1 -1
  78. package/dist/paths.js +4 -2
  79. package/dist/paths.js.map +1 -1
  80. package/dist/pause-marker.d.ts +10 -1
  81. package/dist/pause-marker.js +26 -2
  82. package/dist/pause-marker.js.map +1 -1
  83. package/dist/service-installer.d.ts +8 -0
  84. package/dist/service-installer.js +36 -1
  85. package/dist/service-installer.js.map +1 -1
  86. package/dist/settings-api.d.ts +8 -8
  87. package/dist/settings-api.js +12 -5
  88. package/dist/settings-api.js.map +1 -1
  89. package/dist/status-emojis.d.ts +28 -1
  90. package/dist/status-emojis.js +11 -1
  91. package/dist/status-emojis.js.map +1 -1
  92. package/dist/target-queue-worker.d.ts +67 -0
  93. package/dist/target-queue-worker.js +76 -0
  94. package/dist/target-queue-worker.js.map +1 -0
  95. package/dist/tool-permissions.js +15 -4
  96. package/dist/tool-permissions.js.map +1 -1
  97. package/dist/topic-commands.d.ts +9 -0
  98. package/dist/topic-commands.js +64 -21
  99. package/dist/topic-commands.js.map +1 -1
  100. package/dist/transcript-monitor.js +3 -0
  101. package/dist/transcript-monitor.js.map +1 -1
  102. package/dist/transcript-sources.d.ts +63 -0
  103. package/dist/transcript-sources.js +171 -27
  104. package/dist/transcript-sources.js.map +1 -1
  105. package/dist/types.d.ts +26 -1
  106. package/dist/types.js +9 -1
  107. package/dist/types.js.map +1 -1
  108. package/dist/ui/settings.html +25 -13
  109. package/dist/wake-coordinator.d.ts +143 -0
  110. package/dist/wake-coordinator.js +321 -0
  111. package/dist/wake-coordinator.js.map +1 -0
  112. package/dist/web-api.d.ts +3 -1
  113. package/dist/web-api.js +1 -1
  114. package/dist/web-api.js.map +1 -1
  115. package/dist/web-terminal.d.ts +2 -0
  116. package/dist/web-terminal.js +3 -6
  117. package/dist/web-terminal.js.map +1 -1
  118. package/package.json +1 -1
  119. package/templates/systemd.service.ejs +7 -0
@@ -1,19 +1,20 @@
1
1
  import { type FleetMemory } from "./process-memory.js";
2
2
  import { ReplyDeduper } from "./reply-dedup.js";
3
3
  import type { FleetConfig, RawFleetConfig, InstanceConfig } from "./types.js";
4
- import { type DeliveryStatus, type ResolvedStatusEmojis } from "./status-emojis.js";
4
+ import { type DeliveryStatus, type GuildEmoji, type GuildEmojiGroup, type ResolvedStatusEmojis } from "./status-emojis.js";
5
5
  import { type RouteTarget } from "./fleet-context.js";
6
6
  import { EventLog } from "./event-log.js";
7
7
  import { AdapterWorld } from "./adapter-world.js";
8
8
  import { CostGuard } from "./cost-guard.js";
9
9
  import { IpcClient } from "./channel/ipc-bridge.js";
10
10
  import type { AdapterHealthSnapshot, ChannelAdapter, InboundReaction } from "./channel/types.js";
11
+ import { type BackendCliVersionSnapshot } from "./backend/types.js";
11
12
  import { type Logger } from "./logger.js";
12
13
  import { Scheduler } from "./scheduler/index.js";
13
14
  import type { FleetContext } from "./fleet-context.js";
14
15
  import { TmuxControlClient } from "./tmux-control.js";
15
16
  import { RoutingEngine } from "./routing-engine.js";
16
- import { InstanceLifecycle, type LifecycleContext } from "./instance-lifecycle.js";
17
+ import { InstanceLifecycle, type TransitionHandle, type LifecycleContext } from "./instance-lifecycle.js";
17
18
  import { type ArchiverContext } from "./topic-archiver.js";
18
19
  import { type StatuslineWatcherContext } from "./statusline-watcher.js";
19
20
  import { type OutboundContext } from "./outbound-handlers.js";
@@ -24,6 +25,9 @@ import { type AgentEndpointContext } from "./agent-endpoint.js";
24
25
  import { ClassicChannelManager } from "./classic-channel-manager.js";
25
26
  import { type ExplicitInstanceRemoval } from "./instance-removal.js";
26
27
  import type { InstanceState } from "./backend/types.js";
28
+ import { WakeCoordinator } from "./wake-coordinator.js";
29
+ import { TargetQueueWorker } from "./target-queue-worker.js";
30
+ import { resolveDeliveryWorkerMode } from "./types.js";
27
31
  import { type ConnectionMetadata, type ConnectionBinding, type BindingProbe, type SecretApplyJob, type ProviderSecretApplyJob } from "./connection-secrets.js";
28
32
  import { type ProviderSecretStatus } from "./provider-secret-registry.js";
29
33
  import { ApplyJobStore, type ApplyJob, type ApplyTargetKind, type SelfRestartResult } from "./apply-job.js";
@@ -72,6 +76,12 @@ export interface DeliveryOptions {
72
76
  waitForIdle?: boolean;
73
77
  /** Test/operational override; normal deliveries use the 60 second backstop. */
74
78
  idleTimeoutMs?: number;
79
+ /**
80
+ * Phase 2b: never wake inline. Durable dispatch to a `wake_only` target sets
81
+ * it — the wake coordinator is that target's only waker, so a target that
82
+ * paused after its row was claimed is handed back instead of woken here.
83
+ */
84
+ noInlineWake?: boolean;
75
85
  }
76
86
  export declare const LOGIN_CALLBACK_PREFIX = "login:";
77
87
  /**
@@ -119,6 +129,14 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
119
129
  readonly managerBootId: `${string}-${string}-${string}-${string}-${string}`;
120
130
  deliveryOutbox: DeliveryOutbox | null;
121
131
  private deliveryOutboxRecovered;
132
+ /** Phase 2b: wakes paused targets for queued durable work (delivery_worker ≠ off). */
133
+ wakeCoordinator: WakeCoordinator | null;
134
+ /**
135
+ * Phase 2c: targets whose durable lane a TargetQueueWorker owns
136
+ * (delivery_worker: on). Granted and released only in the pump's
137
+ * synchronous section and only while the lane is empty; the pump skips them.
138
+ */
139
+ readonly queueWorkers: Map<string, TargetQueueWorker>;
122
140
  private deliveryPumpScheduled;
123
141
  private deliveryPumpRunning;
124
142
  private deliveryPumpTimer;
@@ -372,6 +390,17 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
372
390
  sweepReplyObligations(now?: Date): void;
373
391
  private scheduleDeliveryOutboxPump;
374
392
  private runDeliveryOutboxPump;
393
+ /**
394
+ * Phase 2c ownership (design §1.5-A), called synchronously from the pump
395
+ * before its claim loop, so a grant and the pump's own claims cannot
396
+ * interleave. A worker is granted a target's lane only when the target is
397
+ * `on` and its lane is empty: no row in flight in the outbox and no pump
398
+ * dispatch holding it. It gives the lane back only when it is idle and the
399
+ * target is no longer `on` (or has nothing pending). A flag change never
400
+ * takes a lane mid-drain.
401
+ */
402
+ private reconcileQueueWorkers;
403
+ private createQueueWorker;
375
404
  private dispatchDurableDelivery;
376
405
  private waitForDurableLaneRelease;
377
406
  private spawnConcurrency;
@@ -551,8 +580,8 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
551
580
  /**
552
581
  * Ask the daemon to capture the pane before answering, then wait for any state
553
582
  * report produced after this request. The ordinary query is intentionally
554
- * cache-only (idle gates call it frequently); this opt-in refresh is reserved
555
- * for lifecycle decisions where a stale state would strand UI.
583
+ * cache-only; delivery idle gates opt into their own pane/input proof, and
584
+ * this refresh serves lifecycle decisions where a stale state would strand UI.
556
585
  */
557
586
  private refreshInstanceExecutionState;
558
587
  private deliverWithIdleGate;
@@ -582,6 +611,40 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
582
611
  deliverToInstance(instanceName: string, payload: Record<string, unknown>, options?: DeliveryOptions): Promise<boolean | void>;
583
612
  /** Fleet admin is an explicit config allowlist entry, not merely an open/paired user. */
584
613
  isFleetAdmin(userId: string, adapterId?: string): boolean;
614
+ /** Phase 2: delivery_worker for a target (instance override → fleet default → off). */
615
+ deliveryWorkerMode(target: string): ReturnType<typeof resolveDeliveryWorkerMode>;
616
+ /** Active instances mid-restart: they keep their warm slot through the stop → replacement gap. */
617
+ private restartsHoldingSlot;
618
+ /**
619
+ * Instances counted against the wake coordinator's hard cap: running
620
+ * daemons, plus active instances whose restart is between stopping the old
621
+ * daemon and publishing the replacement.
622
+ */
623
+ private warmInstanceNames;
624
+ private createWakeCoordinator;
625
+ /** LifecycleContext: an operator or user wake clears the coordinator's park/backoff for it. */
626
+ onExternalWake(name: string): void;
627
+ /**
628
+ * Phase 2b shared warm-slot admission (design §1.3, §1.6) for every wake
629
+ * that is not the coordinator's own: an operator's wake, a user's message,
630
+ * an explicit start or a restart of a paused instance. With delivery_worker
631
+ * off, or for a target that is not paused (an active restart is already
632
+ * counted), nothing is reserved. A target already being woken is joined —
633
+ * its flight holds the slot — rather than reserved twice. Otherwise a slot
634
+ * is taken under the hard cap, an unleased idle instance is paused to make
635
+ * one, and if none can be, the wake is refused instead of exceeding the cap.
636
+ */
637
+ private acquireWakeSlot;
638
+ private releaseWakeSlot;
639
+ /**
640
+ * An operator's or user's wake (/wake, wake_instance, start_instance on a
641
+ * paused instance, Settings, a channel message). With delivery_worker off it
642
+ * is exactly the old lifecycle wake; otherwise it goes through the shared
643
+ * slot admission and joins any wake already in flight for the target.
644
+ */
645
+ explicitWake(name: string, timeoutMs?: number): Promise<void>;
646
+ /** The least-recently-active idle, unleased, non-general running instance other than `exclude`. */
647
+ private lruUnleasedIdle;
585
648
  changeInstancePauseState(name: string, action: "pause" | "wake"): Promise<"paused" | "awake" | "not_idle">;
586
649
  /** Deliver an already-resolved hot snapshot without depending on IPC timing. */
587
650
  private applyHotConfigUpdate;
@@ -597,9 +660,11 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
597
660
  * and reconcile calls leave this false so a persisted pause remains paused
598
661
  * across a fleet restart.
599
662
  */
600
- resumePaused?: boolean): Promise<void>;
663
+ resumePaused?: boolean,
664
+ /** Phase 2a: the caller's transition, for a start made from inside a restart or wake. */
665
+ transition?: TransitionHandle): Promise<void>;
601
666
  /** Recreate a daemon for a marker-only paused instance after an explicit wake/delivery. */
602
- startPersistedPausedInstance(name: string): Promise<void>;
667
+ startPersistedPausedInstance(name: string, transition?: TransitionHandle): Promise<void>;
603
668
  /**
604
669
  * Start instances with configurable concurrency and stagger delay.
605
670
  * Instances sharing the same working_directory are serialized within a group
@@ -692,13 +757,25 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
692
757
  /** Last-resort completion after RestartProgress could not deliver to its
693
758
  * adopted target. It stays bounded and never wakes a not-ready gateway. */
694
759
  private sendFleetStartCompletionFallback;
695
- stopInstance(name: string): Promise<void>;
760
+ stopInstance(name: string, transition?: TransitionHandle): Promise<void>;
696
761
  /** Restart a single instance, reloading fleet.yaml first to pick up config changes. */
697
762
  restartSingleInstance(name: string, opts?: {
698
763
  freshStart?: boolean;
764
+ explicit?: boolean;
699
765
  }): Promise<void>;
700
766
  isInstanceRestarting(name: string): boolean;
767
+ /** InstanceLifecycleContext: an explicit wake joins the restart in flight. */
768
+ restartInFlight(name: string): Promise<void> | undefined;
769
+ /**
770
+ * Phase 2a: restarting a paused instance is a wake. The stop leaves the
771
+ * pause marker in place, and the start used to skip on it ("Persisted
772
+ * paused instance"), turning a resident pause into a marker-only one that
773
+ * nothing would wake. Clear it before the start; if the start fails, put it
774
+ * back so the instance stays wakeable instead of becoming plain stopped.
775
+ */
776
+ private startAfterRestart;
701
777
  private doRestartSingleInstance;
778
+ private doRestartWithSlot;
702
779
  /**
703
780
  * Mark an instance so its next daemon start skips session resume. Written AFTER
704
781
  * stop (survives the old daemon's cleanup) and BEFORE start so the respawn reads
@@ -960,10 +1037,14 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
960
1037
  */
961
1038
  private refuseTypedIpc;
962
1039
  private dispatchTypedIpc;
1040
+ /** `list_emojis` / `set_persona_emoji` / `preview_emojis` over IPC; the agent endpoint calls the same methods. */
1041
+ private handlePersonaEmoji;
963
1042
  private handleScheduleCrud;
964
1043
  private handleDecisionCrud;
965
1044
  /** Resolve display name for an instance, fallback to instance name. */
966
1045
  resolveDisplayName(instanceName: string): string;
1046
+ /** Inherited keys such as __proto__ must never resolve to a mutable instance. */
1047
+ private ownInstanceConfig;
967
1048
  /** Persist identity to the instance's actual config store. Classic instances
968
1049
  * are registry rows in classicBot.yaml, not fleet.yaml instance entries. */
969
1050
  private setInstanceDisplayName;
@@ -987,6 +1068,9 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
987
1068
  handleDecisionCrudHttp(instance: string, op: string, args: Record<string, unknown>): Promise<unknown>;
988
1069
  handleTaskCrudHttp(instance: string, args: Record<string, unknown>): Promise<unknown>;
989
1070
  handleSetDisplayNameHttp(instance: string, name: string): Promise<unknown>;
1071
+ handleListEmojisHttp(instance: string, refresh: boolean): Promise<unknown>;
1072
+ handleSetPersonaEmojiHttp(instance: string, args: Record<string, unknown>): Promise<unknown>;
1073
+ handlePreviewEmojisHttp(instance: string, args: Record<string, unknown>): Promise<unknown>;
990
1074
  handleSetDescriptionHttp(instance: string, description: string): Promise<unknown>;
991
1075
  private summarizeToolCall;
992
1076
  private handleTaskCrud;
@@ -1077,6 +1161,8 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1077
1161
  private deliveryStatusChains;
1078
1162
  /** #725: in-flight CLI env probes, keyed by backend name. Coalesces concurrent /model requests. */
1079
1163
  private pendingCliEnvProbes;
1164
+ /** Forced vendor catalog refreshes are separate flights, but sysinfo joins either flight. */
1165
+ private pendingVendorCliEnvProbes;
1080
1166
  /**
1081
1167
  * The status emojis for an instance (#1005): its own `status_emojis`, then
1082
1168
  * its channel's `options.status_emojis`, then the platform built-in. An
@@ -1088,27 +1174,67 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1088
1174
  };
1089
1175
  private warnedStatusEmojis;
1090
1176
  /**
1091
- * A Discord connection's server emojis for the Settings picker (#1005).
1092
- * Cached per connection — a server's emoji set changes rarely — and one
1093
- * fetch at a time; `refresh` forces a new one. Uses the running adapter, so
1094
- * the bot token never leaves the server.
1177
+ * A Discord connection's server emojis for the Settings picker (#1005), from
1178
+ * every server its bot can draw on (#1021): the primary `group_id` server,
1179
+ * then each other server the bot is a member of that ClassicBot's
1180
+ * `allowed_guilds` admits (unset = all, as for classic routing). A bot can
1181
+ * react with a custom emoji from any server it is in. Cached per server — a
1182
+ * server's emoji set changes rarely — and one fetch per server at a time;
1183
+ * `refresh` forces new ones. One server refusing (e.g. Missing Access) is
1184
+ * reported on that server and does not hide the others. Uses the running
1185
+ * adapter, so the bot token never leaves the server.
1095
1186
  */
1096
1187
  listGuildEmojis(channelId: string, refresh?: boolean): Promise<{
1097
1188
  ok: true;
1098
1189
  fetched_at: number;
1099
- emojis: Array<{
1100
- id: string;
1101
- name: string;
1102
- animated: boolean;
1103
- available: boolean;
1104
- }>;
1190
+ emojis: GuildEmoji[];
1191
+ guilds: GuildEmojiGroup[];
1105
1192
  } | {
1106
1193
  ok: false;
1107
1194
  error: string;
1108
1195
  }>;
1109
1196
  private static GUILD_EMOJI_TTL_MS;
1197
+ /** Keyed `<connection>\0<server id>`. */
1110
1198
  private guildEmojiCache;
1111
1199
  private guildEmojiFetches;
1200
+ /**
1201
+ * What `instanceName` may pick as its persona emoji (the `list_emojis`
1202
+ * tool): its current status set with where each value comes from, the
1203
+ * standard emojis its platform takes, and on Discord the server emojis its
1204
+ * bot can draw on — the same lists, and the same resolution, as the
1205
+ * Settings picker (#1005/#1021), so an agent and an operator see one truth.
1206
+ */
1207
+ listEmojisFor(instanceName: string, refresh?: boolean): Promise<Record<string, unknown>>;
1208
+ /**
1209
+ * `preview_emojis` (#1040): download a few Discord server emojis so an agent
1210
+ * can look at them before it picks one — a name and an id say nothing about
1211
+ * what an emoji looks like. The fleet fetches, not the agent (not every
1212
+ * backend can), and returns a local path per emoji to Read, as
1213
+ * download_attachment does for an attachment.
1214
+ *
1215
+ * SSRF-safe by construction: nothing from the caller reaches a URL. The
1216
+ * caller names emojis; each must be an available one in a server this bot
1217
+ * can draw on (the list set_persona_emoji checks), and the CDN URL is built
1218
+ * from that listed emoji's numeric id. Static PNG, size-capped, cached by id.
1219
+ */
1220
+ previewEmojis(instanceName: string, args: Record<string, unknown>): Promise<Record<string, unknown>>;
1221
+ private static EMOJI_PREVIEW_MAX;
1222
+ private static EMOJI_PREVIEW_MAX_BYTES;
1223
+ private static EMOJI_PREVIEW_TTL_MS;
1224
+ /** One emoji's static PNG under the inbox, reused while fresh; stale ones are pruned. */
1225
+ private fetchEmojiPreview;
1226
+ /**
1227
+ * `set_persona_emoji`: `instanceName` sets one of its own status emojis —
1228
+ * `delivered` unless it names another — in its per-instance `status_emojis`
1229
+ * override (#1005 addendum 2), so its stamp is told apart from other bots'
1230
+ * on a shared message. The value is judged exactly as Settings and the
1231
+ * react path judge it (statusEmojiProblem on the instance's platform), and
1232
+ * a Discord server emoji must be one its bot can use: an emoji from a
1233
+ * server it is not in would be stored, preview fine, and fail every react.
1234
+ * An empty emoji removes that status's override.
1235
+ */
1236
+ setPersonaEmoji(instanceName: string, args: Record<string, unknown>): Promise<Record<string, unknown>>;
1237
+ private personaEmojiMissing;
1112
1238
  /** What the instructions tell `instanceName` not to react with (its own status set). */
1113
1239
  statusEmojiAvoidList(instanceName: string): string[];
1114
1240
  /** The progress bubble's leading emoji, in the form the channel renders. */
@@ -1128,6 +1254,13 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1128
1254
  * own adapter rather than through reactMessageStatus (classic bots).
1129
1255
  */
1130
1256
  private receivedReactionFor;
1257
+ /**
1258
+ * The stamp for an inbound photo / file a classic bot saved (#1080): the
1259
+ * instance's `status_emojis.photo|attachment`, then its connection's, then
1260
+ * the built-in (📸/📎, or 👌/👍 on Telegram — what these paths always stamped).
1261
+ * Anything else a saved attachment can be counts as a file.
1262
+ */
1263
+ private savedAttachmentReactionFor;
1131
1264
  reactMessageStatus(instanceName: string, chatId: string, messageId: string, status: DeliveryStatus, threadId?: string): void;
1132
1265
  /**
1133
1266
  * Apply a terminal delivery verdict. On Telegram the built-in delivered is
@@ -1624,7 +1757,14 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1624
1757
  /** `/install-cli cancel` — abort the active install and remove its window. */
1625
1758
  cancelInstallSession(): Promise<string>;
1626
1759
  /** `command -v` on a login shell, so PATH additions from rc files count. */
1627
- private verifyBinaryOnLoginShell;
1760
+ /**
1761
+ * The absolute path a fresh login shell resolves `binary` to, or null. Only
1762
+ * a real executable file counts: `command -v` also answers with an alias
1763
+ * definition or a function name, neither of which a spawn could run.
1764
+ */
1765
+ private locateBinaryOnLoginShell;
1766
+ /** Put an installed binary's directory on the fleet's PATH (#1059), once. */
1767
+ private adoptBinaryDirectory;
1628
1768
  /** "Sign in now?" button after a successful install. */
1629
1769
  private handleInstallLoginConfirm;
1630
1770
  /** Discord native `/login` slash — shared by every adapter dispatch block. */
@@ -1711,6 +1851,10 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1711
1851
  private cliEnvPath;
1712
1852
  /** Read the cached CLI env for a backend, or null if missing/stale/unparseable. */
1713
1853
  private readCliEnv;
1854
+ /** Return cached CLI versions immediately. Refresh is started after /sysinfo is sent. */
1855
+ getBackendCliVersionSnapshot(): BackendCliVersionSnapshot;
1856
+ /** Called only after the user-visible sysinfo send/respond has settled. */
1857
+ refreshBackendCliVersions(): void;
1714
1858
  /** True when a cached CLI env is old enough that `/model` should re-probe. */
1715
1859
  private cliEnvNeedsRefresh;
1716
1860
  /**
@@ -1719,6 +1863,7 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1719
1863
  * previous list, never stall the command that asked for it.
1720
1864
  */
1721
1865
  private probeBackendBounded;
1866
+ private startCliEnvProbeWorker;
1722
1867
  /**
1723
1868
  * Resolve the effective model for a fleet or ClassicBot instance, plus where it
1724
1869
  * came from. Single source of truth for `/model` and `/ctx` — precedence:
@@ -1745,6 +1890,8 @@ export declare class FleetManager implements FleetContext, LifecycleContext, Arc
1745
1890
  * the old list off as fresh.
1746
1891
  */
1747
1892
  private probeBackend;
1893
+ /** Preserve the existing cache merge rules for both in-process and worker probes. */
1894
+ private persistCliEnvProbeResult;
1748
1895
  /** Background-probe every distinct backend in use at startup (non-blocking). */
1749
1896
  private probeCliEnvs;
1750
1897
  /** Best-effort model list for `/model`: cached CLI env first, else live probe. Never throws. */