farming-code 2.2.14 → 2.2.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/README.md +3 -3
  2. package/README.zh_cn.md +3 -3
  3. package/THIRD_PARTY_NOTICES.md +17 -1
  4. package/backend/acp/packaged-codex-acp.js +13 -0
  5. package/backend/acp-runtime.js +413 -24
  6. package/backend/agent-manager.js +572 -557
  7. package/backend/agent-provider-session.js +15 -1
  8. package/backend/agent-runtime-binding.js +9 -55
  9. package/backend/chat-runtime.js +28 -0
  10. package/backend/codex-rollout-follower.js +83 -0
  11. package/backend/codex-session-archive.js +12 -1
  12. package/backend/codex-session-history.js +94 -0
  13. package/backend/codex-transcript.js +2 -1
  14. package/backend/config-manager.js +25 -17
  15. package/backend/control-api.js +3 -1
  16. package/backend/farming-app-cli.js +21 -0
  17. package/backend/farming-session-store.js +2 -1
  18. package/backend/native-pty-host-client.js +59 -2
  19. package/backend/npm-update-helper.js +65 -7
  20. package/backend/provider-adapters.js +123 -38
  21. package/backend/provider-session-service.js +138 -34
  22. package/backend/server.js +94 -105
  23. package/backend/storage-layout.js +5 -16
  24. package/backend/update-service.js +94 -5
  25. package/backend/usage-history-client.js +305 -0
  26. package/backend/usage-history-scanner.generated.js +2250 -0
  27. package/backend/usage-history-scanner.ts +2718 -0
  28. package/backend/usage-history-smoke.js +64 -0
  29. package/backend/usage-history-worker.js +34 -0
  30. package/backend/usage-monitor.js +188 -588
  31. package/backend/vendor/usage-parsers/CC_STATISTICS_LICENSE +21 -0
  32. package/backend/vendor/usage-parsers/CODEXBAR_LICENSE +21 -0
  33. package/backend/vendor/usage-parsers/VENDOR.json +45 -0
  34. package/dist/acp/LICENSE.codex-acp +190 -0
  35. package/dist/acp/codex-acp-1.1.4.js +30718 -0
  36. package/dist/assets/App-6yWdwzj8.js +210 -0
  37. package/dist/assets/{FileEditorMarkdownPreview-UlVd0O4D.js → FileEditorMarkdownPreview-R0jwwLME.js} +4 -4
  38. package/dist/assets/FileEditorPane-DNy3LAqS.js +2 -0
  39. package/dist/assets/{IconGlyphs-AU22gPDY.js → IconGlyphs-BsUfqpKN.js} +1 -1
  40. package/dist/assets/ProjectFilesSection-BhDEUVHA.js +12 -0
  41. package/dist/assets/{ReviewPage-CeDKDyZh.js → ReviewPage-ChtByBe3.js} +1 -1
  42. package/dist/assets/{abnfDiagram-VRR7QNED-BgawzDQT.js → abnfDiagram-VRR7QNED-nnglrXFi.js} +1 -1
  43. package/dist/assets/{architectureDiagram-ZJ3FMSHR-DUShwPg0.js → architectureDiagram-ZJ3FMSHR-BEXMaFfY.js} +1 -1
  44. package/dist/assets/{blockDiagram-677ZJIJ3-CeGZviXR.js → blockDiagram-677ZJIJ3-1mCezSBk.js} +1 -1
  45. package/dist/assets/{c4Diagram-LMCZKHZV-CLhYht6S.js → c4Diagram-LMCZKHZV-DhTiI6Uv.js} +1 -1
  46. package/dist/assets/channel-BVWNatUB.js +1 -0
  47. package/dist/assets/{chunk-32BRIVSS-LFYpT-Cu.js → chunk-32BRIVSS-CCdsKd73.js} +1 -1
  48. package/dist/assets/{chunk-52WLFC77-BH6jDw9J.js → chunk-52WLFC77-Gncjk4LF.js} +1 -1
  49. package/dist/assets/{chunk-C7G6YPKG-B_mIUlb7.js → chunk-C7G6YPKG-CiDVUP82.js} +1 -1
  50. package/dist/assets/{chunk-EX3LRPZG-C63hVuAJ.js → chunk-EX3LRPZG-z6gXP2_N.js} +1 -1
  51. package/dist/assets/{chunk-FWX5IMBZ-CboX-WF_.js → chunk-FWX5IMBZ-DMZBccQa.js} +2 -2
  52. package/dist/assets/{chunk-HOUHSVGY-BOgSd6Un.js → chunk-HOUHSVGY-D8tIeoPk.js} +1 -1
  53. package/dist/assets/{chunk-ICXQ74PX-C0K-pgZt.js → chunk-ICXQ74PX-b6oQ2Q17.js} +1 -1
  54. package/dist/assets/{chunk-MOJQB5TN-CVMfwN_7.js → chunk-MOJQB5TN-DAVH_p2a.js} +1 -1
  55. package/dist/assets/{chunk-OGEWGWER-DLT3pxyw.js → chunk-OGEWGWER-DxoiMCI-.js} +1 -1
  56. package/dist/assets/{chunk-PUDLZKDR-Cd079yIQ.js → chunk-PUDLZKDR-NsOWh7HM.js} +1 -1
  57. package/dist/assets/{chunk-Q4XR5HBZ-D0jHa6SO.js → chunk-Q4XR5HBZ-Di4H7L21.js} +1 -1
  58. package/dist/assets/{chunk-V7JOEXUC-CVDtR75H.js → chunk-V7JOEXUC-DttpZg9Y.js} +1 -1
  59. package/dist/assets/{chunk-VAUOI2AC-B-W2_9Ot.js → chunk-VAUOI2AC-UHNr_yhX.js} +1 -1
  60. package/dist/assets/{chunk-VR4S4FIN-FD3kWh32.js → chunk-VR4S4FIN-D-Fmtd4Z.js} +1 -1
  61. package/dist/assets/{chunk-WYO6CB5R-C2bGaS5r.js → chunk-WYO6CB5R-CUxMtfK2.js} +4 -4
  62. package/dist/assets/{chunk-ZGVPDNZ5-ymgts0zo.js → chunk-ZGVPDNZ5-CoV2QEl0.js} +1 -1
  63. package/dist/assets/classDiagram-OUVF2IWQ-Db0ib5iE.js +1 -0
  64. package/dist/assets/classDiagram-v2-EOCWNBFH-Bkf69XF9.js +1 -0
  65. package/dist/assets/code-dark-5esj0bRu.css +1 -0
  66. package/dist/assets/{cynefinDiagram-TSTJHNR4-CwpobXIl.js → cynefinDiagram-TSTJHNR4-0xPI92Lg.js} +1 -1
  67. package/dist/assets/{dagre-VKFMJZFB-Dkhlfjna.js → dagre-VKFMJZFB-DfuMG4gU.js} +1 -1
  68. package/dist/assets/{diagram-FQU43EPY-hA8dicp6.js → diagram-FQU43EPY-CT00bLZ6.js} +1 -1
  69. package/dist/assets/{diagram-G47NLZAW-BTY6JTzO.js → diagram-G47NLZAW-Xbh7zXUx.js} +1 -1
  70. package/dist/assets/{diagram-NH7WQ7WH-xkaHHX9M.js → diagram-NH7WQ7WH-SRDVPfn7.js} +1 -1
  71. package/dist/assets/{diagram-OA4YK3LP-gk_fg9UU.js → diagram-OA4YK3LP-CQRli4Np.js} +1 -1
  72. package/dist/assets/{diagram-WEI45ONY-BvC8xd6T.js → diagram-WEI45ONY-DMf17WQi.js} +1 -1
  73. package/dist/assets/{ebnfDiagram-CCIWWBDH-CR7RaNat.js → ebnfDiagram-CCIWWBDH-DhpFkgJ5.js} +1 -1
  74. package/dist/assets/{erDiagram-Q63AITRT-_M-JFPbj.js → erDiagram-Q63AITRT-1IwxWmJo.js} +1 -1
  75. package/dist/assets/file-icons-DpbrD5ZP.js +1 -0
  76. package/dist/assets/flowDiagram-23GEKE2U-DYFo2xmB.js +1 -0
  77. package/dist/assets/{ganttDiagram-NO4QXBWP-Bl8P1yf_.js → ganttDiagram-NO4QXBWP-BNCdfyr1.js} +1 -1
  78. package/dist/assets/{gitGraphDiagram-IHSO6WYX-DoHa5ysz.js → gitGraphDiagram-IHSO6WYX-pbyWZuiX.js} +1 -1
  79. package/dist/assets/{index-BA-iH2Kg.js → index-C8ZFKye1.js} +2 -2
  80. package/dist/assets/{infoDiagram-FWYZ7A6U-DSFcSuUs.js → infoDiagram-FWYZ7A6U-BcTOgDbe.js} +1 -1
  81. package/dist/assets/{ishikawaDiagram-FXEZZL3T-DdkqullI.js → ishikawaDiagram-FXEZZL3T-DCdvGKrn.js} +1 -1
  82. package/dist/assets/{journeyDiagram-5HDEW3XC-B4hRnQJr.js → journeyDiagram-5HDEW3XC-BZ-1q_IT.js} +1 -1
  83. package/dist/assets/{kanban-definition-HUTT4EX6-tm2FZB2E.js → kanban-definition-HUTT4EX6-BIgejCjj.js} +1 -1
  84. package/dist/assets/{line-CmsjK4kn.js → line-CfptFMmX.js} +1 -1
  85. package/dist/assets/main-DSO3i_Gs.css +1 -0
  86. package/dist/assets/{mermaid.core-C7UT_EEL.js → mermaid.core-gSpX30pV.js} +3 -3
  87. package/dist/assets/{mindmap-definition-LN4V7U3C-DplfjGms.js → mindmap-definition-LN4V7U3C-BKBaI4LW.js} +1 -1
  88. package/dist/assets/{pegDiagram-2B236MQR-lu3SdkQs.js → pegDiagram-2B236MQR-sBvDY3VX.js} +1 -1
  89. package/dist/assets/{pieDiagram-ENE6RG2P-3fHbmDf9.js → pieDiagram-ENE6RG2P-DWlWcu08.js} +1 -1
  90. package/dist/assets/{quadrantDiagram-ABIIQ3AL-a5qoWz-X.js → quadrantDiagram-ABIIQ3AL-DZutUd3J.js} +1 -1
  91. package/dist/assets/{railroadDiagram-RFXS5EU6-D2TOuXW9.js → railroadDiagram-RFXS5EU6-DQb3lXGM.js} +1 -1
  92. package/dist/assets/{requirementDiagram-TGXJPOKE-LQBWpUvd.js → requirementDiagram-TGXJPOKE-DqFGXu2e.js} +1 -1
  93. package/dist/assets/{sankeyDiagram-HTMAVEWB-B1ohYoyK.js → sankeyDiagram-HTMAVEWB-d7ECahnO.js} +1 -1
  94. package/dist/assets/{sequenceDiagram-DBY2YBRQ-C3vM-hMq.js → sequenceDiagram-DBY2YBRQ-DdsbKqct.js} +1 -1
  95. package/dist/assets/{stateDiagram-2N3HPSRC-BvFhOryI.js → stateDiagram-2N3HPSRC-P6iSrgwR.js} +1 -1
  96. package/dist/assets/stateDiagram-v2-6OUMAXLB-DIYSf_qh.js +1 -0
  97. package/dist/assets/{swimlanes-5IMT3BWC-DKF_b-2s.js → swimlanes-5IMT3BWC-BGnZJx1M.js} +1 -1
  98. package/dist/assets/swimlanesDiagram-G3AALYLV-BIkrlKrZ.js +8 -0
  99. package/dist/assets/{timeline-definition-FHXFAJF6-vAs11ux_.js → timeline-definition-FHXFAJF6-rA-r3aUR.js} +1 -1
  100. package/dist/assets/{vennDiagram-L72KCM5P-BybTX_9B.js → vennDiagram-L72KCM5P-DiVKUjA9.js} +1 -1
  101. package/dist/assets/{wardleyDiagram-EHGQE667-CicUmMBR.js → wardleyDiagram-EHGQE667-Cfxh7UOn.js} +1 -1
  102. package/dist/assets/workspace-editor-model-D0Im34S5.js +1 -0
  103. package/dist/assets/{workspace-editor-monaco-BICJESG0.js → workspace-editor-monaco-BIpqcWf1.js} +1 -1
  104. package/dist/assets/workspace-editor-monaco-DLlws5Ig.js +1 -0
  105. package/dist/assets/{workspace-view-state-DvYG_9PH.js → workspace-view-state-BpPINu84.js} +1 -1
  106. package/dist/assets/{xychartDiagram-FW5EYKEG-BhWDyCX-.js → xychartDiagram-FW5EYKEG--hmryQeL.js} +1 -1
  107. package/dist/crt-mermaid-renderer.js +313 -313
  108. package/dist/index.html +1 -1
  109. package/frontend/session-bridge.js +24 -2
  110. package/frontend/skins/crt/app.js +203 -85
  111. package/frontend/skins/crt/index.html +2 -11
  112. package/frontend/skins/crt/styles/effects.css +2 -34
  113. package/package.json +30 -12
  114. package/shared/backend-connection-status.d.ts +25 -0
  115. package/shared/backend-connection-status.js +40 -0
  116. package/shared/browser-protocol.js +3 -3
  117. package/backend/app-server-api.js +0 -917
  118. package/backend/codex-app-server-home.js +0 -39
  119. package/backend/codex-app-server-runtime.js +0 -901
  120. package/dist/assets/App-Bumi772v.js +0 -206
  121. package/dist/assets/FileEditorPane-Dxx4rKOg.js +0 -2
  122. package/dist/assets/ProjectFilesSection-DE7Nb9Jk.js +0 -12
  123. package/dist/assets/channel-Uw90AO0b.js +0 -1
  124. package/dist/assets/classDiagram-OUVF2IWQ-DKW_dtku.js +0 -1
  125. package/dist/assets/classDiagram-v2-EOCWNBFH-C8Fi7-yv.js +0 -1
  126. package/dist/assets/code-dark-DPiuyeSp.css +0 -1
  127. package/dist/assets/code-mobile-3C2Rr-CN.css +0 -1
  128. package/dist/assets/file-icons-Bw2qd5iT.js +0 -1
  129. package/dist/assets/flowDiagram-23GEKE2U-DAiS5Y7G.js +0 -1
  130. package/dist/assets/main-Bqtb5kuz.css +0 -1
  131. package/dist/assets/stateDiagram-v2-6OUMAXLB-WMrz4PNo.js +0 -1
  132. package/dist/assets/swimlanesDiagram-G3AALYLV-BGswC9oC.js +0 -8
  133. package/dist/assets/workspace-editor-model-BQol4qbA.js +0 -1
  134. package/dist/assets/workspace-editor-monaco-DRJ7IaXk.js +0 -1
  135. package/scripts/sync-ghostty-vendor.js +0 -66
  136. /package/dist/assets/{core-D0LFJkDt.js → core-B9MwRjDE.js} +0 -0
