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/main/leftovers.mjs
CHANGED
|
@@ -26,9 +26,11 @@
|
|
|
26
26
|
// leftovers and no record at all is recorded as ended when this app, whose
|
|
27
27
|
// store it is in, has no session for it; the clock starts then, never
|
|
28
28
|
// back-dated.
|
|
29
|
-
// 4. ITS PROGRAMS STOP `
|
|
30
|
-
//
|
|
31
|
-
//
|
|
29
|
+
// 4. ITS PROGRAMS STOP `closeGraceMs` (2 min) AFTER THE TASK IS CLOSED, so a
|
|
30
|
+
// Z that reopens it keeps them. While memory is tight or critical, also
|
|
31
|
+
// `tightIdleMs` (10 min) after the run ended, one task per look, the one
|
|
32
|
+
// whose run ended longest ago first. Never sooner than that long after
|
|
33
|
+
// the switch went on.
|
|
32
34
|
// 5. NOTHING PROTECTED IS EVER STOPPED: AGENTBOX_KEEP=1 in its environment,
|
|
33
35
|
// an executable inside an installed app or the system (Docker Desktop and
|
|
34
36
|
// its VM, a browser an agent opened), an executable that cannot be read,
|
|
@@ -49,10 +51,10 @@
|
|
|
49
51
|
// (main/supervisor.mjs) and everything it starts inherits it; all 40 leftovers
|
|
50
52
|
// that morning carried it, Docker's backend included. The id is read only from
|
|
51
53
|
// the ENVIRONMENT, which is the part of `ps -E` after the arguments `ps` prints
|
|
52
|
-
// without it, and only when both looks agree it is the same process;
|
|
53
|
-
// command's own words counts for
|
|
54
|
-
// (next-server) hides its environment
|
|
55
|
-
// to the same task. Codex threads share one app-server and their commands carry
|
|
54
|
+
// without it, and only when both looks agree it is the same process;
|
|
55
|
+
// /proc/<pid>/environ on Linux. A tag in a command's own words counts for
|
|
56
|
+
// nothing. A program that renames itself (next-server) hides its environment
|
|
57
|
+
// from `ps`, so a process under a tagged one belongs to the same task. Codex threads share one app-server and their commands carry
|
|
56
58
|
// no task id yet, so a Codex task's leftovers are not found: coverage is
|
|
57
59
|
// incomplete and the switch says so.
|
|
58
60
|
|
|
@@ -151,8 +153,69 @@ export function applyExecutables(procs, lsofText) {
|
|
|
151
153
|
return procs;
|
|
152
154
|
}
|
|
153
155
|
|
|
154
|
-
/**
|
|
155
|
-
|
|
156
|
+
/** /proc counts in USER_HZ, which the kernel fixes at 100 whatever its own tick is. */
|
|
157
|
+
const USER_HZ = 100;
|
|
158
|
+
|
|
159
|
+
/** When this computer booted, which /proc/<pid>/stat counts a start time from. */
|
|
160
|
+
function bootSeconds(root) {
|
|
161
|
+
const stat = fs.readFileSync(path.join(root, 'stat'), 'utf8').match(/^btime (\d+)$/m);
|
|
162
|
+
if (stat) return +stat[1];
|
|
163
|
+
const up = Number(String(fs.readFileSync(path.join(root, 'uptime'), 'utf8')).split(/\s+/)[0]);
|
|
164
|
+
return Math.floor(Date.now() / 1000 - up);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* The same record the Mac's three `ps` listings give, read from /proc, because
|
|
169
|
+
* `-E` is BSD's and Linux's procps refuses it (w-bd1806285e).
|
|
170
|
+
*
|
|
171
|
+
* `exe` is the real executable even for a program that renamed itself, so
|
|
172
|
+
* nothing here needs lsof. A process that ends mid-read is left out; one
|
|
173
|
+
* belonging to somebody else keeps an empty executable and no environment,
|
|
174
|
+
* which is what leaves it protected.
|
|
175
|
+
*/
|
|
176
|
+
export function readLinuxProcesses({ root = '/proc', hz = USER_HZ, btime = null } = {}) {
|
|
177
|
+
const boot = btime ?? bootSeconds(root);
|
|
178
|
+
const out = [];
|
|
179
|
+
for (const name of fs.readdirSync(root)) {
|
|
180
|
+
if (!/^\d+$/.test(name)) continue;
|
|
181
|
+
const dir = path.join(root, name);
|
|
182
|
+
let stat;
|
|
183
|
+
try { stat = fs.readFileSync(path.join(dir, 'stat'), 'utf8'); } catch { continue; }
|
|
184
|
+
const close = stat.lastIndexOf(')');
|
|
185
|
+
if (close < 0) continue;
|
|
186
|
+
const comm = stat.slice(stat.indexOf('(') + 1, close);
|
|
187
|
+
// The fields after the command, which is the only one that can hold spaces
|
|
188
|
+
// and brackets: state, the parent, and on to the start time.
|
|
189
|
+
const rest = stat.slice(close + 2).split(' ');
|
|
190
|
+
const read = (f) => { try { return fs.readFileSync(path.join(dir, f), 'utf8'); } catch { return null; } };
|
|
191
|
+
const words = (text) => String(text ?? '').split('\0').filter(Boolean);
|
|
192
|
+
const env = new Map(words(read('environ')).map((s) => {
|
|
193
|
+
const eq = s.indexOf('=');
|
|
194
|
+
return eq < 0 ? [s, ''] : [s.slice(0, eq), s.slice(eq + 1)];
|
|
195
|
+
}));
|
|
196
|
+
const argv = words(read('cmdline')).join(' ');
|
|
197
|
+
const rss = (read('status') ?? '').match(/^VmRSS:\s+(\d+) kB$/m);
|
|
198
|
+
let exe = '';
|
|
199
|
+
try { exe = fs.readlinkSync(path.join(dir, 'exe')).replace(/ \(deleted\)$/, ''); } catch {}
|
|
200
|
+
const item = env.get('ZERO_ITEM');
|
|
201
|
+
out.push({
|
|
202
|
+
pid: +name,
|
|
203
|
+
ppid: +rest[1],
|
|
204
|
+
mb: rss ? +rss[1] / 1024 : 0,
|
|
205
|
+
start: boot + Math.floor(+rest[19] / hz),
|
|
206
|
+
exe,
|
|
207
|
+
cmd: (argv || `[${comm}]`).slice(0, 300),
|
|
208
|
+
item: /^w-[0-9a-f]+$/.test(item ?? '') ? item : null,
|
|
209
|
+
product: env.get('ZERO_PRODUCT')?.split(/\s/)[0] || null,
|
|
210
|
+
keep: env.get('AGENTBOX_KEEP') === '1',
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
return out;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** Every process, tagged with its task where it can be: `ps` on a Mac (about 100 ms), /proc on Linux. */
|
|
217
|
+
export async function listProcesses(platform = process.platform) {
|
|
218
|
+
if (platform !== 'darwin') return readLinuxProcesses();
|
|
156
219
|
const [base, argv, full] = await Promise.all([
|
|
157
220
|
ps(['-axo', 'pid=,ppid=,rss=,lstart=,comm=']),
|
|
158
221
|
ps(['-ww', '-axo', 'pid=,lstart=,command=']),
|
|
@@ -170,7 +233,7 @@ export async function listProcesses() {
|
|
|
170
233
|
return procs;
|
|
171
234
|
}
|
|
172
235
|
|
|
173
|
-
async function readMacPressureWord() {
|
|
236
|
+
export async function readMacPressureWord() {
|
|
174
237
|
const out = await new Promise((resolve) => {
|
|
175
238
|
execFile('/usr/sbin/sysctl', ['-n', 'kern.memorystatus_vm_pressure_level', 'kern.memorystatus_level'], { timeout: 5_000 },
|
|
176
239
|
(err, stdout) => resolve(err ? '' : stdout));
|
|
@@ -215,7 +278,9 @@ export class LeftoverCleaner {
|
|
|
215
278
|
enabledSince = Date.now(),
|
|
216
279
|
live = () => false,
|
|
217
280
|
owns = () => false,
|
|
218
|
-
|
|
281
|
+
// When the task was closed, or null while it is open.
|
|
282
|
+
closedAt = () => null,
|
|
283
|
+
closeGraceMs = 2 * 60_000,
|
|
219
284
|
tightIdleMs = 10 * 60_000,
|
|
220
285
|
confirmMs = 60_000,
|
|
221
286
|
settleMs = 30_000,
|
|
@@ -225,8 +290,9 @@ export class LeftoverCleaner {
|
|
|
225
290
|
enabled = true,
|
|
226
291
|
log = () => {},
|
|
227
292
|
} = {}) {
|
|
228
|
-
Object.assign(this, { list, kill, clock, readPressure, file, enabledSince, live, owns,
|
|
293
|
+
Object.assign(this, { list, kill, clock, readPressure, file, enabledSince, live, owns, closedAt, closeGraceMs, tightIdleMs, confirmMs, settleMs, home, enabled, log });
|
|
229
294
|
this.firstSeen = new Map();
|
|
295
|
+
this.withPrograms = new Set();
|
|
230
296
|
this.lastStatus = { leftovers: [], survivors: [], stopped: null, pressure: 'normal' };
|
|
231
297
|
const saved = this._load();
|
|
232
298
|
this.runs = saved.runs;
|
|
@@ -274,6 +340,9 @@ export class LeftoverCleaner {
|
|
|
274
340
|
|
|
275
341
|
status() { return this.lastStatus; }
|
|
276
342
|
|
|
343
|
+
/** Whether the last look found programs of this task's that could be stopped. */
|
|
344
|
+
hasPrograms(item) { return this.withPrograms.has(item); }
|
|
345
|
+
|
|
277
346
|
/** Stop signalling from this moment, even in a look already under way. */
|
|
278
347
|
disable() { this.enabled = false; }
|
|
279
348
|
|
|
@@ -308,6 +377,7 @@ export class LeftoverCleaner {
|
|
|
308
377
|
return this.lastStatus;
|
|
309
378
|
}
|
|
310
379
|
const view = this._view(procs, now);
|
|
380
|
+
this.withPrograms = new Set([...view.tasks.values()].filter((t) => t.procs.length).map((t) => t.item));
|
|
311
381
|
this._reconcileRuns(view, now);
|
|
312
382
|
this._trackStopping(view, now);
|
|
313
383
|
const due = this._due(view, now, pressure);
|
|
@@ -407,31 +477,53 @@ export class LeftoverCleaner {
|
|
|
407
477
|
}
|
|
408
478
|
}
|
|
409
479
|
|
|
410
|
-
|
|
480
|
+
/** When this task's programs stop, or null while nothing says they should. */
|
|
481
|
+
_stopsAt(item, product, pressure) {
|
|
411
482
|
const run = this.runs[item];
|
|
412
483
|
if (!run || run.state !== 'ended') return null;
|
|
413
484
|
const from = Math.max(run.endedAt, this.enabledSince);
|
|
414
|
-
|
|
485
|
+
let closed = null;
|
|
486
|
+
try { closed = this.closedAt(item, product); } catch { closed = null; }
|
|
487
|
+
const times = [];
|
|
488
|
+
if (Number.isFinite(closed)) times.push(Math.max(from, closed) + this.closeGraceMs);
|
|
489
|
+
if (pressure !== 'normal') times.push(from + this.tightIdleMs);
|
|
490
|
+
return times.length ? Math.min(...times) : null;
|
|
415
491
|
}
|
|
416
492
|
|
|
417
|
-
/**
|
|
493
|
+
/**
|
|
494
|
+
* Programs whose time has come and that have been seen long enough: every
|
|
495
|
+
* closed task's, and while memory is short, one more task's, the one whose
|
|
496
|
+
* run ended longest ago.
|
|
497
|
+
*/
|
|
418
498
|
_due(view, now, pressure) {
|
|
419
499
|
const due = [];
|
|
420
500
|
if (!this.enabled) return due;
|
|
501
|
+
let short = null;
|
|
421
502
|
for (const t of view.tasks.values()) {
|
|
422
503
|
if (this._alive(t)) continue;
|
|
423
|
-
const
|
|
504
|
+
const closed = this._stopsAt(t.item, t.product, 'normal');
|
|
505
|
+
if (closed !== null && now >= closed) { due.push(...this._ready(t, now)); continue; }
|
|
506
|
+
const at = pressure === 'normal' ? null : this._stopsAt(t.item, t.product, pressure);
|
|
424
507
|
if (at === null || now < at) continue;
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
if (now - (this.firstSeen.get(id) ?? now) < this.confirmMs) continue;
|
|
429
|
-
due.push({ item: t.item, id, pid: p.pid });
|
|
430
|
-
}
|
|
508
|
+
const ready = this._ready(t, now);
|
|
509
|
+
const ended = this.runs[t.item].endedAt;
|
|
510
|
+
if (ready.length && (!short || ended < short.ended)) short = { ended, ready };
|
|
431
511
|
}
|
|
512
|
+
if (short) due.push(...short.ready);
|
|
432
513
|
return due;
|
|
433
514
|
}
|
|
434
515
|
|
|
516
|
+
_ready(t, now) {
|
|
517
|
+
const out = [];
|
|
518
|
+
for (const p of t.procs) {
|
|
519
|
+
const id = idOf(p);
|
|
520
|
+
if (this.stopping[id]) continue;
|
|
521
|
+
if (now - (this.firstSeen.get(id) ?? now) < this.confirmMs) continue;
|
|
522
|
+
out.push({ item: t.item, id, pid: p.pid });
|
|
523
|
+
}
|
|
524
|
+
return out;
|
|
525
|
+
}
|
|
526
|
+
|
|
435
527
|
/** One fresh look, every rule again, then SIGTERM to what still passes. */
|
|
436
528
|
async _stop(due, pressure) {
|
|
437
529
|
let procs;
|
|
@@ -448,8 +540,8 @@ export class LeftoverCleaner {
|
|
|
448
540
|
const t = view.tasks.get(d.item);
|
|
449
541
|
if (!t || !t.procs.includes(p)) continue; // protected now, or no longer this task's
|
|
450
542
|
if (this._alive(t)) continue;
|
|
451
|
-
const at = this._stopsAt(d.item, pressure);
|
|
452
|
-
if (at === null || now < at) continue; // a run started meanwhile
|
|
543
|
+
const at = this._stopsAt(d.item, t.product, pressure);
|
|
544
|
+
if (at === null || now < at) continue; // a run started, or the task reopened, meanwhile
|
|
453
545
|
// Switched off while this look was under way: nothing more is signalled.
|
|
454
546
|
if (!this.enabled) break;
|
|
455
547
|
try { this.kill(p.pid, 'SIGTERM'); } catch { continue; }
|
|
@@ -477,7 +569,7 @@ export class LeftoverCleaner {
|
|
|
477
569
|
kept: t.guarded.length,
|
|
478
570
|
mb: all.reduce((n, p) => n + (p.mb ?? 0), 0),
|
|
479
571
|
oldest: Math.min(...all.map((p) => p.start * 1000)),
|
|
480
|
-
stopsAt: t.procs.length ? this._stopsAt(t.item, pressure) : null,
|
|
572
|
+
stopsAt: t.procs.length ? this._stopsAt(t.item, t.product, pressure) : null,
|
|
481
573
|
});
|
|
482
574
|
}
|
|
483
575
|
return out.sort((a, b) => a.oldest - b.oldest);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// The Mac's own Liquid Glass for a window, or null where there is none: not a
|
|
2
|
+
// Mac, a macOS before 26, or a build that could not compile main/native
|
|
3
|
+
// (scripts/build-liquid-glass.mjs). Null means the page draws its own glass.
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
|
|
6
|
+
export function loadLiquidGlass({ mac = process.platform === 'darwin', load = createRequire(import.meta.url) } = {}) {
|
|
7
|
+
if (!mac) return null;
|
|
8
|
+
let native;
|
|
9
|
+
try {
|
|
10
|
+
native = load('./native/liquid-glass/build/liquid-glass.node');
|
|
11
|
+
if (!native.available()) return null;
|
|
12
|
+
} catch {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const handle = (win) => win.getNativeWindowHandle();
|
|
16
|
+
return {
|
|
17
|
+
// tone: 'light' or 'dark' holds the glass that way; leave it out and the
|
|
18
|
+
// glass decides from what is behind it. style: 'clear' for the Mac's clear
|
|
19
|
+
// glass, which lets a light page through; otherwise the regular glass.
|
|
20
|
+
set: (win, rect, { radius, tone, style } = {}) => native.set(handle(win), rect, {
|
|
21
|
+
radius, ...(tone ? { tone } : {}), ...(style ? { style } : {}),
|
|
22
|
+
}),
|
|
23
|
+
clear: (win) => native.clear(handle(win)),
|
|
24
|
+
tone: (win) => native.tone(handle(win)),
|
|
25
|
+
};
|
|
26
|
+
}
|
package/main/live-replies.mjs
CHANGED
|
@@ -15,9 +15,11 @@ import { TURN_CLOSED } from './claude-input.mjs';
|
|
|
15
15
|
// is the result, so without this it has every reason to save the answer for an
|
|
16
16
|
// ending the person is not waiting through.
|
|
17
17
|
//
|
|
18
|
-
// Their words go LAST
|
|
19
|
-
//
|
|
20
|
-
|
|
18
|
+
// Their words go LAST: the newest thing they said is the newest thing in its
|
|
19
|
+
// context, and nothing of ours is written after it. `files` is the supervisor's
|
|
20
|
+
// `attachmentBlock` for this reply: the pictures in it by absolute path, which
|
|
21
|
+
// is also what a cloud run reads to send them up (main/cloud/run.mjs).
|
|
22
|
+
export function liveReplyBrief(answer, files = '') {
|
|
21
23
|
return [
|
|
22
24
|
'This arrived in your thread just now, while you work, and they are watching',
|
|
23
25
|
'for a reply. Do what it asks. If it asks you anything, or says it did not',
|
|
@@ -25,6 +27,7 @@ export function liveReplyBrief(answer) {
|
|
|
25
27
|
'you go back to what you were doing: the sentences you write while you work',
|
|
26
28
|
'are what they read, so an answer saved for the end reads as no answer at all.',
|
|
27
29
|
'Then carry on.',
|
|
30
|
+
...(files ? [files] : []),
|
|
28
31
|
'',
|
|
29
32
|
'What they said:',
|
|
30
33
|
'',
|
|
@@ -49,7 +52,10 @@ export function submitReply(supervisor, payload, commit) {
|
|
|
49
52
|
// A held Remote Control conversation is sitting idle rather than working,
|
|
50
53
|
// and the slash commands it takes stop being commands once prose is wrapped
|
|
51
54
|
// round them. Both reach it exactly as typed.
|
|
52
|
-
const
|
|
55
|
+
const files = session.remoteIdle ? null : supervisor.replyFiles?.(product, answer, session.engine, id);
|
|
56
|
+
const taken = session.remoteIdle
|
|
57
|
+
? session.child.steer(answer)
|
|
58
|
+
: session.child.steer(liveReplyBrief(answer, files?.block), files?.pictures ?? []);
|
|
53
59
|
// SENT NOW: her words go in line first, then the step is cut, in the same
|
|
54
60
|
// tick, so the cut turn's result can never close the input ahead of them.
|
|
55
61
|
// A cut that fails leaves the message waiting its turn, which is still sent.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// A LOCAL APP SHOWS IN THE PANE AND STAYS SIGNED IN.
|
|
2
|
+
//
|
|
3
|
+
// The pane draws an address like http://localhost:3006 in a frame, because a
|
|
4
|
+
// frame keeps every shortcut the app answers from inside a page (the
|
|
5
|
+
// before-input-event handler in main.mjs hears a frame; it would not hear a
|
|
6
|
+
// webview's guest). Two things a local app commonly sends broke that frame:
|
|
7
|
+
//
|
|
8
|
+
// X-Frame-Options / CSP frame-ancestors Chromium refuses to draw the page
|
|
9
|
+
// at all, so the pane sat blank.
|
|
10
|
+
// Next.js apps send both.
|
|
11
|
+
// a SameSite=Lax sign-in cookie the window is a file:// page, so
|
|
12
|
+
// the app in it is cross-site and the
|
|
13
|
+
// cookie is refused: sign-in loops.
|
|
14
|
+
//
|
|
15
|
+
// Both are rewritten here, below the page, for local addresses only and only
|
|
16
|
+
// inside the app's own window. Framing protection exists to stop another site
|
|
17
|
+
// drawing yours under a stranger's pointer; the app drawing her own dev server
|
|
18
|
+
// for her is not that. tests/a-local-app-shows-in-the-pane-and-stays-signed-in.test.mjs
|
|
19
|
+
|
|
20
|
+
const LOCAL_HOSTS = new Set(['localhost', '127.0.0.1', '[::1]']);
|
|
21
|
+
|
|
22
|
+
export function isLocalAddress(url) {
|
|
23
|
+
try {
|
|
24
|
+
const u = new URL(url);
|
|
25
|
+
return (u.protocol === 'http:' || u.protocol === 'https:') && LOCAL_HOSTS.has(u.hostname);
|
|
26
|
+
} catch { return false; }
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const keyOf = (headers, name) => Object.keys(headers).find((k) => k.toLowerCase() === name);
|
|
30
|
+
|
|
31
|
+
function withoutFrameAncestors(policy) {
|
|
32
|
+
return policy.split(';').map((d) => d.trim()).filter((d) => d && !/^frame-ancestors(\s|$)/i.test(d)).join('; ');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// SameSite=None needs Secure, and Chromium takes Secure from http://localhost
|
|
36
|
+
// because it counts loopback as a secure origin.
|
|
37
|
+
function sentInsideTheWindow(cookie) {
|
|
38
|
+
const parts = cookie.split(';').map((p) => p.trim());
|
|
39
|
+
if (parts.some((p) => /^samesite\s*=\s*none$/i.test(p))) return cookie;
|
|
40
|
+
const kept = parts.filter((p) => !/^samesite\s*=/i.test(p));
|
|
41
|
+
if (!kept.some((p) => /^secure$/i.test(p))) kept.push('SameSite=None', 'Secure');
|
|
42
|
+
else kept.push('SameSite=None');
|
|
43
|
+
return kept.join('; ');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The headers a local app's response should carry inside the pane, or null
|
|
48
|
+
* when nothing changes. `details` is Electron's onHeadersReceived details.
|
|
49
|
+
*/
|
|
50
|
+
export function localAppHeaders({ url, resourceType, responseHeaders }) {
|
|
51
|
+
if (!responseHeaders || resourceType === 'mainFrame' || !isLocalAddress(url)) return null;
|
|
52
|
+
const out = { ...responseHeaders };
|
|
53
|
+
let changed = false;
|
|
54
|
+
if (resourceType === 'subFrame') {
|
|
55
|
+
const xfo = keyOf(out, 'x-frame-options');
|
|
56
|
+
if (xfo) { delete out[xfo]; changed = true; }
|
|
57
|
+
const csp = keyOf(out, 'content-security-policy');
|
|
58
|
+
if (csp) {
|
|
59
|
+
const policies = out[csp].map(withoutFrameAncestors).filter(Boolean);
|
|
60
|
+
if (policies.join() !== out[csp].join()) {
|
|
61
|
+
changed = true;
|
|
62
|
+
if (policies.length) out[csp] = policies; else delete out[csp];
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const cookies = keyOf(out, 'set-cookie');
|
|
67
|
+
if (cookies) {
|
|
68
|
+
const next = out[cookies].map(sentInsideTheWindow);
|
|
69
|
+
if (next.join('\n') !== out[cookies].join('\n')) { out[cookies] = next; changed = true; }
|
|
70
|
+
}
|
|
71
|
+
return changed ? out : null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Wire it to the window's own session, for that window's requests only. */
|
|
75
|
+
export function letLocalAppsShowInThePane(contents) {
|
|
76
|
+
const filter = { urls: ['*://localhost/*', '*://127.0.0.1/*', '*://[::1]/*'] };
|
|
77
|
+
contents.session.webRequest.onHeadersReceived(filter, (details, callback) => {
|
|
78
|
+
const ours = details.webContentsId === contents.id;
|
|
79
|
+
const responseHeaders = ours ? localAppHeaders(details) : null;
|
|
80
|
+
callback(responseHeaders ? { responseHeaders } : {});
|
|
81
|
+
});
|
|
82
|
+
}
|