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
|
@@ -26,19 +26,41 @@ import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
|
26
26
|
|
|
27
27
|
const require = createRequire(import.meta.url);
|
|
28
28
|
|
|
29
|
-
// A checkout has scripts/linux-launcher.mjs
|
|
30
|
-
// package
|
|
31
|
-
//
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
// A checkout has scripts/linux-launcher.mjs and scripts/link-own-bin.mjs next
|
|
30
|
+
// to this file. The published package carries neither, so an npm install of
|
|
31
|
+
// that package, including npx, leaves both alone. A missing file is the
|
|
32
|
+
// ordinary case here, not an error.
|
|
33
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
34
|
+
|
|
35
|
+
async function fromCheckout(file) {
|
|
36
|
+
const at = path.join(here, file);
|
|
37
|
+
if (!fs.existsSync(at)) return null;
|
|
34
38
|
try {
|
|
35
|
-
|
|
36
|
-
installLinuxLauncher({ env: process.env });
|
|
39
|
+
return await import(pathToFileURL(at).href);
|
|
37
40
|
} catch {
|
|
38
41
|
// Nothing here is worth stopping an install for.
|
|
42
|
+
return null;
|
|
39
43
|
}
|
|
40
44
|
}
|
|
41
45
|
|
|
46
|
+
const launcher = await fromCheckout('linux-launcher.mjs');
|
|
47
|
+
if (launcher) {
|
|
48
|
+
const { changed, why } = launcher.installLinuxLauncher({ env: process.env });
|
|
49
|
+
if (changed) console.log('agentbox: this checkout is in the app launcher.');
|
|
50
|
+
// A launcher that did not happen says so. Before this, a fresh clone whose
|
|
51
|
+
// Electron binary was not downloaded yet got no launcher and no word about
|
|
52
|
+
// it, and `which agentbox` answered nothing.
|
|
53
|
+
else if (why) console.log(`agentbox: no app launcher was written: ${why}.`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// And the checkout's own command, so `npx agentbox-app` from here starts the
|
|
57
|
+
// browser rather than looking for `agentbox` on PATH.
|
|
58
|
+
const own = await fromCheckout('link-own-bin.mjs');
|
|
59
|
+
if (own) {
|
|
60
|
+
const { why } = own.linkOwnBin();
|
|
61
|
+
if (why) console.log(`agentbox: \`npx agentbox-app\` will not work from this checkout: ${why}.`);
|
|
62
|
+
}
|
|
63
|
+
|
|
42
64
|
function prebuildsDir() {
|
|
43
65
|
// Resolve the package rather than guessing at ../node-pty: npm may have
|
|
44
66
|
// hoisted it, nested it, or put it in a workspace root.
|
|
@@ -67,7 +89,7 @@ try {
|
|
|
67
89
|
fs.chmodSync(helper, 0o755);
|
|
68
90
|
fixed += 1;
|
|
69
91
|
}
|
|
70
|
-
if (fixed) console.log(`agentbox: made ${fixed} node-pty spawn-helper
|
|
92
|
+
if (fixed) console.log(`agentbox: made ${fixed} node-pty spawn-helper binar${fixed === 1 ? 'y' : 'ies'} executable, so the terminal works.`);
|
|
71
93
|
} catch {
|
|
72
94
|
// Nothing here is worth stopping an install for.
|
|
73
95
|
}
|
|
@@ -39,10 +39,29 @@ case "$here" in
|
|
|
39
39
|
exec env ELECTRON_RUN_AS_NODE=1 "$app/MacOS/$exe" "$res/app.asar/main/approval-prompt-server.mjs"
|
|
40
40
|
;;
|
|
41
41
|
*)
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
# RUNNING FROM SOURCE, AND THIS LINE USED TO ASSUME NVM. It prepended
|
|
43
|
+
# $HOME/.nvm/versions/node/<newest>/bin and exec'd node. On a Mac that
|
|
44
|
+
# installed node by Homebrew, Volta, asdf or not at all, that folder is
|
|
45
|
+
# absent, PATH is untouched, and an MCP server booting from a bare login
|
|
46
|
+
# shell has no node on it: the exec failed and every agent died the same
|
|
47
|
+
# four-second death described at the top of this file. Reported from
|
|
48
|
+
# source on 2026-10-07 (issue 21).
|
|
49
|
+
#
|
|
50
|
+
# So the app hands its own binary down in ZERO_APPROVALS_RUNTIME, and
|
|
51
|
+
# ELECTRON_RUN_AS_NODE=1 makes that binary a node, exactly as the packaged
|
|
52
|
+
# branch above does. Nothing on the machine is needed.
|
|
53
|
+
server="$(cd "$here/.." && pwd)/main/approval-prompt-server.mjs"
|
|
54
|
+
if [ -f "$ZERO_APPROVALS_RUNTIME" ] && [ -x "$ZERO_APPROVALS_RUNTIME" ]; then
|
|
55
|
+
exec env ELECTRON_RUN_AS_NODE=1 "$ZERO_APPROVALS_RUNTIME" "$server"
|
|
56
|
+
fi
|
|
57
|
+
# Nobody handed one down, so this is somebody running the script by hand.
|
|
58
|
+
# A node already on PATH wins; nvm's newest is the last resort, for the
|
|
59
|
+
# bare login shell that has never sourced nvm.
|
|
60
|
+
if ! command -v node >/dev/null 2>&1; then
|
|
61
|
+
nvm="$HOME/.nvm/versions/node"
|
|
62
|
+
newest="$(ls "$nvm" 2>/dev/null | tail -1)"
|
|
63
|
+
[ -n "$newest" ] && export PATH="$nvm/$newest/bin:$PATH"
|
|
64
|
+
fi
|
|
65
|
+
exec node "$server"
|
|
47
66
|
;;
|
|
48
67
|
esac
|
|
@@ -69,17 +69,19 @@ function wouldShip(changed) {
|
|
|
69
69
|
// If npm cannot tell us, the honest answer is the cautious one.
|
|
70
70
|
return changed;
|
|
71
71
|
}
|
|
72
|
-
// THE FILES
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
//
|
|
76
|
-
//
|
|
77
|
-
//
|
|
78
|
-
//
|
|
72
|
+
// THE FILES A PUBLISH USED TO REWRITE, which made every attempt poison the
|
|
73
|
+
// next one. `prepack` runs `npm run build`, and the build read the installed
|
|
74
|
+
// Claude Code and wrote what it found over shared/*.generated.*. So a failed
|
|
75
|
+
// publish left those modified and the next publish refused because of dirt the
|
|
76
|
+
// last publish had made. Measured 2026-09-28: one failed attempt left
|
|
77
|
+
// claude-models.generated.mjs changed by a version number, and that alone
|
|
78
|
+
// blocked the retry.
|
|
79
79
|
//
|
|
80
|
-
//
|
|
81
|
-
//
|
|
82
|
-
// committed
|
|
80
|
+
// THE BUILD NO LONGER WRITES THEM (w-6bbb709b1f): it writes
|
|
81
|
+
// shared/*.local.json, which is gitignored, and `npm run read:claude` is what
|
|
82
|
+
// updates the committed tables. This filter stays as the belt for a folder an
|
|
83
|
+
// OLDER build already dirtied, and because what ships is whatever the build
|
|
84
|
+
// produces on the machine publishing, so a difference here changes nothing.
|
|
83
85
|
return changed.filter((f) => packed.has(f) && !/\.generated\./.test(f));
|
|
84
86
|
}
|
|
85
87
|
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/perl
|
|
2
|
+
# A CLOUD RUN, AS THE SUPERVISOR SEES IT: one small process standing in for a
|
|
3
|
+
# run whose relay lives in the shared host (main/cloud/host.mjs). It carries
|
|
4
|
+
# its input, output, signals and exit code there and back. Perl, because every
|
|
5
|
+
# Mac has it and a stand-in in it costs a few megabytes.
|
|
6
|
+
#
|
|
7
|
+
# cloud-shim.pl <host socket> <the relay's own arguments ...>
|
|
8
|
+
use strict;
|
|
9
|
+
use warnings;
|
|
10
|
+
use IO::Socket::UNIX;
|
|
11
|
+
use IO::Select;
|
|
12
|
+
use MIME::Base64 qw(encode_base64 decode_base64);
|
|
13
|
+
use JSON::PP;
|
|
14
|
+
use Cwd qw(getcwd);
|
|
15
|
+
use POSIX qw(:sys_wait_h);
|
|
16
|
+
|
|
17
|
+
my $sockpath = shift @ARGV;
|
|
18
|
+
# A host just started may take a moment to listen.
|
|
19
|
+
my $sock;
|
|
20
|
+
for (1 .. 50) { $sock = IO::Socket::UNIX->new(Type => SOCK_STREAM(), Peer => $sockpath); last if $sock; select(undef, undef, undef, 0.1); }
|
|
21
|
+
if (!$sock) { print STDERR "agentbox cloud: the cloud host is not running ($!)\n"; exit 75; }
|
|
22
|
+
binmode($sock); binmode(STDIN); binmode(STDOUT); binmode(STDERR);
|
|
23
|
+
$sock->autoflush(1);
|
|
24
|
+
|
|
25
|
+
sub put { my ($line) = @_; local $SIG{PIPE} = 'IGNORE'; print {$sock} "$line\n"; }
|
|
26
|
+
|
|
27
|
+
put(JSON::PP->new->canonical->encode({ argv => [@ARGV], env => {%ENV}, cwd => getcwd(), pid => $$ }));
|
|
28
|
+
for my $sig (qw(TERM INT HUP)) { $SIG{$sig} = sub { put("k SIG$sig"); }; }
|
|
29
|
+
|
|
30
|
+
my $sel = IO::Select->new($sock, \*STDIN);
|
|
31
|
+
my ($buf, $code, $parent, $orphaned) = ('', undef, getppid(), 0);
|
|
32
|
+
while (1) {
|
|
33
|
+
my @ready = $sel->can_read(1);
|
|
34
|
+
# The app gone without a word: the run is left going, as on a quit.
|
|
35
|
+
if (!$orphaned && getppid() != $parent) { $orphaned = 1; put('k SIGHUP'); }
|
|
36
|
+
for my $fh (@ready) {
|
|
37
|
+
if ($fh == $sock) {
|
|
38
|
+
my $n = sysread($sock, my $chunk, 65536);
|
|
39
|
+
if (!defined $n) { next if $!{EINTR}; $n = 0; }
|
|
40
|
+
if (!$n) { exit(defined $code ? $code : 75); }
|
|
41
|
+
$buf .= $chunk;
|
|
42
|
+
while ((my $i = index($buf, "\n")) >= 0) {
|
|
43
|
+
my $line = substr($buf, 0, $i);
|
|
44
|
+
$buf = substr($buf, $i + 1);
|
|
45
|
+
my ($tag, $rest) = (substr($line, 0, 1), substr($line, 2));
|
|
46
|
+
if ($tag eq 'o') { my $d = decode_base64($rest); my $off = 0; while ($off < length $d) { my $w = syswrite(STDOUT, $d, length($d) - $off, $off); last unless defined $w; $off += $w; } }
|
|
47
|
+
elsif ($tag eq 'e') { my $d = decode_base64($rest); syswrite(STDERR, $d); }
|
|
48
|
+
elsif ($tag eq 'x') { $code = int($rest); }
|
|
49
|
+
}
|
|
50
|
+
} else {
|
|
51
|
+
my $n = sysread(STDIN, my $chunk, 65536);
|
|
52
|
+
if (!defined $n) { next if $!{EINTR}; $n = 0; }
|
|
53
|
+
if (!$n) { put('I'); $sel->remove(\*STDIN); }
|
|
54
|
+
else { put('i ' . encode_base64($chunk, '')); }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// WHAT ONE LOGIN IS CALLED, in the one rule both sides read: the Settings
|
|
2
|
+
// page, which has named accounts by their email since it had rows, and the
|
|
3
|
+
// sentence a thread gets when a login runs out, which had no name for one at
|
|
4
|
+
// all until w-e1a42f6b21.
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @param {{ email?: string | null, engine?: string, index?: number, total?: number }} account
|
|
8
|
+
* `index` is its place among that engine's accounts, `total` how many there
|
|
9
|
+
* are: one account is not counted, because the number would mean nothing.
|
|
10
|
+
*/
|
|
11
|
+
export function accountName({ email = null, engine = 'claude', index = 0, total = 1 } = {}) {
|
|
12
|
+
if (email) return email;
|
|
13
|
+
const word = engine === 'codex' ? 'Codex' : 'Claude';
|
|
14
|
+
return `${word} account${total > 1 ? ` ${index + 1}` : ''}`;
|
|
15
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// AGENT HOURS: the level, the week, the streak (w-3d0fa23ffb).
|
|
2
|
+
//
|
|
3
|
+
// Pure. A run is `{key, at, start, item, product, engine, seconds, failed,
|
|
4
|
+
// began}`: `at` is when it ended, and a run is counted on the local day it
|
|
5
|
+
// ended. Every run whose agent actually began counts its wall time, failed or
|
|
6
|
+
// not, and overlapping runs each count.
|
|
7
|
+
|
|
8
|
+
export const MASTERY_HOURS = 10_000;
|
|
9
|
+
const MAX_RUN_SECONDS = 24 * 3600;
|
|
10
|
+
const DAY_MS = 86_400_000;
|
|
11
|
+
|
|
12
|
+
// Up to 99, hours grow as level^2.5: level 2 in minutes, 99 at MASTERY_HOURS.
|
|
13
|
+
// Not RuneScape's curve, which spends half its hours on the last seven levels
|
|
14
|
+
// and so reads 82 after one heavy month. Past 99 there is no ceiling and each
|
|
15
|
+
// level costs 5% more than the last, starting from the curve's pace at 99 so
|
|
16
|
+
// no level ever costs less than the one before.
|
|
17
|
+
const RISE = 2.5;
|
|
18
|
+
const PAST = Math.log(1.05);
|
|
19
|
+
const PACE_AT_99 = (MASTERY_HOURS * RISE) / 98;
|
|
20
|
+
// A level starts at its exact hours, not one float step later.
|
|
21
|
+
const EPS = 1e-10;
|
|
22
|
+
|
|
23
|
+
export function hoursForLevel(level) {
|
|
24
|
+
const L = Number(level);
|
|
25
|
+
if (!(L > 1)) return 0;
|
|
26
|
+
if (L <= 99) return MASTERY_HOURS * ((L - 1) / 98) ** RISE;
|
|
27
|
+
return MASTERY_HOURS + (PACE_AT_99 * Math.expm1((L - 99) * PAST)) / PAST;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function levelFor(hours) {
|
|
31
|
+
const h = Number(hours);
|
|
32
|
+
if (!Number.isFinite(h) || h <= 0) return 1;
|
|
33
|
+
if (h < MASTERY_HOURS) return 1 + Math.floor(98 * (h / MASTERY_HOURS) ** (1 / RISE) + EPS);
|
|
34
|
+
return 99 + Math.floor(Math.log1p(((h - MASTERY_HOURS) * PAST) / PACE_AT_99) / PAST + EPS);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const pad = (n) => String(n).padStart(2, '0');
|
|
38
|
+
export const localDate = (ms) => { const d = new Date(ms); return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`; };
|
|
39
|
+
const localMonth = (ms) => localDate(ms).slice(0, 7);
|
|
40
|
+
|
|
41
|
+
function mondayOf(ms) {
|
|
42
|
+
const d = new Date(ms);
|
|
43
|
+
d.setHours(0, 0, 0, 0);
|
|
44
|
+
d.setDate(d.getDate() - ((d.getDay() + 6) % 7));
|
|
45
|
+
return d.getTime();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function startOfDay(ms) {
|
|
49
|
+
const d = new Date(ms);
|
|
50
|
+
d.setHours(0, 0, 0, 0);
|
|
51
|
+
return d.getTime();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const counts = (r) => r && r.began !== false && Number.isFinite(r.at) && Number(r.seconds) > 0;
|
|
55
|
+
|
|
56
|
+
// One line per key. The line written when the run ended beats one read back
|
|
57
|
+
// from its log, which may have been read while the run was still going.
|
|
58
|
+
export function dedupeRuns(runs) {
|
|
59
|
+
const seen = new Map();
|
|
60
|
+
for (const r of runs ?? []) {
|
|
61
|
+
if (!r || typeof r !== 'object' || typeof r.key !== 'string' || !r.key) continue;
|
|
62
|
+
if (!Number.isFinite(r.at) || !(Number(r.seconds) > 0)) continue;
|
|
63
|
+
const had = seen.get(r.key);
|
|
64
|
+
if (!had || (had.backfilled && !r.backfilled)) seen.set(r.key, r);
|
|
65
|
+
}
|
|
66
|
+
return [...seen.values()];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Days in a row with a run, counted back from today, or from yesterday when
|
|
70
|
+
// today has none yet. `dates` are local YYYY-MM-DD strings, from any number of
|
|
71
|
+
// Macs.
|
|
72
|
+
export function streakOf(dates, now = Date.now()) {
|
|
73
|
+
const have = new Set(dates);
|
|
74
|
+
let cursor = startOfDay(now);
|
|
75
|
+
if (!have.has(localDate(cursor))) cursor -= DAY_MS / 2;
|
|
76
|
+
let n = 0;
|
|
77
|
+
while (have.has(localDate(cursor))) {
|
|
78
|
+
n += 1;
|
|
79
|
+
// Half a day back and then to the start of that day survives a DST change.
|
|
80
|
+
cursor = startOfDay(startOfDay(cursor) - DAY_MS / 2);
|
|
81
|
+
}
|
|
82
|
+
return n;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function summarizeRuns(runs, { now = Date.now() } = {}) {
|
|
86
|
+
const weekStartMs = mondayOf(now);
|
|
87
|
+
const dayStartMs = startOfDay(now);
|
|
88
|
+
let total = 0;
|
|
89
|
+
let week = 0;
|
|
90
|
+
let today = 0;
|
|
91
|
+
const active = new Set();
|
|
92
|
+
const months = new Map();
|
|
93
|
+
const first = new Date(now);
|
|
94
|
+
first.setDate(1);
|
|
95
|
+
for (let i = 11; i >= 0; i -= 1) {
|
|
96
|
+
const d = new Date(first.getFullYear(), first.getMonth() - i, 1);
|
|
97
|
+
months.set(`${d.getFullYear()}-${pad(d.getMonth() + 1)}`, 0);
|
|
98
|
+
}
|
|
99
|
+
for (const r of dedupeRuns(runs)) {
|
|
100
|
+
if (!counts(r) || r.at > now) continue;
|
|
101
|
+
const h = Math.min(Number(r.seconds), MAX_RUN_SECONDS) / 3600;
|
|
102
|
+
total += h;
|
|
103
|
+
if (r.at >= weekStartMs) week += h;
|
|
104
|
+
if (r.at >= dayStartMs) today += h;
|
|
105
|
+
active.add(localDate(r.at));
|
|
106
|
+
const m = localMonth(r.at);
|
|
107
|
+
if (months.has(m)) months.set(m, months.get(m) + h);
|
|
108
|
+
}
|
|
109
|
+
const activeDays = [...active].sort().slice(-60);
|
|
110
|
+
return {
|
|
111
|
+
total,
|
|
112
|
+
week,
|
|
113
|
+
weekStart: localDate(weekStartMs),
|
|
114
|
+
today,
|
|
115
|
+
day: localDate(dayStartMs),
|
|
116
|
+
streak: streakOf(activeDays, now),
|
|
117
|
+
activeDays,
|
|
118
|
+
byMonth: [...months].map(([month, hours]) => ({ month, hours })),
|
|
119
|
+
level: levelFor(total),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// One run read back from its trace log, `sessions/<item>/<startedAtMs>.log`:
|
|
124
|
+
// the start is the file's name, the end the `# exited (code) <ISO>` footer,
|
|
125
|
+
// else the file's last write.
|
|
126
|
+
export function runFromTrace({ name, text = '', mtimeMs, item, product }) {
|
|
127
|
+
const m = /^(\d{12,14})\.log$/.exec(String(name ?? ''));
|
|
128
|
+
if (!m) return null;
|
|
129
|
+
const start = Number(m[1]);
|
|
130
|
+
const footer = /# exited \((-?\d+|null)\) (\S+)(?: · [^\n]*)?\s*$/m.exec(String(text));
|
|
131
|
+
const end = footer ? Date.parse(footer[2]) : Number(mtimeMs);
|
|
132
|
+
if (!Number.isFinite(end) || end <= start) return null;
|
|
133
|
+
const seconds = Math.round((end - start) / 1000);
|
|
134
|
+
if (seconds > MAX_RUN_SECONDS) return null;
|
|
135
|
+
return { key: `${item}:${start}`, at: end, start, item, product, engine: null, seconds, failed: footer ? footer[1] !== '0' : null };
|
|
136
|
+
}
|
package/shared/agent-import.mjs
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
/**
|
|
19
19
|
* The label every one of these rows carries, so a second walk through the
|
|
20
20
|
* first run can tell which agents already have a row and file nothing twice. */
|
|
21
|
-
import { NAME
|
|
21
|
+
import { NAME } from '../shared/product-name.mjs';
|
|
22
22
|
export const IMPORT_LABEL = 'agent-import';
|
|
23
23
|
|
|
24
24
|
/**
|
|
@@ -107,11 +107,11 @@ export function agentsNeedingRows(chosen, existingItems = []) {
|
|
|
107
107
|
}
|
|
108
108
|
|
|
109
109
|
/* --------------------------- AND THE THREADS ----------------------------- */
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
//
|
|
110
|
+
// A picked thread becomes a row that carries the conversation on. It first
|
|
111
|
+
// did not: the body said the reply started fresh, and somebody importing a
|
|
112
|
+
// hundred half-finished sessions was asked to restate every one of them
|
|
113
|
+
// (GitHub #44). The row is still only a row here; the resume happens on the
|
|
114
|
+
// first reply, in `Supervisor#importedThreadFor`.
|
|
115
115
|
//
|
|
116
116
|
// Everything else is the agent import's shape, for the same reasons: one row per
|
|
117
117
|
// thing the user ticked, a label so a second press files nothing twice, and a
|
|
@@ -125,6 +125,53 @@ export const THREAD_LABEL = 'thread-import';
|
|
|
125
125
|
* which is stable across renames and is what the transcript is filed under. */
|
|
126
126
|
export const threadLabel = (id) => `thread:${String(id ?? '').trim()}`;
|
|
127
127
|
|
|
128
|
+
/**
|
|
129
|
+
* WHETHER A CHAT ENDED WAITING ON YOU, read off the agent's last reply.
|
|
130
|
+
*
|
|
131
|
+
* Waiting means the reply's last line is a question, or a question followed by
|
|
132
|
+
* the choices it offers. `ask` is that question, cut from the front when it is
|
|
133
|
+
* long, because the question is at the end of the line. */
|
|
134
|
+
const ASK_CHARS = 140;
|
|
135
|
+
const SHORT_ASK = 40;
|
|
136
|
+
const CHOICE = /^(\d+[.)]|[-*+]|[a-z][.)])\s+/i;
|
|
137
|
+
const NOT_WAITING = Object.freeze({ waiting: false, ask: '' });
|
|
138
|
+
|
|
139
|
+
function plainLine(line) {
|
|
140
|
+
return String(line)
|
|
141
|
+
.replace(/^(>\s*)+/, '')
|
|
142
|
+
.replace(/^#{1,6}\s+/, '')
|
|
143
|
+
.replace(/[*`]+/g, '')
|
|
144
|
+
// An underscore between two letters is part of a name (account_id).
|
|
145
|
+
.replace(/(?<![A-Za-z0-9])_+|_+(?![A-Za-z0-9])/g, '')
|
|
146
|
+
.replace(/^[("'“‘\s]+/, '')
|
|
147
|
+
.replace(/[)"'”’\s]+$/, '')
|
|
148
|
+
.trim();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function shortAsk(line) {
|
|
152
|
+
if (line.length <= ASK_CHARS) return line;
|
|
153
|
+
const sentences = line.split(/(?<=[.!?])\s+/);
|
|
154
|
+
let last = sentences.pop();
|
|
155
|
+
// "Shall I do that?" says nothing without the sentence it follows.
|
|
156
|
+
while (last.length < SHORT_ASK && sentences.length && sentences.at(-1).length + 1 + last.length <= ASK_CHARS) {
|
|
157
|
+
last = `${sentences.pop()} ${last}`;
|
|
158
|
+
}
|
|
159
|
+
if (last.length <= ASK_CHARS) return last;
|
|
160
|
+
const tail = line.slice(-(ASK_CHARS - 1));
|
|
161
|
+
const sp = tail.indexOf(' ');
|
|
162
|
+
return `…${sp > 0 && sp < 40 ? tail.slice(sp + 1) : tail}`;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export function howTheChatEnded(said) {
|
|
166
|
+
const lines = String(said ?? '').replace(/\r/g, '').split('\n').map((l) => l.trim()).filter(Boolean);
|
|
167
|
+
let i = lines.length - 1;
|
|
168
|
+
while (i >= 0 && CHOICE.test(lines[i])) i -= 1;
|
|
169
|
+
if (i < 0) return { ...NOT_WAITING };
|
|
170
|
+
const line = plainLine(lines[i].replace(CHOICE, ''));
|
|
171
|
+
if (!line.endsWith('?')) return { ...NOT_WAITING };
|
|
172
|
+
return { waiting: true, ask: shortAsk(line) };
|
|
173
|
+
}
|
|
174
|
+
|
|
128
175
|
/**
|
|
129
176
|
* WHEN SHE HAD IT, in the words a person uses about this week.
|
|
130
177
|
*
|
|
@@ -148,41 +195,22 @@ export function whenWords(when, now = Date.now()) {
|
|
|
148
195
|
/** Where she was when she started it, in the two places she named. */
|
|
149
196
|
export function startedIn(source) {
|
|
150
197
|
if (source === 'codex') return 'in Codex';
|
|
198
|
+
// VS Code, Cursor or Windsurf: the extension says which family, not which one.
|
|
199
|
+
if (source === 'editor') return 'in your code editor';
|
|
151
200
|
return source === 'desktop' ? 'in the Claude Code desktop app' : 'in a terminal';
|
|
152
201
|
}
|
|
153
202
|
|
|
154
203
|
/**
|
|
155
|
-
* ONE IMPORTED THREAD'S WORDS
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
|
|
160
|
-
* a list that has to be read past to find which is which.
|
|
161
|
-
*
|
|
162
|
-
* The last paragraph is the honest one. Agentbox read the top of the transcript
|
|
163
|
-
* to find this name and nothing else, and the reply starts a fresh session. A
|
|
164
|
-
* row that let her believe otherwise would be the same empty promise the agent
|
|
165
|
-
* import had before 08-23, in a new place. */
|
|
166
|
-
export function threadImportRow(thread, { projectName = null, now = Date.now() } = {}) {
|
|
204
|
+
* ONE IMPORTED THREAD'S WORDS, the chat as it was: the title Claude Code gave
|
|
205
|
+
* it, your first message as the body and the agent's last reply as the
|
|
206
|
+
* result, so the thread opens on the question it ended with. The reply
|
|
207
|
+
* carries the conversation on (`Supervisor#importedThreadFor`). */
|
|
208
|
+
export function threadImportRow(thread) {
|
|
167
209
|
const title = String(thread?.title || '').trim();
|
|
168
|
-
const where = String(thread?.short || thread?.folder || '').trim();
|
|
169
|
-
const when = whenWords(thread?.when, now);
|
|
170
|
-
const started = [
|
|
171
|
-
'You started this',
|
|
172
|
-
startedIn(thread?.source),
|
|
173
|
-
when,
|
|
174
|
-
where ? `in ${where}` : '',
|
|
175
|
-
].filter(Boolean).join(' ');
|
|
176
|
-
const inProject = projectName ? ` here in ${projectName}` : '';
|
|
177
|
-
const body = [
|
|
178
|
-
'**Say what you want done next in this thread.**',
|
|
179
|
-
`${started}.`,
|
|
180
|
-
`Reply with the job and ${NAME} runs it${inProject}, answering you here.`,
|
|
181
|
-
`${Name} has not read the conversation, only the line above that names it, and replying starts a fresh session rather than carrying the old one on. So say what you need in the reply.`,
|
|
182
|
-
].join('\n\n');
|
|
183
210
|
return {
|
|
184
211
|
title,
|
|
185
|
-
body,
|
|
212
|
+
body: String(thread?.firstSaid || '').trim() || title,
|
|
213
|
+
result: String(thread?.lastSaid || '').trim(),
|
|
186
214
|
kind: 'question',
|
|
187
215
|
priority: 3,
|
|
188
216
|
labels: [THREAD_LABEL, threadLabel(thread?.id)],
|
package/shared/agents.d.mts
CHANGED