@@ -174,7 +174,7 @@
174
174
  inset: 3px 0 0;
175
175
  display: flex;
176
176
  flex-direction: column;
177
- justify-content: flex-end;
177
+ justify-content: flex-start;
178
178
  gap: 5px;
179
179
  min-height: 0;
180
180
  padding: 0 4px 2px 12px;
@@ -209,7 +209,7 @@
209
209
  display: flex;
210
210
  flex: 0 1 auto;
211
211
  flex-direction: column;
212
- justify-content: flex-end;
212
+ justify-content: flex-start;
213
213
  gap: 5px;
214
214
  min-height: 0;
215
215
  overflow: hidden;
@@ -300,20 +300,11 @@
300
300
  opacity: 0.58;
301
301
  }
302
302
 
303
- .agent-block.working .agent-output:not(.structured-preview) {
304
- animation: blink 0.5s infinite;
305
- }
306
-
307
303
  @keyframes crt-chat-signal {
308
304
  0%, 100% { opacity: 0.45; transform: scale(0.82); }
309
305
  50% { opacity: 1; transform: scale(1); }
310
306
  }
311
307
 
312
- @keyframes blink {
313
- 0%, 100% { opacity: 1; }
314
- 50% { opacity: 0.8; }
315
- }
316
-
317
308
  .sidebar {
318
309
  width: 200px;
319
310
  background: #2a2a2a;
@@ -86,8 +86,7 @@
86
86
  }
