@songsid/agend 2.3.2-beta.1 → 2.3.2-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 (266) hide show
  1. package/THIRD_PARTY_NOTICES.md +40 -0
  2. package/dist/agent-cli.js +21 -2
  3. package/dist/agent-cli.js.map +1 -1
  4. package/dist/agent-endpoint.js +5 -0
  5. package/dist/agent-endpoint.js.map +1 -1
  6. package/dist/antigravity-usage-scan.d.ts +58 -0
  7. package/dist/antigravity-usage-scan.js +257 -0
  8. package/dist/antigravity-usage-scan.js.map +1 -0
  9. package/dist/antigravity-usage-worker.d.ts +1 -0
  10. package/dist/antigravity-usage-worker.js +10 -0
  11. package/dist/antigravity-usage-worker.js.map +1 -0
  12. package/dist/auth-api.js +4 -0
  13. package/dist/auth-api.js.map +1 -1
  14. package/dist/backend/kiro-identity.d.ts +64 -0
  15. package/dist/backend/kiro-identity.js +101 -0
  16. package/dist/backend/kiro-identity.js.map +1 -1
  17. package/dist/backend/kiro-retired-model.d.ts +62 -0
  18. package/dist/backend/kiro-retired-model.js +160 -0
  19. package/dist/backend/kiro-retired-model.js.map +1 -0
  20. package/dist/backend/kiro.d.ts +71 -2
  21. package/dist/backend/kiro.js +352 -11
  22. package/dist/backend/kiro.js.map +1 -1
  23. package/dist/backend/types.d.ts +59 -0
  24. package/dist/backend/types.js.map +1 -1
  25. package/dist/backend-signin-guide.d.ts +1 -0
  26. package/dist/backend-signin-guide.js +9 -0
  27. package/dist/backend-signin-guide.js.map +1 -0
  28. package/dist/backend-signin-pending.d.ts +10 -0
  29. package/dist/backend-signin-pending.js +44 -0
  30. package/dist/backend-signin-pending.js.map +1 -0
  31. package/dist/browser-backend-signins.d.ts +56 -0
  32. package/dist/browser-backend-signins.js +189 -0
  33. package/dist/browser-backend-signins.js.map +1 -0
  34. package/dist/cache-ledger.d.ts +38 -2
  35. package/dist/cache-ledger.js +133 -8
  36. package/dist/cache-ledger.js.map +1 -1
  37. package/dist/cache-prices.d.ts +2 -1
  38. package/dist/cache-prices.js +5 -2
  39. package/dist/cache-prices.js.map +1 -1
  40. package/dist/cache-service.d.ts +68 -0
  41. package/dist/cache-service.js +355 -13
  42. package/dist/cache-service.js.map +1 -1
  43. package/dist/channel/adapters/discord.d.ts +11 -0
  44. package/dist/channel/adapters/discord.js +71 -14
  45. package/dist/channel/adapters/discord.js.map +1 -1
  46. package/dist/channel/mcp-tools.js +29 -2
  47. package/dist/channel/mcp-tools.js.map +1 -1
  48. package/dist/channel/tool-router.js +2 -1
  49. package/dist/channel/tool-router.js.map +1 -1
  50. package/dist/classic-channel-manager.d.ts +11 -0
  51. package/dist/classic-channel-manager.js +39 -1
  52. package/dist/classic-channel-manager.js.map +1 -1
  53. package/dist/cli.js +21 -2
  54. package/dist/cli.js.map +1 -1
  55. package/dist/config-validator.d.ts +7 -1
  56. package/dist/config-validator.js +53 -10
  57. package/dist/config-validator.js.map +1 -1
  58. package/dist/config.d.ts +19 -0
  59. package/dist/config.js +31 -1
  60. package/dist/config.js.map +1 -1
  61. package/dist/cpu-quota.d.ts +23 -0
  62. package/dist/cpu-quota.js +86 -0
  63. package/dist/cpu-quota.js.map +1 -0
  64. package/dist/daemon.d.ts +23 -0
  65. package/dist/daemon.js +106 -7
  66. package/dist/daemon.js.map +1 -1
  67. package/dist/dashboard-permissions.d.ts +20 -6
  68. package/dist/dashboard-permissions.js +58 -9
  69. package/dist/dashboard-permissions.js.map +1 -1
  70. package/dist/doctor.js +2 -1
  71. package/dist/doctor.js.map +1 -1
  72. package/dist/fleet-manager.d.ts +72 -0
  73. package/dist/fleet-manager.js +507 -89
  74. package/dist/fleet-manager.js.map +1 -1
  75. package/dist/forged-envelope-scan.d.ts +9 -0
  76. package/dist/forged-envelope-scan.js +30 -5
  77. package/dist/forged-envelope-scan.js.map +1 -1
  78. package/dist/general-knowledge/skills/credential-profiles/SKILL.md +5 -2
  79. package/dist/general-knowledge/skills/kiro-engine-migration/SKILL.md +14 -1
  80. package/dist/general-knowledge/skills/web-appearance/SKILL.canvas-worker-off.md +24 -1
  81. package/dist/general-knowledge/skills/web-appearance/SKILL.md +24 -1
  82. package/dist/general-knowledge/skills/web-dashboard/SKILL.canvas-worker-off.md +37 -9
  83. package/dist/general-knowledge/skills/web-dashboard/SKILL.md +44 -11
  84. package/dist/instance-config-impact.js +10 -5
  85. package/dist/instance-config-impact.js.map +1 -1
  86. package/dist/instance-lifecycle.d.ts +19 -0
  87. package/dist/instance-lifecycle.js +55 -12
  88. package/dist/instance-lifecycle.js.map +1 -1
  89. package/dist/kiro-db-reader.d.ts +5 -0
  90. package/dist/kiro-db-reader.js +18 -0
  91. package/dist/kiro-db-reader.js.map +1 -1
  92. package/dist/kiro-engine-status.d.ts +2 -0
  93. package/dist/kiro-engine-status.js +9 -0
  94. package/dist/kiro-engine-status.js.map +1 -1
  95. package/dist/kiro-migrate.d.ts +49 -0
  96. package/dist/kiro-migrate.js +105 -0
  97. package/dist/kiro-migrate.js.map +1 -0
  98. package/dist/kiro-transcript-lane.d.ts +2 -0
  99. package/dist/kiro-transcript-lane.js.map +1 -1
  100. package/dist/kiro-transcript-worker.js +1 -0
  101. package/dist/kiro-transcript-worker.js.map +1 -1
  102. package/dist/kiro-tui-forensic.d.ts +7 -0
  103. package/dist/kiro-tui-forensic.js +110 -0
  104. package/dist/kiro-tui-forensic.js.map +1 -0
  105. package/dist/kiro-usage-run.d.ts +7 -0
  106. package/dist/kiro-usage-run.js +39 -0
  107. package/dist/kiro-usage-run.js.map +1 -0
  108. package/dist/kiro-usage-scan.d.ts +49 -0
  109. package/dist/kiro-usage-scan.js +223 -0
  110. package/dist/kiro-usage-scan.js.map +1 -0
  111. package/dist/kiro-usage-worker.d.ts +1 -0
  112. package/dist/kiro-usage-worker.js +10 -0
  113. package/dist/kiro-usage-worker.js.map +1 -0
  114. package/dist/kiro-usage.d.ts +58 -0
  115. package/dist/kiro-usage.js +310 -0
  116. package/dist/kiro-usage.js.map +1 -0
  117. package/dist/locale.js +88 -8
  118. package/dist/locale.js.map +1 -1
  119. package/dist/log-service.js +1 -1
  120. package/dist/log-service.js.map +1 -1
  121. package/dist/login-url.d.ts +4 -0
  122. package/dist/login-url.js +22 -0
  123. package/dist/login-url.js.map +1 -0
  124. package/dist/needs-you-hub.d.ts +2 -1
  125. package/dist/needs-you-hub.js +1 -1
  126. package/dist/needs-you-hub.js.map +1 -1
  127. package/dist/needs-you.d.ts +8 -2
  128. package/dist/needs-you.js +6 -0
  129. package/dist/needs-you.js.map +1 -1
  130. package/dist/notice-delivery.d.ts +16 -0
  131. package/dist/notice-delivery.js +35 -0
  132. package/dist/notice-delivery.js.map +1 -0
  133. package/dist/office-share-page.d.ts +16 -0
  134. package/dist/office-share-page.js +85 -0
  135. package/dist/office-share-page.js.map +1 -0
  136. package/dist/office-share-service.d.ts +91 -0
  137. package/dist/office-share-service.js +176 -0
  138. package/dist/office-share-service.js.map +1 -0
  139. package/dist/office-share.d.ts +258 -0
  140. package/dist/office-share.js +549 -0
  141. package/dist/office-share.js.map +1 -0
  142. package/dist/opencode-usage-scan.d.ts +28 -0
  143. package/dist/opencode-usage-scan.js +92 -0
  144. package/dist/opencode-usage-scan.js.map +1 -0
  145. package/dist/opencode-usage-worker.d.ts +1 -0
  146. package/dist/opencode-usage-worker.js +10 -0
  147. package/dist/opencode-usage-worker.js.map +1 -0
  148. package/dist/outbound-handlers.js +22 -2
  149. package/dist/outbound-handlers.js.map +1 -1
  150. package/dist/outbound-schemas.d.ts +26 -2
  151. package/dist/outbound-schemas.js +27 -2
  152. package/dist/outbound-schemas.js.map +1 -1
  153. package/dist/public-web-gateway.js +7 -1
  154. package/dist/public-web-gateway.js.map +1 -1
  155. package/dist/quickstart-api.js +13 -2
  156. package/dist/quickstart-api.js.map +1 -1
  157. package/dist/quickstart.js +2 -1
  158. package/dist/quickstart.js.map +1 -1
  159. package/dist/remote-card-answer.d.ts +83 -0
  160. package/dist/remote-card-answer.js +208 -0
  161. package/dist/remote-card-answer.js.map +1 -0
  162. package/dist/reply-triggers.d.ts +2 -0
  163. package/dist/reply-triggers.js +3 -0
  164. package/dist/reply-triggers.js.map +1 -0
  165. package/dist/settings-api.d.ts +2 -0
  166. package/dist/settings-api.js +41 -16
  167. package/dist/settings-api.js.map +1 -1
  168. package/dist/settings-change.js +17 -14
  169. package/dist/settings-change.js.map +1 -1
  170. package/dist/settings-effect.js +7 -1
  171. package/dist/settings-effect.js.map +1 -1
  172. package/dist/settings-instance-patch.js +4 -1
  173. package/dist/settings-instance-patch.js.map +1 -1
  174. package/dist/setup-form.d.ts +1 -1
  175. package/dist/setup-form.js +55 -6
  176. package/dist/setup-form.js.map +1 -1
  177. package/dist/setup-host.d.ts +9 -0
  178. package/dist/setup-host.js +127 -6
  179. package/dist/setup-host.js.map +1 -1
  180. package/dist/setup-signin-assets.d.ts +2 -0
  181. package/dist/setup-signin-assets.js +6 -0
  182. package/dist/setup-signin-assets.js.map +1 -0
  183. package/dist/setup-wizard.js +2 -0
  184. package/dist/setup-wizard.js.map +1 -1
  185. package/dist/structured-signin-transport.d.ts +8 -0
  186. package/dist/structured-signin-transport.js +79 -0
  187. package/dist/structured-signin-transport.js.map +1 -0
  188. package/dist/structured-signin.d.ts +131 -0
  189. package/dist/structured-signin.js +388 -0
  190. package/dist/structured-signin.js.map +1 -0
  191. package/dist/tool-permissions.js +12 -0
  192. package/dist/tool-permissions.js.map +1 -1
  193. package/dist/topic-commands.js +6 -2
  194. package/dist/topic-commands.js.map +1 -1
  195. package/dist/transcript-sources.d.ts +26 -2
  196. package/dist/transcript-sources.js +103 -40
  197. package/dist/transcript-sources.js.map +1 -1
  198. package/dist/turn-reply-guard.d.ts +1 -1
  199. package/dist/turn-reply-guard.js +1 -1
  200. package/dist/turn-reply-guard.js.map +1 -1
  201. package/dist/types.d.ts +28 -8
  202. package/dist/ui/backend-signin.js +63 -10
  203. package/dist/ui/chat-strings.js +2 -2
  204. package/dist/ui/fleet-office-editor.js +14 -9
  205. package/dist/ui/fleet-office-layout.js +70 -32
  206. package/dist/ui/fleet-office-model.js +6 -3
  207. package/dist/ui/fleet-office-overview.js +167 -0
  208. package/dist/ui/fleet-office-pack.d.ts +7 -2
  209. package/dist/ui/fleet-office-pack.js +119 -15
  210. package/dist/ui/fleet-office-skin.js +98 -23
  211. package/dist/ui/fleet-office-store.js +39 -5
  212. package/dist/ui/fleet-office-view.js +5 -4
  213. package/dist/ui/fleet-office-zones.js +172 -12
  214. package/dist/ui/fleet-office.js +547 -186
  215. package/dist/ui/fleet-usage.js +19 -15
  216. package/dist/ui/office-share-dialog.js +145 -0
  217. package/dist/ui/office-share-page.js +164 -0
  218. package/dist/ui/panel-chat.js +8 -1
  219. package/dist/ui/panel-log.js +2 -2
  220. package/dist/ui/panel-needs.js +4 -4
  221. package/dist/ui/panel-settings.js +37 -11
  222. package/dist/ui/settings-dialogs.js +8 -1
  223. package/dist/ui/settings-guests.js +17 -7
  224. package/dist/ui/settings-model.js +14 -6
  225. package/dist/ui/settings-registry.js +4 -0
  226. package/dist/ui/settings-strings.js +16 -2
  227. package/dist/ui/shared/app-i18n.js +4 -2
  228. package/dist/ui/shared/app-shell.js +14 -6
  229. package/dist/ui/shared/app-stream.js +2 -1
  230. package/dist/ui/shared/app.css +67 -2
  231. package/dist/ui/shared/office/cozy.png +0 -0
  232. package/dist/ui/shared/side-panel.js +95 -0
  233. package/dist/ui/structured-signin.js +115 -0
  234. package/dist/usage-report.d.ts +20 -0
  235. package/dist/usage-report.js +54 -17
  236. package/dist/usage-report.js.map +1 -1
  237. package/dist/usage-rollup.d.ts +9 -1
  238. package/dist/usage-rollup.js +20 -4
  239. package/dist/usage-rollup.js.map +1 -1
  240. package/dist/web-api.d.ts +18 -0
  241. package/dist/web-api.js +201 -0
  242. package/dist/web-api.js.map +1 -1
  243. package/dist/web-auth.js +1 -1
  244. package/dist/web-auth.js.map +1 -1
  245. package/dist/web-backend-login.d.ts +1 -7
  246. package/dist/web-backend-login.js +2 -24
  247. package/dist/web-backend-login.js.map +1 -1
  248. package/dist/web-office-acts.d.ts +173 -0
  249. package/dist/web-office-acts.js +285 -0
  250. package/dist/web-office-acts.js.map +1 -0
  251. package/dist/web-office-skins.d.ts +3 -2
  252. package/dist/web-office-skins.js +3 -2
  253. package/dist/web-office-skins.js.map +1 -1
  254. package/dist/web-office-store.js +40 -7
  255. package/dist/web-office-store.js.map +1 -1
  256. package/dist/web-settings-patch.d.ts +2 -1
  257. package/dist/web-settings-patch.js +4 -1
  258. package/dist/web-settings-patch.js.map +1 -1
  259. package/dist/working-recovery.d.ts +2 -2
  260. package/dist/working-recovery.js +43 -8
  261. package/dist/working-recovery.js.map +1 -1
  262. package/dist/working-state-journal.d.ts +2 -0
  263. package/dist/working-state-journal.js +16 -1
  264. package/dist/working-state-journal.js.map +1 -1
  265. package/package.json +3 -2
  266. package/templates/windows-shortcuts.ps1 +155 -140
