@harness-mix/cli 0.1.10 → 0.1.12

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 +21 -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 +8 -8
  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
@@ -0,0 +1,312 @@
1
+ import { collaborationIcon } from './collaboration-icon.js';
2
+
3
+ export interface TeamMemberPayload { id: string; name: string; role: string; agent: string; childId?: string; child_thread_id?: string; display_status?: string }
4
+ export interface TeamTaskPayload { id: string; title: string; assignee: string; dependsOn?: string[]; status: string }
5
+ export interface TeamMessagePayload { id: string; fromName?: string; from: string; to: string; body: string; at: number }
6
+ export interface TeamCardPayload {
7
+ action?: string; team_id: string; name: string; goal: string; status: string; lead_thread_id?: string;
8
+ lead?: TeamMemberPayload; members: TeamMemberPayload[]; tasks: TeamTaskPayload[]; messages: TeamMessagePayload[]; updated_at?: number;
9
+ }
10
+ interface TeamSnapshot { id: string; action: string; at: number; team: TeamCardPayload }
11
+ interface TeamInspection { team: TeamCardPayload; snapshots: TeamSnapshot[] }
12
+ interface ActiveTeamContext { threadId: string; anchor: Element }
13
+ interface TeamCardOptions {
14
+ inspectTeam?: (threadId: string, teamId?: string) => Promise<unknown>;
15
+ openThread?: (threadId: string) => Promise<unknown> | unknown;
16
+ activeThread?: () => ActiveTeamContext | null;
17
+ }
18
+
19
+ function jsonObjectAt(value: string, start: number): string | null {
20
+ let depth = 0, quoted = false, escaped = false;
21
+ for (let index = start; index < value.length; index++) {
22
+ const char = value[index];
23
+ if (quoted) { if (escaped) escaped = false; else if (char === '\\') escaped = true; else if (char === '"') quoted = false; continue; }
24
+ if (char === '"') quoted = true; else if (char === '{') depth++; else if (char === '}' && --depth === 0) return value.slice(start, index + 1);
25
+ }
26
+ return null;
27
+ }
28
+ function isTeam(value: unknown): value is TeamCardPayload {
29
+ if (!value || typeof value !== 'object') return false;
30
+ const team = value as Partial<TeamCardPayload>;
31
+ return typeof team.team_id === 'string' && typeof team.name === 'string' && Array.isArray(team.members) && Array.isArray(team.tasks) && Array.isArray(team.messages);
32
+ }
33
+ export function parseTeamPayload(value: string): TeamCardPayload | null {
34
+ if (!value.includes('"team_id"') || !value.includes('"members"') || !value.includes('"tasks"')) return null;
35
+ for (let start = value.indexOf('{'); start >= 0; start = value.indexOf('{', start + 1)) {
36
+ const candidate = jsonObjectAt(value, start); if (!candidate?.includes('"team_id"')) continue;
37
+ try { const parsed: unknown = JSON.parse(candidate); if (isTeam(parsed)) return parsed; } catch {}
38
+ }
39
+ return null;
40
+ }
41
+ function parseInspection(value: unknown): TeamInspection | null {
42
+ if (!value || typeof value !== 'object') return null;
43
+ const result = value as Partial<TeamInspection>;
44
+ if (!isTeam(result.team) || !Array.isArray(result.snapshots)) return null;
45
+ return { team: result.team, snapshots: result.snapshots.filter(entry => entry && typeof entry === 'object' && isTeam((entry as TeamSnapshot).team)) as TeamSnapshot[] };
46
+ }
47
+ const stateColor = (status?: string) => ({ ready: '#8b8b8b', pending: '#8b8b8b', working: '#2878e3', in_progress: '#2878e3', active: '#2878e3', completed: '#1f9d68', blocked: '#c17022', failed: '#d14343', interrupted: '#c17022' }[status ?? ''] ?? '#8b8b8b');
48
+ const stateLabel = (status?: string) => ({ ready: '就绪', pending: '待开始', working: '工作中', in_progress: '进行中', completed: '已完成', blocked: '等待依赖', failed: '失败', interrupted: '已中断', active: '协作中' }[status ?? ''] ?? status ?? '未知');
49
+ const actionLabel = (action?: string) => ({ team_created: '团队建立', task_assigned: '任务分配', task_updated: '任务更新', message_sent: '团队通信', task_started: '开始执行', member_session_ready: '会话就绪', task_settled: '任务结算', task_failed: '任务失败', task_cancelled: '任务取消', task_interrupted: '任务中断', task_resumed: '恢复执行', task_followup: '继续执行' }[action ?? ''] ?? action ?? '实时状态');
50
+ const memberPalette = ['#3b82f6', '#f59e0b', '#10b981', '#8b5cf6', '#f97316', '#ec4899', '#14b8a6', '#6366f1'];
51
+ const memberColor = (index: number) => memberPalette[index % memberPalette.length];
52
+ function el<K extends keyof HTMLElementTagNameMap>(tag: K, className?: string, css?: string): HTMLElementTagNameMap[K] { const node = document.createElement(tag); if (className) node.className = className; if (css) node.style.cssText = css; return node; }
53
+ function text(tag: keyof HTMLElementTagNameMap, value: string, css?: string) { const node = el(tag, undefined, css); node.textContent = value; return node; }
54
+
55
+ const TEAM_STYLE = `
56
+ .harness-mix-team-scroll{scrollbar-width:none}
57
+ .harness-mix-team-scroll::-webkit-scrollbar{display:none}
58
+ .harness-mix-team-workbench{container-type:inline-size}
59
+ .harness-mix-team-body{display:grid;grid-template-columns:minmax(0,1fr) clamp(228px,24vw,300px);min-height:0;overflow:hidden}
60
+ .harness-mix-team-lanes{display:flex;gap:16px;min-height:0;box-sizing:border-box;overflow-x:auto;overflow-y:hidden;padding:18px 16px 10px;justify-content:safe center;scroll-snap-type:x proximity}
61
+ .harness-mix-team-lane{position:relative;flex:1 1 0;min-width:216px;max-width:300px;display:flex;flex-direction:column;min-height:0;padding-top:16px;scroll-snap-align:start}
62
+ .harness-mix-team-lane::before{content:'';position:absolute;top:0;left:50%;height:16px;border-left:2px dashed color-mix(in srgb,currentColor 20%,transparent)}
63
+ .harness-mix-team-lane::after{content:'';position:absolute;top:0;left:-9px;right:-9px;border-top:2px dashed color-mix(in srgb,currentColor 20%,transparent)}
64
+ .harness-mix-team-lane:first-child::after{left:calc(50% - 1px)}
65
+ .harness-mix-team-lane:last-child::after{right:calc(50% - 1px)}
66
+ .harness-mix-team-lane:only-child::after{display:none}
67
+ .harness-mix-team-task-list{display:flex;flex-direction:column;gap:6px;flex:1;min-height:0;overflow-y:auto;padding:2px 8px 8px;scrollbar-width:none}
68
+ .harness-mix-team-task-list::-webkit-scrollbar{display:none}
69
+ .harness-mix-team-feed{display:flex;flex-direction:column;min-height:0;min-width:0;border-left:1px solid color-mix(in srgb,currentColor 9%,transparent)}
70
+ .harness-mix-team-feed-list{flex:1;min-height:0;overflow-y:auto;padding:0 12px 10px;scrollbar-width:thin}
71
+ .harness-mix-team-clamp2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
72
+ .harness-mix-team-clickable{transition:border-color .15s ease,box-shadow .15s ease}
73
+ .harness-mix-team-clickable:hover{border-color:color-mix(in srgb,currentColor 28%,transparent)!important;box-shadow:0 4px 14px color-mix(in srgb,#000 10%,transparent)!important}
74
+ @container (max-width:720px){
75
+ .harness-mix-team-body{grid-template-columns:minmax(0,1fr);grid-template-rows:minmax(0,1fr) auto}
76
+ .harness-mix-team-feed{border-left:0;border-top:1px solid color-mix(in srgb,currentColor 9%,transparent);max-height:136px}
77
+ }`;
78
+
79
+ function metrics(payload: TeamCardPayload) {
80
+ const node = el('div', 'harness-mix-team-metrics', 'display:flex;gap:18px;align-items:center');
81
+ const values: Array<[string, string, string]> = [[`${payload.tasks.filter(task => task.status === 'completed').length}/${payload.tasks.length}`, '完成', '#1f9d68'], [`${payload.tasks.filter(task => task.status === 'in_progress').length}`, '进行中', '#2878e3'], [`${payload.tasks.filter(task => task.status === 'blocked').length}`, '等待', '#c17022']];
82
+ for (const [value, label, color] of values) { const item = el('span', undefined, 'display:grid;justify-items:center;line-height:1.1'); item.append(text('strong', value, `font-size:14px;color:${color}`), text('small', label, 'font-size:10px;margin-top:3px;opacity:.55')); node.append(item); }
83
+ return node;
84
+ }
85
+ const completionOf = (payload: TeamCardPayload) => { const total = payload.tasks.length; const done = payload.tasks.filter(task => task.status === 'completed').length; return { done, total, pct: total ? Math.round((done / total) * 100) : 0 }; };
86
+ function statItem(value: string, label: string, color: string) {
87
+ const item = el('span', undefined, 'display:grid;justify-items:center;line-height:1.1;min-width:30px');
88
+ item.append(text('strong', value, `font-size:15px;font-weight:750;color:${color}`), text('small', label, 'font-size:8.5px;margin-top:2px;opacity:.55;white-space:nowrap'));
89
+ return item;
90
+ }
91
+ function headerStats(payload: TeamCardPayload) {
92
+ const items = [
93
+ statItem(String(payload.tasks.length), '任务总数', 'inherit'),
94
+ statItem(String(payload.tasks.filter(task => task.status === 'in_progress').length), '进行中', '#2878e3'),
95
+ statItem(String(completionOf(payload).done), '已完成', '#1f9d68'),
96
+ statItem(String(payload.tasks.filter(task => task.status === 'blocked' || task.status === 'pending').length), '等待', '#c17022'),
97
+ ];
98
+ const failed = payload.tasks.filter(task => task.status === 'failed').length;
99
+ if (failed) items.push(statItem(String(failed), '失败', '#d14343'));
100
+ return items;
101
+ }
102
+ const pillCss = (status?: string) => { const color = stateColor(status); return `font-size:8px;font-weight:750;padding:2px 7px;border-radius:99px;white-space:nowrap;color:${color};background:color-mix(in srgb,${color} 15%,transparent)`; };
103
+ function statusPill(status?: string) { return text('span', stateLabel(status), pillCss(status)); }
104
+ function statusDot(status: string | undefined, size = 7) { return el('span', undefined, `width:${size}px;height:${size}px;border-radius:50%;flex:none;background:${stateColor(status)}`); }
105
+
106
+ function renderBoard(payload: TeamCardPayload, openThread?: TeamCardOptions['openThread']) {
107
+ const board = el('main', 'harness-mix-team-board harness-mix-team-body', 'height:100%;min-height:0;color:inherit');
108
+ const lead = payload.lead ?? { id: 'lead', name: 'Team Lead', role: '协调与验收', agent: 'codex', display_status: 'working' };
109
+ const tasksOf = (memberId: string) => payload.tasks.filter(task => task.assignee === memberId);
110
+
111
+ const leadCard = () => {
112
+ const button = el('button', 'harness-mix-team-lead', 'appearance:none;border:1px solid color-mix(in srgb,#c35b24 34%,transparent);background:color-mix(in srgb,#c35b24 7%,transparent);box-shadow:0 2px 10px color-mix(in srgb,#c35b24 10%,transparent);color:inherit;font:inherit;display:flex;align-items:center;gap:10px;padding:8px 16px;border-radius:13px;cursor:default'); button.type = 'button'; button.dataset.agent = lead.agent;
113
+ const childId = lead.childId ?? lead.child_thread_id;
114
+ if (childId && openThread) { button.style.cursor = 'pointer'; button.classList.add('harness-mix-team-clickable'); button.title = `打开 ${lead.name} 的原生 Harness 会话`; button.addEventListener('click', () => void openThread(childId)); }
115
+ const avatar = el('span', undefined, 'position:relative;display:grid;place-items:center;width:42px;height:42px;flex:none;border-radius:12px;border:2px solid color-mix(in srgb,#c35b24 45%,transparent);background:Canvas');
116
+ avatar.append(collaborationIcon(lead.agent, lead.name, 32), text('span', '👑', 'position:absolute;top:-12px;right:-10px;font-size:13px;filter:drop-shadow(0 1px 1px rgb(0 0 0/.25))'));
117
+ const copy = el('span', undefined, 'display:grid;min-width:0;text-align:left;line-height:1.3');
118
+ copy.append(text('span', '主导者', 'font-size:8.5px;font-weight:800;letter-spacing:.14em;color:#c35b24'), text('strong', lead.name, 'font-size:13px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap'));
119
+ const status = el('span', undefined, 'display:flex;align-items:center;gap:5px;margin-top:1px');
120
+ status.append(statusDot(lead.display_status), text('span', stateLabel(lead.display_status), `font-size:9px;color:${stateColor(lead.display_status)}`));
121
+ copy.append(status); button.append(avatar, copy); return button;
122
+ };
123
+ const memberCard = (member: TeamMemberPayload, index: number) => {
124
+ const color = memberColor(index), assigned = tasksOf(member.id), done = assigned.filter(task => task.status === 'completed').length;
125
+ const button = el('button', 'harness-mix-team-member', 'appearance:none;width:100%;box-sizing:border-box;border:1px solid color-mix(in srgb,currentColor 10%,transparent);background:color-mix(in srgb,Canvas 92%,transparent);box-shadow:0 2px 8px color-mix(in srgb,#000 6%,transparent);color:inherit;font:inherit;display:grid;grid-template-columns:40px minmax(0,1fr);align-items:center;gap:9px;padding:9px 10px;border-radius:12px;text-align:left;cursor:default'); button.type = 'button'; button.dataset.agent = member.agent;
126
+ const childId = member.childId ?? member.child_thread_id;
127
+ if (childId && openThread) { button.style.cursor = 'pointer'; button.classList.add('harness-mix-team-clickable'); button.title = `打开 ${member.name} 的原生 Harness 会话`; button.addEventListener('click', () => void openThread(childId)); }
128
+ const avatar = el('span', undefined, `position:relative;display:grid;place-items:center;width:40px;height:40px;flex:none;border-radius:11px;border:2px solid ${color};background:Canvas`);
129
+ avatar.append(collaborationIcon(member.agent, member.name, 30), el('span', undefined, `position:absolute;right:-4px;bottom:-4px;width:11px;height:11px;box-sizing:border-box;border-radius:50%;background:${stateColor(member.display_status)};border:2.5px solid Canvas`));
130
+ const copy = el('span', undefined, 'display:grid;min-width:0;line-height:1.25;gap:2px');
131
+ copy.append(text('strong', member.name, 'font-size:12px;font-weight:680;overflow:hidden;text-overflow:ellipsis;white-space:nowrap'));
132
+ const status = el('span', undefined, 'display:flex;align-items:center;gap:5px;min-width:0');
133
+ status.append(text('span', stateLabel(member.display_status), `font-size:9px;color:${stateColor(member.display_status)};white-space:nowrap`), text('span', `${done}/${assigned.length}`, 'font-size:9px;font-weight:650;opacity:.5;margin-left:auto'));
134
+ copy.append(status);
135
+ const progress = el('progress'); progress.max = Math.max(1, assigned.length); progress.value = done; progress.style.cssText = `width:100%;height:4px;margin:0;accent-color:${color}`; progress.title = `${done}/${assigned.length} 个任务完成`;
136
+ copy.append(progress); button.append(avatar, copy); return button;
137
+ };
138
+ const laneOf = (member: TeamMemberPayload, index: number) => {
139
+ const color = memberColor(index), assigned = tasksOf(member.id), done = assigned.filter(task => task.status === 'completed').length;
140
+ const lane = el('div', 'harness-mix-team-lane'); lane.dataset.memberId = member.id;
141
+ lane.append(memberCard(member, index));
142
+ const column = el('div', undefined, `margin-top:9px;flex:1;min-height:0;display:flex;flex-direction:column;border-radius:12px;border:1px solid color-mix(in srgb,${color} 30%,transparent);background:color-mix(in srgb,${color} 7%,transparent)`);
143
+ const columnHead = el('div', undefined, 'display:flex;align-items:flex-start;gap:6px;padding:8px 10px 5px');
144
+ const role = text('span', member.role, 'font-size:9.5px;font-weight:650;line-height:1.35;min-width:0;opacity:.78'); role.className = 'harness-mix-team-clamp2'; role.title = member.role;
145
+ columnHead.append(el('span', undefined, `width:7px;height:7px;border-radius:2.5px;background:${color};flex:none;margin-top:3px`), role, text('span', `${done}/${assigned.length}`, `margin-left:auto;font-size:8.5px;font-weight:750;color:${color};background:color-mix(in srgb,${color} 15%,transparent);padding:1px 6px;border-radius:99px;white-space:nowrap`));
146
+ column.append(columnHead);
147
+ const list = el('div', 'harness-mix-team-task-list');
148
+ for (const task of assigned) {
149
+ const card = el('article', 'harness-mix-team-task', 'display:grid;gap:5px;padding:7px 8px;border-radius:9px;border:1px solid color-mix(in srgb,currentColor 8%,transparent);background:color-mix(in srgb,Canvas 94%,transparent)'); card.dataset.taskId = task.id; card.dataset.taskStatus = task.status;
150
+ const topRow = el('div', undefined, 'display:flex;align-items:center;gap:6px;min-width:0');
151
+ const pill = statusPill(task.status); pill.style.marginLeft = 'auto';
152
+ topRow.append(text('span', `#${task.id}`, 'font-family:ui-monospace,monospace;font-size:8px;opacity:.45;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:92px'), pill);
153
+ const title = text('div', task.title, 'font-size:10.5px;font-weight:620;line-height:1.35'); title.className = 'harness-mix-team-clamp2'; title.title = task.title;
154
+ card.append(topRow, title);
155
+ if ((task.dependsOn?.length ?? 0) > 0) card.append(text('div', `依赖 ${task.dependsOn!.length} 项任务`, 'font-size:8px;opacity:.45'));
156
+ list.append(card);
157
+ }
158
+ if (!assigned.length) list.append(text('div', '等待主导者分配任务', 'font-size:9px;opacity:.42;padding:10px 2px;text-align:center'));
159
+ column.append(list); lane.append(column); return lane;
160
+ };
161
+
162
+ const left = el('section', undefined, 'display:grid;grid-template-rows:auto minmax(0,1fr);min-width:0;min-height:0');
163
+ const org = el('div', 'harness-mix-team-org', 'display:flex;flex-direction:column;align-items:center;gap:5px;padding:10px 14px 0');
164
+ org.append(leadCard(), text('div', '任务拆解 · 进度协调 · 质量验收 · 最终交付', 'font-size:8.5px;opacity:.45;letter-spacing:.04em'));
165
+ const lanes = el('div', 'harness-mix-team-lanes harness-mix-team-scroll');
166
+ if (payload.members.length) payload.members.forEach((member, index) => lanes.append(laneOf(member, index)));
167
+ else lanes.append(text('div', '尚未添加团队成员。', 'font-size:11px;opacity:.5'));
168
+ left.append(org, lanes);
169
+
170
+ const feed = el('aside', 'harness-mix-team-feed');
171
+ const feedHead = el('div', undefined, 'display:flex;align-items:center;gap:6px;padding:11px 12px 8px;flex:none');
172
+ feedHead.append(text('span', '团队动态', 'font-size:10px;font-weight:720;letter-spacing:.06em;opacity:.55'), text('span', String(payload.messages.length), 'font-size:8.5px;font-weight:700;opacity:.6;background:color-mix(in srgb,currentColor 8%,transparent);border-radius:99px;padding:1px 7px'));
173
+ const feedList = el('div', 'harness-mix-team-feed-list');
174
+ for (const message of payload.messages.slice().reverse()) {
175
+ const item = el('article', undefined, 'padding:9px 0;border-top:1px solid color-mix(in srgb,currentColor 7%,transparent)');
176
+ const sender = message.from === 'lead' ? lead : payload.members.find(member => member.id === message.from), receiver = message.to === 'lead' ? lead : payload.members.find(member => member.id === message.to);
177
+ const route = el('div', undefined, 'display:flex;align-items:center;gap:5px;min-width:0;font-size:10.5px;font-weight:700');
178
+ if (sender) route.append(collaborationIcon(sender.agent, sender.name, 16));
179
+ route.append(text('span', message.fromName ?? sender?.name ?? message.from, 'opacity:.75;overflow:hidden;text-overflow:ellipsis;white-space:nowrap'), text('span', '→', 'opacity:.4;font-weight:400'));
180
+ if (receiver) route.append(collaborationIcon(receiver.agent, receiver.name, 16));
181
+ route.append(text('span', message.to === '*' ? '全体' : receiver?.name ?? message.to, 'opacity:.75;overflow:hidden;text-overflow:ellipsis;white-space:nowrap'));
182
+ if (message.at > 0) route.append(text('span', new Date(message.at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }), 'margin-left:auto;font-size:8.5px;font-weight:400;opacity:.4;flex:none'));
183
+ item.append(route, text('div', message.body, 'font-size:11px;line-height:1.5;margin-top:4px;white-space:pre-wrap;overflow-wrap:anywhere;opacity:.88')); feedList.append(item);
184
+ }
185
+ if (!payload.messages.length) feedList.append(text('div', '成员交接、审查请求和结果会实时显示在这里。', 'font-size:10px;line-height:1.5;opacity:.45;padding:10px 0'));
186
+ feed.append(feedHead, feedList);
187
+ board.append(left, feed); return board;
188
+ }
189
+
190
+ function renderSummary(payload: TeamCardPayload, open: () => void) {
191
+ const panel = el('section', 'harness-mix-team-panel', 'box-sizing:border-box;border:1px solid color-mix(in srgb,currentColor 12%,transparent);border-radius:14px;background:color-mix(in srgb,Canvas 90%,transparent);box-shadow:0 8px 28px color-mix(in srgb,#000 7%,transparent);backdrop-filter:blur(18px);color:inherit;font:13px/1.4 system-ui,-apple-system,"Segoe UI",sans-serif;padding:12px 14px;display:grid;gap:10px;min-width:0'); panel.dataset.teamId = payload.team_id; panel.dataset.teamStatus = payload.status;
192
+ const top = el('div', undefined, 'display:flex;align-items:center;gap:12px;min-width:0');
193
+ const identity = el('div', undefined, 'display:grid;grid-template-columns:38px minmax(0,1fr);align-items:center;gap:10px;min-width:0;flex:1');
194
+ const lead = payload.lead ?? { id: 'lead', name: 'Team Lead', role: '协调与验收', agent: 'codex', display_status: 'working' };
195
+ const leadIcon = el('span', undefined, 'position:relative;display:grid;place-items:center;width:38px;height:38px;flex:none;border:2px solid color-mix(in srgb,#c35b24 40%,transparent);border-radius:11px;background:Canvas');
196
+ leadIcon.append(collaborationIcon(lead.agent, lead.name, 28), text('span', '👑', 'position:absolute;top:-11px;right:-9px;font-size:11px'));
197
+ const copy = el('span', undefined, 'display:grid;min-width:0;gap:1px'), eyebrow = text('span', `AGENT TEAM · ${stateLabel(payload.status)}`, `font-size:9px;font-weight:760;letter-spacing:.11em;color:${stateColor(payload.status)}`), title = text('strong', payload.name, 'font-size:13px;font-weight:700;overflow:hidden;text-overflow:ellipsis;white-space:nowrap'); title.className = 'harness-mix-team-name';
198
+ const goal = text('span', payload.goal, 'font-size:10px;opacity:.5;overflow:hidden;text-overflow:ellipsis;white-space:nowrap'); goal.title = payload.goal;
199
+ copy.append(eyebrow, title, goal); identity.append(leadIcon, copy);
200
+ const button = el('button', 'harness-mix-team-open', 'border:1px solid color-mix(in srgb,currentColor 13%,transparent);border-radius:8px;background:color-mix(in srgb,currentColor 5%,transparent);color:inherit;font:650 11px system-ui;padding:7px 10px;cursor:pointer;white-space:nowrap'); button.type = 'button'; button.textContent = '展开详情'; button.addEventListener('click', open); top.append(identity, metrics(payload), button);
201
+ const members = el('div', 'harness-mix-team-summary-members harness-mix-team-scroll', 'display:flex;align-items:center;gap:6px;min-width:0;overflow-x:auto;padding-bottom:1px');
202
+ payload.members.forEach((member, index) => {
203
+ const color = memberColor(index);
204
+ const chip = el('span', undefined, 'display:grid;grid-template-columns:26px minmax(0,1fr);align-items:center;gap:7px;min-width:128px;max-width:190px;padding:5px 9px;border-radius:10px;border:1px solid color-mix(in srgb,currentColor 8%,transparent);background:color-mix(in srgb,currentColor 3%,transparent)'); chip.title = `${member.name} · ${member.role}`;
205
+ const icon = el('span', undefined, `position:relative;display:grid;place-items:center;width:26px;height:26px;flex:none;border-radius:8px;border:1.5px solid ${color};background:Canvas`);
206
+ icon.append(collaborationIcon(member.agent, member.name, 18), el('span', undefined, `position:absolute;right:-3px;bottom:-3px;width:8px;height:8px;box-sizing:border-box;border-radius:50%;background:${stateColor(member.display_status)};border:2px solid Canvas`));
207
+ const label = el('span', undefined, 'display:grid;min-width:0;line-height:1.2');
208
+ label.append(text('strong', member.name, 'font-size:10px;font-weight:650;overflow:hidden;text-overflow:ellipsis;white-space:nowrap'), text('span', member.role, 'font-size:8.5px;opacity:.52;overflow:hidden;text-overflow:ellipsis;white-space:nowrap'), text('span', stateLabel(member.display_status), `font-size:8.5px;color:${stateColor(member.display_status)}`));
209
+ chip.append(icon, label); members.append(chip);
210
+ });
211
+ const completed = payload.tasks.filter(task => task.status === 'completed').length, progress = el('progress'); progress.max = Math.max(1, payload.tasks.length); progress.value = completed; progress.style.cssText = 'width:72px;height:5px;accent-color:#1f9d68;margin-left:auto;flex:none'; progress.title = `${completed}/${payload.tasks.length} 个任务完成`; members.append(progress, text('span', `${completed}/${payload.tasks.length}`, 'font-size:9px;font-weight:700;opacity:.52;white-space:nowrap'));
212
+ panel.append(top, members); return panel;
213
+ }
214
+
215
+ export function installTeamCards(options: TeamCardOptions = {}) {
216
+ if (typeof document === 'undefined') return { scan: () => {}, dispose: () => {} };
217
+ const style = el('style'); style.dataset.harnessMixTeamStyle = 'true'; style.textContent = TEAM_STYLE; (document.head || document.documentElement).append(style);
218
+ let disposed = false, workbench: HTMLElement | null = null, refreshTimer: ReturnType<typeof setInterval> | null = null, playTimer: ReturnType<typeof setInterval> | null = null, activeTimer: ReturnType<typeof setInterval> | null = null;
219
+ let activePanel: HTMLElement | null = null, activeSignature = '', activeThreadId = '', activeRefreshPending = false;
220
+ const signatures = new WeakMap<Element, string>();
221
+ const close = () => { workbench?.remove(); workbench = null; if (refreshTimer) clearInterval(refreshTimer); refreshTimer = null; if (playTimer) clearInterval(playTimer); playTimer = null; };
222
+ const open = (seed: TeamCardPayload) => {
223
+ if (workbench?.dataset.teamId === seed.team_id) { close(); return; }
224
+ close();
225
+ const source = [...document.querySelectorAll<HTMLElement>('.harness-mix-team-panel')].find(node => node.dataset.teamId === seed.team_id);
226
+ if (!source?.parentElement) return;
227
+ workbench = el('section', 'harness-mix-team-workbench', 'box-sizing:border-box;margin:8px 0 12px;border:1px solid color-mix(in srgb,currentColor 11%,transparent);border-radius:14px;background:color-mix(in srgb,Canvas 94%,transparent);box-shadow:0 12px 34px color-mix(in srgb,#000 8%,transparent);backdrop-filter:blur(20px);color:inherit;font:13px/1.4 system-ui,-apple-system,"Segoe UI",sans-serif;display:grid;grid-template-rows:auto minmax(0,1fr);height:clamp(340px,64vh,660px);min-height:300px;overflow:hidden');
228
+ workbench.dataset.teamId = seed.team_id; workbench.dataset.teamSource = source.dataset.teamSource ?? 'tool';
229
+ let current = seed, snapshots: TeamSnapshot[] = [], index = -1;
230
+ const header = el('header', undefined, 'display:flex;align-items:center;gap:14px;flex-wrap:wrap;row-gap:8px;min-height:56px;padding:8px 14px;border-bottom:1px solid color-mix(in srgb,currentColor 9%,transparent);background:color-mix(in srgb,currentColor 2%,transparent)');
231
+ const title = el('div', undefined, 'display:grid;gap:1px;min-width:150px;max-width:min(320px,30vw)');
232
+ const nameRow = el('div', undefined, 'display:flex;align-items:center;gap:7px;min-width:0');
233
+ const teamName = text('strong', current.name, 'font-size:13px;font-weight:750;overflow:hidden;text-overflow:ellipsis;white-space:nowrap'); teamName.className = 'harness-mix-team-name';
234
+ const teamPill = statusPill(current.status);
235
+ nameRow.append(teamName, teamPill);
236
+ const subtitle = text('div', current.goal, 'font-size:9px;opacity:.5;overflow:hidden;text-overflow:ellipsis;white-space:nowrap'); subtitle.title = current.goal;
237
+ title.append(nameRow, subtitle);
238
+ const statsWrap = el('div', undefined, 'display:flex;align-items:center;gap:15px;flex-wrap:wrap');
239
+ const progressWrap = el('div', undefined, 'display:flex;align-items:center;gap:7px;flex:none');
240
+ progressWrap.append(text('span', '整体进度', 'font-size:9px;opacity:.55;white-space:nowrap'));
241
+ const progressBar = el('progress'); progressBar.style.cssText = 'width:92px;height:5px;accent-color:#1f9d68';
242
+ const progressPct = text('strong', '0%', 'font-size:11px;font-weight:750;color:#1f9d68;min-width:30px');
243
+ progressWrap.append(progressBar, progressPct);
244
+ const timeline = el('div', 'harness-mix-team-timeline', 'display:flex;align-items:center;gap:6px;margin-left:auto;min-width:0'), event = text('span', '实时状态', 'font-size:9px;opacity:.55;min-width:60px;text-align:right'), range = el('input'); range.type = 'range'; range.min = '0'; range.max = '0'; range.value = '0'; range.style.cssText = 'width:min(120px,16vw);accent-color:#2878e3';
245
+ const live = el('button', undefined, 'border:1px solid color-mix(in srgb,currentColor 15%,transparent);border-radius:7px;background:transparent;color:inherit;font:600 10px system-ui;padding:5px 7px;cursor:pointer'); live.type = 'button'; live.textContent = '实时';
246
+ const play = el('button', undefined, 'border:1px solid color-mix(in srgb,currentColor 15%,transparent);border-radius:7px;background:color-mix(in srgb,currentColor 6%,transparent);color:inherit;font:600 10px system-ui;padding:5px 8px;cursor:pointer'); play.type = 'button'; play.textContent = '回放';
247
+ const collapse = el('button', 'harness-mix-team-back', 'border:0;background:transparent;color:inherit;font:650 10px system-ui;cursor:pointer;padding:6px 7px;opacity:.68'); collapse.type = 'button'; collapse.textContent = '收起详情'; collapse.addEventListener('click', close); timeline.append(event, range, live, play, collapse); header.append(title, statsWrap, progressWrap, timeline);
248
+ const content = el('div', undefined, 'min-height:0'); workbench.append(header, content); source.after(workbench);
249
+ const render = () => {
250
+ const snapshot = index >= 0 ? snapshots[index] : undefined;
251
+ const visible = snapshot?.team ?? current;
252
+ content.replaceChildren(renderBoard(visible, async threadId => { close(); await options.openThread?.(threadId); }));
253
+ teamName.textContent = visible.name; subtitle.textContent = visible.goal; subtitle.title = visible.goal;
254
+ teamPill.textContent = stateLabel(visible.status); teamPill.style.cssText = pillCss(visible.status);
255
+ statsWrap.replaceChildren(...headerStats(visible));
256
+ const completion = completionOf(visible); progressBar.max = Math.max(1, completion.total); progressBar.value = completion.done; progressPct.textContent = `${completion.pct}%`;
257
+ range.max = String(Math.max(0, snapshots.length - 1));
258
+ range.value = String(index >= 0 ? index : Math.max(0, snapshots.length - 1));
259
+ event.textContent = snapshot ? `${actionLabel(snapshot.action)} · ${new Date(snapshot.at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}` : '● 实时状态';
260
+ };
261
+ range.addEventListener('input', () => { index = Number(range.value); render(); }); live.addEventListener('click', () => { index = -1; render(); });
262
+ play.addEventListener('click', () => { if (playTimer) { clearInterval(playTimer); playTimer = null; play.textContent = '回放'; return; } index = index < 0 ? 0 : index; play.textContent = '暂停'; render(); playTimer = setInterval(() => { if (index >= snapshots.length - 1) { if (playTimer) clearInterval(playTimer); playTimer = null; index = -1; play.textContent = '回放'; } else index++; render(); }, 800); });
263
+ const refresh = async () => { if (!options.inspectTeam || !seed.lead_thread_id || !workbench) return; try { const result = parseInspection(await options.inspectTeam(seed.lead_thread_id, seed.team_id)); if (!result || !workbench) return; current = result.team; snapshots = result.snapshots; render(); } catch {} };
264
+ render(); void refresh(); refreshTimer = setInterval(() => void refresh(), 1500);
265
+ };
266
+ const onKey = (event: KeyboardEvent) => { if (event.key === 'Escape' && workbench) close(); }; document.addEventListener('keydown', onKey);
267
+ const scan = () => {
268
+ if (disposed) return;
269
+ const selector = '[data-testid*="tool"], [data-turn-key], [data-local-conversation-item-target-ids], pre[data-testid*="tool"]';
270
+ for (const candidate of document.querySelectorAll<HTMLElement>(selector)) { if (candidate.closest('.harness-mix-team-panel,.harness-mix-team-workbench')) continue; const payload = parseTeamPayload(candidate.textContent ?? ''); if (!payload) continue; if ([...candidate.querySelectorAll<HTMLElement>(selector)].some(child => parseTeamPayload(child.textContent ?? ''))) continue; const signature = `${payload.updated_at ?? 0}:${payload.tasks.length}:${payload.messages.length}`; if (signatures.get(candidate) === signature) continue; const panel = renderSummary(payload, () => open(payload)); if (candidate.tagName === 'PRE') { if (!candidate.dataset.harnessMixTeamDisplay) candidate.dataset.harnessMixTeamDisplay = candidate.style.display || '__empty__'; candidate.style.display = 'none'; if (candidate.nextElementSibling?.classList.contains('harness-mix-team-panel')) candidate.nextElementSibling.remove(); candidate.after(panel); } else { candidate.querySelector(':scope > .harness-mix-team-panel')?.remove(); candidate.append(panel); } signatures.set(candidate, signature); }
271
+ };
272
+ const removeActivePanel = () => { if (workbench?.dataset.teamSource === 'active-thread') close(); activePanel?.remove(); activePanel = null; activeSignature = ''; activeThreadId = ''; };
273
+ const refreshActiveTeam = async () => {
274
+ if (disposed || activeRefreshPending || !options.inspectTeam || !options.activeThread) return;
275
+ const context = options.activeThread();
276
+ if (!context?.anchor.isConnected) { removeActivePanel(); return; }
277
+ activeRefreshPending = true;
278
+ try {
279
+ const result = parseInspection(await options.inspectTeam(context.threadId));
280
+ if (disposed) return;
281
+ const latest = options.activeThread();
282
+ if (!latest || latest.threadId !== context.threadId || !latest.anchor.isConnected) { removeActivePanel(); return; }
283
+ if (!result) { removeActivePanel(); return; }
284
+ const payload = result.team;
285
+ const signature = `${context.threadId}:${payload.team_id}:${payload.updated_at ?? 0}:${payload.tasks.length}:${payload.messages.length}`;
286
+ const inlinePanel = [...document.querySelectorAll<HTMLElement>('.harness-mix-team-panel')]
287
+ .find(node => node !== activePanel && node.dataset.teamId === payload.team_id);
288
+ if (inlinePanel) { removeActivePanel(); return; }
289
+ if (activePanel?.isConnected && activeSignature === signature && activeThreadId === context.threadId) return;
290
+ const reopen = workbench?.dataset.teamId === payload.team_id && workbench.dataset.teamSource === 'active-thread';
291
+ removeActivePanel();
292
+ activePanel = renderSummary(payload, () => open(payload));
293
+ activePanel.classList.add('harness-mix-team-launcher');
294
+ activePanel.dataset.teamSource = 'active-thread';
295
+ activePanel.style.cssText += ';margin:8px 16px 0;flex:none;position:relative;z-index:11';
296
+ const parent = latest.anchor.parentElement;
297
+ if (!parent) { removeActivePanel(); return; }
298
+ parent.insertBefore(activePanel, latest.anchor);
299
+ activeSignature = signature;
300
+ activeThreadId = context.threadId;
301
+ if (reopen) open(payload);
302
+ } catch {
303
+ removeActivePanel();
304
+ } finally {
305
+ activeRefreshPending = false;
306
+ }
307
+ };
308
+ const observer = new MutationObserver(scan); observer.observe(document.body || document.documentElement, { childList: true, subtree: true, characterData: true }); scan();
309
+ void refreshActiveTeam();
310
+ activeTimer = setInterval(() => void refreshActiveTeam(), 1500);
311
+ return { scan, close, dispose() { disposed = true; observer.disconnect(); if (activeTimer) clearInterval(activeTimer); activeTimer = null; removeActivePanel(); close(); style.remove(); document.removeEventListener('keydown', onKey); document.querySelectorAll('.harness-mix-team-panel').forEach(node => node.remove()); document.querySelectorAll<HTMLElement>('[data-harness-mix-team-display]').forEach(node => { node.style.display = node.dataset.harnessMixTeamDisplay === '__empty__' ? '' : node.dataset.harnessMixTeamDisplay ?? ''; delete node.dataset.harnessMixTeamDisplay; }); } };
312
+ }
@@ -23,7 +23,7 @@ function itemIdCount(node: Element): number {
23
23
 
24
24
  /**
25
25
  * Codex renders transcript text for the Command Execution lane only, and it is
26
- * the lane codexhost projects external Harness Reasoning through. This records
26
+ * the lane harnessmix projects external Harness Reasoning through. This records
27
27
  * bounded structural counts so a Desktop update that drops the lane, or stops
28
28
  * publishing Item ids, is detected instead of silently hiding projected text.
29
29
  */
@@ -14,8 +14,8 @@
14
14
  * cannot express, while each control still sets its own inline
15
15
  * height/padding/font-size to size itself.
16
16
  */
17
- const STYLE_ATTRIBUTE = "data-codexhost-trigger-chip-style";
18
- export const TRIGGER_CHIP_CLASS = "codexhost-trigger-chip";
17
+ const STYLE_ATTRIBUTE = "data-harnessmix-trigger-chip-style";
18
+ export const TRIGGER_CHIP_CLASS = "harnessmix-trigger-chip";
19
19
 
20
20
  export function ensureRendererTriggerChipStyle(ownerDocument: Document): void {
21
21
  if (ownerDocument.querySelector(`style[${STYLE_ATTRIBUTE}]`)) return;
@@ -1,4 +1,4 @@
1
- import type { ThreadUsageSnapshot } from "@codexhost/shared-contracts";
1
+ import type { ThreadUsageSnapshot } from "@harnessmix/shared-contracts";
2
2
 
3
3
  import type { RendererSettingsLocale } from "./settings/localization.js";
4
4
 
@@ -400,7 +400,7 @@ export function mountRendererUsageControl(
400
400
  const messages = rendererUsageMessages(locale);
401
401
 
402
402
  const root = document.createElement("div");
403
- root.dataset.codexhostUsageControl = composerId;
403
+ root.dataset.harnessmixUsageControl = composerId;
404
404
  root.className = "relative min-w-0";
405
405
  root.style.display = "none";
406
406
  root.style.alignItems = "center";
@@ -436,7 +436,7 @@ export function mountRendererUsageControl(
436
436
  trigger.style.letterSpacing = "0";
437
437
 
438
438
  const ringSlot = document.createElement("span");
439
- ringSlot.dataset.codexhostUsageRing = "";
439
+ ringSlot.dataset.harnessmixUsageRing = "";
440
440
  ringSlot.style.display = "inline-flex";
441
441
  ringSlot.style.flex = "0 0 auto";
442
442
  ringSlot.style.alignItems = "center";
@@ -567,7 +567,7 @@ export function renderRendererUsageControl(
567
567
  return false;
568
568
  }
569
569
 
570
- const ringSlot = control.trigger.querySelector<HTMLElement>("[data-codexhost-usage-ring]");
570
+ const ringSlot = control.trigger.querySelector<HTMLElement>("[data-harnessmix-usage-ring]");
571
571
  const contextPercent =
572
572
  usage?.contextUsagePercent !== undefined
573
573
  ? usage.contextUsagePercent
@@ -1,4 +1,4 @@
1
- import type { CodexAccountSummary } from "@codexhost/shared-contracts";
1
+ import type { CodexAccountSummary } from "@harnessmix/shared-contracts";
2
2
 
3
3
  import { codexAccountDisplayName } from "../renderer-codex-account-options.js";
4
4
  import {
@@ -15,7 +15,7 @@ import type {
15
15
  CodexAccountUsageResult,
16
16
  CodexAccountResetCreditConsumeParams,
17
17
  CodexAccountResetCreditConsumeResult,
18
- } from "@codexhost/shared-contracts";
18
+ } from "@harnessmix/shared-contracts";
19
19
 
20
20
  import {
21
21
  accountListFocusRestorer,
@@ -1,4 +1,4 @@
1
- import type { AccountCreditsSnapshot } from "@codexhost/shared-contracts";
1
+ import type { AccountCreditsSnapshot } from "@harnessmix/shared-contracts";
2
2
 
3
3
  import { formatRendererCreditsReset, rendererCreditsTone } from "../renderer-credits-control.js";
4
4
  import { formatRendererCreditsPercent } from "../renderer-usage-control.js";
@@ -1,4 +1,4 @@
1
- import type { CodexhostError, HarnessInspection } from "@codexhost/shared-contracts";
1
+ import type { HarnessMixError, HarnessInspection } from "@harnessmix/shared-contracts";
2
2
 
3
3
  import {
4
4
  getSharedAgentGroupPreferenceStore,
@@ -16,7 +16,7 @@ import type { RendererSettingsPageDefinition, RendererSettingsPageMountContext }
16
16
  import { createRendererSettingsIcon } from "./icons.js";
17
17
  import type { RendererSettingsMessages } from "./localization.js";
18
18
 
19
- export const CODEXHOST_GITHUB_ISSUES_NEW_URL =
19
+ export const HARNESSMIX_GITHUB_ISSUES_NEW_URL =
20
20
  "https://github.com/emo-xiaoyu/harness-mix/issues/new";
21
21
 
22
22
  export const HARNESS_INSTALL_COMMANDS: Readonly<Partial<Record<ExternalRendererAgent, { command: string }>>> = Object.freeze({
@@ -58,7 +58,7 @@ const HARNESS_INSTALL_URLS: Readonly<Record<ExternalRendererAgent, string>> = Ob
58
58
  export interface RendererConnectionAgentSnapshot {
59
59
  readonly agent: ExternalRendererAgent;
60
60
  readonly availability: RendererAgentAvailability;
61
- readonly error: CodexhostError | null;
61
+ readonly error: HarnessMixError | null;
62
62
  readonly webUiAvailable?: true;
63
63
  }
64
64
 
@@ -89,7 +89,7 @@ interface ConnectionListItem {
89
89
  readonly key: string;
90
90
  readonly name: string;
91
91
  readonly availability: ConnectionAvailability;
92
- readonly error: CodexhostError | null;
92
+ readonly error: HarnessMixError | null;
93
93
  readonly agentSnapshot?: RendererConnectionAgentSnapshot;
94
94
  readonly openWebUi?: () => Promise<void>;
95
95
  }
@@ -130,7 +130,7 @@ function diagnosticText(
130
130
  ): string {
131
131
  const error = item.error;
132
132
  return [
133
- "codexhost connection diagnostics",
133
+ "harnessmix connection diagnostics",
134
134
  `host: ${hostId}`,
135
135
  `agent: ${item.name}`,
136
136
  `status: ${item.availability}`,
@@ -841,7 +841,7 @@ function renderConnectionInspector(
841
841
  actions.className = "settings-connection-error-actions";
842
842
  const issue = document.createElement("a");
843
843
  issue.className = "settings-command-button settings-command-button--secondary";
844
- issue.href = CODEXHOST_GITHUB_ISSUES_NEW_URL;
844
+ issue.href = HARNESSMIX_GITHUB_ISSUES_NEW_URL;
845
845
  issue.target = "_blank";
846
846
  issue.rel = "noopener noreferrer";
847
847
  issue.append(messages.connectionOpenIssue, createRendererSettingsIcon("external-link", 14));
@@ -1095,7 +1095,7 @@ export function createConnectionsSettingsPage(
1095
1095
  tabs.setAttribute("role", "tablist");
1096
1096
  tabs.setAttribute("aria-label", messages.connectionHosts);
1097
1097
  const scrollRight = createHostScrollButton(document, "right", messages);
1098
- const panelId = "codexhost-settings-connection-host-panel";
1098
+ const panelId = "harnessmix-settings-connection-host-panel";
1099
1099
 
1100
1100
  snapshot.hosts.forEach((host, index) => {
1101
1101
  const tab = document.createElement("button");
@@ -1,4 +1,4 @@
1
- import type { HarnessAccountListResult } from "@codexhost/shared-contracts";
1
+ import type { HarnessAccountListResult } from "@harnessmix/shared-contracts";
2
2
  import { KNOWN_RENDERER_AGENTS } from "../agent-selection-state.js";
3
3
  import { createRendererAgentIcon } from "../renderer-agent-icon.js";
4
4
  import { createRendererSettingsIcon } from "./icons.js";
@@ -131,7 +131,7 @@ export function createRendererSettingsIcon(name: RendererSettingsIconName, size
131
131
  "aria-hidden": "true",
132
132
  focusable: "false",
133
133
  });
134
- icon.classList.add("codexhost-settings-icon");
134
+ icon.classList.add("harnessmix-settings-icon");
135
135
  return icon;
136
136
  }
137
137
 
@@ -148,6 +148,6 @@ export function createRendererSettingsBrandIcon(size = 22, ownerDocument?: Docum
148
148
  icon.style.width = `${size}px`;
149
149
  icon.style.height = `${size}px`;
150
150
  icon.style.objectFit = "contain";
151
- icon.classList.add("codexhost-settings-icon");
151
+ icon.classList.add("harnessmix-settings-icon");
152
152
  return icon;
153
153
  }
@@ -4,7 +4,7 @@ import type {
4
4
  UpdateStartResult,
5
5
  UpdateStatus,
6
6
  UpdateStatusResult,
7
- } from "@codexhost/shared-contracts";
7
+ } from "@harnessmix/shared-contracts";
8
8
 
9
9
  import {
10
10
  createRendererSettingsPageRegistry,
@@ -46,9 +46,9 @@ import {
46
46
  runBoundedRendererUpdateRequest,
47
47
  } from "./update-request.js";
48
48
 
49
- export const CODEXHOST_GITHUB_REPOSITORY_URL = "https://github.com/emo-xiaoyu/harness-mix";
50
- export const CODEXHOST_RELEASES_LATEST_URL = `${CODEXHOST_GITHUB_REPOSITORY_URL}/releases/latest`;
51
- export const CODEXHOST_NPM_MANUAL_UPDATE_COMMAND = "npm install -g harness-mix@latest";
49
+ export const HARNESSMIX_GITHUB_REPOSITORY_URL = "https://github.com/emo-xiaoyu/harness-mix";
50
+ export const HARNESSMIX_RELEASES_LATEST_URL = `${HARNESSMIX_GITHUB_REPOSITORY_URL}/releases/latest`;
51
+ export const HARNESSMIX_NPM_MANUAL_UPDATE_COMMAND = "npm install -g harness-mix@latest";
52
52
 
53
53
  interface RendererUserAgentData {
54
54
  readonly platform?: string;
@@ -198,7 +198,7 @@ export function aboutPage(
198
198
  checkUpdateBtn.className = "settings-command-button settings-command-button--secondary";
199
199
  checkUpdateBtn.append(createRendererSettingsIcon("updates", 14), messages.checkUpdateNow);
200
200
  checkUpdateBtn.addEventListener("click", () => {
201
- const shell = document.querySelector("[data-codexhost-settings-shell]");
201
+ const shell = document.querySelector("[data-harnessmix-settings-shell]");
202
202
  const updatesNavBtn = (shell?.shadowRoot ?? document).querySelector<HTMLButtonElement>(
203
203
  'button[data-page-id="updates"]',
204
204
  );
@@ -221,11 +221,11 @@ export function aboutPage(
221
221
  openSource.textContent = messages.aboutOpenSource;
222
222
  const repository = document.createElement("a");
223
223
  repository.className = "settings-about-repository-link";
224
- repository.href = CODEXHOST_GITHUB_REPOSITORY_URL;
224
+ repository.href = HARNESSMIX_GITHUB_REPOSITORY_URL;
225
225
  repository.target = "_blank";
226
226
  repository.rel = "noopener noreferrer";
227
227
  const repositoryUrl = document.createElement("code");
228
- repositoryUrl.textContent = CODEXHOST_GITHUB_REPOSITORY_URL;
228
+ repositoryUrl.textContent = HARNESSMIX_GITHUB_REPOSITORY_URL;
229
229
  repository.append(
230
230
  createRendererSettingsIcon("external-link", 14),
231
231
  messages.aboutRepository,
@@ -312,7 +312,7 @@ export function updatesPage(
312
312
  const manualNpmCommandRow = document.createElement("div");
313
313
  manualNpmCommandRow.className = "settings-update-command";
314
314
  const manualNpmCommand = document.createElement("code");
315
- manualNpmCommand.textContent = CODEXHOST_NPM_MANUAL_UPDATE_COMMAND;
315
+ manualNpmCommand.textContent = HARNESSMIX_NPM_MANUAL_UPDATE_COMMAND;
316
316
  const copyCommand = document.createElement("button");
317
317
  copyCommand.type = "button";
318
318
  copyCommand.className = "settings-update-command__copy";
@@ -330,7 +330,7 @@ export function updatesPage(
330
330
  restore(messages.updateCopyFailed);
331
331
  return;
332
332
  }
333
- void clipboard.writeText(CODEXHOST_NPM_MANUAL_UPDATE_COMMAND).then(
333
+ void clipboard.writeText(HARNESSMIX_NPM_MANUAL_UPDATE_COMMAND).then(
334
334
  () => restore(messages.updateCommandCopied),
335
335
  () => restore(messages.updateCopyFailed),
336
336
  );
@@ -347,7 +347,7 @@ export function updatesPage(
347
347
  manualWindowsInstallerActions.className = "settings-update-actions";
348
348
  const manualWindowsInstallerLink = document.createElement("a");
349
349
  manualWindowsInstallerLink.className = "settings-update-link";
350
- manualWindowsInstallerLink.href = CODEXHOST_RELEASES_LATEST_URL;
350
+ manualWindowsInstallerLink.href = HARNESSMIX_RELEASES_LATEST_URL;
351
351
  manualWindowsInstallerLink.target = "_blank";
352
352
  manualWindowsInstallerLink.rel = "noopener noreferrer";
353
353
  manualWindowsInstallerLink.append(
@@ -363,7 +363,7 @@ export function updatesPage(
363
363
  actions.className = "settings-update-actions";
364
364
  const releaseLink = document.createElement("a");
365
365
  releaseLink.className = "settings-update-link";
366
- releaseLink.href = CODEXHOST_RELEASES_LATEST_URL;
366
+ releaseLink.href = HARNESSMIX_RELEASES_LATEST_URL;
367
367
  releaseLink.target = "_blank";
368
368
  releaseLink.rel = "noopener noreferrer";
369
369
  releaseLink.append(
@@ -133,6 +133,15 @@
133
133
  border-color: rgba(16, 163, 127, 0.35);
134
134
  }
135
135
 
136
+ .pet-card[data-state="installing"] .pet-card__stage,
137
+ .pet-card[data-state="uninstalling"] .pet-card__stage {
138
+ opacity: 0.55;
139
+ }
140
+
141
+ .pet-card[data-state="failed"] {
142
+ border-color: rgba(239, 68, 68, 0.35);
143
+ }
144
+
136
145
  .pet-card__stage {
137
146
  position: relative;
138
147
  display: flex;
@@ -214,6 +223,30 @@
214
223
  border: 1px solid rgba(16, 163, 127, 0.3);
215
224
  }
216
225
 
226
+ .pet-card__badge--failed {
227
+ background: rgba(239, 68, 68, 0.15);
228
+ color: #f87171;
229
+ border: 1px solid rgba(239, 68, 68, 0.3);
230
+ }
231
+
232
+ .pet-card__status {
233
+ margin: 0 0 10px;
234
+ font-size: 11.5px;
235
+ color: var(--text-secondary, rgba(255, 255, 255, 0.6));
236
+ }
237
+
238
+ .pet-card__error {
239
+ margin: 0 0 10px;
240
+ padding: 6px 8px;
241
+ border-radius: 6px;
242
+ background: rgba(239, 68, 68, 0.08);
243
+ border: 1px solid rgba(239, 68, 68, 0.25);
244
+ color: #f87171;
245
+ font-size: 11.5px;
246
+ line-height: 1.4;
247
+ word-break: break-word;
248
+ }
249
+
217
250
  .pet-card__description {
218
251
  margin: 0 0 14px;
219
252
  font-size: 12px;