87
87
 
88
88
  #farming-crt.no-crt .crt-phosphor-noise,
89
- #farming-crt.no-crt .crt-scan-beam,
90
- #farming-crt.no-crt .agent-output-afterimage {
89
+ #farming-crt.no-crt .crt-scan-beam {
91
90
  display: none;
92
91
  }
93
92
 
@@ -112,15 +111,6 @@
112
111
  }
113
112
  }
114
113
 
115
- #farming-crt .agent-output-afterimage {
116
- pointer-events: none;
117
- user-select: none;
118
- opacity: 0.34;
119
- filter: blur(0.35px);
120
- mix-blend-mode: screen;
121
- animation: crt-content-afterimage 620ms cubic-bezier(0.16, 0.72, 0.28, 1) forwards;
122
- }
123
-
124
114
  #farming-crt .xterm-screen {
125
115
  position: relative;
126
116
  }
@@ -150,30 +140,8 @@
150
140
  color: #b98282;
151
141
  }
152
142
 
153
- #farming-crt .agent-output-afterimage {
154
- position: absolute;
155
- inset: 0;
156
- z-index: 2;
157
- }
158
-
159
- @keyframes crt-content-afterimage {
160
- 0% {
161
- opacity: 0.34;
162
- filter: blur(0.25px) brightness(1.08);
163
- }
164
- 45% {
165
- opacity: 0.13;
166
- filter: blur(0.65px) brightness(0.94);
167
- }
168
- 100% {
169
- opacity: 0;
170
- filter: blur(1.2px) brightness(0.72);
171
- }
172
- }
173
-
174
143
  @media (prefers-reduced-motion: reduce) {
175
- #farming-crt .crt-scan-beam,
176
- #farming-crt .agent-output-afterimage {
144
+ #farming-crt .crt-scan-beam {
177
145
  display: none;
178
146
  }