@@ -0,0 +1,86 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { availableParallelism, platform } from "node:os";
3
+ const defaultDeps = {
4
+ platform: platform(),
5
+ availableParallelism,
6
+ readFile: (path) => readFileSync(path, "utf8"),
7
+ };
8
+ export function effectiveCpuCount(deps = defaultDeps) {
9
+ const parallelism = Math.max(1, Math.floor(deps.availableParallelism()) || 1);
10
+ if (deps.platform !== "linux")
11
+ return parallelism;
12
+ const quota = cgroupCpuQuota(deps);
13
+ return quota == null ? parallelism : Math.max(1, Math.min(parallelism, Math.ceil(quota)));
14
+ }
15
+ /** The tightest CFS quota on this process, in CPUs; null when unlimited or unreadable. */
16
+ export function cgroupCpuQuota(deps) {
17
+ let selfCgroup;
18
+ try {
19
+ selfCgroup = deps.readFile("/proc/self/cgroup");
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ const lines = selfCgroup.split("\n");
25
+ const v2 = lines.find(l => l.startsWith("0::"));
26
+ if (v2) {
27
+ const fromV2 = v2Quota(deps, v2.slice(3).trim());
28
+ if (fromV2 != null)
29
+ return fromV2;
30
+ }
31
+ // Hybrid hosts list both; a v1 cpu controller line is "N:cpu,cpuacct:/path" (any order).
32
+ const v1 = lines.map(l => l.split(":")).find(p => p.length >= 3 && p[1].split(",").includes("cpu"));
33
+ return v1 ? v1Quota(deps, v1.slice(2).join(":").trim()) : null;
34
+ }
35
+ /** A cgroup's own quota says nothing about its parents': check every level up to the mount. */
36
+ function ancestry(base, path) {
37
+ const segments = path.split("/").filter(Boolean);
38
+ // A path outside our cgroup namespace ("/../..") does not exist under our mount: only the mount root applies.
39
+ if (segments.includes(".."))
40
+ return [base];
41
+ const dirs = [];
42
+ for (let i = segments.length; i >= 0; i--)
43
+ dirs.push([base, ...segments.slice(0, i)].join("/"));
44
+ return dirs;
45
+ }
46
+ function v2Quota(deps, path) {
47
+ let tightest = null;
48
+ for (const dir of ancestry("/sys/fs/cgroup", path)) {
49
+ let text;
50
+ try {
51
+ text = deps.readFile(`${dir}/cpu.max`);
52
+ }
53
+ catch {
54
+ continue;
55
+ }
56
+ const match = /^(\d+|max)\s+(\d+)\s*$/.exec(text.trim());
57
+ if (!match || match[1] === "max")
58
+ continue;
59
+ const cpus = Number(match[1]) / Number(match[2]);
60
+ if (Number.isFinite(cpus) && cpus > 0 && (tightest == null || cpus < tightest))
61
+ tightest = cpus;
62
+ }
63
+ return tightest;
64
+ }
65
+ function v1Quota(deps, path) {
66
+ let tightest = null;
67
+ for (const mount of ["/sys/fs/cgroup/cpu", "/sys/fs/cgroup/cpu,cpuacct"]) {
68
+ for (const dir of ancestry(mount, path)) {
69
+ let quota, period;
70
+ try {
71
+ quota = Number(deps.readFile(`${dir}/cpu.cfs_quota_us`).trim());
72
+ period = Number(deps.readFile(`${dir}/cpu.cfs_period_us`).trim());
73
+ }
74
+ catch {
75
+ continue;
76
+ }
77
+ if (!Number.isFinite(quota) || !Number.isFinite(period) || quota <= 0 || period <= 0)
78
+ continue; // -1 = unlimited
79
+ const cpus = quota / period;
80
+ if (tightest == null || cpus < tightest)
81
+ tightest = cpus;
82
+ }
83
+ }
84
+ return tightest;
85
+ }
86
+ //# sourceMappingURL=cpu-quota.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cpu-quota.js","sourceRoot":"","sources":["../src/cpu-quota.ts"],"names":[],"mappings":"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"}
package/dist/daemon.d.ts CHANGED
@@ -8,6 +8,7 @@ import { type PauseReason } from "./pause-marker.js";
8
8
  import { MessageBus } from "./channel/message-bus.js";
9
9
  import type { CliBackend, ErrorPattern, InstanceState, InstanceStateSnapshot } from "./backend/types.js";
10
10
  import { HangDetector } from "./hang-detector.js";
11
+ import { type RemoteCardAction, type RemoteCardOutcome } from "./remote-card-answer.js";
11
12
  import type { TmuxControlClient } from "./tmux-control.js";
12
13
  import type { FleetInstructionsParams } from "./instructions.js";
13
14
  import type { SpawnGate } from "./spawn-gate.js";
@@ -553,6 +554,12 @@ export declare class Daemon extends EventEmitter {
553
554
  private dialogParkedKey;
554
555
  private dialogParkedInteractionEpisode;
555
556
  private dialogParkedReported;
557
+ /** #2675: the card on screen that a person can answer from the chat — what it asks, since when, and whether it was posted. */
558
+ private remoteCardShown;
559
+ /** #2675: when (performance.now, taken before its capture) the newest read the card tracker used was started. */
560
+ private remoteCardReadAt;
561
+ /** #2675: an answer from the chat is being keyed in (one at a time). */
562
+ private remoteCardAnswering;
556
563
  /**
557
564
  * #1691: the prompt at the bottom of the pane that no backend table knows — its block, since when (performance.now)
558
565
  * it has been unchanged, and whether that has lasted UNRECOGNISED_PROMPT_STABLE_MS. Updated by the runtime scan.
@@ -935,6 +942,8 @@ export declare class Daemon extends EventEmitter {
935
942
  private lastDetectedErrorType;
936
943
  private static errorPatternKey;
937
944
  /** Read the occurrence baseline so a lifecycle-owned restart can carry it forward. */
945
+ /** #2648: kiro only — what a model error on the current launch should do (see kiro-retired-model.ts). */
946
+ kiroModelError(): import("./backend/kiro-retired-model.js").KiroModelErrorVerdict | null;
938
947
  getErrorPatternOccurrenceCount(type: ErrorPattern["type"], pattern: RegExp): number;
939
948
  /** Seed a replacement daemon with an already-reported pattern count. */
940
949
  seedErrorPatternOccurrenceCount(type: ErrorPattern["type"], pattern: RegExp, count: number): void;
@@ -1781,6 +1790,20 @@ export declare class Daemon extends EventEmitter {
1781
1790
  * dialog's static description and a count, never the pane: a pane can hold anything the agent printed.
1782
1791
  */
1783
1792
  private noteDialogAnswer;
1793
+ /**
1794
+ * #2675: a held card a person can answer from the chat (the dialog's remoteCard reader) is posted once it has stayed
1795
+ * the same card for REMOTE_CARD_STABLE_MS — `remote_card` with what it asks; the fleet posts it with its buttons. When
1796
+ * it closes or another card replaces it, `remote_card_gone` retires that post. Moving through the card (ours or the
1797
+ * person's in the pane) is the same card: its identity has no cursor. `readAt` is when the pane's capture was started
1798
+ * (performance.now): a read that started before the newest one used here finishes late and says nothing about now —
1799
+ * it may neither retire a newer card nor bring an older one back (#2677 review).
1800
+ */
1801
+ private trackRemoteCard;
1802
+ /**
1803
+ * #2675: answer the card on screen from the chat, as the person chose: only while it is the card they saw
1804
+ * (`identity`), on a verified cursor, under the pane write lock (remote-card-answer.ts). Never logs the answer.
1805
+ */
1806
+ answerRemoteCard(identity: string, action: RemoteCardAction): Promise<RemoteCardOutcome>;
1784
1807
  /**
1785
1808
  * Remember how long a blocking dialog has been on screen. Once it has
1786
1809
  * outlived DIALOG_PARKED_NOTIFY_MS — the auto-dismiss did not take, or the
package/dist/daemon.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { dashboardAccessOf } from "./dashboard-permissions.js";
1
2
  import { agentWhatsNew, agendVersion, planWhatsNew, readWhatsNewRecord, recordWhatsNew, whatsNewNotice } from "./agent-whats-new.js";
2
3
  import { join, dirname, resolve } from "node:path";
3
4
  import { checkoutTarget, readCheckouts, releaseCandidate, reposRoot, verifyWorktree, writeCheckouts } from "./repo-worktree-guard.js";
@@ -42,6 +43,7 @@ import { parseReplyButtons, replyButtonsFallbackText } from "./reply-buttons.js"
42
43
  import { HangDetector } from "./hang-detector.js";
43
44
  import { writeSecretFile } from "./secret-file.js";
44
45
  import { PaneWriteLock } from "./pane-write-lock.js";
46
+ import { answerRemoteCard } from "./remote-card-answer.js";
45
47
  import { buildFleetInstructions } from "./instructions.js";
46
48
  import { formatHumanInboundMessage, prepareDeliveryWire, steerInboundEnvelope, BTW_INBOUND_PREFIX, humanBodyHash, humanOwnerObjectId } from "./human-delivery-receipts.js";
47
49
  import { formatCrossInstanceInboundMessage, renderCrossInstanceHandoffMetadata, } from "./cross-instance-envelope.js";
@@ -86,6 +88,8 @@ const WEB_THEME_IPC = Object.freeze({
86
88
  apply_web_effect: "fleet_apply_web_effect",
87
89
  remove_web_effect: "fleet_remove_web_effect",
88
90
  delete_web_effect: "fleet_delete_web_effect",
91
+ // #2578: its own character in the Office view — the args as they are (the fleet checks them).
92
+ office_view: "fleet_office_view", office_set: "fleet_office_set",
89
93
  });
90
94
  /** The largest picture any slot may take (a card slot's ceiling; the fleet checks the limit in force): read no more. */
91
95
  const WEB_THEME_ASSET_MAX_BYTES = ASSET_UPLOAD_MAX_BYTES;
@@ -570,6 +574,8 @@ export const OWN_SWITCH_WAIT_MS = 6_000;
570
574
  const OWN_SWITCH_SETTLE_MS = 3_000;
571
575
  /** A blocking dialog still on screen this long after first being seen is reported for a human. */
572
576
  const DIALOG_PARKED_NOTIFY_MS = 60_000;
577
+ /** #2675: a card a person can answer from the chat is posted once it has been on screen, unchanged, this long. */
578
+ const REMOTE_CARD_STABLE_MS = 1_500;
573
579
  /** #1691: a prompt no table knows must sit unchanged this long (monotonic) before it holds deliveries and is reported. */
574
580
  export const UNRECOGNISED_PROMPT_STABLE_MS = 60_000;
575
581
  /** #1691: the rows under a prompt a backend without a composer reader shows its ready chrome in (status bar, hint). */
@@ -1254,6 +1260,12 @@ export class Daemon extends EventEmitter {
1254
1260
  dialogParkedKey = null;
1255
1261
  dialogParkedInteractionEpisode = null;
1256
1262
  dialogParkedReported = false;
1263
+ /** #2675: the card on screen that a person can answer from the chat — what it asks, since when, and whether it was posted. */
1264
+ remoteCardShown = null;
1265
+ /** #2675: when (performance.now, taken before its capture) the newest read the card tracker used was started. */
1266
+ remoteCardReadAt = -Infinity;
1267
+ /** #2675: an answer from the chat is being keyed in (one at a time). */
1268
+ remoteCardAnswering = false;
1257
1269
  /**
1258
1270
  * #1691: the prompt at the bottom of the pane that no backend table knows — its block, since when (performance.now)
1259
1271
  * it has been unchanged, and whether that has lasted UNRECOGNISED_PROMPT_STABLE_MS. Updated by the runtime scan.
@@ -1749,6 +1761,11 @@ export class Daemon extends EventEmitter {
1749
1761
  return `${ep.type}:${ep.pattern.source}`;
1750
1762
  }
1751
1763
  /** Read the occurrence baseline so a lifecycle-owned restart can carry it forward. */
1764
+ /** #2648: kiro only — what a model error on the current launch should do (see kiro-retired-model.ts). */
1765
+ kiroModelError() {
1766
+ const backend = this.backend;
1767
+ return typeof backend?.onModelError === "function" ? backend.onModelError() : null;
1768
+ }
1752
1769
  getErrorPatternOccurrenceCount(type, pattern) {
1753
1770
  return this.lastErrorCount.get(`${type}:${pattern.source}`) ?? 0;
1754
1771
  }
@@ -1825,6 +1842,9 @@ export class Daemon extends EventEmitter {
1825
1842
  this.spawnGate = spawnGate;
1826
1843
  this.stormWindow = stormWindow;
1827
1844
  this.backendOutage = backendOutage;
1845
+ // The live process owns its adopted configuration. Fleet defaults may be re-resolved in place after a save;
1846
+ // sharing that object would activate cold changes before the normal restart/apply boundary.
1847
+ this.config = structuredClone(config);
1828
1848
  if (!rootLogger)
1829
1849
  throw new Error("Daemon requires a shared root logger");
1830
1850
  this.runtimeIdentity ??= {
@@ -2400,7 +2420,7 @@ export class Daemon extends EventEmitter {
2400
2420
  // (statusline transcript); codex/kiro/opencode read their CLI's own
2401
2421
  // conversation store via a pluggable source. Backends with no known
2402
2422
  // source stay inert exactly as before.
2403
- this.transcriptMonitor = this.buildTranscriptMonitor(createTranscriptSource(this.config.backend ?? "claude-code", this.config.working_directory, this.credentialProfileStore()));
2423
+ this.transcriptMonitor = this.buildTranscriptMonitor(createTranscriptSource(this.config.backend ?? "claude-code", this.config.working_directory, this.credentialProfileStore(), () => this.backend?.transcriptLaunch?.() ?? null));
2404
2424
  const transcriptMonitor = this.transcriptMonitor;
2405
2425
  const transcriptFence = this.launchFenceEpoch;
2406
2426
  // Baseline in the isolate before this daemon accepts new work. A
@@ -3732,6 +3752,7 @@ export class Daemon extends EventEmitter {
3732
3752
  if (!answersBackedOff)
3733
3753
  this.dialogAnswers = null;
3734
3754
  this.trackDialogParked(blockingSeen);
3755
+ this.trackRemoteCard(blockingSeen, pane, captureMono);
3735
3756
  if (blockingSeen)
3736
3757
  return; // held dialog: skip error checks this cycle
3737
3758
  this.evaluateErrorPatterns(pane, patterns, readyPattern, Date.now(), busyPattern);
@@ -5851,8 +5872,8 @@ export class Daemon extends EventEmitter {
5851
5872
  generation: turn.generation,
5852
5873
  reason,
5853
5874
  recoveryStarted: true,
5875
+ message: formatReplyDropDetection(turn, reason),
5854
5876
  });
5855
- this.deliverReplyDropNotice("inst.reply_drop_retrying", "replydrop", "Reply-drop status", turn, reason, false);
5856
5877
  this.queueReplyRecoveryPrompt(turn);
5857
5878
  }
5858
5879
  reportReplyDropWithoutRetry(turn, reason) {
@@ -5862,8 +5883,8 @@ export class Daemon extends EventEmitter {
5862
5883
  generation: turn.generation,
5863
5884
  reason,
5864
5885
  recoveryStarted: false,
5886
+ message: formatReplyDropDetection(turn, reason),
5865
5887
  });
5866
- this.deliverReplyDropNotice("inst.reply_drop_unknown", "replydrop", "Unconfirmed reply status", turn, reason, true);
5867
5888
  }
5868
5889
  queueReplyRecoveryPrompt(turn) {
5869
5890
  const deliveryEpoch = this.deliveryEpoch;
@@ -5955,6 +5976,7 @@ export class Daemon extends EventEmitter {
5955
5976
  correlationId: turn.target.correlationId,
5956
5977
  generation: turn.generation,
5957
5978
  reason,
5979
+ message: formatReplyDropDetection(turn, reason),
5958
5980
  });
5959
5981
  this.deliverReplyDropNotice("inst.reply_drop_unrecovered", "replydropwarn", "Reply-drop recovery warning", turn, reason, true);
5960
5982
  }
@@ -5969,7 +5991,7 @@ export class Daemon extends EventEmitter {
5969
5991
  }
5970
5992
  this.lastReplyDropWarningAt = now;
5971
5993
  }
5972
- void this.deliverDaemonReply(t(key, formatReplyDropDetection(turn, reason)), kind, title, turn.target, true);
5994
+ void this.deliverDaemonReply(t(key), kind, title, turn.target, true);
5973
5995
  }
5974
5996
  /** Relay the pane's final text to the channel, marked as a daemon proxy reply. */
5975
5997
  async sendProxyReply(pane, target) {
@@ -6666,6 +6688,10 @@ export class Daemon extends EventEmitter {
6666
6688
  if (update.tool_progress === null || ["off", "standard", "verbose"].includes(String(update.tool_progress))) {
6667
6689
  this.updateToolProgress(update.tool_progress === null ? undefined : update.tool_progress);
6668
6690
  }
6691
+ if (typeof update.reply_triggers === "boolean")
6692
+ this.config.reply_triggers = update.reply_triggers;
6693
+ else if (update.reply_triggers === null)
6694
+ delete this.config.reply_triggers;
6669
6695
  if (typeof update.reply_completion_guard === "boolean") {
6670
6696
  this.config.reply_completion_guard = update.reply_completion_guard;
6671
6697
  }
@@ -6719,6 +6745,10 @@ export class Daemon extends EventEmitter {
6719
6745
  else if (update.board_cards_at_once === null)
6720
6746
  delete this.config.board_cards_at_once;
6721
6747
  // The fleet reads it at each tool call; kept current here for the next spawn's tool menu.
6748
+ if (typeof update.office_access === "boolean")
6749
+ this.config.office_access = update.office_access;
6750
+ else if (update.office_access === null)
6751
+ delete this.config.office_access;
6722
6752
  if (update.dashboard && typeof update.dashboard === "object" && !dashboardAccessProblem(update.dashboard))
6723
6753
  this.config.dashboard = update.dashboard;
6724
6754
  else if (update.dashboard === null)
@@ -7948,9 +7978,11 @@ export class Daemon extends EventEmitter {
7948
7978
  && dialogs.some(other => other !== dialog && Daemon.dialogMatches(other, pane)))
7949
7979
  continue;
7950
7980
  this.trackDialogParked(dialog);
7981
+ this.trackRemoteCard(dialog, pane, probeMono);
7951
7982
  return { state: "dialog", dialog };
7952
7983
  }
7953
7984
  this.trackDialogParked(null);
7985
+ this.trackRemoteCard(null, pane, probeMono);
7954
7986
  return { state: "clear" };
7955
7987
  }
7956
7988
  /**
@@ -8191,6 +8223,73 @@ export class Daemon extends EventEmitter {
8191
8223
  this.logger.warn({ dialog: dialog.description, attempts: episode.ignored, holdsDeliveries }, "Runtime dialog is ignoring AgEnD's answer — reporting for a human");
8192
8224
  this.emit("dialog_answer_ignored", { name: this.name, description: dialog.description, attempts: episode.ignored, holdsDeliveries });
8193
8225
  }
8226
+ /**
8227
+ * #2675: a held card a person can answer from the chat (the dialog's remoteCard reader) is posted once it has stayed
8228
+ * the same card for REMOTE_CARD_STABLE_MS — `remote_card` with what it asks; the fleet posts it with its buttons. When
8229
+ * it closes or another card replaces it, `remote_card_gone` retires that post. Moving through the card (ours or the
8230
+ * person's in the pane) is the same card: its identity has no cursor. `readAt` is when the pane's capture was started
8231
+ * (performance.now): a read that started before the newest one used here finishes late and says nothing about now —
8232
+ * it may neither retire a newer card nor bring an older one back (#2677 review).
8233
+ */
8234
+ trackRemoteCard(dialog, pane, readAt) {
8235
+ if (readAt < this.remoteCardReadAt)
8236
+ return;
8237
+ this.remoteCardReadAt = readAt;
8238
+ const card = dialog?.remoteCard?.(pane) ?? null;
8239
+ const shown = this.remoteCardShown;
8240
+ if (shown && shown.identity !== card?.identity) {
8241
+ this.remoteCardShown = null;
8242
+ if (shown.posted)
8243
+ this.emit("remote_card_gone", { name: this.name, identity: shown.identity });
8244
+ }
8245
+ if (!card)
8246
+ return;
8247
+ if (!this.remoteCardShown) {
8248
+ this.remoteCardShown = { identity: card.identity, since: performance.now(), posted: false };
8249
+ return;
8250
+ }
8251
+ if (this.remoteCardShown.posted || performance.now() - this.remoteCardShown.since < REMOTE_CARD_STABLE_MS)
8252
+ return;
8253
+ this.remoteCardShown.posted = true;
8254
+ this.logger.info({ kind: card.kind }, "A card a person can answer from the chat is on screen — posting it");
8255
+ this.emit("remote_card", { name: this.name, card });
8256
+ }
8257
+ /**
8258
+ * #2675: answer the card on screen from the chat, as the person chose: only while it is the card they saw
8259
+ * (`identity`), on a verified cursor, under the pane write lock (remote-card-answer.ts). Never logs the answer.
8260
+ */
8261
+ async answerRemoteCard(identity, action) {
8262
+ const tmux = this.tmux;
8263
+ const readers = this.runtimeDialogs().filter(dialog => dialog.remoteCard);
8264
+ if (!tmux || readers.length === 0)
8265
+ return { outcome: "stale" };
8266
+ if (this.remoteCardAnswering)
8267
+ return { outcome: "refused", reason: "another answer to this card is being keyed in" };
8268
+ this.remoteCardAnswering = true;
8269
+ try {
8270
+ const outcome = await answerRemoteCard({
8271
+ locked: fn => this.paneWriteLock.run(fn),
8272
+ // An unreadable screen (a failed capture, another spawn's pane) is unknown — never "the card closed".
8273
+ read: () => this.tmux === tmux ? tmux.capturePane().catch(() => null) : Promise.resolve(null),
8274
+ key: key => this.tmux !== tmux ? Promise.resolve(false) : key === "Space" ? tmux.sendKeys(" ") : tmux.sendSpecialKey(key),
8275
+ paste: text => this.tmux !== tmux ? Promise.resolve(false) : tmux.pasteBuffer(text),
8276
+ sleep: ms => new Promise(resolve => setTimeout(resolve, ms)),
8277
+ now: () => performance.now(),
8278
+ }, pane => {
8279
+ for (const dialog of readers) {
8280
+ const card = dialog.remoteCard(pane);
8281
+ if (card)
8282
+ return card;
8283
+ }
8284
+ return null;
8285
+ }, identity, action);
8286
+ this.logger.info({ action: action.kind, ...outcome }, "Answered a card from the chat");
8287
+ return outcome;
8288
+ }
8289
+ finally {
8290
+ this.remoteCardAnswering = false;
8291
+ }
8292
+ }
8194
8293
  /**
8195
8294
  * Remember how long a blocking dialog has been on screen. Once it has
8196
8295
  * outlived DIALOG_PARKED_NOTIFY_MS — the auto-dismiss did not take, or the
@@ -10821,7 +10920,7 @@ export class Daemon extends EventEmitter {
10821
10920
  fleetCwd: process.cwd(),
10822
10921
  onWarning: (warning) => {
10823
10922
  if (warning.problem === "fleet_dir_fallback") {
10824
- this.logger.warn({ field: warning.field, path: warning.path, legacyPath: warning.legacyPath }, `${warning.field} file: ref is not under the instance's working directory (${warning.path}); read ${warning.legacyPath} from the fleet directory instead — make the path absolute or move the file. The fallback is removed in 2.2.`);
10923
+ this.logger.warn({ field: warning.field, path: warning.path, legacyPath: warning.legacyPath }, `${warning.field} file: ref is not under the instance's working directory (${warning.path}); read ${warning.legacyPath} from the fleet directory instead — make the path absolute or move the file. A later release will remove this fallback.`);
10825
10924
  const key = `${warning.field}:${warning.path}`;
10826
10925
  if (!this.promptFileFallbackNoticed.has(key)) {
10827
10926
  this.promptFileFallbackNoticed.add(key);
@@ -10909,7 +11008,7 @@ export class Daemon extends EventEmitter {
10909
11008
  mcpEnv.AGEND_TOOL_SET = toolSet;
10910
11009
  // The dashboard features the person switched off: out of the tool menu from this start (the fleet refuses them
10911
11010
  // at once, whatever the menu still shows).
10912
- const dashboardOff = dashboardFeaturesOff(this.config.dashboard);
11011
+ const dashboardOff = dashboardFeaturesOff(dashboardAccessOf(this.config));
10913
11012
  if (dashboardOff.length)
10914
11013
  mcpEnv.AGEND_DASHBOARD_OFF = dashboardOff.join(",");
10915
11014
  if (this.config.display_name)
@@ -11348,7 +11447,7 @@ export class Daemon extends EventEmitter {
11348
11447
  // out loud — this start does NOT continue the previous conversation.
11349
11448
  this.logger.error({ attempts: failures }, "Giving up on resuming after repeated startup failures — starting fresh. "
11350
11449
  + "The previous conversation is NOT continued; its context is lost to this session.");
11351
- this.emit("context_lost", this.name, "resume_repeatedly_failed");
11450
+ this.emit("context_lost", this.name, "resume_repeatedly_failed", failures);
11352
11451
  }
11353
11452
  this.setSessionAside(proven ? "cli_reported_no_conversation" : "resume_failed_repeatedly");
11354
11453
  this.skipResume = true;