agentbox-app 0.1.7 → 0.1.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 (244) hide show
  1. package/README.md +209 -55
  2. package/bin/agentbox.mjs +6 -0
  3. package/briefs/message-rules.md +13 -3
  4. package/briefs/worker.md +63 -49
  5. package/briefs/writing-rules.md +90 -131
  6. package/main/account-discovery.mjs +21 -20
  7. package/main/account-tooling.mjs +9 -10
  8. package/main/agent-activity.mjs +45 -5
  9. package/main/agent-schedule.mjs +14 -14
  10. package/main/agent-sessions.mjs +94 -10
  11. package/main/agent-updates.mjs +114 -0
  12. package/main/agents.mjs +52 -46
  13. package/main/analytics.mjs +27 -0
  14. package/main/approval-prompt-server.mjs +2 -2
  15. package/main/artifact-path.mjs +11 -0
  16. package/main/claude-bin.mjs +31 -5
  17. package/main/claude-input.mjs +45 -3
  18. package/main/claude-plan.mjs +11 -11
  19. package/main/code-change.mjs +3 -3
  20. package/main/codex-account.mjs +1 -1
  21. package/main/codex-bin.mjs +17 -0
  22. package/main/codex-memory-gate.mjs +260 -0
  23. package/main/codex-models.mjs +12 -7
  24. package/main/codex-threads.mjs +46 -23
  25. package/main/codex-usage-file.mjs +7 -7
  26. package/main/codex-usage.mjs +4 -4
  27. package/main/codex-watch.mjs +12 -12
  28. package/main/config.mjs +68 -8
  29. package/main/dev-window.mjs +9 -9
  30. package/main/doc-scheme.mjs +2 -0
  31. package/main/engine-setup.mjs +193 -0
  32. package/main/feedback.mjs +55 -0
  33. package/main/folder-pictures.mjs +48 -0
  34. package/main/frame-scrollbars.mjs +90 -0
  35. package/main/fresh-user.mjs +6 -3
  36. package/main/git-change-offthread.mjs +70 -0
  37. package/main/git-change-thread.mjs +11 -0
  38. package/main/git-change.mjs +1 -1
  39. package/main/img-scheme.mjs +70 -1
  40. package/main/instruction-settings.mjs +92 -54
  41. package/main/ipc.mjs +316 -42
  42. package/main/leftovers.mjs +518 -0
  43. package/main/live-replies.mjs +43 -5
  44. package/main/machine.mjs +47 -0
  45. package/main/main.mjs +119 -15
  46. package/main/memory-gate-history.mjs +254 -0
  47. package/main/memory-gate-server.mjs +461 -0
  48. package/main/memory-gate.mjs +206 -0
  49. package/main/message-priority.mjs +87 -0
  50. package/main/rail-note.mjs +2 -2
  51. package/main/refresh-agent-models.mjs +20 -0
  52. package/main/repeats.mjs +4 -4
  53. package/main/row-label.mjs +114 -51
  54. package/main/serve.mjs +67 -5
  55. package/main/settings.mjs +223 -26
  56. package/main/ship-queue.mjs +279 -0
  57. package/main/sign-in-files.mjs +39 -0
  58. package/main/source-updater.mjs +298 -0
  59. package/main/store/home.mjs +47 -2
  60. package/main/store/work-items.mjs +150 -6
  61. package/main/store.mjs +235 -9
  62. package/main/supervisor.mjs +1444 -406
  63. package/main/task-commands.mjs +8 -10
  64. package/main/task-folders.mjs +74 -13
  65. package/main/task-remote-control.mjs +3 -3
  66. package/main/task-terminals.mjs +2 -1
  67. package/main/team/index.mjs +440 -0
  68. package/main/team/memory-cloud.mjs +247 -0
  69. package/main/team/projects.mjs +162 -0
  70. package/main/team/session.mjs +225 -0
  71. package/main/team/sign-in.mjs +106 -0
  72. package/main/team/supabase-backend.mjs +231 -0
  73. package/main/team/sync.mjs +163 -0
  74. package/main/updater.mjs +15 -5
  75. package/main/write-before-reload.mjs +50 -0
  76. package/mcp/core/page.mjs +9 -11
  77. package/mcp/core/work.mjs +91 -25
  78. package/mcp/tools.mjs +12 -6
  79. package/package.json +21 -9
  80. package/renderer/dist/assets/agentbox-icon-F1oN9nj_.svg +15 -0
  81. package/renderer/dist/assets/index-B-2Az952.css +32 -0
  82. package/renderer/dist/assets/index-D6qncgai.js +1168 -0
  83. package/renderer/dist/index.html +2 -2
  84. package/scripts/memory-gate-hook.sh +59 -0
  85. package/shared/agent-import.mjs +38 -15
  86. package/shared/agents.d.mts +26 -8
  87. package/shared/agents.mjs +100 -108
  88. package/shared/analytics-events.mjs +19 -2
  89. package/shared/answers.mjs +12 -0
  90. package/shared/bridge-map.d.mts +12 -0
  91. package/shared/bridge-map.mjs +37 -1
  92. package/shared/claude-commands.generated.mjs +2 -2
  93. package/shared/claude-models.generated.mjs +4 -4
  94. package/shared/claude-usage.mjs +6 -6
  95. package/shared/codex-import.mjs +7 -7
  96. package/shared/codex-modes.d.mts +50 -0
  97. package/shared/codex-usage.mjs +7 -8
  98. package/shared/demo-world.mjs +5 -5
  99. package/shared/engines.mjs +27 -10
  100. package/shared/feedback.d.mts +14 -0
  101. package/shared/feedback.mjs +44 -0
  102. package/shared/first-run-examples.mjs +4 -4
  103. package/shared/first-run-practice.d.mts +16 -0
  104. package/shared/first-run-practice.mjs +176 -70
  105. package/shared/fresh-user-home.mjs +22 -3
  106. package/shared/instruction-defaults.json +2 -2
  107. package/shared/product-name.mjs +4 -2
  108. package/shared/project-folder-check.mjs +6 -0
  109. package/shared/rank.d.mts +1 -0
  110. package/shared/rank.mjs +22 -0
  111. package/shared/referenced-files.mjs +1 -1
  112. package/shared/schemes.d.mts +11 -0
  113. package/shared/schemes.mjs +1 -1
  114. package/shared/shortcuts.d.mts +41 -0
  115. package/shared/shortcuts.mjs +236 -0
  116. package/shared/spawn-trouble.d.mts +2 -0
  117. package/shared/spawn-trouble.mjs +39 -18
  118. package/shared/team-rules.d.mts +17 -0
  119. package/shared/team-rules.mjs +230 -0
  120. package/shared/team-status.d.mts +11 -0
  121. package/shared/team-status.mjs +90 -0
  122. package/shared/terminal-links.d.mts +2 -0
  123. package/shared/terminal-links.mjs +55 -0
  124. package/shared/terminal-state.d.mts +1 -0
  125. package/shared/terminal-state.mjs +16 -0
  126. package/shared/thread-cards.d.mts +19 -0
  127. package/shared/thread-cards.mjs +254 -0
  128. package/shared/usage.d.mts +1 -1
  129. package/shared/usage.mjs +6 -7
  130. package/shared/work-items.mjs +255 -27
  131. package/shared/work-lines.mjs +393 -16
  132. package/worker-permissions.json +1 -1
  133. package/renderer/dist/assets/cel-dusk-CS5I7kJS.webp +0 -0
  134. package/renderer/dist/assets/cel-dusk-DUslqS6B.webp +0 -0
  135. package/renderer/dist/assets/cel-dusk-Jt_xVGxp.webp +0 -0
  136. package/renderer/dist/assets/cel-dusk-sm-BBkV-tWT.webp +0 -0
  137. package/renderer/dist/assets/frost-haze-CxPSOBEg.webp +0 -0
  138. package/renderer/dist/assets/frost-haze-sm-C_w21qgd.webp +0 -0
  139. package/renderer/dist/assets/ice-BC8luINc.webp +0 -0
  140. package/renderer/dist/assets/ice-CP9PrKHo.webp +0 -0
  141. package/renderer/dist/assets/ice-river-D6ziOhLY.webp +0 -0
  142. package/renderer/dist/assets/ice-river-UVM2-JY_.webp +0 -0
  143. package/renderer/dist/assets/ice-river-bErJwYWW.webp +0 -0
  144. package/renderer/dist/assets/ice-river-sm-Bg1U-SIj.webp +0 -0
  145. package/renderer/dist/assets/ice-sm-CbVcg3_D.webp +0 -0
  146. package/renderer/dist/assets/index-B7hhfHrT.js +0 -684
  147. package/renderer/dist/assets/index-CwiDv5bL.css +0 -32
  148. package/renderer/dist/assets/lake-C0WaW-6E.webp +0 -0
  149. package/renderer/dist/assets/lake-CSKjLC5K.webp +0 -0
  150. package/renderer/dist/assets/lake-ETGcOb25.webp +0 -0
  151. package/renderer/dist/assets/lake-harbour-BCQRbrHb.webp +0 -0
  152. package/renderer/dist/assets/lake-harbour-B_wfXTmE.webp +0 -0
  153. package/renderer/dist/assets/lake-harbour-Te1pEvBh.webp +0 -0
  154. package/renderer/dist/assets/lake-harbour-sm-Cme_ShEg.webp +0 -0
  155. package/renderer/dist/assets/lake-sm-CbG72Hbv.webp +0 -0
  156. package/renderer/dist/assets/lino-coast-CUZHcucI.webp +0 -0
  157. package/renderer/dist/assets/lino-coast-DP4J7cgd.webp +0 -0
  158. package/renderer/dist/assets/lino-coast-kOIAffr_.webp +0 -0
  159. package/renderer/dist/assets/lino-coast-sm-C1Mdbgit.webp +0 -0
  160. package/renderer/dist/assets/moon-pines-BskgnnXR.webp +0 -0
  161. package/renderer/dist/assets/moon-pines-CFSIIwt0.webp +0 -0
  162. package/renderer/dist/assets/moon-pines-PNhdOYww.webp +0 -0
  163. package/renderer/dist/assets/moon-pines-sm-C6K1NomK.webp +0 -0
  164. package/renderer/dist/assets/orbit-rings-2XV36Ch3.webp +0 -0
  165. package/renderer/dist/assets/orbit-rings-C4NrcYGQ.webp +0 -0
  166. package/renderer/dist/assets/orbit-rings-DGLk07dT.webp +0 -0
  167. package/renderer/dist/assets/orbit-rings-sm-Dky3YdvL.webp +0 -0
  168. package/renderer/dist/assets/peach-haze-2-C6f7xnWw.webp +0 -0
  169. package/renderer/dist/assets/peach-haze-2-sm-Dj_Ez_Sb.webp +0 -0
  170. package/renderer/dist/assets/pixel-harbour-DQjqMROg.webp +0 -0
  171. package/renderer/dist/assets/pixel-harbour-Dw71H_bc.webp +0 -0
  172. package/renderer/dist/assets/pixel-harbour-kOZfm-GM.webp +0 -0
  173. package/renderer/dist/assets/pixel-harbour-sm-Dturjuky.webp +0 -0
  174. package/renderer/dist/assets/pixel-orbit-C296JVMO.webp +0 -0
  175. package/renderer/dist/assets/pixel-orbit-C4oMRDSx.webp +0 -0
  176. package/renderer/dist/assets/pixel-orbit-CqVmQ4eh.webp +0 -0
  177. package/renderer/dist/assets/pixel-orbit-sm-CHagC_nO.webp +0 -0
  178. package/renderer/dist/assets/pixel-ridge-C6LYu6uE.webp +0 -0
  179. package/renderer/dist/assets/pixel-ridge-CIUCEESs.webp +0 -0
  180. package/renderer/dist/assets/pixel-ridge-sm-BnE0F_w-.webp +0 -0
  181. package/renderer/dist/assets/riso-hills-7heKVtry.webp +0 -0
  182. package/renderer/dist/assets/riso-hills-CIjAL3J6.webp +0 -0
  183. package/renderer/dist/assets/riso-hills-sm-DHsnbCfP.webp +0 -0
  184. package/renderer/dist/assets/slate-haze-BPWdkNsw.webp +0 -0
  185. package/renderer/dist/assets/slate-haze-sm-B0Cb5a2W.webp +0 -0
  186. package/renderer/dist/assets/valley-haze-BDHPqoJy.webp +0 -0
  187. package/renderer/dist/assets/valley-haze-sm-CTyjmPAG.webp +0 -0
  188. package/renderer/dist/assets/vector-dunes-DzzWLdKo.webp +0 -0
  189. package/renderer/dist/assets/vector-dunes-Yr9NBQUy.webp +0 -0
  190. package/renderer/dist/assets/vector-dunes-sm-D8MYY6ms.webp +0 -0
  191. package/renderer/dist/assets/watercolour-mist-BCGKN4u4.webp +0 -0
  192. package/renderer/dist/assets/watercolour-mist-BF-jk5MC.webp +0 -0
  193. package/renderer/dist/assets/watercolour-mist-sm-Ds1xzTw9.webp +0 -0
  194. package/renderer/dist/assets/woodblock-sea-B1um67Z9.webp +0 -0
  195. package/renderer/dist/assets/woodblock-sea-DKQdYs32.webp +0 -0
  196. package/renderer/dist/assets/woodblock-sea-sm-BJzNq8xh.webp +0 -0
  197. package/renderer/dist/emulator/audio-rules.mjs +0 -74
  198. package/renderer/dist/emulator/data/compression/README.md +0 -11
  199. package/renderer/dist/emulator/data/compression/extract7z.js +0 -1
  200. package/renderer/dist/emulator/data/compression/extractzip.js +0 -1
  201. package/renderer/dist/emulator/data/compression/libunrar.js +0 -519
  202. package/renderer/dist/emulator/data/compression/libunrar.wasm +0 -0
  203. package/renderer/dist/emulator/data/cores/README.md +0 -22
  204. package/renderer/dist/emulator/data/cores/mgba-legacy-wasm.data +0 -0
  205. package/renderer/dist/emulator/data/cores/mgba-thread-legacy-wasm.data +0 -0
  206. package/renderer/dist/emulator/data/cores/mgba-thread-wasm.data +0 -0
  207. package/renderer/dist/emulator/data/cores/mgba-wasm.data +0 -0
  208. package/renderer/dist/emulator/data/cores/package.json +0 -65
  209. package/renderer/dist/emulator/data/cores/reports/mgba.json +0 -1
  210. package/renderer/dist/emulator/data/emulator.css +0 -1614
  211. package/renderer/dist/emulator/data/loader.js +0 -170
  212. package/renderer/dist/emulator/data/localization/README.md +0 -63
  213. package/renderer/dist/emulator/data/localization/af-FR.json +0 -339
  214. package/renderer/dist/emulator/data/localization/ar-AR.json +0 -301
  215. package/renderer/dist/emulator/data/localization/ben-BEN.json +0 -301
  216. package/renderer/dist/emulator/data/localization/de-GER.json +0 -301
  217. package/renderer/dist/emulator/data/localization/el-GR.json +0 -301
  218. package/renderer/dist/emulator/data/localization/en-US.json +0 -339
  219. package/renderer/dist/emulator/data/localization/es-ES.json +0 -310
  220. package/renderer/dist/emulator/data/localization/fa-AF.json +0 -310
  221. package/renderer/dist/emulator/data/localization/hi-HI.json +0 -301
  222. package/renderer/dist/emulator/data/localization/it-IT.json +0 -302
  223. package/renderer/dist/emulator/data/localization/ja-JA.json +0 -301
  224. package/renderer/dist/emulator/data/localization/jv-JV.json +0 -301
  225. package/renderer/dist/emulator/data/localization/ko-KO.json +0 -336
  226. package/renderer/dist/emulator/data/localization/pt-BR.json +0 -361
  227. package/renderer/dist/emulator/data/localization/retroarch.json +0 -617
  228. package/renderer/dist/emulator/data/localization/ro-RO.json +0 -310
  229. package/renderer/dist/emulator/data/localization/ru-RU.json +0 -301
  230. package/renderer/dist/emulator/data/localization/tr-TR.json +0 -310
  231. package/renderer/dist/emulator/data/localization/vi-VN.json +0 -302
  232. package/renderer/dist/emulator/data/localization/zh-CN.json +0 -351
  233. package/renderer/dist/emulator/data/src/GameManager.js +0 -464
  234. package/renderer/dist/emulator/data/src/compression.js +0 -142
  235. package/renderer/dist/emulator/data/src/emulator.js +0 -6158
  236. package/renderer/dist/emulator/data/src/gamepad.js +0 -167
  237. package/renderer/dist/emulator/data/src/nipplejs.js +0 -1
  238. package/renderer/dist/emulator/data/src/shaders.js +0 -236
  239. package/renderer/dist/emulator/data/src/socket.io.min.js +0 -7
  240. package/renderer/dist/emulator/data/src/storage.js +0 -125
  241. package/renderer/dist/emulator/data/version.json +0 -5
  242. package/renderer/dist/emulator/host.js +0 -299
  243. package/renderer/dist/emulator/index.html +0 -28
  244. package/renderer/dist/emulator/provenance.json +0 -6
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Agentbox</title>
7
- <script type="module" crossorigin src="./assets/index-B7hhfHrT.js"></script>
8
- <link rel="stylesheet" crossorigin href="./assets/index-CwiDv5bL.css">
7
+ <script type="module" crossorigin src="./assets/index-D6qncgai.js"></script>
8
+ <link rel="stylesheet" crossorigin href="./assets/index-B-2Az952.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
@@ -0,0 +1,59 @@
1
+ #!/bin/sh
2
+ # ASK AGENTBOX WHETHER MEMORY ALLOWS THIS COMMAND, BEFORE IT RUNS (w-3958c3753d).
3
+ #
4
+ # Claude Code runs this as a PreToolUse hook on every Bash call of a worker
5
+ # Agentbox started ("pre"), and again after it ("post"). The answer comes from
6
+ # main/memory-gate-server.mjs over a local socket and is printed as it arrives:
7
+ # nothing at all means "carry on as normal", and a deny is JSON Claude Code
8
+ # reads. While the Mac is short of memory the answer simply arrives later.
9
+ #
10
+ # IT FAILS OPEN, FAST, ON PURPOSE. Measured on Claude Code 2.1.289: a hook that
11
+ # times out, crashes or prints garbage lets the command run anyway, so there is
12
+ # no strict fail-closed to be had. What this script promises instead is that it
13
+ # never hangs an agent: no socket means run now; a socket nobody answers on
14
+ # (the app crashed) is retried a few times in case another Agentbox takes over,
15
+ # then run now; and every wait ends inside the hook's own time limit.
16
+ #
17
+ # curl and not nc: macOS nc quits before a slow answer arrives. curl ships on
18
+ # every Mac, waits, and costs about 9 ms per check.
19
+
20
+ mode="$1"
21
+ sock="${AGENTBOX_GATE_SOCK:-}"
22
+ [ -n "$sock" ] && [ -S "$sock" ] || exit 0
23
+
24
+ input=$(cat)
25
+ [ -n "$input" ] || input=null
26
+
27
+ # Only what is safe to paste into JSON gets through from the environment.
28
+ clean() { printf '%s' "$1" | tr -cd 'A-Za-z0-9._-'; }
29
+ item=$(clean "${AGENTBOX_GATE_ITEM:-}")
30
+ product=$(clean "${AGENTBOX_GATE_PRODUCT:-}")
31
+ score="${AGENTBOX_GATE_SCORE:-0}"
32
+ case "$score" in ''|*[!0-9]*) score=0 ;; esac
33
+
34
+ body=$(printf '{"v":1,"event":"%s","item":"%s","product":"%s","score":%s,"ppid":%s,"hook":%s}' \
35
+ "$mode" "$item" "$product" "$score" "$PPID" "$input")
36
+
37
+ if [ "$mode" != pre ]; then
38
+ printf '%s' "$body" | curl -s --unix-socket "$sock" --max-time 5 --data-binary @- "http://agentbox/$mode" >/dev/null 2>&1
39
+ exit 0
40
+ fi
41
+
42
+ # curl runs as a child we can stop: if Claude Code stops this hook while it
43
+ # waits, curl goes with it, the connection closes, and the app forgets the
44
+ # request instead of holding its place in line. curl prints the answer itself.
45
+ pid=
46
+ trap '[ -n "$pid" ] && kill "$pid" 2>/dev/null; exit 0' TERM INT HUP
47
+ tries=0
48
+ while :; do
49
+ printf '%s' "$body" | curl -s -f --unix-socket "$sock" --max-time "${AGENTBOX_GATE_MAX_S:-1700}" --data-binary @- http://agentbox/pre &
50
+ pid=$!
51
+ wait "$pid"
52
+ code=$?
53
+ pid=
54
+ [ "$code" -eq 0 ] && exit 0
55
+ tries=$((tries + 1))
56
+ [ "$tries" -ge 5 ] && exit 0
57
+ [ -S "$sock" ] || exit 0
58
+ sleep "${AGENTBOX_GATE_RETRY_S:-1}"
59
+ done
@@ -106,16 +106,16 @@ export function agentsNeedingRows(chosen, existingItems = []) {
106
106
  return [...byName.values()];
107
107
  }