179
147
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "farming-code",
3
- "version": "2.2.14",
3
+ "version": "2.2.17",
4
4
  "description": "Remote browser workspace for supervising AI coding agents",
5
5
  "main": "backend/server.js",
6
6
  "bin": {
@@ -8,8 +8,10 @@
8
8
  },
9
9
  "files": [
10
10
  "backend/*.js",
11
+ "backend/usage-history-scanner.ts",
11
12
  "backend/acp/",
12
13
  "backend/data/",
14
+ "backend/vendor/usage-parsers/",
13
15
  "bin/",
14
16
  "config/*.example",
15
17
  "dist/",
@@ -19,7 +21,6 @@
19
21
  "frontend/themes/",
20
22
  "frontend/vendor/ghostty-web/",
21
23
  "shared/",
22
- "scripts/sync-ghostty-vendor.js",
23
24
  "LICENSE",
24
25
  "README.md",
25
26
  "README.zh_cn.md",
@@ -29,18 +30,21 @@
29
30
  ],
30
31
  "scripts": {
31
32
  "sync:ghostty-vendor": "node scripts/sync-ghostty-vendor.js",
32
- "postinstall": "node scripts/sync-ghostty-vendor.js",
33
+ "prepare:acp-vendor": "node scripts/prepare-codex-acp-vendor.js --copy",
34
+ "build:usage-history": "node scripts/build-usage-history-scanner.js",
35
+ "prebuild": "node scripts/build-usage-history-scanner.js && node scripts/sync-ghostty-vendor.js && node scripts/prepare-codex-acp-vendor.js",
33
36
  "prepack": "FARMING_BASE_PATH=/farming npm run build",
37
+ "pretest": "npm run prepare:acp-vendor && npm run build:usage-history",
34
38
  "start": "npm run build && node backend/server.js",
35
39
  "start:net": "node backend/farming-net-server.js",
36
40
  "start:no-auth": "FARMING_DISABLE_AUTH=1 npm start",
37
- "predev:backend": "npm run build:crt-markdown",
41
+ "predev:backend": "npm run prepare:acp-vendor && npm run build:usage-history && npm run build:crt-markdown",
38
42
  "dev:backend": "node backend/server.js",
39
43
  "dev:frontend": "vite",
40
- "predev": "npm run build:crt-markdown",
44
+ "predev": "npm run prepare:acp-vendor && npm run build:usage-history && npm run build:crt-markdown",
41
45
  "dev": "node backend/server.js & vite --open & wait",
42
46
  "build:crt-markdown": "node -e \"require('fs').rmSync('dist/crt-markdown-assets',{recursive:true,force:true})\" && esbuild src/crt-markdown-renderer.tsx --bundle --outdir=dist --entry-names=crt-markdown-renderer --asset-names=crt-markdown-assets/[name]-[hash] --platform=browser --format=iife --target=es2022 --loader:.woff=file --loader:.woff2=file --loader:.ttf=file --minify && esbuild src/crt-mermaid-runtime.ts --bundle --outfile=dist/crt-mermaid-renderer.js --platform=browser --format=iife --target=es2022 --minify",
43
- "build": "vite build && npm run build:crt-markdown",
47
+ "build": "vite build && npm run build:crt-markdown && npm run prepare:acp-vendor",
44
48
  "deploy:remote": "./scripts/deploy.sh up",
45
49
  "deploy:remote:no-auth": "./scripts/deploy.sh up --disable-auth",
46
50
  "release:cli": "./scripts/package-cli-release.sh",
@@ -55,7 +59,6 @@
55
59
  "release:remote:linux-compat": "./scripts/install-remote-linux-compat-release.sh",
56
60
  "docs:product:screenshots": "node scripts/capture-product-screenshots.js",
57
61
  "test": "node scripts/run-tests.js",
58
- "test:codex-app-server:real": "FARMING_REAL_CODEX_APP_SERVER_SMOKE=1 node scripts/smoke-codex-app-server.js",
59
62
  "test:pre-release:codex-ui": "FARMING_REAL_CODEX_BIN=\"$(command -v codex)\" FARMING_CODEX_BIN=\"$PWD/tests/e2e/fixtures/real-codex-no-update\" FARMING_REAL_CODEX_RELEASE_CASE=1 FARMING_E2E_REAL_CODEX=1 FARMING_PLAYWRIGHT_INTERNAL=1 playwright test tests/e2e/internal/real-codex-release-case.spec.ts --project=chromium --workers=1 --retries=0 --trace=retain-on-failure",
60
63
  "test:pre-release:terminal-input": "playwright test tests/e2e/terminal-input-performance.spec.ts --project=chromium --workers=1 --retries=0 --trace=retain-on-failure",
61
64
  "test:performance:audit": "node tests/performance/agent-usage-hotpath.js && FARMING_PLAYWRIGHT_INTERNAL=1 playwright test tests/e2e/internal/performance-bottlenecks.spec.ts --project=chromium --workers=1 --retries=0 --trace=retain-on-failure",
@@ -68,10 +71,11 @@
68
71
  "test:e2e:local": "FARMING_BASE_PATH=/farming npm run build && node scripts/e2e.js local",
69
72
  "test:e2e:remote": "FARMING_BASE_PATH=/farming npm run build && node scripts/e2e.js remote",
70
73
  "test:remote-terminal:smoke": "node scripts/smoke-remote-terminal.js",
74
+ "test:remote-terminal:chaos": "node scripts/smoke-remote-terminal-chaos.js",
71
75
  "test:e2e:workspaces:local": "FARMING_BASE_PATH=/farming npm run build && node scripts/e2e-workspaces.js local",
72
76
  "test:e2e:workspaces:remote": "FARMING_BASE_PATH=/farming npm run build && node scripts/e2e-workspaces.js remote",
73
- "typecheck": "tsc --noEmit",
74
- "lint": "eslint --max-warnings=0 \"backend/**/*.js\" \"frontend/**/*.js\" \"scripts/**/*.js\" bin/farming --ignore-pattern \"frontend/vendor/**\" --ignore-pattern \"frontend/themes/**\"",
77
+ "typecheck": "tsc --noEmit && tsc -p tsconfig.usage.json",
78
+ "lint": "eslint --max-warnings=0 \"backend/**/*.js\" \"frontend/**/*.js\" \"scripts/**/*.js\" bin/farming --ignore-pattern \"backend/usage-history-scanner.generated.js\" --ignore-pattern \"frontend/vendor/**\" --ignore-pattern \"frontend/themes/**\"",
75
79
  "check": "npm run typecheck && npm run lint && npm test"
76
80
  },
