@harness-mix/cli 0.1.8 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +12 -0
- package/README.md +51 -43
- package/docs/harness-management.md +1 -1
- package/docs/native-acp.md +7 -2
- package/docs/task-handoff-design.md +65 -0
- package/licenses/codex-styler-Apache-2.0.txt +193 -0
- package/licenses/heige-codex-skin-studio-MIT.txt +22 -0
- package/output/native-build/desktop-controller.mjs +2 -1
- package/output/native-build/renderer-extension.js +651 -9
- package/package.json +188 -188
- package/scripts/acp-capabilities-probe.cjs +1 -0
- package/scripts/build-native.cjs +1 -1
- package/scripts/codex-adapter-test.cjs +44 -0
- package/scripts/collaboration-recovery-test.cjs +3 -0
- package/scripts/e2e-codex.cjs +3 -1
- package/scripts/e2e-native-acp.cjs +1 -1
- package/scripts/error-kind-test.cjs +107 -0
- package/scripts/handoff-checkpoint-test.cjs +38 -0
- package/scripts/integrations-test.cjs +5 -2
- package/scripts/kiro-cursor-adapters-test.cjs +18 -0
- package/scripts/native-acp-depth-test.cjs +1 -1
- package/scripts/native-protocol-test.cjs +60 -4
- package/scripts/native-ui-smoke.cjs +92 -2
- package/scripts/switch-harness-test.cjs +79 -12
- package/scripts/tool-concurrency-regression-test.cjs +8 -6
- package/src/assets/icons/cline-color.svg +1 -0
- package/src/assets/skins/codex-styler/ASSET_LICENSES.md +36 -0
- package/src/assets/skins/codex-styler/NOTICE +11 -0
- package/src/assets/skins/codex-styler/themes/gilded-grandeur/hero.webp +0 -0
- package/src/assets/skins/codex-styler/themes/merry-big-top/hero.webp +0 -0
- package/src/assets/skins/codex-styler/themes/nocturne-studio/hero.webp +0 -0
- package/src/assets/skins/codex-styler/themes/quiet-garden/hero.webp +0 -0
- package/src/assets/skins/heige/ASSET_PROVENANCE.md +56 -0
- package/src/assets/skins/heige/NOTICE.md +13 -0
- package/src/assets/skins/heige/themes/dalao-dianyan/hero.webp +0 -0
- package/src/assets/skins/heige/themes/dalao-dianyan/theme.json +14 -0
- package/src/assets/skins/heige/themes/deepspace-dawn/hero.webp +0 -0
- package/src/assets/skins/heige/themes/deepspace-dawn/theme.json +14 -0
- package/src/assets/skins/heige/themes/deepspace-star/hero.webp +0 -0
- package/src/assets/skins/heige/themes/deepspace-star/theme.json +14 -0
- package/src/assets/skins/heige/themes/dragonball-nimbus/hero.webp +0 -0
- package/src/assets/skins/heige/themes/dragonball-nimbus/theme.json +16 -0
- package/src/assets/skins/heige/themes/dragonball-super-saiyan/hero.webp +0 -0
- package/src/assets/skins/heige/themes/dragonball-super-saiyan/theme.json +16 -0
- package/src/assets/skins/heige/themes/genshin-dawn/hero.webp +0 -0
- package/src/assets/skins/heige/themes/genshin-dawn/theme.json +14 -0
- package/src/assets/skins/heige/themes/genshin-night/hero.webp +0 -0
- package/src/assets/skins/heige/themes/genshin-night/theme.json +14 -0
- package/src/assets/skins/heige/themes/miku-488137/hero.webp +0 -0
- package/src/assets/skins/heige/themes/miku-488137/logo.webp +0 -0
- package/src/assets/skins/heige/themes/miku-488137/polaroid.webp +0 -0
- package/src/assets/skins/heige/themes/miku-488137/theme.json +16 -0
- package/src/assets/skins/heige/themes/naruto-hokage/hero.webp +0 -0
- package/src/assets/skins/heige/themes/naruto-hokage/theme.json +14 -0
- package/src/assets/skins/heige/themes/naruto-sasuke/hero.webp +0 -0
- package/src/assets/skins/heige/themes/naruto-sasuke/theme.json +14 -0
- package/src/assets/skins/heige/themes/wuthering-echo/hero.webp +0 -0
- package/src/assets/skins/heige/themes/wuthering-echo/theme.json +14 -0
- package/src/assets/skins/heige/themes/wuthering-tide/hero.webp +0 -0
- package/src/assets/skins/heige/themes/wuthering-tide/theme.json +14 -0
- package/src/main/adapters/cline.js +22 -0
- package/src/main/adapters/codex.js +78 -8
- package/src/main/adapters/index.js +2 -1
- package/src/main/adapters/native-acp-command.js +1 -0
- package/src/main/harness-adapter/error-kind.js +82 -0
- package/src/main/harness-adapter/event-normalizer.js +7 -1
- package/src/main/host/core-session.js +1 -1
- package/src/main/host/handoff-access.js +23 -4
- package/src/main/host/handoff-checkpoints.js +9 -2
- package/src/main/host/handoff-tools.js +3 -0
- package/src/main/host/handoff.js +11 -2
- package/src/main/host/runtime.js +272 -163
- package/src/main/host/session-history.js +54 -15
- package/src/main/native/icons.js +3 -2
- package/src/main/native/pets.js +234 -0
- package/src/main/native/protocol.js +197 -56
- package/src/main/protocol-core/projector.js +44 -41
- package/src/native-ui/desktop-control/dist/production-controller.d.ts.map +1 -1
- package/src/native-ui/desktop-control/dist/production-controller.js +1 -0
- package/src/native-ui/desktop-control/dist/production-controller.js.map +1 -1
- package/src/native-ui/desktop-control/dist/tsconfig.tsbuildinfo +1 -1
- package/src/native-ui/desktop-control/src/production-controller.ts +1 -0
- package/src/native-ui/desktop-control/test/production-controller.test.ts +1 -0
- package/src/native-ui/renderer-extension/dist/types/agent-selection-state.d.ts +4 -2
- package/src/native-ui/renderer-extension/dist/types/agent-selection-state.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-agent-icon.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-agent-picker.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-binding-probe.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-harness-mentions.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-settings-lifecycle.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/renderer-sidebar-agent-icons.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/connections-page.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/icons.d.ts +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/icons.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/localization.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/pages.d.ts +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/pages.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/shell.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/dist/types/settings/skin-market.d.ts +4 -0
- package/src/native-ui/renderer-extension/dist/types/settings/skin-market.d.ts.map +1 -0
- package/src/native-ui/renderer-extension/dist/types/settings/skin-runtime.d.ts +31 -0
- package/src/native-ui/renderer-extension/dist/types/settings/skin-runtime.d.ts.map +1 -0
- package/src/native-ui/renderer-extension/dist/types/tsconfig.tsbuildinfo +1 -1
- package/src/native-ui/renderer-extension/dist/types/versioned-renderer-adapter.d.ts.map +1 -1
- package/src/native-ui/renderer-extension/package.json +1 -1
- package/src/native-ui/renderer-extension/src/agent-selection-state.ts +16 -0
- package/src/native-ui/renderer-extension/src/assets.d.ts +5 -0
- package/src/native-ui/renderer-extension/src/renderer-agent-icon.ts +5 -4
- package/src/native-ui/renderer-extension/src/renderer-agent-picker.ts +1 -0
- package/src/native-ui/renderer-extension/src/renderer-binding-probe.ts +9 -6
- package/src/native-ui/renderer-extension/src/renderer-harness-handoff.ts +2 -2
- package/src/native-ui/renderer-extension/src/renderer-harness-mentions.ts +2 -0
- package/src/native-ui/renderer-extension/src/renderer-settings-lifecycle.ts +2 -0
- package/src/native-ui/renderer-extension/src/renderer-sidebar-agent-icons.ts +1 -0
- package/src/native-ui/renderer-extension/src/settings/connections-page.ts +2 -0
- package/src/native-ui/renderer-extension/src/settings/icons.ts +6 -0
- package/src/native-ui/renderer-extension/src/settings/localization.ts +4 -2
- package/src/native-ui/renderer-extension/src/settings/pages.ts +5 -2
- package/src/native-ui/renderer-extension/src/settings/shell.ts +3 -2
- package/src/native-ui/renderer-extension/src/settings/skin-market.css +213 -0
- package/src/native-ui/renderer-extension/src/settings/skin-market.ts +174 -0
- package/src/native-ui/renderer-extension/src/settings/skin-runtime.ts +399 -0
- package/src/native-ui/renderer-extension/src/versioned-renderer-adapter.ts +2 -1
- package/src/native-ui/renderer-extension/test/settings/localization.test.ts +11 -1
- package/src/native-ui/renderer-extension/test/settings/shell.test.ts +3 -0
- package/src/native-ui/renderer-extension/test/settings/skin-runtime.test.ts +136 -0
- package/src/native-ui/shared-contracts/dist/thread-harness-switch.d.ts +7 -0
- package/src/native-ui/shared-contracts/dist/thread-harness-switch.d.ts.map +1 -1
- package/src/native-ui/shared-contracts/dist/thread-harness-switch.js +3 -0
- package/src/native-ui/shared-contracts/dist/thread-harness-switch.js.map +1 -1
- package/src/native-ui/shared-contracts/dist/tsconfig.tsbuildinfo +1 -1
- package/src/native-ui/shared-contracts/src/thread-harness-switch.ts +3 -0
package/package.json
CHANGED
|
@@ -1,188 +1,188 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@harness-mix/cli",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"license": "Apache-2.0",
|
|
5
|
-
"description": "Harness Mix native Codex UI bridge for Codex, Pi, Claude Code, DeepSeek Harness, Antigravity, CodeBuddy, Kiro CLI, Cursor CLI and other native coding harnesses.",
|
|
6
|
-
"keywords": [
|
|
7
|
-
"codex",
|
|
8
|
-
"codex-desktop",
|
|
9
|
-
"coding-agent",
|
|
10
|
-
"harness",
|
|
11
|
-
"pi",
|
|
12
|
-
"claude-code",
|
|
13
|
-
"deepseek",
|
|
14
|
-
"antigravity",
|
|
15
|
-
"codebuddy",
|
|
16
|
-
"kiro",
|
|
17
|
-
"cursor",
|
|
18
|
-
"qoder",
|
|
19
|
-
"zcode",
|
|
20
|
-
"trae",
|
|
21
|
-
"ai"
|
|
22
|
-
],
|
|
23
|
-
"homepage": "https://github.com/emo-xiaoyu/harness-mix#readme",
|
|
24
|
-
"bugs": "https://github.com/emo-xiaoyu/harness-mix/issues",
|
|
25
|
-
"repository": {
|
|
26
|
-
"type": "git",
|
|
27
|
-
"url": "git+https://github.com/emo-xiaoyu/harness-mix.git"
|
|
28
|
-
},
|
|
29
|
-
"bin": {
|
|
30
|
-
"harness-mix": "scripts/launch-codex.cjs"
|
|
31
|
-
},
|
|
32
|
-
"publishConfig": {
|
|
33
|
-
"access": "public",
|
|
34
|
-
"registry": "https://registry.npmjs.org"
|
|
35
|
-
},
|
|
36
|
-
"postinstall": "node scripts/install-native.cjs",
|
|
37
|
-
"files": [
|
|
38
|
-
"CHANGELOG.md",
|
|
39
|
-
"src",
|
|
40
|
-
"scripts",
|
|
41
|
-
"config",
|
|
42
|
-
"docs",
|
|
43
|
-
"licenses",
|
|
44
|
-
"NOTICE",
|
|
45
|
-
"Start-Codex.cmd",
|
|
46
|
-
"output/native-build/harness-mix-shim.exe",
|
|
47
|
-
"output/native-build/harness-mix-appx.exe",
|
|
48
|
-
"output/native-build/harness-mix-secret.exe",
|
|
49
|
-
"output/native-build/desktop-controller.mjs",
|
|
50
|
-
"output/native-build/renderer-extension.js",
|
|
51
|
-
"!src/main/native/rs/target",
|
|
52
|
-
"!**/*.log",
|
|
53
|
-
"output/native-build/harness-mix-shim"
|
|
54
|
-
],
|
|
55
|
-
"os": [
|
|
56
|
-
"win32",
|
|
57
|
-
"darwin",
|
|
58
|
-
"linux"
|
|
59
|
-
],
|
|
60
|
-
"cpu": [
|
|
61
|
-
"x64",
|
|
62
|
-
"arm64"
|
|
63
|
-
],
|
|
64
|
-
"workspaces": [
|
|
65
|
-
"src/native-ui/shared-contracts",
|
|
66
|
-
"src/native-ui/desktop-control",
|
|
67
|
-
"src/native-ui/renderer-extension"
|
|
68
|
-
],
|
|
69
|
-
"engines": {
|
|
70
|
-
"node": ">=22.19.0 <23 || >=24 <25"
|
|
71
|
-
},
|
|
72
|
-
"scripts": {
|
|
73
|
-
"test:integrations": "node scripts/integrations-test.cjs",
|
|
74
|
-
"smoke:integrations-ui": "electron scripts/integrations-ui-smoke.cjs",
|
|
75
|
-
"e2e:integrations": "node scripts/e2e-integrations.cjs",
|
|
76
|
-
"health:harnesses": "node scripts/harness-health-check.cjs",
|
|
77
|
-
"test:dsh-collaboration-acp": "node scripts/dsh-collaboration-acp-test.cjs",
|
|
78
|
-
"test:codebuddy-migration": "node scripts/codebuddy-migration-test.cjs",
|
|
79
|
-
"e2e:native-acp": "node scripts/e2e-native-acp.cjs --live",
|
|
80
|
-
"test:native-acp-depth": "node scripts/native-acp-depth-test.cjs",
|
|
81
|
-
"test:kiro-cursor": "node scripts/kiro-cursor-adapters-test.cjs",
|
|
82
|
-
"test:docs": "node scripts/docs-command-test.cjs",
|
|
83
|
-
"typecheck:native-ui": "tsc -b src/native-ui/shared-contracts/tsconfig.json src/native-ui/desktop-control/tsconfig.json src/native-ui/renderer-extension/tsconfig.json --pretty false",
|
|
84
|
-
"test:native-ui": "vitest run --config vitest.config.mjs",
|
|
85
|
-
"test:ci": "npm run test:docs && npm run check && npm run typecheck:native-ui && npm run test:native-ui && npm run test:core-all && npm run test:native-protocol && npm run test:native-compatibility && npm run test:platform",
|
|
86
|
-
"test:storage-verification": "node scripts/storage-verification-test.cjs",
|
|
87
|
-
"test:collaboration": "node scripts/collaboration-test.cjs",
|
|
88
|
-
"test:switch-harness": "node scripts/switch-harness-test.cjs",
|
|
89
|
-
"smoke:collaboration-ui": "electron scripts/collaboration-ui-smoke.cjs",
|
|
90
|
-
"smoke:chatgpt-context-ui": "electron scripts/chatgpt-context-ui-smoke.cjs",
|
|
91
|
-
"e2e:collaboration": "node scripts/e2e-collaboration.cjs",
|
|
92
|
-
"test:native-rollback": "node scripts/native-rollback-test.cjs",
|
|
93
|
-
"test:native-images": "node scripts/native-images-test.cjs",
|
|
94
|
-
"build:native": "node scripts/build-native.cjs",
|
|
95
|
-
"test:native-protocol": "node scripts/native-protocol-test.cjs",
|
|
96
|
-
"test:native-sidebar": "node scripts/native-sidebar-test.cjs",
|
|
97
|
-
"smoke:native-ui": "electron scripts/native-ui-smoke.cjs",
|
|
98
|
-
"start": "node scripts/launch-codex.cjs",
|
|
99
|
-
"prepublishOnly": "npm run check && npm run test:core-all && npm run build:native",
|
|
100
|
-
"check:native": "node scripts/launch-codex.cjs --check",
|
|
101
|
-
"test:native-config": "node scripts/native-config-test.cjs",
|
|
102
|
-
"test:native-compatibility": "node scripts/native-compatibility-test.cjs",
|
|
103
|
-
"e2e:native": "node scripts/e2e-native-host.cjs",
|
|
104
|
-
"e2e:native:codex": "node scripts/e2e-native-host.cjs --live-codex",
|
|
105
|
-
"e2e:native:pi": "node scripts/e2e-native-host.cjs --live --harness=pi",
|
|
106
|
-
"e2e:native:dsh": "node scripts/e2e-native-host.cjs --live --harness=deepseek-harness",
|
|
107
|
-
"e2e:native:claude": "node scripts/e2e-native-host.cjs --live --harness=claude-code",
|
|
108
|
-
"start:codex": "node scripts/launch-codex.cjs",
|
|
109
|
-
"check": "node scripts/check.cjs",
|
|
110
|
-
"test:contracts": "node scripts/contracts-test.cjs",
|
|
111
|
-
"test:projector": "node scripts/projector-test.cjs",
|
|
112
|
-
"test:turn": "node scripts/turn-manager-test.cjs",
|
|
113
|
-
"test:sequence": "node scripts/sequence-test.cjs",
|
|
114
|
-
"test:shadow": "node scripts/shadow-test.cjs",
|
|
115
|
-
"test:arch": "node scripts/architecture-test.cjs",
|
|
116
|
-
"test:core-replay": "node scripts/core-replay-test.cjs",
|
|
117
|
-
"test:adapters": "node scripts/adapters-test.cjs",
|
|
118
|
-
"test:dsh-adapter": "node scripts/dsh-adapter-test.cjs",
|
|
119
|
-
"test:codex-adapter": "node scripts/codex-adapter-test.cjs",
|
|
120
|
-
"test:antigravity-adapter": "node scripts/antigravity-adapter-test.cjs",
|
|
121
|
-
"test:openclaw-adapter": "node scripts/openclaw-adapter-test.cjs",
|
|
122
|
-
"test:core-concurrency": "node scripts/core-concurrency-test.cjs",
|
|
123
|
-
"test:thread-title": "node scripts/thread-title-test.cjs",
|
|
124
|
-
"test:handoff": "node scripts/handoff-checkpoint-test.cjs && node scripts/switch-harness-test.cjs",
|
|
125
|
-
"test:core-all": "node scripts/contracts-test.cjs && node scripts/projector-test.cjs && node scripts/turn-manager-test.cjs && node scripts/sequence-test.cjs && node scripts/shadow-test.cjs && node scripts/architecture-test.cjs && node scripts/adapters-test.cjs && node scripts/dsh-adapter-test.cjs && node scripts/codex-adapter-test.cjs && node scripts/codex-accounts-test.cjs && node scripts/antigravity-adapter-test.cjs && node scripts/openclaw-adapter-test.cjs && node scripts/core-replay-test.cjs && node scripts/determinism-test.cjs && node scripts/core-runtime-test.cjs && node scripts/core-services-test.cjs && node scripts/native-file-change-test.cjs && node scripts/native-updater-test.cjs && node scripts/native-update-apply-test.cjs && node scripts/native-vendor-adapters-test.cjs && node scripts/core-concurrency-test.cjs && node scripts/concurrency-layers-test.cjs && node scripts/tool-concurrency-regression-test.cjs && node scripts/handoff-checkpoint-test.cjs && node scripts/switch-harness-test.cjs && node scripts/native-acp-depth-test.cjs && node scripts/thread-title-test.cjs && node scripts/native-job-object-test.cjs && node scripts/integrations-test.cjs && node scripts/storage-verification-test.cjs",
|
|
126
|
-
"test:codex-accounts": "node scripts/codex-accounts-test.cjs",
|
|
127
|
-
"smoke:codex-accounts-ui": "electron scripts/codex-accounts-ui-smoke.cjs",
|
|
128
|
-
"test:transcript": "node scripts/transcript-test.cjs",
|
|
129
|
-
"test:workspace": "node scripts/workspace-test.cjs",
|
|
130
|
-
"e2e:pi": "node scripts/e2e-pi.cjs",
|
|
131
|
-
"e2e:shadow-pi": "node scripts/e2e-shadow.cjs pi",
|
|
132
|
-
"e2e:shadow-claude": "node scripts/e2e-shadow.cjs claude",
|
|
133
|
-
"e2e:shadow-dsh": "node scripts/e2e-shadow.cjs dsh",
|
|
134
|
-
"e2e:dsh": "node scripts/e2e-dsh.cjs",
|
|
135
|
-
"e2e:openclaw": "node scripts/e2e-openclaw.cjs",
|
|
136
|
-
"e2e:openclaw:image": "node scripts/e2e-openclaw-image.cjs",
|
|
137
|
-
"e2e:codex": "node scripts/e2e-codex.cjs",
|
|
138
|
-
"e2e:delegate": "node scripts/e2e-delegate.cjs",
|
|
139
|
-
"test:determinism": "node scripts/determinism-test.cjs",
|
|
140
|
-
"test:core-runtime": "node scripts/core-runtime-test.cjs",
|
|
141
|
-
"e2e:core-pi": "node scripts/e2e-core-resume.cjs pi",
|
|
142
|
-
"e2e:core-claude": "node scripts/e2e-core-resume.cjs claude",
|
|
143
|
-
"e2e:core-dsh": "node scripts/e2e-core-resume.cjs dsh",
|
|
144
|
-
"e2e:core-openclaw": "node scripts/e2e-core-resume.cjs openclaw",
|
|
145
|
-
"test:services": "node scripts/core-services-test.cjs",
|
|
146
|
-
"e2e:core-fork": "node scripts/e2e-core-fork.cjs",
|
|
147
|
-
"e2e:commands-pi": "node scripts/e2e-native-commands.cjs pi",
|
|
148
|
-
"e2e:commands-claude": "node scripts/e2e-native-commands.cjs claude",
|
|
149
|
-
"test:core": "npm run test:core-all",
|
|
150
|
-
"test:interactions": "node scripts/core-services-test.cjs",
|
|
151
|
-
"test:native-files": "node scripts/native-file-change-test.cjs",
|
|
152
|
-
"e2e:core-files": "node scripts/e2e-core-files.cjs",
|
|
153
|
-
"e2e:claude": "node scripts/e2e-core-resume.cjs claude",
|
|
154
|
-
"update": "node scripts/launch-codex.cjs --update",
|
|
155
|
-
"test:native-updater": "node scripts/native-updater-test.cjs",
|
|
156
|
-
"test:native-update-apply": "node scripts/native-update-apply-test.cjs",
|
|
157
|
-
"test:native-job-object": "node scripts/native-job-object-test.cjs",
|
|
158
|
-
"test:native-secret": "node scripts/native-secret-test.cjs",
|
|
159
|
-
"diagnostics": "node scripts/diagnostics.cjs",
|
|
160
|
-
"test:native-vendors": "node scripts/native-vendor-adapters-test.cjs",
|
|
161
|
-
"test:collaboration-recovery": "node scripts/collaboration-recovery-test.cjs",
|
|
162
|
-
"test:tool-concurrency": "node scripts/tool-concurrency-regression-test.cjs",
|
|
163
|
-
"test:platform": "node scripts/platform-test.cjs",
|
|
164
|
-
"test:shim": "node scripts/native-shim-test.cjs",
|
|
165
|
-
"publish:native": "node scripts/publish-native-package.cjs"
|
|
166
|
-
},
|
|
167
|
-
"devDependencies": {
|
|
168
|
-
"@types/node": "24.13.3",
|
|
169
|
-
"electron": "^43.3.0",
|
|
170
|
-
"esbuild": "0.28.1",
|
|
171
|
-
"typescript": "6.0.3",
|
|
172
|
-
"vitest": "4.1.10"
|
|
173
|
-
},
|
|
174
|
-
"dependencies": {
|
|
175
|
-
"@anthropic-ai/claude-agent-sdk": "0.3.263",
|
|
176
|
-
"@deepseek-ai/dsh": "0.1.2-rc.1",
|
|
177
|
-
"lucide": "1.28.0",
|
|
178
|
-
"zod": "4.4.3"
|
|
179
|
-
},
|
|
180
|
-
"optionalDependencies": {
|
|
181
|
-
"@harness-mix/native-win32-x64": "0.1.6",
|
|
182
|
-
"@harness-mix/native-win32-arm64": "0.1.6",
|
|
183
|
-
"@harness-mix/native-darwin-x64": "0.1.6",
|
|
184
|
-
"@harness-mix/native-darwin-arm64": "0.1.6",
|
|
185
|
-
"@harness-mix/native-linux-x64": "0.1.6",
|
|
186
|
-
"@harness-mix/native-linux-arm64": "0.1.6"
|
|
187
|
-
}
|
|
188
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@harness-mix/cli",
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"description": "Harness Mix native Codex UI bridge for Codex, Pi, Claude Code, DeepSeek Harness, Antigravity, CodeBuddy, Kiro CLI, Cursor CLI and other native coding harnesses.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"codex",
|
|
8
|
+
"codex-desktop",
|
|
9
|
+
"coding-agent",
|
|
10
|
+
"harness",
|
|
11
|
+
"pi",
|
|
12
|
+
"claude-code",
|
|
13
|
+
"deepseek",
|
|
14
|
+
"antigravity",
|
|
15
|
+
"codebuddy",
|
|
16
|
+
"kiro",
|
|
17
|
+
"cursor",
|
|
18
|
+
"qoder",
|
|
19
|
+
"zcode",
|
|
20
|
+
"trae",
|
|
21
|
+
"ai"
|
|
22
|
+
],
|
|
23
|
+
"homepage": "https://github.com/emo-xiaoyu/harness-mix#readme",
|
|
24
|
+
"bugs": "https://github.com/emo-xiaoyu/harness-mix/issues",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/emo-xiaoyu/harness-mix.git"
|
|
28
|
+
},
|
|
29
|
+
"bin": {
|
|
30
|
+
"harness-mix": "scripts/launch-codex.cjs"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public",
|
|
34
|
+
"registry": "https://registry.npmjs.org"
|
|
35
|
+
},
|
|
36
|
+
"postinstall": "node scripts/install-native.cjs",
|
|
37
|
+
"files": [
|
|
38
|
+
"CHANGELOG.md",
|
|
39
|
+
"src",
|
|
40
|
+
"scripts",
|
|
41
|
+
"config",
|
|
42
|
+
"docs",
|
|
43
|
+
"licenses",
|
|
44
|
+
"NOTICE",
|
|
45
|
+
"Start-Codex.cmd",
|
|
46
|
+
"output/native-build/harness-mix-shim.exe",
|
|
47
|
+
"output/native-build/harness-mix-appx.exe",
|
|
48
|
+
"output/native-build/harness-mix-secret.exe",
|
|
49
|
+
"output/native-build/desktop-controller.mjs",
|
|
50
|
+
"output/native-build/renderer-extension.js",
|
|
51
|
+
"!src/main/native/rs/target",
|
|
52
|
+
"!**/*.log",
|
|
53
|
+
"output/native-build/harness-mix-shim"
|
|
54
|
+
],
|
|
55
|
+
"os": [
|
|
56
|
+
"win32",
|
|
57
|
+
"darwin",
|
|
58
|
+
"linux"
|
|
59
|
+
],
|
|
60
|
+
"cpu": [
|
|
61
|
+
"x64",
|
|
62
|
+
"arm64"
|
|
63
|
+
],
|
|
64
|
+
"workspaces": [
|
|
65
|
+
"src/native-ui/shared-contracts",
|
|
66
|
+
"src/native-ui/desktop-control",
|
|
67
|
+
"src/native-ui/renderer-extension"
|
|
68
|
+
],
|
|
69
|
+
"engines": {
|
|
70
|
+
"node": ">=22.19.0 <23 || >=24 <25"
|
|
71
|
+
},
|
|
72
|
+
"scripts": {
|
|
73
|
+
"test:integrations": "node scripts/integrations-test.cjs",
|
|
74
|
+
"smoke:integrations-ui": "electron scripts/integrations-ui-smoke.cjs",
|
|
75
|
+
"e2e:integrations": "node scripts/e2e-integrations.cjs",
|
|
76
|
+
"health:harnesses": "node scripts/harness-health-check.cjs",
|
|
77
|
+
"test:dsh-collaboration-acp": "node scripts/dsh-collaboration-acp-test.cjs",
|
|
78
|
+
"test:codebuddy-migration": "node scripts/codebuddy-migration-test.cjs",
|
|
79
|
+
"e2e:native-acp": "node scripts/e2e-native-acp.cjs --live",
|
|
80
|
+
"test:native-acp-depth": "node scripts/native-acp-depth-test.cjs",
|
|
81
|
+
"test:kiro-cursor": "node scripts/kiro-cursor-adapters-test.cjs",
|
|
82
|
+
"test:docs": "node scripts/docs-command-test.cjs",
|
|
83
|
+
"typecheck:native-ui": "tsc -b src/native-ui/shared-contracts/tsconfig.json src/native-ui/desktop-control/tsconfig.json src/native-ui/renderer-extension/tsconfig.json --pretty false",
|
|
84
|
+
"test:native-ui": "vitest run --config vitest.config.mjs",
|
|
85
|
+
"test:ci": "npm run test:docs && npm run check && npm run typecheck:native-ui && npm run test:native-ui && npm run test:core-all && npm run test:native-protocol && npm run test:native-compatibility && npm run test:platform",
|
|
86
|
+
"test:storage-verification": "node scripts/storage-verification-test.cjs",
|
|
87
|
+
"test:collaboration": "node scripts/collaboration-test.cjs",
|
|
88
|
+
"test:switch-harness": "node scripts/switch-harness-test.cjs",
|
|
89
|
+
"smoke:collaboration-ui": "electron scripts/collaboration-ui-smoke.cjs",
|
|
90
|
+
"smoke:chatgpt-context-ui": "electron scripts/chatgpt-context-ui-smoke.cjs",
|
|
91
|
+
"e2e:collaboration": "node scripts/e2e-collaboration.cjs",
|
|
92
|
+
"test:native-rollback": "node scripts/native-rollback-test.cjs",
|
|
93
|
+
"test:native-images": "node scripts/native-images-test.cjs",
|
|
94
|
+
"build:native": "node scripts/build-native.cjs",
|
|
95
|
+
"test:native-protocol": "node scripts/native-protocol-test.cjs",
|
|
96
|
+
"test:native-sidebar": "node scripts/native-sidebar-test.cjs",
|
|
97
|
+
"smoke:native-ui": "electron scripts/native-ui-smoke.cjs",
|
|
98
|
+
"start": "node scripts/launch-codex.cjs",
|
|
99
|
+
"prepublishOnly": "npm run check && npm run test:core-all && npm run build:native",
|
|
100
|
+
"check:native": "node scripts/launch-codex.cjs --check",
|
|
101
|
+
"test:native-config": "node scripts/native-config-test.cjs",
|
|
102
|
+
"test:native-compatibility": "node scripts/native-compatibility-test.cjs",
|
|
103
|
+
"e2e:native": "node scripts/e2e-native-host.cjs",
|
|
104
|
+
"e2e:native:codex": "node scripts/e2e-native-host.cjs --live-codex",
|
|
105
|
+
"e2e:native:pi": "node scripts/e2e-native-host.cjs --live --harness=pi",
|
|
106
|
+
"e2e:native:dsh": "node scripts/e2e-native-host.cjs --live --harness=deepseek-harness",
|
|
107
|
+
"e2e:native:claude": "node scripts/e2e-native-host.cjs --live --harness=claude-code",
|
|
108
|
+
"start:codex": "node scripts/launch-codex.cjs",
|
|
109
|
+
"check": "node scripts/check.cjs",
|
|
110
|
+
"test:contracts": "node scripts/contracts-test.cjs",
|
|
111
|
+
"test:projector": "node scripts/projector-test.cjs",
|
|
112
|
+
"test:turn": "node scripts/turn-manager-test.cjs",
|
|
113
|
+
"test:sequence": "node scripts/sequence-test.cjs",
|
|
114
|
+
"test:shadow": "node scripts/shadow-test.cjs",
|
|
115
|
+
"test:arch": "node scripts/architecture-test.cjs",
|
|
116
|
+
"test:core-replay": "node scripts/core-replay-test.cjs",
|
|
117
|
+
"test:adapters": "node scripts/adapters-test.cjs",
|
|
118
|
+
"test:dsh-adapter": "node scripts/dsh-adapter-test.cjs",
|
|
119
|
+
"test:codex-adapter": "node scripts/codex-adapter-test.cjs",
|
|
120
|
+
"test:antigravity-adapter": "node scripts/antigravity-adapter-test.cjs",
|
|
121
|
+
"test:openclaw-adapter": "node scripts/openclaw-adapter-test.cjs",
|
|
122
|
+
"test:core-concurrency": "node scripts/core-concurrency-test.cjs",
|
|
123
|
+
"test:thread-title": "node scripts/thread-title-test.cjs",
|
|
124
|
+
"test:handoff": "node scripts/handoff-checkpoint-test.cjs && node scripts/switch-harness-test.cjs",
|
|
125
|
+
"test:core-all": "node scripts/contracts-test.cjs && node scripts/projector-test.cjs && node scripts/turn-manager-test.cjs && node scripts/sequence-test.cjs && node scripts/shadow-test.cjs && node scripts/architecture-test.cjs && node scripts/adapters-test.cjs && node scripts/dsh-adapter-test.cjs && node scripts/codex-adapter-test.cjs && node scripts/codex-accounts-test.cjs && node scripts/antigravity-adapter-test.cjs && node scripts/openclaw-adapter-test.cjs && node scripts/core-replay-test.cjs && node scripts/determinism-test.cjs && node scripts/core-runtime-test.cjs && node scripts/core-services-test.cjs && node scripts/native-file-change-test.cjs && node scripts/native-updater-test.cjs && node scripts/native-update-apply-test.cjs && node scripts/native-vendor-adapters-test.cjs && node scripts/core-concurrency-test.cjs && node scripts/concurrency-layers-test.cjs && node scripts/tool-concurrency-regression-test.cjs && node scripts/handoff-checkpoint-test.cjs && node scripts/switch-harness-test.cjs && node scripts/native-acp-depth-test.cjs && node scripts/thread-title-test.cjs && node scripts/native-job-object-test.cjs && node scripts/integrations-test.cjs && node scripts/storage-verification-test.cjs",
|
|
126
|
+
"test:codex-accounts": "node scripts/codex-accounts-test.cjs",
|
|
127
|
+
"smoke:codex-accounts-ui": "electron scripts/codex-accounts-ui-smoke.cjs",
|
|
128
|
+
"test:transcript": "node scripts/transcript-test.cjs",
|
|
129
|
+
"test:workspace": "node scripts/workspace-test.cjs",
|
|
130
|
+
"e2e:pi": "node scripts/e2e-pi.cjs",
|
|
131
|
+
"e2e:shadow-pi": "node scripts/e2e-shadow.cjs pi",
|
|
132
|
+
"e2e:shadow-claude": "node scripts/e2e-shadow.cjs claude",
|
|
133
|
+
"e2e:shadow-dsh": "node scripts/e2e-shadow.cjs dsh",
|
|
134
|
+
"e2e:dsh": "node scripts/e2e-dsh.cjs",
|
|
135
|
+
"e2e:openclaw": "node scripts/e2e-openclaw.cjs",
|
|
136
|
+
"e2e:openclaw:image": "node scripts/e2e-openclaw-image.cjs",
|
|
137
|
+
"e2e:codex": "node scripts/e2e-codex.cjs",
|
|
138
|
+
"e2e:delegate": "node scripts/e2e-delegate.cjs",
|
|
139
|
+
"test:determinism": "node scripts/determinism-test.cjs",
|
|
140
|
+
"test:core-runtime": "node scripts/core-runtime-test.cjs",
|
|
141
|
+
"e2e:core-pi": "node scripts/e2e-core-resume.cjs pi",
|
|
142
|
+
"e2e:core-claude": "node scripts/e2e-core-resume.cjs claude",
|
|
143
|
+
"e2e:core-dsh": "node scripts/e2e-core-resume.cjs dsh",
|
|
144
|
+
"e2e:core-openclaw": "node scripts/e2e-core-resume.cjs openclaw",
|
|
145
|
+
"test:services": "node scripts/core-services-test.cjs",
|
|
146
|
+
"e2e:core-fork": "node scripts/e2e-core-fork.cjs",
|
|
147
|
+
"e2e:commands-pi": "node scripts/e2e-native-commands.cjs pi",
|
|
148
|
+
"e2e:commands-claude": "node scripts/e2e-native-commands.cjs claude",
|
|
149
|
+
"test:core": "npm run test:core-all",
|
|
150
|
+
"test:interactions": "node scripts/core-services-test.cjs",
|
|
151
|
+
"test:native-files": "node scripts/native-file-change-test.cjs",
|
|
152
|
+
"e2e:core-files": "node scripts/e2e-core-files.cjs",
|
|
153
|
+
"e2e:claude": "node scripts/e2e-core-resume.cjs claude",
|
|
154
|
+
"update": "node scripts/launch-codex.cjs --update",
|
|
155
|
+
"test:native-updater": "node scripts/native-updater-test.cjs",
|
|
156
|
+
"test:native-update-apply": "node scripts/native-update-apply-test.cjs",
|
|
157
|
+
"test:native-job-object": "node scripts/native-job-object-test.cjs",
|
|
158
|
+
"test:native-secret": "node scripts/native-secret-test.cjs",
|
|
159
|
+
"diagnostics": "node scripts/diagnostics.cjs",
|
|
160
|
+
"test:native-vendors": "node scripts/native-vendor-adapters-test.cjs",
|
|
161
|
+
"test:collaboration-recovery": "node scripts/collaboration-recovery-test.cjs",
|
|
162
|
+
"test:tool-concurrency": "node scripts/tool-concurrency-regression-test.cjs",
|
|
163
|
+
"test:platform": "node scripts/platform-test.cjs",
|
|
164
|
+
"test:shim": "node scripts/native-shim-test.cjs",
|
|
165
|
+
"publish:native": "node scripts/publish-native-package.cjs"
|
|
166
|
+
},
|
|
167
|
+
"devDependencies": {
|
|
168
|
+
"@types/node": "24.13.3",
|
|
169
|
+
"electron": "^43.3.0",
|
|
170
|
+
"esbuild": "0.28.1",
|
|
171
|
+
"typescript": "6.0.3",
|
|
172
|
+
"vitest": "4.1.10"
|
|
173
|
+
},
|
|
174
|
+
"dependencies": {
|
|
175
|
+
"@anthropic-ai/claude-agent-sdk": "0.3.263",
|
|
176
|
+
"@deepseek-ai/dsh": "0.1.2-rc.1",
|
|
177
|
+
"lucide": "1.28.0",
|
|
178
|
+
"zod": "4.4.3"
|
|
179
|
+
},
|
|
180
|
+
"optionalDependencies": {
|
|
181
|
+
"@harness-mix/native-win32-x64": "0.1.6",
|
|
182
|
+
"@harness-mix/native-win32-arm64": "0.1.6",
|
|
183
|
+
"@harness-mix/native-darwin-x64": "0.1.6",
|
|
184
|
+
"@harness-mix/native-darwin-arm64": "0.1.6",
|
|
185
|
+
"@harness-mix/native-linux-x64": "0.1.6",
|
|
186
|
+
"@harness-mix/native-linux-arm64": "0.1.6"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
@@ -20,6 +20,7 @@ const TARGETS = {
|
|
|
20
20
|
},
|
|
21
21
|
zcode: () => cliSpawn(process.env.HARNESS_MIX_ZCODE_EXECUTABLE || 'zcode', ['acp']),
|
|
22
22
|
trae: () => cliSpawn(process.env.HARNESS_MIX_TRAE_EXECUTABLE || 'traecli', ['acp', 'serve']),
|
|
23
|
+
cline: () => cliSpawn(process.env.HARNESS_MIX_CLINE_EXECUTABLE || 'cline', ['--acp']),
|
|
23
24
|
hermes: () => ({ command: process.env.HARNESS_MIX_HERMES_EXECUTABLE || 'hermes.exe', args: ['acp'] }),
|
|
24
25
|
};
|
|
25
26
|
|
package/scripts/build-native.cjs
CHANGED
|
@@ -28,7 +28,7 @@ async function main() {
|
|
|
28
28
|
icons.harnesses['deepseek-harness'] = icons.harnesses.dsh;
|
|
29
29
|
await esbuild.build({ ...common, entryPoints: ['src/native-ui/renderer-extension/src/production-entry.ts'],
|
|
30
30
|
platform: 'browser', format: 'iife', outfile: path.join(out, 'renderer-extension.js'),
|
|
31
|
-
loader: { '.svg': 'dataurl', '.png': 'dataurl', '.css': 'text' },
|
|
31
|
+
loader: { '.svg': 'dataurl', '.png': 'dataurl', '.webp': 'dataurl', '.css': 'text' },
|
|
32
32
|
banner: { js: `globalThis.__HARNESS_MIX_ICONS__=${JSON.stringify(icons)};globalThis.__HARNESS_MIX_MODEL_FAMILIES__=${JSON.stringify(MODEL_FAMILIES.map(f => ({ id: f.id, pattern: f.regex.source })))};` } });
|
|
33
33
|
await esbuild.build({ ...common, entryPoints: ['src/native-ui/desktop-control/src/release-main.ts'],
|
|
34
34
|
platform: 'node', format: 'esm', outfile: path.join(out, 'desktop-controller.mjs') });
|
|
@@ -79,5 +79,49 @@ function fakeSession() {
|
|
|
79
79
|
|
|
80
80
|
assert.equal(usageView({ last: { totalTokens: 50 }, total: {}, modelContextWindow: 200 }).contextPercent, 25);
|
|
81
81
|
assert.deepEqual(modelView({ model: 'gpt-x', displayName: 'GPT X', supportedReasoningEfforts: [], isDefault: true }).id, 'gpt-x');
|
|
82
|
+
|
|
83
|
+
// 权限透传:Desktop 选择(回合级)优先,缺失时回退线程级设置,均转发到原生 turn/start
|
|
84
|
+
const sendSession = fakeSession();
|
|
85
|
+
sendSession.model = { id: 'gpt-x' };
|
|
86
|
+
sendSession.turnPermissions = { approvalPolicy: 'on-request', sandboxPolicy: { type: 'readOnly' } };
|
|
87
|
+
const sentRequests = [];
|
|
88
|
+
sendSession.host = { async request(method, params) { sentRequests.push({ method, params }); return { turn: { id: `turn-${sentRequests.length}` } }; } };
|
|
89
|
+
const first = adapter.send(sendSession, '第一轮', {}, { images: [], turnPermissions: { approvalPolicy: 'never', approvalsReviewer: 'guardian', sandboxPolicy: { type: 'dangerFullAccess' } } });
|
|
90
|
+
const turnStart = sentRequests.find(r => r.method === 'turn/start');
|
|
91
|
+
assert.equal(turnStart.params.approvalPolicy, 'never', '回合级权限覆盖优先转发');
|
|
92
|
+
assert.equal(turnStart.params.approvalsReviewer, 'guardian_subagent', 'Desktop 的 guardian 归一化为原生枚举');
|
|
93
|
+
assert.deepEqual(turnStart.params.sandboxPolicy, { type: 'dangerFullAccess' });
|
|
94
|
+
projectNotification({ method: 'turn/completed', params: { threadId: 'thread-native', turn: { id: 'turn-1', status: 'completed' } } }, sendSession, () => {});
|
|
95
|
+
await first;
|
|
96
|
+
sentRequests.length = 0;
|
|
97
|
+
const second = adapter.send(sendSession, '第二轮', {}, { images: [] });
|
|
98
|
+
const fallbackStart = sentRequests.find(r => r.method === 'turn/start');
|
|
99
|
+
assert.equal(fallbackStart.params.approvalPolicy, 'on-request', '无线索级覆盖时回退线程级设置');
|
|
100
|
+
assert.deepEqual(fallbackStart.params.sandboxPolicy, { type: 'readOnly' });
|
|
101
|
+
projectNotification({ method: 'turn/completed', params: { threadId: 'thread-native', turn: { id: 'turn-1', status: 'completed' } } }, sendSession, () => {});
|
|
102
|
+
await second;
|
|
103
|
+
|
|
104
|
+
// Queue resume can race app-server's active-turn cleanup. Retry only that transient
|
|
105
|
+
// without surfacing a failed Core turn or duplicating unrelated failures.
|
|
106
|
+
const retrySession = fakeSession();
|
|
107
|
+
let startAttempts = 0;
|
|
108
|
+
retrySession.host = { async request(method) {
|
|
109
|
+
assert.equal(method, 'turn/start');
|
|
110
|
+
startAttempts++;
|
|
111
|
+
if (startAttempts < 3) throw new Error("Agent is already processing. Specify streamingBehavior ('steer' or 'followUp') to queue the message.");
|
|
112
|
+
return { turn: { id: 'turn-after-settlement' } };
|
|
113
|
+
} };
|
|
114
|
+
const retried = adapter.send(retrySession, '编辑后的排队消息', {}, { images: [] });
|
|
115
|
+
while (startAttempts < 3) await new Promise(resolve => setTimeout(resolve, 10));
|
|
116
|
+
assert.equal(retrySession.state.nativeTurnId, 'turn-after-settlement');
|
|
117
|
+
projectNotification({ method: 'turn/completed', params: { threadId: 'thread-native', turn: { id: 'turn-after-settlement', status: 'completed' } } }, retrySession, () => {});
|
|
118
|
+
await retried;
|
|
119
|
+
assert.equal(startAttempts, 3, 'Only the transient app-server busy race is retried');
|
|
120
|
+
|
|
121
|
+
const fatalSession = fakeSession();
|
|
122
|
+
let fatalAttempts = 0;
|
|
123
|
+
fatalSession.host = { async request() { fatalAttempts++; throw new Error('Authentication required'); } };
|
|
124
|
+
await assert.rejects(adapter.send(fatalSession, '不可重试的错误', {}, { images: [] }), /Authentication required/);
|
|
125
|
+
assert.equal(fatalAttempts, 1, 'Unrelated app-server errors are never retried or hidden');
|
|
82
126
|
console.log('codex adapter: native notifications, usage, multi-question and approvals passed');
|
|
83
127
|
})().catch(error => { console.error(error); process.exitCode = 1; });
|
|
@@ -97,6 +97,9 @@ async function main() {
|
|
|
97
97
|
const params = { harnessId: 'all-harnesses', nativeSessionId: rows.candidates[0].nativeSessionId };
|
|
98
98
|
const context = await rt.history.context(params);
|
|
99
99
|
assert.equal(context.harnessId, 'pi'); assert.match(context.transcript, /User: old question[\s\S]*Assistant: old answer/);
|
|
100
|
+
assert.equal(context.sessionRef, params.nativeSessionId);
|
|
101
|
+
assert.equal(context.messageCount, 2); assert.equal(context.returned, 2);
|
|
102
|
+
assert.equal(context.hasMore, false); assert.equal(context.nextOffset, null);
|
|
100
103
|
assert.equal(rt.sessions.size, 0, 'Referencing history does not launch or import a model session');
|
|
101
104
|
const [one, two] = await Promise.all([rt.history.import(params), rt.history.import(params)]);
|
|
102
105
|
assert.equal(one.threadId, two.threadId); assert.equal(calls.filter(c => c === 'read').length, 2);
|
package/scripts/e2e-codex.cjs
CHANGED
|
@@ -50,7 +50,9 @@ async function settle(thread) {
|
|
|
50
50
|
runtime = new HostRuntime({ dataDirectory });
|
|
51
51
|
await runtime.initialize();
|
|
52
52
|
const resumed = runtime.threads.find(thread => thread.nativeSessionId === forkNativeId);
|
|
53
|
-
assert.ok(resumed
|
|
53
|
+
assert.ok(resumed, 'persisted Codex task survives reload');
|
|
54
|
+
// 分片存储:重启后线程是 storage stub,getThread 水合后才标记惰性恢复
|
|
55
|
+
assert.ok(runtime.getThread(resumed.id)?.restore, 'persisted Codex task is lazily resumable');
|
|
54
56
|
await runtime.send(resumed.id, 'What CODEX-FORK token did I ask you to remember? Reply only the token.');
|
|
55
57
|
await settle(resumed);
|
|
56
58
|
assert.match(resumed.messages.at(-1).text, /CODEX-FORK-4172/);
|
|
@@ -6,7 +6,7 @@ const path = require('node:path');
|
|
|
6
6
|
fs.mkdirSync(directory, { recursive: true });
|
|
7
7
|
const reports = [];
|
|
8
8
|
const selected = process.argv.find(a => a.startsWith('--harness='))?.slice(10);
|
|
9
|
-
for (const file of (selected ? selected.split(',') : ['codebuddy', 'kiro', 'cursor', 'qoder', 'zcode', 'trae'])) {
|
|
9
|
+
for (const file of (selected ? selected.split(',') : ['codebuddy', 'kiro', 'cursor', 'qoder', 'zcode', 'trae', 'cline'])) {
|
|
10
10
|
const mod = require('../src/main/adapters/' + file), adapter = mod.create();
|
|
11
11
|
const report = { harnessId: mod.manifest.id, inspection: await adapter.inspect(), live: false };
|
|
12
12
|
reports.push(report);
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
const assert = require('node:assert/strict');
|
|
2
|
+
const { classifyError, errorActions, mapCodexErrorInfo, codexErrorInfoKey, ERROR_KINDS } = require('../src/main/harness-adapter/error-kind');
|
|
3
|
+
const { EventNormalizer } = require('../src/main/harness-adapter/event-normalizer');
|
|
4
|
+
const { ProtocolCore } = require('../src/main/protocol-core/protocol-core');
|
|
5
|
+
const { CoreSession } = require('../src/main/host/core-session');
|
|
6
|
+
const { NativeProtocol } = require('../src/main/native/protocol');
|
|
7
|
+
|
|
8
|
+
function main() {
|
|
9
|
+
// 1) 显式归类优先:适配器从原生结构化错误给出的 errorKind 原样采纳
|
|
10
|
+
assert.equal(classifyError({ errorKind: 'quota', message: 'whatever' }), 'quota');
|
|
11
|
+
assert.equal(classifyError({ errorKind: 'bogus', message: '401 unauthorized' }), 'auth');
|
|
12
|
+
|
|
13
|
+
// 2) Codex 原生 CodexErrorInfo:字符串与单键对象两种线格式都打平映射
|
|
14
|
+
assert.equal(mapCodexErrorInfo('usageLimitExceeded'), 'quota');
|
|
15
|
+
assert.equal(mapCodexErrorInfo({ responseStreamDisconnected: {} }), 'network');
|
|
16
|
+
assert.equal(mapCodexErrorInfo('internalServerError'), 'server');
|
|
17
|
+
assert.equal(mapCodexErrorInfo('sandboxError'), null); // 未确认语义的变体不猜
|
|
18
|
+
assert.equal(codexErrorInfoKey({ usageLimitExceeded: null }), 'usageLimitExceeded');
|
|
19
|
+
assert.equal(classifyError({ codexErrorInfo: 'unauthorized', message: 'stream disconnected' }), 'auth');
|
|
20
|
+
|
|
21
|
+
// 3) HTTP 状态码信号
|
|
22
|
+
assert.equal(classifyError({ statusCode: 401 }), 'auth');
|
|
23
|
+
assert.equal(classifyError({ statusCode: 403 }), 'auth');
|
|
24
|
+
assert.equal(classifyError({ statusCode: 429 }), 'quota');
|
|
25
|
+
assert.equal(classifyError({ statusCode: 400 }), 'refused');
|
|
26
|
+
assert.equal(classifyError({ statusCode: 503 }), 'server');
|
|
27
|
+
|
|
28
|
+
// 4) 消息特征归类(含优先级陷阱)
|
|
29
|
+
assert.equal(classifyError({ message: 'Invalid API key provided' }), 'auth');
|
|
30
|
+
assert.equal(classifyError({ message: 'Rate limit reached, please slow down' }), 'quota');
|
|
31
|
+
assert.equal(classifyError({ message: 'request failed: connect ECONNREFUSED 127.0.0.1' }), 'network');
|
|
32
|
+
assert.equal(classifyError({ message: 'Connection refused by peer' }), 'network'); // refused 字样不误导为请求被拒
|
|
33
|
+
assert.equal(classifyError({ message: 'stream disconnected while reading' }), 'network');
|
|
34
|
+
assert.equal(classifyError({ message: 'upstream 502 Bad Gateway' }), 'server');
|
|
35
|
+
assert.equal(classifyError({ message: 'the request was rejected by the server' }), 'refused');
|
|
36
|
+
assert.equal(classifyError({ message: '模型返回了奇怪的内容' }), 'unknown');
|
|
37
|
+
assert.equal(classifyError({}), 'unknown');
|
|
38
|
+
assert.ok(ERROR_KINDS.includes(classifyError({ message: '任何错误' })));
|
|
39
|
+
|
|
40
|
+
// 5) 动作推导:login 按 Harness 真实登录能力过滤
|
|
41
|
+
assert.deepEqual(errorActions('auth', { canLogin: true }), ['login', 'newSession']);
|
|
42
|
+
assert.deepEqual(errorActions('auth', { canLogin: false }), ['newSession']);
|
|
43
|
+
assert.deepEqual(errorActions('network'), ['retry']);
|
|
44
|
+
assert.deepEqual(errorActions('quota'), ['newSession']);
|
|
45
|
+
assert.deepEqual(errorActions('bogus'), ['retry', 'newSession']);
|
|
46
|
+
|
|
47
|
+
// 6) Normalizer:error 事件 → turn.failed 携带 errorKind 与 codexErrorInfo
|
|
48
|
+
const normalizer = new EventNormalizer({ threadId: 'thread_1', source: 'codex' });
|
|
49
|
+
normalizer.beginTurn('turn_1', 'go');
|
|
50
|
+
const failed = normalizer.normalize({ kind: 'error', message: 'Codex 回合失败', codexErrorInfo: 'usageLimitExceeded' });
|
|
51
|
+
assert.equal(failed.at(-1).type, 'turn.failed');
|
|
52
|
+
assert.equal(failed.at(-1).payload.errorKind, 'quota');
|
|
53
|
+
assert.equal(failed.at(-1).payload.codexErrorInfo, 'usageLimitExceeded');
|
|
54
|
+
// Turn 已结算后迟到的 error 事件被忽略
|
|
55
|
+
assert.deepEqual(normalizer.normalize({ kind: 'error', message: 'late' }), []);
|
|
56
|
+
|
|
57
|
+
// 7) Core:turn.failed 把 errorKind 落到 Turn 状态
|
|
58
|
+
const core = new ProtocolCore();
|
|
59
|
+
core.createThread({ id: 'thread_1', workspaceId: '/tmp' });
|
|
60
|
+
const turn = core.turns.create({ threadId: 'thread_1' });
|
|
61
|
+
core.dispatch({ threadId: 'thread_1', turnId: turn.id, type: 'turn.started' });
|
|
62
|
+
core.dispatch({ threadId: 'thread_1', turnId: turn.id, type: 'turn.failed', payload: { message: '网络错误', errorKind: 'network' } });
|
|
63
|
+
assert.equal(turn.status, 'error');
|
|
64
|
+
assert.equal(turn.error, '网络错误');
|
|
65
|
+
assert.equal(turn.errorKind, 'network');
|
|
66
|
+
|
|
67
|
+
// 8) CoreSession:失败分类投影到线程模型
|
|
68
|
+
const execution = new CoreSession();
|
|
69
|
+
const thread = { id: 'thread_2', harnessId: 'pi', nativeSessionId: 's1', cwd: process.cwd(), messages: [], tools: [], connectionStatus: 'ready' };
|
|
70
|
+
execution.threadCreated(thread);
|
|
71
|
+
execution.turnStarted(thread, '跑一下');
|
|
72
|
+
const { settled } = execution.apply(thread, { kind: 'error', message: '429 too many requests' });
|
|
73
|
+
assert.equal(settled, true);
|
|
74
|
+
assert.equal(thread.status, 'error');
|
|
75
|
+
assert.match(thread.error, /429/);
|
|
76
|
+
assert.equal(thread.errorKind, 'quota');
|
|
77
|
+
|
|
78
|
+
// 9) 协议投影:turn() 透传原生 codexErrorInfo;turn-error 查询给出分类与动作
|
|
79
|
+
const fakeRuntime = {
|
|
80
|
+
threads: [{ id: 'thread_3', harnessId: 'claude', error: 'Invalid API key', errorKind: 'auth' }],
|
|
81
|
+
getThread(id) { return this.threads.find(t => t.id === id); },
|
|
82
|
+
core: { subscribe: () => () => {}, getItemsForTurn: () => [] },
|
|
83
|
+
subscribe: () => () => {},
|
|
84
|
+
adapters: new Map(),
|
|
85
|
+
status: {},
|
|
86
|
+
};
|
|
87
|
+
const protocol = new NativeProtocol(fakeRuntime, () => {});
|
|
88
|
+
const projected = protocol.turn({ id: 'turn_9', status: 'error', error: 'boom', codexErrorInfo: 'usageLimitExceeded' });
|
|
89
|
+
assert.equal(projected.error.codexErrorInfo, 'usageLimitExceeded');
|
|
90
|
+
const noInfo = protocol.turn({ id: 'turn_10', status: 'error', error: 'boom' });
|
|
91
|
+
assert.equal(noInfo.error.codexErrorInfo, null);
|
|
92
|
+
return (async () => {
|
|
93
|
+
const state = await protocol.request('codexhost/harness/turn-error', { threadId: 'thread_3' });
|
|
94
|
+
assert.equal(state.errorKind, 'auth');
|
|
95
|
+
assert.equal(state.error, 'Invalid API key');
|
|
96
|
+
assert.deepEqual(state.actions, ['login', 'newSession']); // claude-code 有 loginCommand
|
|
97
|
+
fakeRuntime.threads[0].errorKind = null;
|
|
98
|
+
const cleared = await protocol.request('codexhost/harness/turn-error', { threadId: 'thread_3' });
|
|
99
|
+
assert.equal(cleared.errorKind, null);
|
|
100
|
+
assert.deepEqual(cleared.actions, []);
|
|
101
|
+
await assert.rejects(protocol.request('codexhost/harness/turn-error', { threadId: 'nope' }), /Unknown thread/);
|
|
102
|
+
protocol.close?.();
|
|
103
|
+
console.log('PASS: error classification (explicit/codexErrorInfo/status/pattern/unknown), actions, normalizer/core/thread projection, turn-error query');
|
|
104
|
+
})();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
main().catch(error => { console.error(error); process.exitCode = 1; });
|