agentbox-app 0.1.12 → 0.1.16
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.
- package/README.md +24 -9
- package/bin/agentbox.mjs +23 -1
- package/briefs/message-rules.md +36 -8
- package/briefs/worker.md +46 -23
- package/main/account-discovery.mjs +122 -30
- package/main/account-tooling.mjs +29 -1
- package/main/account-usage.mjs +46 -0
- package/main/acp.mjs +296 -0
- package/main/agent-homes.mjs +158 -0
- package/main/agent-sessions.mjs +311 -260
- package/main/agent-updates.mjs +9 -22
- package/main/agents.mjs +179 -466
- package/main/analytics.mjs +42 -2
- package/main/answer-modes.mjs +103 -37
- package/main/approval-prompt-core.mjs +197 -0
- package/main/approval-prompt-server.mjs +4 -138
- package/main/approvals.mjs +101 -297
- package/main/artifact-path.mjs +47 -18
- package/main/claude-bin.mjs +45 -311
- package/main/claude-input.mjs +57 -7
- package/main/claude-launch-env.mjs +54 -0
- package/main/claude-models.mjs +39 -7
- package/main/claude-plan.mjs +64 -16
- package/main/claude-session-open.mjs +28 -0
- package/main/claude-usage-process.mjs +40 -0
- package/main/claude-usage.mjs +94 -59
- package/main/cloud/account.mjs +179 -0
- package/main/cloud/aws.mjs +127 -0
- package/main/cloud/browser-return.mjs +58 -0
- package/main/cloud/clients.mjs +15 -0
- package/main/cloud/codex-cloud.mjs +53 -0
- package/main/cloud/config.mjs +107 -0
- package/main/cloud/docs.mjs +219 -0
- package/main/cloud/exec.mjs +27 -0
- package/main/cloud/host.mjs +165 -0
- package/main/cloud/kit.mjs +80 -0
- package/main/cloud/logins.mjs +543 -0
- package/main/cloud/managed.mjs +115 -0
- package/main/cloud/marker.mjs +104 -0
- package/main/cloud/org.mjs +53 -0
- package/main/cloud/reuse.mjs +208 -0
- package/main/cloud/run-cli.mjs +177 -0
- package/main/cloud/run.mjs +1934 -0
- package/main/cloud/usage.mjs +76 -0
- package/main/cloud-permission.mjs +51 -0
- package/main/codex-account.mjs +78 -0
- package/main/codex-app-server.mjs +276 -409
- package/main/codex-approvals.mjs +148 -433
- package/main/codex-bin.mjs +51 -249
- package/main/codex-models.mjs +20 -2
- package/main/codex-session.mjs +246 -506
- package/main/codex-threads-worker.mjs +12 -0
- package/main/codex-threads.mjs +112 -11
- package/main/codex-usage-file.mjs +5 -3
- package/main/codex-usage.mjs +56 -7
- package/main/codex-watch.mjs +83 -5
- package/main/codex.mjs +95 -363
- package/main/config.mjs +37 -5
- package/main/corner-tag.mjs +810 -0
- package/main/crash-report.mjs +26 -3
- package/main/dev-window.mjs +1 -1
- package/main/engine-bin.mjs +545 -0
- package/main/engine-setup.mjs +25 -24
- package/main/feedback.mjs +14 -31
- package/main/folder-pictures.mjs +2 -2
- package/main/freeze-recorder-thread.mjs +86 -0
- package/main/freeze-recorder.mjs +146 -0
- package/main/fresh-user.mjs +20 -9
- package/main/git-change-offthread.mjs +17 -3
- package/main/git-change-thread.mjs +5 -2
- package/main/harnesses/claude-stream.mjs +208 -0
- package/main/harnesses/claude.mjs +105 -0
- package/main/harnesses/codex.mjs +72 -0
- package/main/harnesses/common.mjs +78 -0
- package/main/harnesses/instructions-file.mjs +116 -0
- package/main/harnesses/opencode.mjs +234 -0
- package/main/harnesses.mjs +65 -0
- package/main/importable-threads.mjs +96 -0
- package/main/ipc.mjs +520 -135
- package/main/leftovers.mjs +117 -25
- package/main/liquid-glass.mjs +26 -0
- package/main/live-replies.mjs +10 -4
- package/main/local-app-frames.mjs +82 -0
- package/main/main-went-red.mjs +330 -0
- package/main/main.mjs +248 -37
- package/main/memory-gate-history.mjs +85 -20
- package/main/memory-gate-server.mjs +129 -11
- package/main/memory-gate.mjs +62 -8
- package/main/memory-log.mjs +124 -0
- package/main/menu.mjs +4 -2
- package/main/message-priority.mjs +2 -2
- package/main/mic.mjs +38 -0
- package/main/native/liquid-glass/build/liquid-glass.node +0 -0
- package/main/new-chats-watch.mjs +110 -0
- package/main/new-user-window.mjs +25 -0
- package/main/notify.mjs +64 -5
- package/main/opencode-server.mjs +271 -0
- package/main/opencode.mjs +287 -0
- package/main/phone-alerts.mjs +117 -0
- package/main/phone-inbox.mjs +625 -0
- package/main/phone-link.mjs +571 -0
- package/main/phone-uploads.mjs +476 -0
- package/main/picture-shape.mjs +114 -0
- package/main/quit-sequence.mjs +143 -0
- package/main/refresh-agent-models.mjs +15 -2
- package/main/relay-address.mjs +28 -0
- package/main/relay-client.mjs +314 -0
- package/main/repeats.mjs +10 -4
- package/main/row-label.mjs +18 -47
- package/main/run-change.mjs +13 -0
- package/main/run-ledger.mjs +135 -0
- package/main/runs-on.mjs +32 -35
- package/main/save-attachments.mjs +41 -0
- package/main/serve.mjs +155 -9
- package/main/settings.mjs +364 -50
- package/main/shell-path.mjs +234 -0
- package/main/ship-conflict-brief.mjs +119 -0
- package/main/ship-queue.mjs +134 -20
- package/main/sign-in-files.mjs +3 -7
- package/main/source-updater.mjs +45 -11
- package/main/stage-attachment.mjs +68 -0
- package/main/stall-watch.mjs +50 -0
- package/main/start-hold.mjs +73 -0
- package/main/store/home.mjs +87 -232
- package/main/store/paths.mjs +11 -0
- package/main/store/teammates-files.mjs +99 -0
- package/main/store/work-items.mjs +231 -13
- package/main/store.mjs +227 -53
- package/main/supervisor.mjs +3865 -699
- package/main/task-commands.mjs +13 -17
- package/main/task-folders-offthread.mjs +6 -1
- package/main/task-folders.mjs +897 -105
- package/main/task-terminals.mjs +147 -41
- package/main/team/index.mjs +114 -10
- package/main/team/memory-cloud.mjs +183 -1
- package/main/team/room-hours.mjs +48 -0
- package/main/team/room-setup.mjs +31 -0
- package/main/team/rooms-memory.mjs +454 -0
- package/main/team/rooms-shape.mjs +42 -0
- package/main/team/rooms-supabase.mjs +324 -0
- package/main/team/rooms.mjs +575 -0
- package/main/team/session.mjs +96 -26
- package/main/team/supabase-backend.mjs +180 -0
- package/main/team/sync.mjs +109 -1
- package/main/teammates.mjs +580 -0
- package/main/terminal-host.mjs +143 -0
- package/main/terminal-hosts.mjs +261 -0
- package/main/transcript-search.mjs +80 -0
- package/main/updater.mjs +71 -9
- package/main/webview-guard.mjs +45 -0
- package/main/worktree-include.mjs +365 -0
- package/mcp/core/documents.mjs +3 -1
- package/mcp/core/repeats.mjs +88 -0
- package/mcp/core/teammates.mjs +222 -0
- package/mcp/core/work.mjs +76 -4
- package/mcp/stdio.mjs +24 -11
- package/mcp/tools.mjs +116 -8
- package/package.json +30 -5
- package/renderer/dist/assets/abnfDiagram-YUKMZFIV-CoWB6YUK.js +1 -0
- package/renderer/dist/assets/arc-Ch0NrCul.js +1 -0
- package/renderer/dist/assets/architectureDiagram-47P4ROYG-CXz9M5tQ.js +36 -0
- package/renderer/dist/assets/blockDiagram-E7TT5TSB-DchGUuHH.js +140 -0
- package/renderer/dist/assets/c4Diagram-CRA5TL53-Cip-zNyr.js +38 -0
- package/renderer/dist/assets/channel-BQuQSL--.js +1 -0
- package/renderer/dist/assets/chunk-2Q5K7J3B-BoXid_2r.js +1 -0
- package/renderer/dist/assets/chunk-5VM5RSS4-Cpez1rRz.js +15 -0
- package/renderer/dist/assets/chunk-7TKQ45FW-DKA84YkE.js +1 -0
- package/renderer/dist/assets/chunk-AW2ZBBNX-Dg-SumPG.js +88 -0
- package/renderer/dist/assets/chunk-FVRAUYC3-06TCvPm1.js +2 -0
- package/renderer/dist/assets/chunk-HTAEGDNF-CMEBy1Td.js +1 -0
- package/renderer/dist/assets/chunk-JWPE2WC7-BJ2ObmV-.js +1 -0
- package/renderer/dist/assets/chunk-KQW6MTUR-CGWOYXUE.js +1 -0
- package/renderer/dist/assets/chunk-XXDRQBXY-CiZp07XC.js +1 -0
- package/renderer/dist/assets/classDiagram-v2-K4WV4PDN-DJNIX719.js +217 -0
- package/renderer/dist/assets/cornerTag-CPgvu-q3.js +1 -0
- package/renderer/dist/assets/cornerTag-oMfEjzCO.css +1 -0
- package/renderer/dist/assets/cose-bilkent-JH36ORCC-CbkyZOUH.js +1 -0
- package/renderer/dist/assets/cynefin-EF2NZ3EQ-78iOroZO.js +141 -0
- package/renderer/dist/assets/cynefinDiagram-3GCD6N5R-GcCopMs7.js +62 -0
- package/renderer/dist/assets/cytoscape.esm-C5JX3QLV.js +331 -0
- package/renderer/dist/assets/dagre-W4DXFKR2-DHLlXLkz.js +4 -0
- package/renderer/dist/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/renderer/dist/assets/diagram-2UJZ2QOL-DuZSUHcH.js +200 -0
- package/renderer/dist/assets/diagram-OVF4WLC6-Ckxu3cqH.js +24 -0
- package/renderer/dist/assets/diagram-PFPMY2P6-CsTw9Ycn.js +30 -0
- package/renderer/dist/assets/diagram-UMYRVEAY-CTXd8qVg.js +24 -0
- package/renderer/dist/assets/diagram-YEKJPTXX-CJs1T_9m.js +41 -0
- package/renderer/dist/assets/diagram-ZIFT7M5P-CvjI23mf.js +3 -0
- package/renderer/dist/assets/ebnfDiagram-VR2GEFS7-d_IeAzOJ.js +1 -0
- package/renderer/dist/assets/elk-IJKZMXRS-zo9KFP3N.js +27 -0
- package/renderer/dist/assets/erDiagram-O2IAPWRE-DqfYf5Dt.js +99 -0
- package/renderer/dist/assets/flowDiagram-OXPTDLAJ-DAWsMLmo.js +213 -0
- package/renderer/dist/assets/ganttDiagram-R7TSEDQI-4ml_bhwR.js +292 -0
- package/renderer/dist/assets/gitGraphDiagram-XJZIOB7I-B_WcqSId.js +106 -0
- package/renderer/dist/assets/graph-DGbsTEsI.js +1 -0
- package/renderer/dist/assets/infoDiagram-5W2HQ5XZ-CI-jYqzc.js +2 -0
- package/renderer/dist/assets/init-Gi6I4Gst.js +1 -0
- package/renderer/dist/assets/ishikawaDiagram-K3B6WC7H-B56VWRlV.js +70 -0
- package/renderer/dist/assets/journeyDiagram-COXZFDF6-D1-p09Lr.js +139 -0
- package/renderer/dist/assets/kanban-definition-P3RFRI5V-Cv3w7JoN.js +89 -0
- package/renderer/dist/assets/katex-C5jXJg4s.js +257 -0
- package/renderer/dist/assets/linear-C35V2Spi.js +1 -0
- package/renderer/dist/assets/main-BcoBiGwv.css +32 -0
- package/renderer/dist/assets/main-CLnIOulD.js +1191 -0
- package/renderer/dist/assets/mermaid.core-BzGT5Vo9.js +314 -0
- package/renderer/dist/assets/mindmap-definition-LZFPQGKD-BZUfuymC.js +96 -0
- package/renderer/dist/assets/ordinal-Cboi1Yqb.js +1 -0
- package/renderer/dist/assets/pegDiagram-BGZESJAR-DFh9XNGe.js +1 -0
- package/renderer/dist/assets/pieDiagram-CAPJLFHJ-C65tPVsy.js +39 -0
- package/renderer/dist/assets/product-name-CSNW6d7s.js +40 -0
- package/renderer/dist/assets/quadrantDiagram-GDMTTRAM-Cushj_nk.js +7 -0
- package/renderer/dist/assets/railroadDiagram-SM67HX2B-DZGebGx5.js +1 -0
- package/renderer/dist/assets/requirementDiagram-X7JNWC4A-DpAB0MNo.js +84 -0
- package/renderer/dist/assets/sankeyDiagram-UM26HJRW-D-29rHra.js +40 -0
- package/renderer/dist/assets/sequenceDiagram-ZO4K6R2Y-FfOQAZol.js +169 -0
- package/renderer/dist/assets/sizeCapture-INFHLROL-C_n6fDBY.js +1 -0
- package/renderer/dist/assets/stateDiagram-v2-TBUQTH76-BZjenzJG.js +291 -0
- package/renderer/dist/assets/swimlanes-N4OXWK64-DxaMU9vX.js +1 -0
- package/renderer/dist/assets/swimlanesDiagram-K3J5GTZL-Cb2kM6rr.js +8 -0
- package/renderer/dist/assets/timeline-definition-YOQAKGHF-DTg5HJKz.js +120 -0
- package/renderer/dist/assets/usecaseDiagram-VIAY4XPW-Bc3MZDsl.js +370 -0
- package/renderer/dist/assets/vennDiagram-BLWOH2XV-GIVGk9Id.js +34 -0
- package/renderer/dist/assets/wardleyDiagram-YMQ3BMBF-NmJnbQOg.js +78 -0
- package/renderer/dist/assets/xychartDiagram-TAQBALBS-p-kfGfnW.js +7 -0
- package/renderer/dist/corner-tag.html +13 -0
- package/renderer/dist/emulator/audio-rules.mjs +74 -0
- package/renderer/dist/emulator/data/compression/README.md +11 -0
- package/renderer/dist/emulator/data/compression/extract7z.js +1 -0
- package/renderer/dist/emulator/data/compression/extractzip.js +1 -0
- package/renderer/dist/emulator/data/compression/libunrar.js +519 -0
- package/renderer/dist/emulator/data/compression/libunrar.wasm +0 -0
- package/renderer/dist/emulator/data/cores/README.md +22 -0
- package/renderer/dist/emulator/data/cores/mgba-legacy-wasm.data +0 -0
- package/renderer/dist/emulator/data/cores/mgba-thread-legacy-wasm.data +0 -0
- package/renderer/dist/emulator/data/cores/mgba-thread-wasm.data +0 -0
- package/renderer/dist/emulator/data/cores/mgba-wasm.data +0 -0
- package/renderer/dist/emulator/data/cores/package.json +65 -0
- package/renderer/dist/emulator/data/cores/reports/mgba.json +1 -0
- package/renderer/dist/emulator/data/emulator.css +1614 -0
- package/renderer/dist/emulator/data/loader.js +170 -0
- package/renderer/dist/emulator/data/localization/README.md +63 -0
- package/renderer/dist/emulator/data/localization/af-FR.json +339 -0
- package/renderer/dist/emulator/data/localization/ar-AR.json +301 -0
- package/renderer/dist/emulator/data/localization/ben-BEN.json +301 -0
- package/renderer/dist/emulator/data/localization/de-GER.json +301 -0
- package/renderer/dist/emulator/data/localization/el-GR.json +301 -0
- package/renderer/dist/emulator/data/localization/en-US.json +339 -0
- package/renderer/dist/emulator/data/localization/es-ES.json +310 -0
- package/renderer/dist/emulator/data/localization/fa-AF.json +310 -0
- package/renderer/dist/emulator/data/localization/hi-HI.json +301 -0
- package/renderer/dist/emulator/data/localization/it-IT.json +302 -0
- package/renderer/dist/emulator/data/localization/ja-JA.json +301 -0
- package/renderer/dist/emulator/data/localization/jv-JV.json +301 -0
- package/renderer/dist/emulator/data/localization/ko-KO.json +336 -0
- package/renderer/dist/emulator/data/localization/pt-BR.json +361 -0
- package/renderer/dist/emulator/data/localization/retroarch.json +617 -0
- package/renderer/dist/emulator/data/localization/ro-RO.json +310 -0
- package/renderer/dist/emulator/data/localization/ru-RU.json +301 -0
- package/renderer/dist/emulator/data/localization/tr-TR.json +310 -0
- package/renderer/dist/emulator/data/localization/vi-VN.json +302 -0
- package/renderer/dist/emulator/data/localization/zh-CN.json +351 -0
- package/renderer/dist/emulator/data/src/GameManager.js +464 -0
- package/renderer/dist/emulator/data/src/compression.js +142 -0
- package/renderer/dist/emulator/data/src/emulator.js +6158 -0
- package/renderer/dist/emulator/data/src/gamepad.js +167 -0
- package/renderer/dist/emulator/data/src/nipplejs.js +1 -0
- package/renderer/dist/emulator/data/src/shaders.js +236 -0
- package/renderer/dist/emulator/data/src/socket.io.min.js +7 -0
- package/renderer/dist/emulator/data/src/storage.js +125 -0
- package/renderer/dist/emulator/data/version.json +5 -0
- package/renderer/dist/emulator/host.js +297 -0
- package/renderer/dist/emulator/index.html +28 -0
- package/renderer/dist/emulator/provenance.json +6 -0
- package/renderer/dist/index.html +16 -3
- package/scripts/after-install.mjs +30 -8
- package/scripts/approval-server.sh +24 -5
- package/scripts/before-publish.mjs +12 -10
- package/scripts/cloud-shim.pl +57 -0
- package/shared/account-names.d.mts +6 -0
- package/shared/account-names.mjs +15 -0
- package/shared/agent-hours.mjs +136 -0
- package/shared/agent-import.mjs +62 -34
- package/shared/agents.d.mts +1 -0
- package/shared/agents.mjs +126 -522
- package/shared/analytics-events.mjs +12 -0
- package/shared/approval-card.mjs +36 -0
- package/shared/bridge-map.mjs +45 -1
- package/shared/claude-code-shape.mjs +6 -0
- package/shared/claude-commands.generated.mjs +6 -4
- package/shared/claude-models.generated.mjs +6 -4
- package/shared/claude-usage.d.mts +1 -0
- package/shared/claude-usage.mjs +42 -1
- package/shared/cloud-hand-back.d.mts +7 -0
- package/shared/cloud-hand-back.mjs +20 -0
- package/shared/cloud-kit.d.mts +219 -0
- package/shared/cloud-kit.mjs +341 -0
- package/shared/cloud-login-name.mjs +4 -0
- package/shared/cloud-start.mjs +17 -0
- package/shared/cloud-versions.mjs +23 -0
- package/shared/codex-import.mjs +2 -2
- package/shared/codex-modes.d.mts +22 -9
- package/shared/codex-modes.mjs +67 -11
- package/shared/codex-usage.mjs +108 -2
- package/shared/corner-tag.d.mts +36 -0
- package/shared/corner-tag.mjs +396 -0
- package/shared/dead-run-trace.mjs +19 -2
- package/shared/engines.mjs +76 -300
- package/shared/feedback.d.mts +7 -0
- package/shared/feedback.mjs +25 -0
- package/shared/first-run-practice.mjs +17 -24
- package/shared/harness-definitions.mjs +111 -0
- package/shared/instruction-defaults.json +2 -2
- package/shared/key-caps.d.mts +14 -0
- package/shared/key-caps.mjs +68 -0
- package/shared/message-edits.d.mts +7 -0
- package/shared/message-edits.mjs +35 -0
- package/shared/move-thread.d.mts +24 -0
- package/shared/move-thread.mjs +112 -0
- package/shared/named-threads.mjs +72 -0
- package/shared/not-shipped.d.mts +22 -0
- package/shared/not-shipped.mjs +89 -0
- package/shared/notify-rules.d.mts +31 -0
- package/shared/notify-rules.mjs +55 -8
- package/shared/phone-files.mjs +28 -0
- package/shared/phone-settings.mjs +118 -0
- package/shared/phone-snapshot.d.mts +16 -0
- package/shared/phone-snapshot.mjs +348 -0
- package/shared/picture-formats.d.mts +1 -0
- package/shared/picture-formats.mjs +13 -0
- package/shared/provider-commands.mjs +10 -2
- package/shared/rank.d.mts +4 -1
- package/shared/rank.mjs +82 -19
- package/shared/relay-address.mjs +6 -0
- package/shared/relay-crypto.mjs +165 -0
- package/shared/repeats.d.mts +8 -0
- package/shared/repeats.mjs +33 -2
- package/shared/room-cards.mjs +167 -0
- package/shared/room-links.d.mts +4 -0
- package/shared/room-links.mjs +21 -0
- package/shared/runs-on.d.mts +3 -13
- package/shared/runs-on.mjs +31 -52
- package/shared/shipped-note.d.mts +4 -0
- package/shared/shipped-note.mjs +6 -0
- package/shared/shortcuts.mjs +24 -10
- package/shared/spawn-trouble.d.mts +4 -0
- package/shared/spawn-trouble.mjs +484 -30
- package/shared/team-rules.mjs +9 -2
- package/shared/teammates.d.mts +19 -0
- package/shared/teammates.mjs +756 -0
- package/shared/terminal-focus.d.mts +1 -0
- package/shared/terminal-focus.mjs +13 -0
- package/shared/terminal-input.d.mts +1 -0
- package/shared/terminal-input.mjs +30 -0
- package/shared/terminal-keys.d.mts +1 -0
- package/shared/terminal-keys.mjs +16 -0
- package/shared/terminal-size.d.mts +4 -0
- package/shared/terminal-size.mjs +29 -0
- package/shared/thread-cards.mjs +4 -1
- package/shared/usage.d.mts +12 -0
- package/shared/usage.mjs +56 -3
- package/shared/websites.d.mts +15 -0
- package/shared/websites.mjs +61 -0
- package/shared/where-it-runs-from.d.mts +43 -0
- package/shared/where-it-runs-from.mjs +155 -0
- package/shared/work-items.mjs +150 -29
- package/shared/work-lines.mjs +93 -245
- package/shared/xterm-invalid-range.d.mts +2 -0
- package/shared/xterm-invalid-range.mjs +58 -0
- package/renderer/dist/assets/index-ChKsQkRw.js +0 -1169
- package/renderer/dist/assets/index-ClBXnq3B.css +0 -32
package/shared/work-items.mjs
CHANGED
|
@@ -32,6 +32,8 @@
|
|
|
32
32
|
// epoch, and neither erases the other. Same rule as beats in
|
|
33
33
|
// shared/dashboard.mjs.
|
|
34
34
|
|
|
35
|
+
import { resolveEdits } from './message-edits.mjs';
|
|
36
|
+
|
|
35
37
|
/* ------------------------------- lifecycle ------------------------------- */
|
|
36
38
|
// The only states the claim machinery reasons about. Everything else about what
|
|
37
39
|
// a work item is (kind, labels) is free-form text the layer above interprets.
|
|
@@ -155,6 +157,16 @@ export const WORK_ITEM_FIELDS = [
|
|
|
155
157
|
// mark on ONE line rather than a value the row holds, so the fold skips it;
|
|
156
158
|
// the chat reads it per line (renderer/src/thread-history.ts).
|
|
157
159
|
'inReplyTo',
|
|
160
|
+
// AN EDIT OR A DELETION OF ONE MESSAGE: `{ on, text }` or `{ on, gone: true }`,
|
|
161
|
+
// where `on` is the message's line uid. A delta like `react`, read back as
|
|
162
|
+
// `edits` and only from the message's own author (shared/message-edits.mjs).
|
|
163
|
+
'edit',
|
|
164
|
+
// WHICH COMMAND FROM HER PHONE WROTE THIS LINE (docs/cloud/PHONE-PLAN.md):
|
|
165
|
+
// the command's id, on the line of the reply or the new thread it made. It
|
|
166
|
+
// is how the computer, starting again after stopping half way through a
|
|
167
|
+
// command, knows for certain whether that command already landed, rather
|
|
168
|
+
// than guessing from the words (Codex's third review of step 1, finding 5).
|
|
169
|
+
'fromPhone',
|
|
158
170
|
];
|
|
159
171
|
|
|
160
172
|
// THE SUMMARY IS SHARED BETWEEN THE PERSON AND THE AGENT. Everywhere else the
|
|
@@ -366,6 +378,14 @@ function str(value, max) {
|
|
|
366
378
|
return trimmed.slice(0, lo) + mark(trimmed.length - lo);
|
|
367
379
|
}
|
|
368
380
|
|
|
381
|
+
// A text field whose empty string MEANS something: nothing chosen. Only a
|
|
382
|
+
// string may clear it, so a `null` that reached here without going through
|
|
383
|
+
// `answerItem` is still dropped rather than guessed at.
|
|
384
|
+
function clearable(value, max) {
|
|
385
|
+
if (typeof value !== 'string') return undefined;
|
|
386
|
+
return value.trim() ? str(value, max) : '';
|
|
387
|
+
}
|
|
388
|
+
|
|
369
389
|
function coerceField(field, value) {
|
|
370
390
|
switch (field) {
|
|
371
391
|
case 'title': return str(value, MAX_TITLE);
|
|
@@ -388,7 +408,28 @@ function coerceField(field, value) {
|
|
|
388
408
|
// shared/effort-levels.mjs, and the spawn gates on them, so a value this
|
|
389
409
|
// module does not recognise is a run at Claude Code's own choice rather
|
|
390
410
|
// than a row that never runs.
|
|
391
|
-
case 'kind': case 'product': case 'parent':
|
|
411
|
+
case 'kind': case 'product': case 'parent': return str(value, MAX_SHORT);
|
|
412
|
+
// THESE TWO ARE CLEARED BY WRITING '' AND SO '' IS A REAL VALUE, exactly
|
|
413
|
+
// as runAt's 0 and start's 'now' are, and for the same reason: a field that
|
|
414
|
+
// coerces to undefined is dropped by the fold, so without a falsy value
|
|
415
|
+
// that survives, a model could be chosen and never unchosen.
|
|
416
|
+
//
|
|
417
|
+
// They used to sit on the line above, which cost us the most common crash
|
|
418
|
+
// of launch week. The reply box's drawer hands a pick back as null for
|
|
419
|
+
// "nothing chosen" and sends `{ model, effort }` whenever it was touched at
|
|
420
|
+
// all; `answerItem` turns null into '' because `modelForEngine` reads the
|
|
421
|
+
// empty string as nothing chosen. `str()` then dropped it, `pickFields`
|
|
422
|
+
// answered null, and `buildLine` threw — before the answer was written,
|
|
423
|
+
// because the model is written first on purpose. So opening the drawer,
|
|
424
|
+
// picking a model and pressing send lost the message, with nothing on
|
|
425
|
+
// screen to say so. Five of the 14 crashes since the Oct 6 launch, on two
|
|
426
|
+
// installs (PostHog, 2026-10-08).
|
|
427
|
+
//
|
|
428
|
+
// `engine` JOINED THEM WHEN A REPLY COULD FIRST CARRY ONE (w-c9da359466).
|
|
429
|
+
// It is written beside the model by the same call, so clearing it back to
|
|
430
|
+
// the workspace default would have thrown in exactly the place described
|
|
431
|
+
// above, before the answer was written, losing the message.
|
|
432
|
+
case 'model': case 'effort': case 'engine': return clearable(value, MAX_SHORT);
|
|
392
433
|
case 'status': return WORK_ITEM_STATUSES.includes(value) ? value : undefined;
|
|
393
434
|
case 'priority': return Number.isFinite(value) ? Math.trunc(value) : undefined;
|
|
394
435
|
// When this item may next be acted on, in epoch ms. 0 means unscheduled,
|
|
@@ -416,10 +457,11 @@ function coerceField(field, value) {
|
|
|
416
457
|
// A ts rather than a flag, so her NEXT answer outdates it by carrying a
|
|
417
458
|
// later one, with nothing to clear and nobody who has to remember to.
|
|
418
459
|
case 'answeredThrough': return Number.isFinite(value) ? Math.trunc(value) : undefined;
|
|
460
|
+
// An empty list is a real value: it is how the last label, `ship` above
|
|
461
|
+
// all, comes off.
|
|
419
462
|
case 'labels': {
|
|
420
463
|
if (!Array.isArray(value)) return undefined;
|
|
421
|
-
|
|
422
|
-
return labels.length ? labels : undefined;
|
|
464
|
+
return value.map((l) => str(l, MAX_SHORT)).filter(Boolean).slice(0, MAX_LABELS);
|
|
423
465
|
}
|
|
424
466
|
case 'assignee': case 'runner': return shortId(value) ?? undefined;
|
|
425
467
|
case 'due': return calendarDay(value);
|
|
@@ -440,6 +482,15 @@ function coerceField(field, value) {
|
|
|
440
482
|
return value.off === true ? { on, emoji, off: true } : { on, emoji };
|
|
441
483
|
}
|
|
442
484
|
case 'inReplyTo': return shortId(value) ?? undefined;
|
|
485
|
+
case 'edit': {
|
|
486
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;
|
|
487
|
+
const on = shortId(value.on);
|
|
488
|
+
if (!on) return undefined;
|
|
489
|
+
if (value.gone === true) return { on, gone: true };
|
|
490
|
+
const text = str(value.text, MAX_TEXT_BYTES);
|
|
491
|
+
return text ? { on, text } : undefined;
|
|
492
|
+
}
|
|
493
|
+
case 'fromPhone': return typeof value === 'string' && /^[0-9a-f-]{8,64}$/i.test(value) ? value : undefined;
|
|
443
494
|
case 'visibility': return value === 'private' || value === 'team' || value === 'people' ? value : undefined;
|
|
444
495
|
// An empty list is a real value: it is how the last chosen person comes
|
|
445
496
|
// off a thread, and the thread then reaches nobody until she names one.
|
|
@@ -497,12 +548,67 @@ function rollUpReactions(presses) {
|
|
|
497
548
|
return out;
|
|
498
549
|
}
|
|
499
550
|
|
|
500
|
-
|
|
501
|
-
|
|
551
|
+
// Lease expiry is computed at READ time, never written. A held claim whose
|
|
552
|
+
// lease has lapsed reads as open again, which is what makes an abandoned item
|
|
553
|
+
// recoverable without anyone having to notice it was abandoned.
|
|
554
|
+
//
|
|
555
|
+
// The same derivation covers a released claim, and that is the point: only an
|
|
556
|
+
// item still sitting at `claimed` with nobody holding it goes back to open.
|
|
557
|
+
// Any status a worker or the founder actually chose (done, blocked, or one we
|
|
558
|
+
// have not invented yet) is theirs, and nothing about giving a claim back
|
|
559
|
+
// overwrites it.
|
|
560
|
+
export function finishItem(raw, now = Date.now()) {
|
|
561
|
+
// A copy, one level deep, so the raw item can be folded on and a finished
|
|
562
|
+
// one handed out is never changed under its holder.
|
|
563
|
+
const item = {};
|
|
564
|
+
for (const [k, v] of Object.entries(raw)) {
|
|
565
|
+
item[k] = Array.isArray(v) ? [...v]
|
|
566
|
+
: v instanceof Map ? new Map(v)
|
|
567
|
+
: v instanceof Set ? new Set(v)
|
|
568
|
+
: v && Object.getPrototypeOf(v) === Object.prototype ? { ...v } : v;
|
|
569
|
+
}
|
|
570
|
+
item.claimExpired = !!(item.claim && item.claim.leaseUntil < now);
|
|
571
|
+
if (item.status === 'claimed' && (!item.claim || item.claimExpired)) item.status = 'open';
|
|
572
|
+
if (item.reacts) {
|
|
573
|
+
const chips = rollUpReactions(item.reacts);
|
|
574
|
+
delete item.reacts;
|
|
575
|
+
if (chips) item.reactions = chips;
|
|
576
|
+
}
|
|
577
|
+
const closes = item.closes;
|
|
578
|
+
delete item.closes;
|
|
579
|
+
const editLines = item.editLines;
|
|
580
|
+
delete item.editLines;
|
|
581
|
+
const edits = editLines ? resolveEdits(item.said ?? [], editLines) : null;
|
|
582
|
+
if (edits?.size) item.edits = Object.fromEntries(edits);
|
|
583
|
+
if (item.said) {
|
|
584
|
+
const said = edits?.size ? item.said.flatMap((s) => {
|
|
585
|
+
const e = s.uid ? edits.get(s.uid) : null;
|
|
586
|
+
if (!e) return [s];
|
|
587
|
+
return e.gone ? [] : [{ ...s, text: e.text.trim().slice(0, TALK_TEXT) }];
|
|
588
|
+
}) : item.said;
|
|
589
|
+
delete item.said;
|
|
590
|
+
if (Array.isArray(item.people) && item.people.length) {
|
|
591
|
+
item.talk = talkOf(said);
|
|
592
|
+
const settled = settledBy(closes ?? [], said);
|
|
593
|
+
if (settled) item.talk.settled = settled;
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return item;
|
|
597
|
+
}
|
|
502
598
|
|
|
599
|
+
/** A line that writes the row's short name and nothing else (see the fold's foot). */
|
|
600
|
+
function onlyTheName(line) {
|
|
601
|
+
if (line.claim || line.release || line.heartbeat) return false;
|
|
602
|
+
const fields = Object.keys(line.patch ?? {});
|
|
603
|
+
return fields.length === 1 && fields[0] === 'label';
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
/** Lines folded onto `items` in place, unfinished: `finishItem` makes each one readable. */
|
|
607
|
+
export function foldRawInto(items, lines, touched = null) {
|
|
503
608
|
for (const raw of Array.isArray(lines) ? lines : []) {
|
|
504
609
|
const line = normalizeLine(raw);
|
|
505
610
|
if (!line) continue;
|
|
611
|
+
touched?.add(line.id);
|
|
506
612
|
|
|
507
613
|
let item = items.get(line.id);
|
|
508
614
|
if (!item) {
|
|
@@ -560,6 +666,11 @@ export function foldWorkItems(lines, now = Date.now()) {
|
|
|
560
666
|
if (line.by && words && words.trim()) {
|
|
561
667
|
(item.said ??= []).push({ uid: line.uid ?? null, by: line.by, ts: line.ts, text: words.trim().slice(0, TALK_TEXT), inReplyTo: patch.inReplyTo ?? null, body: typeof patch.answer !== 'string' });
|
|
562
668
|
}
|
|
669
|
+
// Who closed the chat and when, so `whatWaits` can tell a reopen by your own
|
|
670
|
+
// message (still settled) from an undo of the close (not).
|
|
671
|
+
if (line.by && typeof patch.status === 'string') {
|
|
672
|
+
(item.closes ??= []).push({ by: line.by, ts: line.ts, done: patch.status === 'done', spoke: !!(words && words.trim()) });
|
|
673
|
+
}
|
|
563
674
|
|
|
564
675
|
for (const [field, value] of Object.entries(patch)) {
|
|
565
676
|
// A REACTION IS ACCUMULATED, NOT HELD. Every other field below keeps one
|
|
@@ -581,6 +692,10 @@ export function foldWorkItems(lines, now = Date.now()) {
|
|
|
581
692
|
// WHICH MESSAGE A REPLY ANSWERS belongs to that reply's line alone. Held
|
|
582
693
|
// as a value, the row would carry the newest reply's parent forever.
|
|
583
694
|
if (field === 'inReplyTo') continue;
|
|
695
|
+
if (field === 'edit') {
|
|
696
|
+
(item.editLines ??= []).push({ on: value.on, by: line.by ?? null, ts: line.ts, ...(value.gone ? { gone: true } : { text: value.text }) });
|
|
697
|
+
continue;
|
|
698
|
+
}
|
|
584
699
|
const held = item.wrote[field];
|
|
585
700
|
// There used to be an exception here, for machinery spending a one-off
|
|
586
701
|
// permission mode over the founder's own grant. That field is not on the
|
|
@@ -593,34 +708,23 @@ export function foldWorkItems(lines, now = Date.now()) {
|
|
|
593
708
|
if (line.by) item.wrote[field].by = line.by;
|
|
594
709
|
}
|
|
595
710
|
|
|
596
|
-
|
|
711
|
+
// THE APP WRITING A ROW'S NAME IS NOT NEWS ABOUT THE ROW. Lists break ties
|
|
712
|
+
// on `updatedAt`, so every unnamed thread the namer reached climbed to the
|
|
713
|
+
// top reading "updated just now". Read here rather than at the write, as
|
|
714
|
+
// the heartbeat rule above is, because the lines that did it are in the
|
|
715
|
+
// ledger already. Only the name ALONE: a line that carries it with anything
|
|
716
|
+
// else carries that too.
|
|
717
|
+
if (!onlyTheName(line)) item.updatedAt = Math.max(item.updatedAt, line.ts);
|
|
597
718
|
if (line.ts < item.createdAt) item.createdAt = line.ts;
|
|
598
719
|
}
|
|
599
720
|
|
|
600
|
-
|
|
601
|
-
// lease has lapsed reads as open again, which is what makes an abandoned item
|
|
602
|
-
// recoverable without anyone having to notice it was abandoned.
|
|
603
|
-
//
|
|
604
|
-
// The same derivation covers a released claim, and that is the point: only an
|
|
605
|
-
// item still sitting at `claimed` with nobody holding it goes back to open.
|
|
606
|
-
// Any status a worker or the founder actually chose (done, blocked, or one we
|
|
607
|
-
// have not invented yet) is theirs, and nothing about giving a claim back
|
|
608
|
-
// overwrites it.
|
|
609
|
-
for (const item of items.values()) {
|
|
610
|
-
item.claimExpired = !!(item.claim && item.claim.leaseUntil < now);
|
|
611
|
-
if (item.status === 'claimed' && (!item.claim || item.claimExpired)) item.status = 'open';
|
|
612
|
-
if (item.reacts) {
|
|
613
|
-
const chips = rollUpReactions(item.reacts);
|
|
614
|
-
delete item.reacts;
|
|
615
|
-
if (chips) item.reactions = chips;
|
|
616
|
-
}
|
|
617
|
-
if (item.said) {
|
|
618
|
-
const said = item.said;
|
|
619
|
-
delete item.said;
|
|
620
|
-
if (Array.isArray(item.people) && item.people.length) item.talk = talkOf(said);
|
|
621
|
-
}
|
|
622
|
-
}
|
|
721
|
+
}
|
|
623
722
|
|
|
723
|
+
export function foldWorkItems(lines, now = Date.now()) {
|
|
724
|
+
const raw = new Map();
|
|
725
|
+
foldRawInto(raw, lines);
|
|
726
|
+
const items = new Map();
|
|
727
|
+
for (const [id, item] of raw) items.set(id, finishItem(item, now));
|
|
624
728
|
return items;
|
|
625
729
|
}
|
|
626
730
|
|
|
@@ -640,6 +744,23 @@ const TALK_KEEP = 100;
|
|
|
640
744
|
* `whatWaits` (shared/team-rules.mjs) and the row's one line; the messages
|
|
641
745
|
* themselves are read off the ledger by the thread view, as before.
|
|
642
746
|
*/
|
|
747
|
+
/**
|
|
748
|
+
* For each person, the moment they last marked the chat done, or nothing if
|
|
749
|
+
* they reopened it since without saying anything (an undo). A reopen that
|
|
750
|
+
* carries their words keeps the moment: speaking is not taking the close back.
|
|
751
|
+
* So does one that follows their words since the close, because sending
|
|
752
|
+
* writes the message and the reopen as two lines (`answerItem`, main/store.mjs).
|
|
753
|
+
*/
|
|
754
|
+
function settledBy(closes, said = []) {
|
|
755
|
+
const at = {};
|
|
756
|
+
const spokeSince = (by, from, to) => said.some((s) => s.by === by && !s.body && s.ts > from && s.ts <= to);
|
|
757
|
+
for (const c of [...closes].sort((a, b) => a.ts - b.ts)) {
|
|
758
|
+
if (c.done) at[c.by] = c.ts;
|
|
759
|
+
else if (!c.spoke && !spokeSince(c.by, at[c.by], c.ts)) delete at[c.by];
|
|
760
|
+
}
|
|
761
|
+
return Object.keys(at).length ? at : null;
|
|
762
|
+
}
|
|
763
|
+
|
|
643
764
|
function talkOf(said) {
|
|
644
765
|
const lines = [...said].sort((a, b) => a.ts - b.ts);
|
|
645
766
|
const chat = [];
|