77
81
  "keywords": [
@@ -96,7 +100,7 @@
96
100
  "access": "public"
97
101
  },
98
102
  "engines": {
99
- "node": ">=22"
103
+ "node": "^22.13.0 || >=24.0.0"
100
104
  },
101
105
  "dependencies": {
102
106
  "@agentclientprotocol/claude-agent-acp": "0.59.0",
@@ -112,7 +116,7 @@
112
116
  "ansi-to-html": "^0.7.2",
113
117
  "chokidar": "^5.0.0",
114
118
  "diff": "^9.0.0",
115
- "express": "^4.18.2",
119
+ "express": "^4.22.2",
116
120
  "ghostty-web": "^0.4.0",
117
121
  "highlight.js": "^11.11.1",
118
122
  "katex": "^0.17.0",
@@ -136,19 +140,33 @@
136
140
  "devDependencies": {
137
141
  "@eslint/js": "^10.0.1",
138
142
  "@playwright/test": "^1.59.1",
143
+ "@types/node": "^26.1.1",
139
144
  "@types/react": "^19.2.14",
140
145
  "@types/react-dom": "^19.2.3",
141
146
  "@vitejs/plugin-react": "^6.0.1",
142
147
  "@yao-pkg/pkg": "6.20.0",
143
148
  "esbuild": "^0.27.7",
144
149
  "eslint": "^10.2.0",
150
+ "patch-package": "8.0.1",
145
151
  "puppeteer": "^24.40.0",
146
152
  "tsx": "^4.21.0",
147
153
  "typescript": "^6.0.2",
148
154
  "vite": "^8.0.3"
149
155
  },
150
156
  "overrides": {
157
+ "@hono/node-server": "2.0.11",
158
+ "express@^4.22.2": {
159
+ ".": "$express",
160
+ "body-parser": "1.20.6"
161
+ },
151
162
  "qs": "6.15.3",
152
- "dompurify": "3.4.11"
163
+ "dompurify": "3.4.12"
164
+ },
165
+ "allowScripts": {
166
+ "esbuild@0.27.7": true,
167
+ "esbuild@0.28.1": true,
168
+ "node-pty@1.2.0-beta.12": true,
169
+ "fsevents": false,
170
+ "puppeteer": false
153
171
  }
154
172
  }
