@harness-mix/cli 0.1.11 → 0.2.0

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 (306) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/NOTICE +16 -2
  3. package/README.md +265 -3
  4. package/docs/cross-platform.md +3 -3
  5. package/docs/multi-agent-collaboration.md +37 -23
  6. package/docs/native-acp.md +2 -2
  7. package/docs/native-codex.md +5 -5
  8. package/docs/{superpowers/specs → specs}/2026-09-13-native-hardening-design.md +2 -2
  9. package/docs/storage-verification-design.md +5 -5
  10. package/licenses/lobe-icons-MIT.txt +21 -0
  11. package/output/native-build/desktop-controller.mjs +24 -24
  12. package/output/native-build/harness-mix-secret.exe +0 -0
  13. package/output/native-build/harness-mix-shim.exe +0 -0
  14. package/output/native-build/renderer-extension.js +1325 -658
  15. package/package.json +2 -2
  16. package/scripts/adapters-test.cjs +9 -1
  17. package/scripts/antigravity-adapter-test.cjs +381 -284
  18. package/scripts/build-native.cjs +64 -46
  19. package/scripts/codex-accounts-test.cjs +1 -1
  20. package/scripts/codex-accounts-ui-smoke.cjs +1 -1
  21. package/scripts/collaboration-recovery-test.cjs +11 -2
  22. package/scripts/collaboration-test.cjs +114 -27
  23. package/scripts/collaboration-ui-smoke.cjs +45 -8
  24. package/scripts/concurrency-layers-test.cjs +5 -0
  25. package/scripts/diagnostics.cjs +1 -1
  26. package/scripts/e2e-native-host.cjs +13 -13
  27. package/scripts/error-kind-test.cjs +3 -3
  28. package/scripts/integrations-test.cjs +2 -2
  29. package/scripts/integrations-ui-smoke.cjs +6 -6
  30. package/scripts/native-config-test.cjs +6 -6
  31. package/scripts/native-job-object-test.cjs +1 -1
  32. package/scripts/native-protocol-test.cjs +44 -38
  33. package/scripts/native-rollback-test.cjs +1 -1
  34. package/scripts/native-secret-test.cjs +1 -1
  35. package/scripts/native-shim-test.cjs +1 -1
  36. package/scripts/native-sidebar-test.cjs +4 -4
  37. package/scripts/native-ui-smoke.cjs +12 -12
  38. package/scripts/pets-test.cjs +223 -3
  39. package/scripts/platform-test.cjs +6 -6
  40. package/scripts/publish-native-package.cjs +1 -1
  41. package/scripts/test-live-mentions.cjs +2 -2
  42. package/scripts/workspace-test.cjs +4 -2
  43. package/src/assets/icons/PROVENANCE.md +92 -0
  44. package/src/main/adapters/antigravity.js +1415 -1368
  45. package/src/main/adapters/claude.js +1 -1
  46. package/src/main/adapters/codex-app-server.js +1 -1
  47. package/src/main/adapters/dsh.js +1 -1
  48. package/src/main/adapters/index.js +1 -1
  49. package/src/main/adapters/pi-usage.js +2 -2
  50. package/src/main/harness-adapter/error-kind.js +1 -1
  51. package/src/main/harness-adapter/manifest.js +7 -1
  52. package/src/main/host/collaboration-tools.js +8 -1
  53. package/src/main/host/collaboration-worktree.js +27 -1
  54. package/src/main/host/collaboration.js +348 -15
  55. package/src/main/host/runtime.js +23 -15
  56. package/src/main/native/codex-accounts.js +1 -1
  57. package/src/main/native/config.js +9 -9
  58. package/src/main/native/host.js +1 -1
  59. package/src/main/native/launcher.js +10 -8
  60. package/src/main/native/pets.js +188 -49
  61. package/src/main/native/platform.js +19 -9
  62. package/src/main/native/protocol.js +83 -80
  63. package/src/main/native/rs/crates/appx/Cargo.toml +1 -1
  64. package/src/main/native/rs/crates/secret/Cargo.toml +1 -1
  65. package/src/main/native/rs/crates/secret/src/main.rs +3 -3
  66. package/src/main/native/rs/crates/shim/Cargo.toml +1 -1
  67. package/src/main/native/rs/crates/shim/src/main.rs +2 -2
  68. package/src/main/native/thread-list.js +1 -1
  69. package/src/main/shared-contracts/capability.js +3 -1
  70. package/src/main/workspace/core-review.js +4 -3
  71. package/src/native-ui/README.md +2 -2
  72. package/src/native-ui/desktop-control/dist/contract-audit.js +4 -4
  73. package/src/native-ui/desktop-control/dist/index.d.ts +1 -1
  74. package/src/native-ui/desktop-control/dist/index.js +2 -2
  75. package/src/native-ui/desktop-control/dist/index.js.map +1 -1
  76. package/src/native-ui/desktop-control/dist/main-process-title-policy.js +5 -5
  77. package/src/native-ui/desktop-control/dist/main-process-title-policy.js.map +1 -1
  78. package/src/native-ui/desktop-control/dist/production-controller.js +3 -3
  79. package/src/native-ui/desktop-control/dist/production-controller.js.map +1 -1
  80. package/src/native-ui/desktop-control/dist/release-main.js +1 -1
  81. package/src/native-ui/desktop-control/dist/release-main.js.map +1 -1
  82. package/src/native-ui/desktop-control/dist/renderer-cdp-control-session.js +1 -1
  83. package/src/native-ui/desktop-control/dist/renderer-cdp-control-session.js.map +1 -1
  84. package/src/native-ui/desktop-control/dist/renderer-control-session.js +3 -3
  85. package/src/native-ui/desktop-control/dist/renderer-control-session.js.map +1 -1
  86. package/src/native-ui/desktop-control/dist/renderer-draft-prewarm-runtime.js +25 -25
  87. package/src/native-ui/desktop-control/dist/renderer-draft-prewarm-runtime.js.map +1 -1
  88. package/src/native-ui/desktop-control/dist/tsconfig.tsbuildinfo +1 -1
  89. package/src/native-ui/desktop-control/package.json +2 -2
  90. package/src/native-ui/desktop-control/scripts/build-release.mjs +2 -2
  91. package/src/native-ui/desktop-control/src/contract-audit.ts +4 -4
  92. package/src/native-ui/desktop-control/src/index.ts +2 -2
  93. package/src/native-ui/desktop-control/src/main-process-title-policy.ts +5 -5
  94. package/src/native-ui/desktop-control/src/production-controller.ts +3 -3
  95. package/src/native-ui/desktop-control/src/release-main.ts +1 -1
  96. package/src/native-ui/desktop-control/src/renderer-cdp-control-session.ts +1 -1
  97. package/src/native-ui/desktop-control/src/renderer-control-session.ts +3 -3
  98. package/src/native-ui/desktop-control/src/renderer-draft-prewarm-runtime.ts +25 -25
  99. package/src/native-ui/desktop-control/test/index.test.ts +1 -1
  100. package/src/native-ui/desktop-control/test/production-controller.test.ts +1 -1
  101. package/src/native-ui/desktop-control/test/renderer-cdp-control-session.test.ts +1 -1
  102. package/src/native-ui/desktop-control/test/renderer-draft-prewarm-policy.test.ts +43 -43
  103. package/src/native-ui/renderer-extension/dist/types/agent-group-preference.d.ts +1 -1
  104. package/src/native-ui/renderer-extension/dist/types/agent-group-preference.d.ts.map +1 -1
  105. package/src/native-ui/renderer-extension/dist/types/agent-selection-state.d.ts +1 -1
  106. package/src/native-ui/renderer-extension/dist/types/agent-selection-state.d.ts.map +1 -1
  107. package/src/native-ui/renderer-extension/dist/types/contract-audit.d.ts +1 -1
  108. package/src/native-ui/renderer-extension/dist/types/contract-audit.d.ts.map +1 -1
  109. package/src/native-ui/renderer-extension/dist/types/index.d.ts +3 -1
  110. package/src/native-ui/renderer-extension/dist/types/index.d.ts.map +1 -1
  111. package/src/native-ui/renderer-extension/dist/types/production-entry.d.ts +1 -1
  112. package/src/native-ui/renderer-extension/dist/types/production-entry.d.ts.map +1 -1
  113. package/src/native-ui/renderer-extension/dist/types/renderer-agent-picker.d.ts +2 -2
  114. package/src/native-ui/renderer-extension/dist/types/renderer-agent-picker.d.ts.map +1 -1
  115. package/src/native-ui/renderer-extension/dist/types/renderer-binding-probe.d.ts +3 -3
  116. package/src/native-ui/renderer-extension/dist/types/renderer-binding-probe.d.ts.map +1 -1
  117. package/src/native-ui/renderer-extension/dist/types/renderer-codex-account-options.d.ts +1 -1
  118. package/src/native-ui/renderer-extension/dist/types/renderer-codex-account-options.d.ts.map +1 -1
  119. package/src/native-ui/renderer-extension/dist/types/renderer-codex-account-state.d.ts +1 -1
  120. package/src/native-ui/renderer-extension/dist/types/renderer-codex-account-state.d.ts.map +1 -1
  121. package/src/native-ui/renderer-extension/dist/types/renderer-collab-cards.d.ts +1 -1
  122. package/src/native-ui/renderer-extension/dist/types/renderer-collab-cards.d.ts.map +1 -1
  123. package/src/native-ui/renderer-extension/dist/types/renderer-composer-dom.d.ts +1 -1
  124. package/src/native-ui/renderer-extension/dist/types/renderer-composer-dom.d.ts.map +1 -1
  125. package/src/native-ui/renderer-extension/dist/types/renderer-credits-control.d.ts +1 -1
  126. package/src/native-ui/renderer-extension/dist/types/renderer-credits-control.d.ts.map +1 -1
  127. package/src/native-ui/renderer-extension/dist/types/renderer-fork-control.d.ts +1 -1
  128. package/src/native-ui/renderer-extension/dist/types/renderer-fork-control.d.ts.map +1 -1
  129. package/src/native-ui/renderer-extension/dist/types/renderer-harness-command-claim.d.ts +1 -1
  130. package/src/native-ui/renderer-extension/dist/types/renderer-harness-command-claim.d.ts.map +1 -1
  131. package/src/native-ui/renderer-extension/dist/types/renderer-harness-command-control.d.ts +1 -1
  132. package/src/native-ui/renderer-extension/dist/types/renderer-harness-command-control.d.ts.map +1 -1
  133. package/src/native-ui/renderer-extension/dist/types/renderer-harness-handoff.d.ts +1 -1
  134. package/src/native-ui/renderer-extension/dist/types/renderer-harness-handoff.d.ts.map +1 -1
  135. package/src/native-ui/renderer-extension/dist/types/renderer-harness-localization.d.ts +1 -1
  136. package/src/native-ui/renderer-extension/dist/types/renderer-harness-localization.d.ts.map +1 -1
  137. package/src/native-ui/renderer-extension/dist/types/renderer-harness-mentions.d.ts +1 -0
  138. package/src/native-ui/renderer-extension/dist/types/renderer-harness-mentions.d.ts.map +1 -1
  139. package/src/native-ui/renderer-extension/dist/types/renderer-model-client.d.ts +36 -31
  140. package/src/native-ui/renderer-extension/dist/types/renderer-model-client.d.ts.map +1 -1
  141. package/src/native-ui/renderer-extension/dist/types/renderer-model-picker.d.ts +1 -1
  142. package/src/native-ui/renderer-extension/dist/types/renderer-model-picker.d.ts.map +1 -1
  143. package/src/native-ui/renderer-extension/dist/types/renderer-new-thread-preference.d.ts +2 -2
  144. package/src/native-ui/renderer-extension/dist/types/renderer-new-thread-preference.d.ts.map +1 -1
  145. package/src/native-ui/renderer-extension/dist/types/renderer-permission-mode-picker.d.ts +1 -1
  146. package/src/native-ui/renderer-extension/dist/types/renderer-permission-mode-picker.d.ts.map +1 -1
  147. package/src/native-ui/renderer-extension/dist/types/renderer-permission-mode-preference.d.ts +2 -2
  148. package/src/native-ui/renderer-extension/dist/types/renderer-permission-mode-preference.d.ts.map +1 -1
  149. package/src/native-ui/renderer-extension/dist/types/renderer-request-sender.d.ts +18 -2
  150. package/src/native-ui/renderer-extension/dist/types/renderer-request-sender.d.ts.map +1 -1
  151. package/src/native-ui/renderer-extension/dist/types/renderer-session-import-client.d.ts +1 -1
  152. package/src/native-ui/renderer-extension/dist/types/renderer-session-import-client.d.ts.map +1 -1
  153. package/src/native-ui/renderer-extension/dist/types/renderer-sidebar-agent-icons.d.ts +2 -2
  154. package/src/native-ui/renderer-extension/dist/types/renderer-sidebar-agent-icons.d.ts.map +1 -1
  155. package/src/native-ui/renderer-extension/dist/types/renderer-team-cards.d.ts +58 -0
  156. package/src/native-ui/renderer-extension/dist/types/renderer-team-cards.d.ts.map +1 -0
  157. package/src/native-ui/renderer-extension/dist/types/renderer-transcript-dom.d.ts +1 -1
  158. package/src/native-ui/renderer-extension/dist/types/renderer-trigger-chip-style.d.ts +1 -1
  159. package/src/native-ui/renderer-extension/dist/types/renderer-trigger-chip-style.d.ts.map +1 -1
  160. package/src/native-ui/renderer-extension/dist/types/renderer-usage-control.d.ts +1 -1
  161. package/src/native-ui/renderer-extension/dist/types/renderer-usage-control.d.ts.map +1 -1
  162. package/src/native-ui/renderer-extension/dist/types/settings/accounts-list.d.ts +1 -1
  163. package/src/native-ui/renderer-extension/dist/types/settings/accounts-list.d.ts.map +1 -1
  164. package/src/native-ui/renderer-extension/dist/types/settings/accounts-page.d.ts +1 -1
  165. package/src/native-ui/renderer-extension/dist/types/settings/accounts-page.d.ts.map +1 -1
  166. package/src/native-ui/renderer-extension/dist/types/settings/accounts-usage.d.ts +1 -1
  167. package/src/native-ui/renderer-extension/dist/types/settings/accounts-usage.d.ts.map +1 -1
  168. package/src/native-ui/renderer-extension/dist/types/settings/connections-page.d.ts +3 -3
  169. package/src/native-ui/renderer-extension/dist/types/settings/connections-page.d.ts.map +1 -1
  170. package/src/native-ui/renderer-extension/dist/types/settings/harness-accounts.d.ts +1 -1
  171. package/src/native-ui/renderer-extension/dist/types/settings/harness-accounts.d.ts.map +1 -1
  172. package/src/native-ui/renderer-extension/dist/types/settings/pages.d.ts +4 -4
  173. package/src/native-ui/renderer-extension/dist/types/settings/pages.d.ts.map +1 -1
  174. package/src/native-ui/renderer-extension/dist/types/settings/pet-market.d.ts.map +1 -1
  175. package/src/native-ui/renderer-extension/dist/types/settings/session-import-list-controls.d.ts +1 -1
  176. package/src/native-ui/renderer-extension/dist/types/settings/session-import-list-controls.d.ts.map +1 -1
  177. package/src/native-ui/renderer-extension/dist/types/settings/session-import-page.d.ts +1 -1
  178. package/src/native-ui/renderer-extension/dist/types/settings/session-import-page.d.ts.map +1 -1
  179. package/src/native-ui/renderer-extension/dist/types/settings/shell.d.ts +2 -2
  180. package/src/native-ui/renderer-extension/dist/types/settings/shell.d.ts.map +1 -1
  181. package/src/native-ui/renderer-extension/dist/types/settings/trigger.d.ts +1 -1
  182. package/src/native-ui/renderer-extension/dist/types/settings/trigger.d.ts.map +1 -1
  183. package/src/native-ui/renderer-extension/dist/types/tsconfig.tsbuildinfo +1 -1
  184. package/src/native-ui/renderer-extension/dist/types/versioned-renderer-adapter.d.ts +18 -18
  185. package/src/native-ui/renderer-extension/dist/types/versioned-renderer-adapter.d.ts.map +1 -1
  186. package/src/native-ui/renderer-extension/package.json +2 -2
  187. package/src/native-ui/renderer-extension/src/agent-group-preference.ts +1 -1
  188. package/src/native-ui/renderer-extension/src/agent-selection-state.ts +31 -16
  189. package/src/native-ui/renderer-extension/src/audit-entry.ts +1 -1
  190. package/src/native-ui/renderer-extension/src/contract-audit.ts +4 -4
  191. package/src/native-ui/renderer-extension/src/index.ts +4 -2
  192. package/src/native-ui/renderer-extension/src/install-renderer-binding.ts +2 -2
  193. package/src/native-ui/renderer-extension/src/production-entry.ts +3 -3
  194. package/src/native-ui/renderer-extension/src/renderer-agent-picker.ts +7 -7
  195. package/src/native-ui/renderer-extension/src/renderer-binding-probe.ts +112 -89
  196. package/src/native-ui/renderer-extension/src/renderer-codex-account-options.ts +1 -1
  197. package/src/native-ui/renderer-extension/src/renderer-codex-account-state.ts +1 -1
  198. package/src/native-ui/renderer-extension/src/renderer-collab-cards.ts +1 -1
  199. package/src/native-ui/renderer-extension/src/renderer-composer-dom.ts +12 -12
  200. package/src/native-ui/renderer-extension/src/renderer-credits-control.ts +7 -7
  201. package/src/native-ui/renderer-extension/src/renderer-external-steering.ts +3 -3
  202. package/src/native-ui/renderer-extension/src/renderer-fork-control.ts +1 -1
  203. package/src/native-ui/renderer-extension/src/renderer-harness-command-claim.ts +1 -1
  204. package/src/native-ui/renderer-extension/src/renderer-harness-command-control.ts +3 -3
  205. package/src/native-ui/renderer-extension/src/renderer-harness-handoff.ts +1 -1
  206. package/src/native-ui/renderer-extension/src/renderer-harness-localization.ts +1 -1
  207. package/src/native-ui/renderer-extension/src/renderer-harness-mentions.ts +4 -0
  208. package/src/native-ui/renderer-extension/src/renderer-integrations-client.ts +5 -5
  209. package/src/native-ui/renderer-extension/src/renderer-model-client.ts +63 -42
  210. package/src/native-ui/renderer-extension/src/renderer-model-picker.ts +16 -16
  211. package/src/native-ui/renderer-extension/src/renderer-new-thread-preference.ts +2 -2
  212. package/src/native-ui/renderer-extension/src/renderer-permission-mode-picker.ts +3 -3
  213. package/src/native-ui/renderer-extension/src/renderer-permission-mode-preference.ts +2 -2
  214. package/src/native-ui/renderer-extension/src/renderer-request-sender.ts +46 -3
  215. package/src/native-ui/renderer-extension/src/renderer-session-import-client.ts +4 -4
  216. package/src/native-ui/renderer-extension/src/renderer-sidebar-agent-icons.ts +24 -20
  217. package/src/native-ui/renderer-extension/src/renderer-team-cards.ts +312 -0
  218. package/src/native-ui/renderer-extension/src/renderer-transcript-dom.ts +1 -1
  219. package/src/native-ui/renderer-extension/src/renderer-trigger-chip-style.ts +2 -2
  220. package/src/native-ui/renderer-extension/src/renderer-usage-control.ts +4 -4
  221. package/src/native-ui/renderer-extension/src/settings/accounts-list.ts +1 -1
  222. package/src/native-ui/renderer-extension/src/settings/accounts-page.ts +1 -1
  223. package/src/native-ui/renderer-extension/src/settings/accounts-usage.ts +1 -1
  224. package/src/native-ui/renderer-extension/src/settings/connections-page.ts +7 -7
  225. package/src/native-ui/renderer-extension/src/settings/harness-accounts.ts +1 -1
  226. package/src/native-ui/renderer-extension/src/settings/icons.ts +2 -2
  227. package/src/native-ui/renderer-extension/src/settings/pages.ts +11 -11
  228. package/src/native-ui/renderer-extension/src/settings/pet-market.css +33 -0
  229. package/src/native-ui/renderer-extension/src/settings/pet-market.ts +173 -91
  230. package/src/native-ui/renderer-extension/src/settings/pets-client.ts +5 -5
  231. package/src/native-ui/renderer-extension/src/settings/release-notes.ts +1 -1
  232. package/src/native-ui/renderer-extension/src/settings/session-import-list-controls.ts +1 -1
  233. package/src/native-ui/renderer-extension/src/settings/session-import-page.ts +1 -1
  234. package/src/native-ui/renderer-extension/src/settings/shell.css +15 -15
  235. package/src/native-ui/renderer-extension/src/settings/shell.ts +11 -11
  236. package/src/native-ui/renderer-extension/src/settings/skin-runtime.ts +17 -17
  237. package/src/native-ui/renderer-extension/src/settings/trigger.ts +1 -1
  238. package/src/native-ui/renderer-extension/src/versioned-renderer-adapter.ts +20 -20
  239. package/src/native-ui/renderer-extension/test/agent-selection-state.test.ts +60 -1
  240. package/src/native-ui/renderer-extension/test/codebuddy-migration.test.ts +1 -1
  241. package/src/native-ui/renderer-extension/test/renderer-agent-picker.test.ts +1 -1
  242. package/src/native-ui/renderer-extension/test/renderer-binding-probe-host-catalog.test.ts +15 -9
  243. package/src/native-ui/renderer-extension/test/renderer-binding-probe.test.ts +15 -15
  244. package/src/native-ui/renderer-extension/test/renderer-codex-account-state.test.ts +1 -1
  245. package/src/native-ui/renderer-extension/test/renderer-composer-permissions.test.ts +4 -4
  246. package/src/native-ui/renderer-extension/test/renderer-external-steering-rpc.test.ts +2 -2
  247. package/src/native-ui/renderer-extension/test/renderer-external-steering.test.ts +3 -3
  248. package/src/native-ui/renderer-extension/test/renderer-fork-control.test.ts +4 -4
  249. package/src/native-ui/renderer-extension/test/renderer-harness-command-claim.test.ts +1 -1
  250. package/src/native-ui/renderer-extension/test/renderer-harness-command-control.test.ts +1 -1
  251. package/src/native-ui/renderer-extension/test/renderer-model-client.test.ts +12 -11
  252. package/src/native-ui/renderer-extension/test/renderer-model-picker.test.ts +1 -1
  253. package/src/native-ui/renderer-extension/test/renderer-native-thread-ownership.test.ts +6 -6
  254. package/src/native-ui/renderer-extension/test/renderer-new-thread-preference.test.ts +1 -1
  255. package/src/native-ui/renderer-extension/test/renderer-permission-mode-picker.test.ts +1 -1
  256. package/src/native-ui/renderer-extension/test/renderer-permission-mode-preference.test.ts +1 -1
  257. package/src/native-ui/renderer-extension/test/renderer-request-timeout.test.ts +80 -0
  258. package/src/native-ui/renderer-extension/test/renderer-settings-lifecycle.test.ts +2 -2
  259. package/src/native-ui/renderer-extension/test/renderer-sidebar-agent-icons.test.ts +10 -3
  260. package/src/native-ui/renderer-extension/test/renderer-unsupported-methods.test.ts +1 -1
  261. package/src/native-ui/renderer-extension/test/settings/pages.test.ts +5 -5
  262. package/src/native-ui/renderer-extension/test/settings/release-notes.test.ts +9 -9
  263. package/src/native-ui/renderer-extension/test/versioned-renderer-adapter.test.ts +3 -3
  264. package/src/native-ui/shared-contracts/dist/errors.d.ts +2 -2
  265. package/src/native-ui/shared-contracts/dist/errors.d.ts.map +1 -1
  266. package/src/native-ui/shared-contracts/dist/errors.js +1 -1
  267. package/src/native-ui/shared-contracts/dist/errors.js.map +1 -1
  268. package/src/native-ui/shared-contracts/dist/harness-models.d.ts +40 -0
  269. package/src/native-ui/shared-contracts/dist/harness-models.d.ts.map +1 -1
  270. package/src/native-ui/shared-contracts/dist/harness-models.js +23 -2
  271. package/src/native-ui/shared-contracts/dist/harness-models.js.map +1 -1
  272. package/src/native-ui/shared-contracts/dist/harness-route.d.ts +1 -1
  273. package/src/native-ui/shared-contracts/dist/harness-route.d.ts.map +1 -1
  274. package/src/native-ui/shared-contracts/dist/harness-route.js +1 -1
  275. package/src/native-ui/shared-contracts/dist/harness-route.js.map +1 -1
  276. package/src/native-ui/shared-contracts/dist/harness-session-import.d.ts +1 -1
  277. package/src/native-ui/shared-contracts/dist/harness-session-import.d.ts.map +1 -1
  278. package/src/native-ui/shared-contracts/dist/harness-session-import.js +1 -1
  279. package/src/native-ui/shared-contracts/dist/harness-session-import.js.map +1 -1
  280. package/src/native-ui/shared-contracts/dist/index.d.ts +3 -3
  281. package/src/native-ui/shared-contracts/dist/index.d.ts.map +1 -1
  282. package/src/native-ui/shared-contracts/dist/index.js +2 -2
  283. package/src/native-ui/shared-contracts/dist/index.js.map +1 -1
  284. package/src/native-ui/shared-contracts/dist/tsconfig.tsbuildinfo +1 -1
  285. package/src/native-ui/shared-contracts/dist/updates.js +1 -1
  286. package/src/native-ui/shared-contracts/dist/updates.js.map +1 -1
  287. package/src/native-ui/shared-contracts/package.json +1 -1
  288. package/src/native-ui/shared-contracts/src/errors.ts +3 -3
  289. package/src/native-ui/shared-contracts/src/harness-models.ts +23 -2
  290. package/src/native-ui/shared-contracts/src/harness-route.ts +1 -1
  291. package/src/native-ui/shared-contracts/src/harness-session-import.ts +1 -1
  292. package/src/native-ui/shared-contracts/src/index.ts +3 -3
  293. package/src/native-ui/shared-contracts/src/updates.ts +1 -1
  294. package/src/native-ui/shared-contracts/test/browser-bundle.test.ts +3 -3
  295. package/src/native-ui/shared-contracts/test/deepseek-modern-sessions.test.ts +1 -1
  296. package/src/native-ui/shared-contracts/test/errors.test.ts +9 -9
  297. package/src/native-ui/shared-contracts/test/harness-commands.test.ts +1 -1
  298. package/src/native-ui/shared-contracts/test/harness-models.test.ts +3 -3
  299. package/src/native-ui/shared-contracts/test/harness-permission-modes.test.ts +1 -1
  300. package/src/native-ui/shared-contracts/test/harness-plugins.test.ts +1 -1
  301. package/src/native-ui/shared-contracts/test/harness-session-import.test.ts +1 -1
  302. package/src/native-ui/shared-contracts/test/index.test.ts +3 -3
  303. package/src/native-ui/shared-contracts/test/json-rpc.test.ts +1 -1
  304. package/src/native-ui/shared-contracts/test/thread-usage.test.ts +1 -1
  305. package/src/native-ui/shared-contracts/test/updates.test.ts +4 -4
  306. /package/licenses/{codex-host-MIT.txt → bytepioneer-MIT.txt} +0 -0