108
108
 
109
- /* ------------------------- AND THE THREADS SHE MEANT ----------------------- */
110
- // She was offered three things a picked thread could do and she picked the
111
- // plainest one. It does NOT resume the conversation, and that is the half these
112
- // words have to carry, because a row named after a conversation she had on
113
- // Friday is a row anybody would assume was carrying it on. So the body says, in
114
- // her vocabulary, that this starts fresh.
109
+ /* --------------------------- AND THE THREADS ----------------------------- */
110
+ // Of the three things a picked thread could do, this is the plainest one. It
111
+ // does NOT resume the conversation, and that is the half these words have to
112
+ // carry, because a row named after an earlier conversation is a row anybody
113
+ // would assume was carrying it on. So the body says, in plain words, that this
114
+ // starts fresh.
115
115
  //
116
116
  // Everything else is the agent import's shape, for the same reasons: one row per
117
- // thing she ticked, a label so a second press files nothing twice, and a
118
- // question so the supervisor waits for her rather than starting on its own.
117
+ // thing the user ticked, a label so a second press files nothing twice, and a
118
+ // question so the supervisor waits for the user rather than starting on its own.
119
119
 
120
120
  /** The label every imported thread carries. */
121
121
  export const THREAD_LABEL = 'thread-import';
@@ -128,9 +128,11 @@ export const threadLabel = (id) => `thread:${String(id ?? '').trim()}`;
128
128
  /**
129
129
  * WHEN SHE HAD IT, in the words a person uses about this week.
130
130
  *
131
- * The window is seven days (`RECENT_DAYS`, main/agent-sessions.mjs), so a day
132
- * name covers all of it and a date never has to appear. Anything the arithmetic
133
- * cannot place says nothing rather than guessing. */
131
+ * Inside a week a day name is the plain word. The window is ten days
132
+ * (`RECENT_DAYS`, main/agent-sessions.mjs), and past a week a day name would
133
+ * point at the wrong Monday, so those say the date. Anything the arithmetic
134
+ * cannot place, or anything far outside the window, says nothing rather than
135
+ * guessing. */
134
136
  export function whenWords(when, now = Date.now()) {
135
137
  const then = new Date(Number(when) || 0);
136
138
  if (!Number.isFinite(then.getTime()) || !when) return '';
@@ -139,6 +141,7 @@ export function whenWords(when, now = Date.now()) {
139
141
  if (days <= 0) return 'today';
140
142
  if (days === 1) return 'yesterday';
141
143
  if (days < 7) return `on ${then.toLocaleDateString('en-US', { weekday: 'long' })}`;
144
+ if (days < 14) return `on ${then.toLocaleDateString('en-US', { month: 'long', day: 'numeric' })}`;
142
145
  return '';
143
146
  }
144
147
 
@@ -151,10 +154,10 @@ export function startedIn(source) {
151
154
  /**
152
155
  * ONE IMPORTED THREAD'S WORDS.
153
156
  *
154
- * The title is the thread's own, which is the first thing she typed into it, so
155
- * the row in her inbox is called what she would call it. Ours is not added in
156
- * front of it: a list of rows all opening with the same three words is a list
157
- * she has to read past to find which is which.
157
+ * The title is the thread's own, which is the first thing the user typed into
158
+ * it, so the row in the inbox is called what they would call it. Ours is not
159
+ * added in front of it: a list of rows all opening with the same three words is
160
+ * a list that has to be read past to find which is which.
158
161
  *
159
162
  * The last paragraph is the honest one. Agentbox read the top of the transcript
160
163
  * to find this name and nothing else, and the reply starts a fresh session. A
@@ -207,6 +210,26 @@ export function threadsNeedingRows(chosen, existingItems = []) {
207
210
  return [...byId.values()];
208
211
  }
209
212
 
213
+ /**
214
+ * WHICH CONVERSATIONS ARE ALREADY IN, so the card offers only the rest
215
+ * (w-db6f5e331e). A Claude Code conversation is in once any row carries
216
+ * `thread:<id>`; a Codex one once any row carries `codex:<id>`, except the
217
+ * row that records a no, because the card is the way back to that one. Each
218
+ * thread comes back as it was, with `imported: true` on the ones that are in. */
219
+ export function markImported(threads = [], items = []) {
220
+ const inbox = new Set();
221
+ for (const item of items ?? []) {
222
+ const labels = item?.labels ?? [];
223
+ const declined = labels.includes('not-imported') && item?.status === 'done';
224
+ for (const label of labels) {
225
+ if (typeof label !== 'string') continue;
226
+ if (label.startsWith('thread:')) inbox.add(label.slice(7));
227
+ else if (label.startsWith('codex:') && !declined) inbox.add(label.slice(6));
228
+ }
229
+ }
230
+ return (threads ?? []).map((t) => (inbox.has(String(t?.id ?? '')) ? { ...t, imported: true } : t));
231
+ }
232
+
210
233
  /**
211
234
  * WHICH AGENT A ROW IS ABOUT, or null for every other row in the inbox.
212
235
  *
@@ -17,20 +17,20 @@ export interface AgentLike {
17
17
  // paragraphs that said what was done.
18
18
  lastSaid?: string;
19
19
  saidAt?: number;
20
- // The session's own one-line title of itself, the last thing SHE typed into
20
+ // The session's own one-line title of itself, the last thing the user typed into
21
21
  // it, and the files it has had its hands on. Read off the transcript tail
22
22
  // that main/agents.mjs was already reading.
23
23
  about?: string;
24
24
  lastAsked?: string;
25
25
  touched?: string[];
26
- // EVERY MESSAGE SHE TYPED into that session, oldest first. The first one is
26
+ // EVERY MESSAGE THE USER TYPED into that session, oldest first. The first one is
27
27
  // the ask and is what makes a five-day-old card recallable; the rest say
28
28
  // where the thread got to.
29
29
  asked?: { at: number; text: string }[];
30
30
  product?: string | null;
31
31
  productName?: string | null;
32
32
  startedByZero?: boolean;
33
- // The moment SHE said she would come back to it, and when she said so.
33
+ // The moment the user said they would come back to it, and when they said so.
34
34
  // Set by the founder alone; main/agent-schedule.mjs keeps it.
35
35
  runAt?: number;
36
36
  runAtSetAt?: number;
@@ -56,15 +56,15 @@ export function howLong(ms: number): string;
56
56
  export function whereItRuns(agent: AgentLike): string;
57
57
  export function lastWord(agent: AgentLike, budget?: number): string;
58
58
  // The END of its last reply, which is where an agent puts its answer. `lastWord`
59
- // takes the front, which is right for her words and wrong for its own.
59
+ // takes the front, which is right for the user's words and wrong for its own.
60
60
  export function howItEnded(raw: string | null | undefined, budget?: number): string;
61
61
  export function lastAsk(agent: AgentLike, budget?: number): string;
62
62
  export function whatItIs(agent: AgentLike): string;
63
63
  export function agentTitle(agent: AgentLike, now?: number): string;
64
64
  export function herWords(agent: AgentLike): { at: number; text: string }[];
65
65
 
66
- // One shape, hers, picked 2026-08-17: the message she started it with, up to
67
- // three later messages of hers, where it stopped, where it is working. There is
66
+ // One shape: the message the user started it with, up to three later messages
67
+ // of theirs, where it stopped, where it is working. There is
68
68
  // no setting and no second shape on purpose.
69
69
  export function agentRow(
70
70
  agent: AgentLike,
@@ -107,7 +107,7 @@ export interface AgentTurnLike {
107
107
  kind?: undefined;
108
108
  }
109
109
 
110
- // ONE THING THE AGENT RAN, between two messages. Shape B, hers.
110
+ // ONE THING THE AGENT RAN, between two messages. Shape B.
111
111
  export interface AgentWorkLike {
112
112
  kind: 'work';
113
113
  at: number;
@@ -127,7 +127,7 @@ export type AgentEventLike = AgentTurnLike | AgentWorkLike;
127
127
  export const WORK_CHARS: number;
128
128
  export const WORK_RUN: number;
129
129
  export const WORK_TOTAL: number;
130
- // WHAT A TOOL CALL SAYS — the three rules her 2026-08-20 report split apart:
130
+ // WHAT A TOOL CALL SAYS, in three rules:
131
131
  // the verb, the subject and the fold. Implemented in shared/work-lines.mjs and
132
132
  // re-exported from shared/agents.mjs so nothing needs a second import.
133
133
  export function workVerb(name: string): string;
@@ -139,6 +139,15 @@ export function workSubject(
139
139
  export function fullSubject(input: Record<string, unknown> | null | undefined): string;
140
140
  export function shortPath(raw: string, cwd?: string, home?: string): string;
141
141
  export function plainCommand(raw: string): string;
142
+ // What a shell command did, in words, or null to leave it as the command. And
143
+ // the steps that are the store's own records rather than the work, which are
144
+ // not drawn at all.
145
+ export function commandWork(
146
+ raw: string | null | undefined,
147
+ cwd?: string,
148
+ home?: string,
149
+ ): { verb: string; doing: string; subject: string } | null;
150
+ export function isBookkeeping(name: string | null | undefined): boolean;
142
151
  export const RUN_MIN: number;
143
152
  export function groupWork<T extends { kind?: string }>(
144
153
  events: T[],
@@ -183,6 +192,15 @@ export function capRuns(
183
192
  export function saidCount(events: AgentEventLike[]): number;
184
193
  export const TRAIL_OPENING: number;
185
194
  export const TRAIL_TURNS: number;
195
+ // TOOL-CALL SCAFFOLDING THAT LEAKED INTO THE PROSE, cut off the end of it.
196
+ // item-thread.ts has read this since it was written and it was simply missing
197
+ // from this file, which is why the screen's typecheck could not see it.
198
+ //
199
+ // A string in and a string out, which is every typed caller. The .mjs also
200
+ // hands anything that is not a string straight back, for the untyped callers
201
+ // that pass it whatever a stored field held; a declaration saying so would
202
+ // have to lie about the string case, so the guard stays a runtime one.
203
+ export function unleaked(text: string): string;
186
204
  export function conversationWindow(
187
205
  turns: AgentTurnLike[],
188
206
  bounds?: { opening?: number; keep?: number },