@@ -0,0 +1,25 @@
1
+ export const BACKEND_INITIAL_CONNECT_GRACE_MS: number
2
+ export const BACKEND_HEARTBEAT_STALE_MS: number
3
+
4
+ export type BackendConnectionState = 'connecting' | 'lost' | 'stale' | null
5
+ export interface PageVisibilitySnapshot {
6
+ visible: boolean
7
+ visibleSince: number
8
+ }
9
+
10
+ export function classifyBackendConnection(input: {
11
+ connected: boolean
12
+ everConnected: boolean
13
+ lastMessageAt: number
14
+ visibleSince: number
15
+ now: number
16
+ }): BackendConnectionState
17
+
18
+ export function reducePageVisibilitySnapshot(
19
+ current: PageVisibilitySnapshot,
20
+ event: {
21
+ eventType: string
22
+ documentVisible: boolean
23
+ changedAt: number
24
+ },
25
+ ): PageVisibilitySnapshot
@@ -0,0 +1,40 @@
1
+ const BACKEND_INITIAL_CONNECT_GRACE_MS = 3000;
2
+ const BACKEND_HEARTBEAT_STALE_MS = 6000;
3
+
4
+ function classifyBackendConnection({
5
+ connected,
6
+ everConnected,
7
+ lastMessageAt,
8
+ visibleSince,
9
+ now,
10
+ }) {
11
+ const observationStartedAt = Math.max(lastMessageAt, visibleSince);
12
+ const elapsed = Math.max(0, now - observationStartedAt);
13
+ if (!connected && everConnected) return 'lost';
14
+ if (!connected && elapsed >= BACKEND_INITIAL_CONNECT_GRACE_MS) return 'connecting';
15
+ if (connected && elapsed >= BACKEND_HEARTBEAT_STALE_MS) return 'stale';
16
+ return null;
17
+ }
18
+
19
+ function reducePageVisibilitySnapshot(current, {
20
+ eventType,
21
+ documentVisible,
22
+ changedAt,
23
+ }) {
24
+ const visible = eventType === 'pagehide' ? false : documentVisible;
25
+ if (visible === current.visible) {
26
+ if (!visible || eventType !== 'pageshow') return current;
27
+ return { visible: true, visibleSince: changedAt };
28
+ }
29
+ return {
30
+ visible,
31
+ visibleSince: visible ? changedAt : current.visibleSince,
32
+ };
33
+ }
34
+
35
+ module.exports = {
36
+ BACKEND_INITIAL_CONNECT_GRACE_MS,
37
+ BACKEND_HEARTBEAT_STALE_MS,
38
+ classifyBackendConnection,
39
+ reducePageVisibilitySnapshot,
40
+ };
@@ -6,7 +6,6 @@ const CLIENT_MESSAGE_TYPES = new Set([
6
6
  'start-agent',
7
7
  'input',
8
8
  'composer-input',
9
- 'app-server-request-response',
10
9
  'acp-permission-response',
11
10
  'interrupt-agent',
12
11
  'focus-agent',
@@ -24,6 +23,7 @@ const SERVER_MESSAGE_TYPES = new Set([
24
23
  'command-ack',
25
24
  'state',
26
25
  'error',
26
+ 'composer-input-result',
27
27
  'agent-started',
28
28
  'session-output',
29
29
  'session-preview',
@@ -80,8 +80,7 @@ function validateClientMessage(value) {
80
80
  case 'protocol-hello': valid = Number.isInteger(value.protocolVersion); break;
81
81
  case 'start-agent': valid = stringField(value, 'command'); break;
82
82
  case 'input': valid = stringField(value, 'agentId', true) && (typeof value.input === 'string' || Array.isArray(value.inputParts)); break;
83
- case 'composer-input': valid = stringField(value, 'message') && stringField(value, 'agentId', true); break;
84
- case 'app-server-request-response':
83
+ case 'composer-input': valid = stringField(value, 'message') && stringField(value, 'agentId', true) && stringField(value, 'requestId', true); break;
85
84
  case 'acp-permission-response': valid = stringField(value, 'agentId') && stringField(value, 'requestId'); break;
86
85
  case 'focus-agent': valid = value.agentId === null || stringField(value, 'agentId'); break;
87
86
  case 'resize-agent': valid = stringField(value, 'agentId') && finiteField(value, 'cols') && finiteField(value, 'rows'); break;
@@ -102,6 +101,7 @@ function validateServerMessage(value) {
102
101
  case 'error': valid = stringField(value, 'message'); break;
103
102
  case 'command-ack': valid = stringField(value, 'requestId') && stringField(value, 'command'); break;
104
103
  case 'state': valid = objectMessage(value.state) && Array.isArray(value.state.agents); break;
104
+ case 'composer-input-result': valid = stringField(value, 'requestId') && stringField(value, 'agentId') && typeof value.accepted === 'boolean' && stringField(value, 'message', true); break;
105
105
  case 'agent-started': valid = stringField(value, 'agentId'); break;
106
106
  case 'session-output': valid = objectMessage(value.stream) && stringField(value.stream, 'agentId'); break;
107
107
  case 'session-preview': valid = objectMessage(value.preview) && stringField(value.preview, 'agentId'); break;