@@ -2,9 +2,15 @@
2
2
 
3
3
  const assert = require('node:assert/strict');
4
4
  const fs = require('node:fs');
5
+ const http = require('node:http');
5
6
  const os = require('node:os');
6
7
  const path = require('node:path');
7
- const { createPetMarket, readAsarHeader } = require('../src/main/native/pets');
8
+ const {
9
+ createPetMarket,
10
+ readAsarHeader,
11
+ isWebpBuffer,
12
+ validatePetMetadata,
13
+ } = require('../src/main/native/pets');
8
14
 
9
15
  function buildSyntheticAsar(targetPath, petName, blobContent) {
10
16
  const tree = {
@@ -36,6 +42,16 @@ function buildSyntheticAsar(targetPath, petName, blobContent) {
36
42
  fs.writeFileSync(targetPath, asarBuf);
37
43
  }
38
44
 
45
+ // 合法 WebP 容器头:RIFF + size + WEBP + VP8 块
46
+ function webpPayload(label) {
47
+ return Buffer.concat([
48
+ Buffer.from('RIFF', 'latin1'),
49
+ Buffer.from([0x20, 0x00, 0x00, 0x00]),
50
+ Buffer.from('WEBPVP8 ', 'latin1'),
51
+ Buffer.from(`--${label}--`, 'latin1'),
52
+ ]);
53
+ }
54
+
39
55
  (async () => {
40
56
  const testRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-mix-pets-test-'));
41
57
  const fakeAsarDir = path.join(testRoot, 'resources');
@@ -51,10 +67,61 @@ function buildSyntheticAsar(targetPath, petName, blobContent) {
51
67
  fs.mkdirSync(petsDir, { recursive: true });
52
68
 
53
69
  const env = {
54
- CODEXHOST_STOCK_CODEX_PATH: fakeCodexBin,
70
+ HARNESSMIX_STOCK_CODEX_PATH: fakeCodexBin,
55
71
  HARNESS_MIX_PETS_DIR: petsDir,
56
72
  };
57
73
 
74
+ // 本地 HTTP 服务器模拟社区下载源,覆盖 成功/500/坏签名/超大/截断/慢响应 场景
75
+ const server = http.createServer((req, res) => {
76
+ const url = new URL(req.url, 'http://127.0.0.1');
77
+ if (url.pathname === '/ok.webp') {
78
+ const body = webpPayload('community');
79
+ res.writeHead(200, { 'content-type': 'image/webp', 'content-length': body.length });
80
+ res.end(body);
81
+ return;
82
+ }
83
+ if (url.pathname === '/bad-sig.webp') {
84
+ const body = Buffer.from('NOT-A-REAL-WEBP-PAYLOAD', 'latin1');
85
+ res.writeHead(200, { 'content-type': 'image/webp', 'content-length': body.length });
86
+ res.end(body);
87
+ return;
88
+ }
89
+ if (url.pathname === '/huge.webp') {
90
+ // 声明 64MB,应在读取 body 前被 content-length 预检拦截
91
+ res.writeHead(200, { 'content-type': 'image/webp', 'content-length': 64 * 1024 * 1024 });
92
+ res.end(webpPayload('huge'));
93
+ return;
94
+ }
95
+ if (url.pathname === '/truncated.webp') {
96
+ // 声明长度大于实际发送:客户端应下载失败
97
+ res.writeHead(200, { 'content-type': 'image/webp', 'content-length': 1000 });
98
+ try {
99
+ res.end(Buffer.from('RIFF....WEBP', 'latin1'));
100
+ } catch {
101
+ res.destroy();
102
+ }
103
+ return;
104
+ }
105
+ if (url.pathname === '/slow.webp') {
106
+ setTimeout(() => {
107
+ const body = webpPayload('slow');
108
+ res.writeHead(200, { 'content-type': 'image/webp', 'content-length': body.length });
109
+ res.end(body);
110
+ }, 300);
111
+ return;
112
+ }
113
+ res.writeHead(500);
114
+ res.end('boom');
115
+ });
116
+ await new Promise((resolve, reject) => {
117
+ server.once('error', reject);
118
+ server.listen(0, '127.0.0.1', resolve);
119
+ });
120
+ const baseUrl = `http://127.0.0.1:${server.address().port}`;
121
+
122
+ const leftoverArtifacts = () =>
123
+ fs.readdirSync(petsDir).filter(name => name.startsWith('.tmp-') || name.startsWith('.bak-'));
124
+
58
125
  try {
59
126
  // 1. Verify readAsarHeader
60
127
  const asarInfo = readAsarHeader(fakeAsarPath);
@@ -90,7 +157,7 @@ function buildSyntheticAsar(targetPath, petName, blobContent) {
90
157
  assert.throws(() => market.preview({ id: '../bad-pet' }), /Invalid pet id/);
91
158
  assert.throws(() => market.preview({ id: 'non-existent-pet' }), /Unknown pet/);
92
159
 
93
- // 4. Test install() of official pet
160
+ // 4. Test install() of official pet(原子流程:临时目录 -> 校验 -> 切换)
94
161
  const installRes = await market.install({ id: 'synthetic-buddy' });
95
162
  assert.equal(installRes.id, 'synthetic-buddy');
96
163
  assert.equal(installRes.installed, true);
@@ -102,6 +169,7 @@ function buildSyntheticAsar(targetPath, petName, blobContent) {
102
169
  const petSpritePath = path.join(installedDir, 'spritesheet.webp');
103
170
  assert.ok(fs.existsSync(petJsonPath), 'pet.json exists');
104
171
  assert.ok(fs.existsSync(petSpritePath), 'spritesheet.webp exists');
172
+ assert.deepEqual(leftoverArtifacts(), [], 'no staging/backup dirs left after official install');
105
173
 
106
174
  const meta = JSON.parse(fs.readFileSync(petJsonPath, 'utf8'));
107
175
  assert.equal(meta.id, 'synthetic-buddy');
@@ -139,8 +207,160 @@ function buildSyntheticAsar(targetPath, petName, blobContent) {
139
207
  const uninstalledEntry = catalogAfterUninstall.data.find(p => p.id === 'synthetic-buddy');
140
208
  assert.equal(uninstalledEntry.installed, false);
141
209
 
210
+ // 7. 社区下载安装成功路径(本地 HTTP 源),安装后无临时/备份目录残留
211
+ const communityInstall = await market.install({
212
+ id: 'community-pet',
213
+ displayName: 'Community Pet',
214
+ spritesheetUrl: `${baseUrl}/ok.webp`,
215
+ });
216
+ assert.equal(communityInstall.installed, true);
217
+ assert.equal(communityInstall.alreadyInstalled, false);
218
+ const communityDir = path.join(petsDir, 'community-pet');
219
+ assert.ok(fs.existsSync(path.join(communityDir, 'pet.json')));
220
+ assert.ok(fs.existsSync(path.join(communityDir, 'spritesheet.webp')));
221
+ const communityMeta = JSON.parse(fs.readFileSync(path.join(communityDir, 'pet.json'), 'utf8'));
222
+ assert.equal(communityMeta.displayName, 'Community Pet');
223
+ assert.equal(communityMeta.spriteVersionNumber, 1);
224
+ assert.deepEqual(leftoverArtifacts(), [], 'no staging/backup dirs left after community install');
225
+
226
+ // 8. 下载失败(HTTP 500):拒绝安装且不留下任何目录
227
+ await assert.rejects(
228
+ market.install({ id: 'dl-fail-pet', spritesheetUrl: `${baseUrl}/missing.webp` }),
229
+ /Download failed \(500\)/,
230
+ );
231
+ assert.ok(!fs.existsSync(path.join(petsDir, 'dl-fail-pet')), 'failed install must not leave a pet dir');
232
+ assert.deepEqual(leftoverArtifacts(), [], 'download failure must not leave staging dirs');
233
+
234
+ // 9. 校验失败:坏 WebP 签名
235
+ await assert.rejects(
236
+ market.install({ id: 'bad-sig-pet', spritesheetUrl: `${baseUrl}/bad-sig.webp` }),
237
+ /RIFF\/WEBP signature/,
238
+ );
239
+ assert.ok(!fs.existsSync(path.join(petsDir, 'bad-sig-pet')));
240
+ assert.deepEqual(leftoverArtifacts(), [], 'signature failure must not leave staging dirs');
241
+
242
+ // 10. 校验失败:content-length 超过大小上限(预检拦截)
243
+ await assert.rejects(
244
+ market.install({ id: 'huge-pet', spritesheetUrl: `${baseUrl}/huge.webp` }),
245
+ /too large/,
246
+ );
247
+ assert.ok(!fs.existsSync(path.join(petsDir, 'huge-pet')));
248
+ assert.deepEqual(leftoverArtifacts(), []);
249
+
250
+ // 11. 下载截断(声明长度与实际不符):拒绝安装且清理
251
+ await assert.rejects(
252
+ market.install({ id: 'truncated-pet', spritesheetUrl: `${baseUrl}/truncated.webp` }),
253
+ );
254
+ assert.ok(!fs.existsSync(path.join(petsDir, 'truncated-pet')));
255
+ assert.deepEqual(leftoverArtifacts(), []);
256
+
257
+ // 12. pet.json 必填字段校验:displayName 非法时在下载前拒绝,不创建目录
258
+ await assert.rejects(
259
+ market.install({ id: 'meta-bad-pet', displayName: 123, spritesheetUrl: `${baseUrl}/ok.webp` }),
260
+ /displayName/,
261
+ );
262
+ assert.ok(!fs.existsSync(path.join(petsDir, 'meta-bad-pet')));
263
+ assert.deepEqual(leftoverArtifacts(), []);
264
+
265
+ // 13. 路径安全:目录穿越 / 斜杠注入 / 大写 id 一律拒绝
266
+ await assert.rejects(market.install({ id: '../escape' }), /Invalid pet id/);
267
+ await assert.rejects(market.install({ id: 'a/b' }), /Invalid pet id/);
268
+ await assert.rejects(market.install({ id: 'a\\b' }), /Invalid pet id/);
269
+ await assert.rejects(market.install({ id: 'UPPERCASE' }), /Invalid pet id/);
270
+ assert.throws(() => market.uninstall({ id: '..\\evil' }), /Invalid pet id/);
271
+ assert.throws(() => market.uninstall({ id: '../evil' }), /Invalid pet id/);
272
+ assert.deepEqual(leftoverArtifacts(), []);
273
+ assert.ok(!fs.existsSync(path.join(testRoot, 'escape')), 'nothing written outside pets root');
274
+
275
+ // 14. 并发防护:同一 pet 安装进行中,第二个安装与卸载都被拒绝
276
+ const slowInstall = market.install({ id: 'conc-pet', spritesheetUrl: `${baseUrl}/slow.webp` });
277
+ await assert.rejects(
278
+ market.install({ id: 'conc-pet', spritesheetUrl: `${baseUrl}/slow.webp` }),
279
+ /in progress/,
280
+ );
281
+ assert.throws(() => market.uninstall({ id: 'conc-pet' }), /in progress/);
282
+ const slowResult = await slowInstall;
283
+ assert.equal(slowResult.installed, true);
284
+ assert.deepEqual(leftoverArtifacts(), []);
285
+ // 操作释放后可以正常卸载
286
+ const concUninstall = market.uninstall({ id: 'conc-pet' });
287
+ assert.equal(concUninstall.removed, true);
288
+
289
+ // 15. 修复损坏目录:已有目录缺少精灵图时,走 备份->切换 流程完成安装且不残留 .bak
290
+ const brokenDir = path.join(petsDir, 'broken-pet');
291
+ fs.mkdirSync(brokenDir, { recursive: true });
292
+ fs.writeFileSync(path.join(brokenDir, 'pet.json'), '{"id":"broken-pet"}');
293
+ const fixRes = await market.install({
294
+ id: 'broken-pet',
295
+ displayName: 'Broken Pet',
296
+ spritesheetUrl: `${baseUrl}/ok.webp`,
297
+ });
298
+ assert.equal(fixRes.alreadyInstalled, false);
299
+ assert.ok(fs.existsSync(path.join(brokenDir, 'spritesheet.webp')), 'spritesheet repaired');
300
+ const fixedMeta = JSON.parse(fs.readFileSync(path.join(brokenDir, 'pet.json'), 'utf8'));
301
+ assert.equal(fixedMeta.displayName, 'Broken Pet');
302
+ assert.deepEqual(leftoverArtifacts(), [], 'swap with existing dir must not leave backup dirs');
303
+
304
+ // 16. 已安装列表不容忍损坏目录:pet.json 无法解析或缺少精灵图的目录不出现
305
+ const badJsonDir = path.join(petsDir, 'bad-json-pet');
306
+ fs.mkdirSync(badJsonDir);
307
+ fs.writeFileSync(path.join(badJsonDir, 'pet.json'), '{not json');
308
+ fs.writeFileSync(path.join(badJsonDir, 'spritesheet.webp'), webpPayload('x'));
309
+ const noSheetDir = path.join(petsDir, 'no-sheet-pet');
310
+ fs.mkdirSync(noSheetDir);
311
+ fs.writeFileSync(path.join(noSheetDir, 'pet.json'), JSON.stringify({ id: 'no-sheet-pet' }));
312
+ const robustCatalogIds = market.catalog().data.map(p => p.id);
313
+ assert.ok(!robustCatalogIds.includes('bad-json-pet'), 'unparseable pet.json excluded');
314
+ assert.ok(!robustCatalogIds.includes('no-sheet-pet'), 'missing spritesheet excluded');
315
+ assert.ok(robustCatalogIds.includes('community-pet'), 'healthy install still listed');
316
+ assert.ok(robustCatalogIds.includes('broken-pet'), 'repaired install now listed');
317
+
318
+ // 17. 崩溃残留清扫:超过年龄的 .tmp-* / .bak-* 在下一次安装/卸载时被清理
319
+ const staleTmp = path.join(petsDir, '.tmp-stale-pet-0-0-aaaaaa');
320
+ const staleBak = path.join(petsDir, '.bak-stale-pet-0-0-bbbbbb');
321
+ fs.mkdirSync(staleTmp);
322
+ fs.mkdirSync(staleBak);
323
+ const oldTime = new Date(Date.now() - 60 * 60 * 1000);
324
+ fs.utimesSync(staleTmp, oldTime, oldTime);
325
+ fs.utimesSync(staleBak, oldTime, oldTime);
326
+ market.uninstall({ id: 'no-such-pet' });
327
+ assert.ok(!fs.existsSync(staleTmp), 'stale .tmp dir swept');
328
+ assert.ok(!fs.existsSync(staleBak), 'stale .bak dir swept');
329
+
330
+ // 18. 校验辅助函数单元测试
331
+ assert.equal(isWebpBuffer(webpPayload('t')), true);
332
+ assert.equal(isWebpBuffer(Buffer.from('RIFF....WEBP', 'latin1')), true);
333
+ assert.equal(isWebpBuffer(Buffer.from('RIFF....AVIF', 'latin1')), false);
334
+ assert.equal(isWebpBuffer(Buffer.from('WEBP....RIFF', 'latin1')), false);
335
+ assert.equal(isWebpBuffer(Buffer.from('RIFF', 'latin1')), false);
336
+ assert.equal(isWebpBuffer(Buffer.alloc(0)), false);
337
+
338
+ assert.throws(() => validatePetMetadata(null, 'x'), /must be an object/);
339
+ assert.throws(
340
+ () => validatePetMetadata({ id: 'y', displayName: 'A', spriteVersionNumber: 1, spritesheetPath: 'spritesheet.webp' }, 'x'),
341
+ /id mismatch/,
342
+ );
343
+ assert.throws(
344
+ () => validatePetMetadata({ id: 'x', displayName: ' ', spriteVersionNumber: 1, spritesheetPath: 'spritesheet.webp' }, 'x'),
345
+ /displayName/,
346
+ );
347
+ assert.throws(
348
+ () => validatePetMetadata({ id: 'x', displayName: 'A', spriteVersionNumber: 0, spritesheetPath: 'spritesheet.webp' }, 'x'),
349
+ /spriteVersionNumber/,
350
+ );
351
+ assert.throws(
352
+ () => validatePetMetadata({ id: 'x', displayName: 'A', spriteVersionNumber: 1, spritesheetPath: '../evil.webp' }, 'x'),
353
+ /spritesheetPath/,
354
+ );
355
+ assert.equal(
356
+ validatePetMetadata({ id: 'x', displayName: 'A', spriteVersionNumber: 2, spritesheetPath: 'spritesheet.webp' }, 'x').id,
357
+ 'x',
358
+ );
359
+
142
360
  console.log('Pets market native tests passed successfully!');
143
361
  } finally {
362
+ try { server.closeAllConnections(); } catch { /* Node < 18.2 无此 API */ }
363
+ server.close();
144
364
  fs.rmSync(testRoot, { recursive: true, force: true });
145
365
  }
146
366
  })();
@@ -10,12 +10,12 @@ const { evaluateDesktopCompatibility, enforceDesktopCompatibility } = require('.
10
10
 
11
11
  async function main() {
12
12
  const home = path.resolve(os.tmpdir(), 'hm-home');
13
- assert.equal(dataDirectory({}, 'darwin', home), path.join(home, 'Library/Application Support/harness-mix/codexhost'));
14
- assert.equal(dataDirectory({}, 'linux', home), path.join(home, '.local/share/harness-mix/codexhost'));
15
- assert.equal(dataDirectory({ XDG_DATA_HOME: home }, 'linux', '/ignored'), path.join(home, 'harness-mix/codexhost'));
13
+ assert.equal(dataDirectory({}, 'darwin', home), path.join(home, 'Library/Application Support/harnessmix'));
14
+ assert.equal(dataDirectory({}, 'linux', home), path.join(home, '.local/share/harnessmix'));
15
+ assert.equal(dataDirectory({ XDG_DATA_HOME: home }, 'linux', '/ignored'), path.join(home, 'harnessmix'));
16
16
  assert.equal(dataDirectory({ XDG_DATA_HOME: 'relative' }, 'linux', home), dataDirectory({}, 'linux', home));
17
- assert.equal(dataDirectory({ CODEXHOST_DATA_DIR: home }, 'darwin'), home);
18
- assert.equal(dataDirectory({ APPDATA: home }, 'win32'), path.join(home, 'harness-mix/codexhost'));
17
+ assert.equal(dataDirectory({ HARNESSMIX_DATA_DIR: home }, 'darwin'), home);
18
+ assert.equal(dataDirectory({ APPDATA: home }, 'win32'), path.join(home, 'harnessmix'));
19
19
  for (const platform of ['win32', 'darwin', 'linux']) {
20
20
  assert.equal(path.basename(nativePaths(platform).shim), executableName('harness-mix-shim', platform));
21
21
  assert.equal('activation' in nativePaths(platform), platform === 'win32');
@@ -24,7 +24,7 @@ async function main() {
24
24
  assert.throws(() => enforceDesktopCompatibility(result, { HARNESS_MIX_STRICT_COMPATIBILITY: '1' }));
25
25
  }
26
26
  assert.equal(evaluateDesktopCompatibility('1.2.3', undefined, 'darwin').state, 'unverified');
27
- const env = { HARNESS_MIX_DESKTOP_EXECUTABLE: process.execPath, CODEXHOST_STOCK_CODEX_PATH: process.execPath };
27
+ const env = { HARNESS_MIX_DESKTOP_EXECUTABLE: process.execPath, HARNESSMIX_STOCK_CODEX_PATH: process.execPath };
28
28
  assert.equal(inspectPosix(env, 'linux').version, 'unknown');
29
29
  assert.equal(inspectPosix({ ...env, HARNESS_MIX_DESKTOP_VERSION: '1.2.3' }, 'linux').stock, fs.realpathSync(process.execPath));
30
30
  assert.throws(() => inspectPosix({}, 'linux'), /Install Codex Desktop/);
@@ -24,7 +24,7 @@ if (!sourceOnly) {
24
24
  }
25
25
  fs.writeFileSync(path.join(pkg, 'package.json'), JSON.stringify({
26
26
  name: `@harness-mix/native-${key}`, version, description: `Harness Mix native runtime for ${key}${sourceOnly ? ' (source-only; build locally)' : ''}`,
27
- license: 'Apache-2.0', os: [platform], cpu: [arch], files: ['bin'], publishConfig: { access: 'public' },
27
+ license: '(Apache-2.0 OR MIT)', os: [platform], cpu: [arch], files: ['bin'], publishConfig: { access: 'public' },
28
28
  }, null, 2) + '\n');
29
29
  fs.writeFileSync(path.join(pkg, 'README.md'), `# @harness-mix/native-${key}\n\nNative runtime selected automatically by @harness-mix/cli.\n`);
30
30
  const publish = flags.includes('--publish');
@@ -43,14 +43,14 @@ async function main() {
43
43
  console.log('Waiting for probe to mount...');
44
44
  await evaluate(`(async () => {
45
45
  for (let i = 0; i < 50; i++) {
46
- if (window.__codexhostRendererBindingProbeV1 && document.querySelector('.ProseMirror')) break;
46
+ if (window.__harnessmixRendererBindingProbeV1 && document.querySelector('.ProseMirror')) break;
47
47
  await new Promise(r => setTimeout(r, 100));
48
48
  }
49
49
  })()`);
50
50
 
51
51
  const directClientTest = await evaluate(`(async () => {
52
52
  try {
53
- const probe = window.__codexhostRendererBindingProbeV1;
53
+ const probe = window.__harnessmixRendererBindingProbeV1;
54
54
  return {
55
55
  hasProbe: !!probe,
56
56
  probeKeys: probe ? Object.keys(probe) : []
@@ -54,7 +54,9 @@ const { HostRuntime } = require('../src/main/host/runtime');
54
54
  rt.subscribe(e => { if (e.type === 'turn/diff/updated') updates.push(e); });
55
55
  await rt.store.load();
56
56
  rt.adapters.set('test', {
57
- manifest: { id: 'test', name: 'Test', capabilities: {} },
57
+ // Even a Harness that advertises nativePatch may omit a native file event.
58
+ // Host final Diff must still close the gap from its authoritative snapshot.
59
+ manifest: { id: 'test', name: 'Test', capabilities: { nativeDiff: true, nativePatch: true } },
58
60
  open: async () => ({}), close: async () => {},
59
61
  send: async (_session, _text, { emit }) => {
60
62
  emit({ kind: 'text-delta', text: 'progress' });
@@ -73,7 +75,7 @@ const { HostRuntime } = require('../src/main/host/runtime');
73
75
  assert.equal(t.status, 'ready');
74
76
  const answer = t.messages.at(-1);
75
77
  assert.deepEqual(answer.coreItems.filter(i => ['agent_message', 'tool_call'].includes(i.type)).map(i => i.type), ['agent_message', 'tool_call', 'agent_message']);
76
- assert.equal(answer.review.files.length, 1);
78
+ assert.equal(answer.review.files.length, 1, 'Host final Diff supplements a missing native patch');
77
79
  assert.equal(answer.review.files[0].path, 'dirty.js');
78
80
  assert.ok(updates.some(e => e.turnId === answer.id && e.review?.live && e.review.files.some(f => f.path === 'dirty.js')), 'Runtime pushes live diff without Renderer polling');
79
81
  assert.ok(updates.some(e => e.turnId === answer.id && e.review?.live === false), 'Runtime pushes final diff');
@@ -0,0 +1,92 @@
1
+ # Icon provenance
2
+
3
+ 33 brand marks are bundled in this directory and read by `src/main/native/icons.js`.
4
+ They exist so the UI can label the harnesses and models this project integrates with.
5
+ Every mark remains a trademark of its owner; see the trademark note at the end.
6
+
7
+ ## Redistributed from lobehub/lobe-icons — 24 of 33 (MIT)
8
+
9
+ `@lobehub/icons-static-svg` v1.95.0, `Copyright (c) 2023 LobeHub`.
10
+ Source: https://github.com/lobehub/lobe-icons
11
+ License text: `licenses/lobe-icons-MIT.txt`
12
+
13
+ Fifteen files are byte-identical to the upstream package:
14
+
15
+ | local | upstream |
16
+ | --- | --- |
17
+ | `claude-color.svg` | `claude-color.svg` |
18
+ | `cline-color.svg` | `cline.svg` |
19
+ | `cursor-cli-color.svg` | `cursor.svg` |
20
+ | `deepseek-color.svg` | `deepseek-color.svg` |
21
+ | `grok-color.svg` | `grok.svg` |
22
+ | `model-claude.svg` | `claude.svg` |
23
+ | `model-deepseek.svg` | `deepseek.svg` |
24
+ | `model-kimi.svg` | `kimi.svg` |
25
+ | `model-minimax.svg` | `minimax.svg` |
26
+ | `model-openai.svg` | `openai.svg` |
27
+ | `model-qwen-color.svg` | `qwen-color.svg` |
28
+ | `model-xiaomimimo.svg` | `xiaomimimo.svg` |
29
+ | `openclaw-color.svg` | `openclaw-color.svg` |
30
+ | `opencode-color.svg` | `opencode.svg` |
31
+ | `pi.svg` | `pi.svg` |
32
+
33
+ Nine more carry the same artwork (identical `path` data) behind a slightly different
34
+ export wrapper, so they come from the same set:
35
+
36
+ | local | upstream |
37
+ | --- | --- |
38
+ | `antigravity-color.svg` | `antigravity-color.svg` |
39
+ | `cursor.svg` | `cursor.svg` |
40
+ | `model-gemini.svg` | `gemini.svg` |
41
+ | `model-grok.svg` | `grok.svg` |
42
+ | `model-zai.svg` | `zai.svg` |
43
+ | `qoder-color.svg` | `qoder-color.svg` |
44
+ | `trae-color.svg` | `trae-color.svg` |
45
+ | `workbuddy-color.svg` | `yuanbao-color.svg` |
46
+ | `zcode-color.svg` | `zai.svg` |
47
+
48
+ Note that two local file names do not match the mark they contain: `workbuddy-color.svg`
49
+ is the upstream *Yuanbao* mark, and `zcode-color.svg` is the upstream *Z.ai* mark.
50
+ The upstream `<title>` element in those files still carries the original names.
51
+
52
+ ## Bundled from product brand marks — 8 of 33
53
+
54
+ | local | known origin |
55
+ | --- | --- |
56
+ | `kiro-cli-color.svg` | Official Kiro icon, `https://kiro.dev/icon.svg`. Byte-identical to `src/native-ui/renderer-extension/src/assets/kiro-agent.svg`, whose provenance is recorded in that directory's `README.md`. |
57
+ | `codex-color.svg`, `codex-harness.svg` | The Codex mark. Both names hold the same bytes and both are referenced (`adapters/codex.js` uses `codex-color.svg`, `native/icons.js` and `README.md` use `codex-harness.svg`). |
58
+ | `codebuddy-color.svg` | CodeBuddy harness mark. Source record not kept. |
59
+ | `hermes-color.svg` | Hermes harness mark. Source record not kept. |
60
+ | `omp-color.svg` | Oh My Pi harness mark whose source record was not kept. It is **not** the official mark: `omp-agent.svg` in the renderer assets has identical path data to the official Oh My Pi favicon (`packages/collab-web/public/favicon.svg`), while this file is a different, simpler shape. |
61
+ | `model-astra.svg` | Drawn in this repository (gradient disc), not third-party artwork. |
62
+ | `model-hunyuan.svg` | Drawn in this repository (rounded plate with a glyph), not third-party artwork. |
63
+
64
+ ## Unknown provenance — 1 of 33
65
+
66
+ `pinumber1_80899.svg` is a pi glyph exported by Adobe Illustrator 18.1.1; the file name
67
+ matches the download naming of free icon sites. It is used as the Pi harness icon
68
+ (`src/main/adapters/pi.js`). The exact source and its license could not be established,
69
+ so it should be replaced with original artwork or have its source recorded.
70
+
71
+ ## Usage
72
+
73
+ `src/main/native/icons.js` resolves icons through an explicit file list and nothing globs
74
+ this directory, so three files are currently referenced by no code path:
75
+
76
+ | file | why it is unused |
77
+ | --- | --- |
78
+ | `cursor-cli-color.svg` | Both the `cursor` and `cursor-cli` entries resolve to `cursor.svg`. |
79
+ | `model-grok.svg` | The `grok` model family resolves to `grok-color.svg`. The other eleven model families all use `model-*.svg`, so this is the convention-consistent file — either it should be wired up or the duplicate dropped. |
80
+ | `workbuddy-color.svg` | Every alias map resolves `workbuddy` to `codebuddy`, which uses `codebuddy-color.svg`. |
81
+
82
+ `grok-color.svg` and `model-grok.svg` carry identical path data, so despite the names they
83
+ are the same artwork under two file names.
84
+
85
+ Everything in this directory is published: `package.json` lists `src` in `files`.
86
+
87
+ ## Trademarks
88
+
89
+ These marks are the property of their respective owners and are bundled only to identify
90
+ the harnesses and models this project integrates with. No trademark right, endorsement or
91
+ affiliation is claimed. Copyright licenses covering a mark (such as the MIT license above)
92
+ do not grant any trademark right.