@ckanner/flywheel 0.32.0 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/CHANGELOG.md +17 -1
  2. package/README.md +11 -2
  3. package/README.zh-CN.md +6 -1
  4. package/THIRD_PARTY_NOTICES.md +42 -0
  5. package/bin/runtime.js +25 -31
  6. package/cordis.patch.yml +5 -0
  7. package/dist/bridge.mjs +421 -0
  8. package/dist/claude-code-pro-bridge.mjs +82 -0
  9. package/dist/claude-code-pro-worker.mjs +5 -0
  10. package/dist/client.js +4078 -0
  11. package/dist/codex-pro-bridge.mjs +75 -0
  12. package/dist/codex-pro-worker.mjs +5 -0
  13. package/dist/console-read.mjs +51 -0
  14. package/dist/control.mjs +218 -0
  15. package/dist/index.mjs +185 -0
  16. package/dist/installation.mjs +56 -0
  17. package/dist/machine-worker.mjs +241 -0
  18. package/dist/policy.mjs +91 -0
  19. package/dist/prewarm.mjs +136 -0
  20. package/dist/protocol.mjs +260 -0
  21. package/dist/task-association.mjs +127 -0
  22. package/dist/worker.mjs +52 -0
  23. package/dist/workspaces.mjs +42 -0
  24. package/docs/README.md +1 -1
  25. package/docs/README.zh-CN.md +1 -1
  26. package/docs/design.md +8 -5
  27. package/docs/en/configuration.md +1 -1
  28. package/docs/en/contributing.md +5 -6
  29. package/docs/en/flow-console.md +1 -1
  30. package/docs/en/getting-started.md +13 -3
  31. package/docs/en/releasing.md +132 -174
  32. package/docs/validation/2026-11-13-release-0.32.0.md +78 -0
  33. package/docs/validation/2026-11-13-release-0.32.1.md +83 -0
  34. package/docs/validation/2026-11-14-single-package.md +60 -0
  35. package/docs/validation/README.md +3 -0
  36. package/docs/zh-CN/configuration.md +1 -1
  37. package/docs/zh-CN/contributing.md +4 -5
  38. package/docs/zh-CN/flow-console.md +1 -1
  39. package/docs/zh-CN/getting-started.md +10 -4
  40. package/docs/zh-CN/releasing.md +97 -81
  41. package/native/darwin-amd64/flywheel +0 -0
  42. package/native/darwin-arm64/flywheel +0 -0
  43. package/native/linux-amd64/flywheel +0 -0
  44. package/native/linux-arm64/flywheel +0 -0
  45. package/native/manifest.json +22 -0
  46. package/node_modules/dsh-subagent-codex-pro/CHANGELOG.md +403 -0
  47. package/node_modules/dsh-subagent-codex-pro/LICENSE +21 -0
  48. package/node_modules/dsh-subagent-codex-pro/README.md +557 -0
  49. package/node_modules/dsh-subagent-codex-pro/cordis.patch.yml +30 -0
  50. package/node_modules/dsh-subagent-codex-pro/docs/README.zh.md +355 -0
  51. package/node_modules/dsh-subagent-codex-pro/docs/machine-lifecycle-validation.md +65 -0
  52. package/node_modules/dsh-subagent-codex-pro/docs/machine-lifecycle.md +144 -0
  53. package/node_modules/dsh-subagent-codex-pro/docs/machine-lifecycle.zh.md +98 -0
  54. package/node_modules/dsh-subagent-codex-pro/docs/machine.md +194 -0
  55. package/node_modules/dsh-subagent-codex-pro/docs/orchestration.zh.md +86 -0
  56. package/node_modules/dsh-subagent-codex-pro/lib/codex-exec.js +68 -0
  57. package/node_modules/dsh-subagent-codex-pro/lib/codex-exec.js.map +1 -0
  58. package/node_modules/dsh-subagent-codex-pro/lib/dsh-types.js +15 -0
  59. package/node_modules/dsh-subagent-codex-pro/lib/dsh-types.js.map +1 -0
  60. package/node_modules/dsh-subagent-codex-pro/lib/index.js +830 -0
  61. package/node_modules/dsh-subagent-codex-pro/lib/index.js.map +1 -0
  62. package/node_modules/dsh-subagent-codex-pro/lib/jobs.js +35 -0
  63. package/node_modules/dsh-subagent-codex-pro/lib/jobs.js.map +1 -0
  64. package/node_modules/dsh-subagent-codex-pro/lib/jsonrpc.js +229 -0
  65. package/node_modules/dsh-subagent-codex-pro/lib/jsonrpc.js.map +1 -0
  66. package/node_modules/dsh-subagent-codex-pro/lib/machine-cli.js +101 -0
  67. package/node_modules/dsh-subagent-codex-pro/lib/machine-cli.js.map +1 -0
  68. package/node_modules/dsh-subagent-codex-pro/lib/machine-local.js +122 -0
  69. package/node_modules/dsh-subagent-codex-pro/lib/machine-local.js.map +1 -0
  70. package/node_modules/dsh-subagent-codex-pro/lib/machine-recovery.js +167 -0
  71. package/node_modules/dsh-subagent-codex-pro/lib/machine-recovery.js.map +1 -0
  72. package/node_modules/dsh-subagent-codex-pro/lib/machine-supervision.js +141 -0
  73. package/node_modules/dsh-subagent-codex-pro/lib/machine-supervision.js.map +1 -0
  74. package/node_modules/dsh-subagent-codex-pro/lib/machine-supervisor.js +128 -0
  75. package/node_modules/dsh-subagent-codex-pro/lib/machine-supervisor.js.map +1 -0
  76. package/node_modules/dsh-subagent-codex-pro/lib/machine.js +104 -0
  77. package/node_modules/dsh-subagent-codex-pro/lib/machine.js.map +1 -0
  78. package/node_modules/dsh-subagent-codex-pro/lib/process-guardian.js +156 -0
  79. package/node_modules/dsh-subagent-codex-pro/lib/process-guardian.js.map +1 -0
  80. package/node_modules/dsh-subagent-codex-pro/lib/run.js +842 -0
  81. package/node_modules/dsh-subagent-codex-pro/lib/run.js.map +1 -0
  82. package/node_modules/dsh-subagent-codex-pro/lib/structured.js +329 -0
  83. package/node_modules/dsh-subagent-codex-pro/lib/structured.js.map +1 -0
  84. package/node_modules/dsh-subagent-codex-pro/lib/tool.js +295 -0
  85. package/node_modules/dsh-subagent-codex-pro/lib/tool.js.map +1 -0
  86. package/node_modules/dsh-subagent-codex-pro/lib/types/codex-exec.d.ts +88 -0
  87. package/node_modules/dsh-subagent-codex-pro/lib/types/codex-exec.d.ts.map +1 -0
  88. package/node_modules/dsh-subagent-codex-pro/lib/types/dsh-types.d.ts +179 -0
  89. package/node_modules/dsh-subagent-codex-pro/lib/types/dsh-types.d.ts.map +1 -0
  90. package/node_modules/dsh-subagent-codex-pro/lib/types/index.d.ts +266 -0
  91. package/node_modules/dsh-subagent-codex-pro/lib/types/index.d.ts.map +1 -0
  92. package/node_modules/dsh-subagent-codex-pro/lib/types/jobs.d.ts +34 -0
  93. package/node_modules/dsh-subagent-codex-pro/lib/types/jobs.d.ts.map +1 -0
  94. package/node_modules/dsh-subagent-codex-pro/lib/types/jsonrpc.d.ts +113 -0
  95. package/node_modules/dsh-subagent-codex-pro/lib/types/jsonrpc.d.ts.map +1 -0
  96. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-cli.d.ts +3 -0
  97. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-cli.d.ts.map +1 -0
  98. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-local.d.ts +4 -0
  99. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-local.d.ts.map +1 -0
  100. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-recovery.d.ts +53 -0
  101. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-recovery.d.ts.map +1 -0
  102. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-supervision.d.ts +8 -0
  103. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-supervision.d.ts.map +1 -0
  104. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-supervisor.d.ts +2 -0
  105. package/node_modules/dsh-subagent-codex-pro/lib/types/machine-supervisor.d.ts.map +1 -0
  106. package/node_modules/dsh-subagent-codex-pro/lib/types/machine.d.ts +70 -0
  107. package/node_modules/dsh-subagent-codex-pro/lib/types/machine.d.ts.map +1 -0
  108. package/node_modules/dsh-subagent-codex-pro/lib/types/process-guardian.d.ts +22 -0
  109. package/node_modules/dsh-subagent-codex-pro/lib/types/process-guardian.d.ts.map +1 -0
  110. package/node_modules/dsh-subagent-codex-pro/lib/types/run.d.ts +386 -0
  111. package/node_modules/dsh-subagent-codex-pro/lib/types/run.d.ts.map +1 -0
  112. package/node_modules/dsh-subagent-codex-pro/lib/types/structured.d.ts +35 -0
  113. package/node_modules/dsh-subagent-codex-pro/lib/types/structured.d.ts.map +1 -0
  114. package/node_modules/dsh-subagent-codex-pro/lib/types/tool.d.ts +107 -0
  115. package/node_modules/dsh-subagent-codex-pro/lib/types/tool.d.ts.map +1 -0
  116. package/node_modules/dsh-subagent-codex-pro/lib/types/usage.d.ts +131 -0
  117. package/node_modules/dsh-subagent-codex-pro/lib/types/usage.d.ts.map +1 -0
  118. package/node_modules/dsh-subagent-codex-pro/lib/types/wire.d.ts +321 -0
  119. package/node_modules/dsh-subagent-codex-pro/lib/types/wire.d.ts.map +1 -0
  120. package/node_modules/dsh-subagent-codex-pro/lib/usage.js +356 -0
  121. package/node_modules/dsh-subagent-codex-pro/lib/usage.js.map +1 -0
  122. package/node_modules/dsh-subagent-codex-pro/lib/wire.js +986 -0
  123. package/node_modules/dsh-subagent-codex-pro/lib/wire.js.map +1 -0
  124. package/node_modules/dsh-subagent-codex-pro/package.json +76 -0
  125. package/npm/install.js +59 -6
  126. package/package.json +74 -12
  127. package/plugins/dsh/LICENSE +21 -0
  128. package/plugins/dsh/PROTOCOL.md +607 -0
  129. package/plugins/dsh/README.en.md +4 -0
  130. package/plugins/dsh/README.md +342 -0
  131. package/plugins/dsh/README.zh-CN.md +279 -0
  132. package/plugins/dsh/THIRD_PARTY_NOTICES.md +42 -0
  133. package/plugins/dsh/vendor/README.md +17 -0
  134. package/plugins/dsh/vendor/codex-pro.json +16 -0
@@ -0,0 +1,403 @@
1
+ # Changelog
2
+
3
+ ## 0.9.0 (source candidate, unreleased)
4
+
5
+ - Add lifecycle v1 with awaited configuration-checked thread-ready, dispatch-intent,
6
+ dispatch-possible and turn-accepted checkpoints. A failed ACK cannot silently
7
+ continue a turn; the possible-send window remains explicitly ambiguous.
8
+ - Add a separately grouped machine supervisor for opted-in lifecycle/journal
9
+ calls. Caller death aborts native work and persists the original complete
10
+ receipt; a lost terminal notification never rewrites a completed run as cancelled.
11
+ - Add exclusive private, atomic and fsynced invocation journals plus a read-only
12
+ recoverMachine entry. Missing/corrupt evidence remains unknown, not a retry.
13
+ - Record typed execution.dispatch without inferring model execution from a PID,
14
+ progress text, a thread ID, or cleanup success. Require explicit boolean
15
+ persistence evidence on thread/start.
16
+ - Exercise real checkpoint rejection, caller process-group SIGKILL, original
17
+ receipt recovery and built-package lifecycle paths with offline app-server
18
+ fixtures. No new live-account or installed desktop acceptance is claimed.
19
+
20
+ ## 0.8.0
21
+
22
+ Released 2026-11-03.
23
+
24
+ - Add the public protocol-1 machine API and single-request CLI, preserving run identity, actual process facts, configuration and usage completeness without changing DSH Host result shapes.
25
+ - Supervise POSIX Codex groups with an IPC-lifeline guardian so caller death triggers bounded cleanup; never substitute supervisor exit for the actual Codex exit. A live caller's normal stop now exits the guardian as soon as the app-server is gone instead of paying the full dispose grace; caller-death cleanup keeps the full grace.
26
+ - Confirm cleanup from a final independent absence probe, retaining unknown status for EPERM while allowing a later ESRCH to resolve a Darwin exit race.
27
+ - Reject missing or conflicting effective configuration before sending a task. Preserve full sandbox policy and request-only effort evidence.
28
+ - Default to workspace-write + never; full access remains explicit and tool overrides cannot expand configured permissions.
29
+ - Align DSH rc.5 capabilities, reject unsupported provider/maxTokens overrides, and reject dispose when cleanup is unconfirmed.
30
+ - Correct malformed, early, foreign-turn and resumed token-usage accounting; unknown counters and costs are not zero. A resumed thread's historical replay is adopted even when it arrives after turn/start; a different-turn snapshot after live current-turn usage remains unattributed.
31
+ - Add Ubuntu/macOS Node22/24 CI, real packed-package/public-entry tests, migration notes and Flywheel/PR workflow documentation.
32
+ - Accept the protocol-defaulted `cacheWriteInputTokens`, preserve bounded approval diagnostics, gate the model-facing permission enum to the configured policy, handle CLI EPIPE, and retain startup failure causes in machine receipts.
33
+ - Real Codex 0.165 app-server live cases pass 4/4 (including resume/usage replay); real DSH Desktop smoke is not claimed.
34
+
35
+ ## 0.7.0
36
+
37
+ Adapter reliability and observability hardening. Released 2026-11-01. The
38
+ user's global Codex login/config is untouched.
39
+
40
+ - **One deadline for the whole delegation.** A single derived abort signal now
41
+ covers `initialize`, `thread/start`/`thread/resume`, `thread/name/set`, and the
42
+ turn. Startup hangs can no longer outlive `runTimeoutMs`; `0` still disables
43
+ the deadline. Timeout, caller cancellation, protocol failure, and process exit
44
+ are classified distinctly, settlement occurs once, and teardown is idempotent.
45
+ An auto-resume retry inherits the original absolute deadline instead of a
46
+ fresh full timeout.
47
+ - **Resume applies requested configuration.** On the 0.165 protocol,
48
+ `thread/resume` sends explicit model, cwd, and permission overrides and checks
49
+ the response's effective `model`, `cwd`, `approvalPolicy`, `approvalsReviewer`,
50
+ and `sandbox`. A mismatch fails an explicit resume; a remembered session
51
+ thread with incompatible configuration is replaced by a new thread under the
52
+ same deadline. `thread/start` no longer sends `reasoningEffort`, which is not
53
+ in the 0.165/0.166 start parameters; thinking remains a per-turn `effort`.
54
+ - **Read-only review mode.** Added `read-only` (`approvalPolicy: never`,
55
+ `sandbox: read-only`), available in configuration and per-call as
56
+ `permission_mode`. `never` remains only "do not prompt"; the default
57
+ write-capable mode is unchanged.
58
+ - **Token usage and rate limits.** `thread/tokenUsage/updated` is folded from
59
+ thread-cumulative snapshots into a run delta: resume replays are baselines,
60
+ duplicates/out-of-order snapshots never add, missing baselines are `unknown`
61
+ rather than zero, and observed usage survives failure/timeout/cancel.
62
+ `account/rateLimits/updated` is stored separately from token usage and is
63
+ never merged into it.
64
+ - **Result envelope separated.** Final text, structured result, thread id,
65
+ usage, configuration, diagnostics, cleanup, and schema errors are distinct
66
+ fields on the internal outcome. A schema-constrained answer stays pure JSON:
67
+ the persistent-thread marker is not appended to it, and parse/schema
68
+ verification is fail-closed. The DSH provider/tool/job contracts are
69
+ unchanged; they carry no usage field, so usage/rate limits are reported in
70
+ the outcome and diagnostic log rather than invented host fields.
71
+ - **Provable process cleanup.** POSIX children are process-group leaders;
72
+ teardown signals the group, escalates to `SIGKILL` after a separate grace, and
73
+ verifies the group is gone. Unconfirmed cleanup is reported, including for
74
+ descendants that ignore `SIGTERM`; there is no global `killall`.
75
+ - **Tests and docs.** Added fake-app-server lifecycle tests, usage-accounting
76
+ tests, structured-verification tests, resume-override tests, result-marker
77
+ tests, and permission-forwarding tests. Updated README and Chinese README to
78
+ match the 0.165 baseline and to separate offline, real-Codex, and real-DSH
79
+ desktop validation. Validation baseline: installed Codex 0.165.0; live
80
+ app-server cases 4/4 passed and the `codex exec` live case passed; official
81
+ 0.166.0 schemas reviewed, no 0.166 runtime executed; real DSH desktop smoke
82
+ still not run.
83
+
84
+ ## 0.6.4
85
+
86
+ Tests only; the shipped runtime is unchanged.
87
+
88
+ The live suite still read `delegateOnce` as if it returned the answer string, but
89
+ the function has returned `{ text, threadId, images }` since persistent threads
90
+ landed. Both live cases therefore failed their assertion even though the real
91
+ app-server turn had answered correctly; they now read `outcome.text`.
92
+
93
+ Verified against `@openai/codex` 0.164.0: the hermetic suite passes, and both
94
+ live cases complete a real turn (model + reasoning effort, and the defaults).
95
+ The 0.164.0 app-server protocol keeps every message phase and server request
96
+ this wire handles; it only adds optional `TurnStartParams` fields
97
+ (`parentTurnId`, `rootTurnId`) and two notifications this provider ignores.
98
+
99
+ ## 0.6.3
100
+
101
+ A missing Codex executable now fails one delegation instead of the Host.
102
+
103
+ `spawn codex` reports `ENOENT` when the executable is not on the Host's `PATH`
104
+ — for example after a Node version switch through a version manager drops the
105
+ global npm install. The run failed correctly, but the process-cleanup path
106
+ attached its termination-timer cleanup with a bare `finally()` on the
107
+ already-rejected exit promise. That derived rejection was unhandled, and the
108
+ Host's global unhandled-rejection handler escalates it to a fatal load failure:
109
+ DSH Desktop exited instead of returning the delegation error, taking every
110
+ running session with it. Cleanup now handles both settlements, so the only
111
+ observable result is a failed run with its diagnostic.
112
+
113
+ Add a regression test: a delegation whose executable is missing rejects
114
+ without leaving an unhandled rejection behind.
115
+
116
+ The README now records how to point `command` at an absolute executable for a
117
+ Host whose launch-time `PATH` does not carry the global install.
118
+
119
+ ## 0.6.2
120
+
121
+ Compatibility with DSH 0.2.1's subagent seam and the Codex app-server it drives.
122
+
123
+ - Accept the `partial_answer` agent-message phase. It is retained as a fallback answer and selection stays
124
+ final → partial → unphased, matching the official provider as of DSH 0.2.1. A turn that emitted only a partial
125
+ answer no longer fails with `unknown agent message phase "partial_answer"`.
126
+ - Use the working directory the shared subagent service selected (`request.cwd`) when one is supplied, falling
127
+ back to the parent session's directory. Provider-row and workflow dispatch now honour it; this plugin's own
128
+ tool path is unchanged because it already resolves the directory itself.
129
+ - Document the changed official activation model: since DSH 0.2.1 the official `subagent_codex` is a global Host
130
+ tool, and this plugin's per-Agent registration shadows it for the configured presets rather than a per-preset
131
+ disabled row switching it off. A same-scope duplicate still collides, so the profile must not enable a
132
+ same-name `tool-subagent` row beside this provider.
133
+
134
+ ## 0.6.1
135
+
136
+ The deadline is now a parameter, so a prompt can set it.
137
+
138
+ `timeout_ms` overrides the configured `runTimeoutMs` for one delegation, and `0` means no deadline at all. The
139
+ default was already a plugin setting, which made it usable only by editing a profile and restarting — plugin
140
+ configuration is not hot-reloaded, and a model cannot pass a value that no parameter declares. Now the routine
141
+ that needs tens of minutes and the lookup that needs seconds can be told apart by the model itself, in the same
142
+ turn, without a restart.
143
+
144
+ `0` is forwarded rather than treated as "unset": asking for no deadline is a different request from asking for
145
+ the configured one.
146
+
147
+ The README now records how a profile overrides this package's row. The loader replaces the whole `config` map
148
+ rather than merging it — read out of `applyEntryPatches`, which assigns each top-level field in turn, `config`
149
+ being one of them — so overriding `runTimeoutMs` without restating `presets` mounts a row that matches no
150
+ preset and therefore serves no session. The failure is silent, the log line names the presets actually received,
151
+ and both READMEs now carry the wrong and right shapes side by side.
152
+
153
+ Also corrects a contradiction in the capabilities table: `outputSchema` was listed as ✅ and, three rows later,
154
+ still inside the ❌ row left over from 0.6.0. The three refusals that remain — `maxDepth`, persona, `toolFilter`
155
+ — are now described as not applicable rather than not implemented, with the reason: a Codex delegation is a
156
+ leaf with no DSH child to cap, its tools are Codex's own rather than this harness's, and a persona is a system
157
+ instruction for a child agent where this one already takes the task in `prompt`.
158
+
159
+ ## 0.6.0
160
+
161
+
162
+ The answer can now be made machine-readable, and the capability table stops understating what this provider can
163
+ do.
164
+
165
+ `output_schema` hands Codex a JSON Schema its final answer must conform to, so a later step reads the answer
166
+ instead of parsing prose and hoping. The schema must be object-rooted, the same rule the harness applies to a
167
+ schema it passes a provider. The app-server enforces it: a measured run returned
168
+ `{"verdict":"pass","reason":"…","count":2}` with no extra keys and every required one present. The answer still
169
+ arrives as text, and that text is JSON.
170
+
171
+ It is sent on the **turn**: the same field on `thread/start` is accepted and then silently ignored — measured
172
+ both ways, and the thread-level form produced prose. Another silent-ignore, like a missing `localImage` path.
173
+
174
+ `capabilities.outputSchema` is now `true` rather than `false`, because it is now honored: a schema the harness
175
+ puts on a `tool-subagent` row reaches Codex, and the answer is parsed so the caller receives `structured`
176
+ alongside the text. Declaring it while ignoring it would have been worse than the old `false`.
177
+
178
+ The `apply` diagnostic line now names the version, so a restart's log says which build is loaded. It previously
179
+ could not tell two releases apart: 0.3.3 and 0.4.0 logged identically.
180
+
181
+ ## 0.5.0
182
+
183
+
184
+ Pictures now travel both ways. `images` hands Codex pictures alongside the task:
185
+
186
+ ```js
187
+ tools.subagent_codex({ description: "Match this design", prompt: "…", images: ["/tmp/design.png"] })
188
+ ```
189
+
190
+ Each path must be absolute, must exist, and must be a file, and the call fails before anything is spawned
191
+ otherwise. That check is load-bearing rather than decorative: **the app-server silently ignores a `localImage`
192
+ path that does not exist** — measured, with the turn completing normally and not one error item — so an
193
+ unchecked typo would produce a delegation that quietly lacks the picture its task was about.
194
+
195
+ The pictures go out as the app-server's `localImage` variant, which the error messages themselves identified as
196
+ one of `text`, `image`, `localImage`, `audio`, `localAudio`. Its `image` variant wants an `ImageReference` this
197
+ plugin cannot construct — both `{type:'image', data, mimeType}` and a `data:` URL are rejected with
198
+ `did not match any variant of untagged enum ImageReference` — so a host path is not a workaround but the form
199
+ that needs no encoding at all.
200
+
201
+ A delegation prompt remains text. An image block arriving there is refused with a message naming the `images`
202
+ parameter instead of the old flat refusal, because the harness can put an image in a prompt but a tool call's
203
+ arguments are JSON and the model has no bytes to put in them.
204
+
205
+ Verified live: a delegation whose prompt never mentioned a path, given one image, answered "Settings, Models" —
206
+ the two words on it.
207
+
208
+ ## 0.4.0
209
+
210
+
211
+ A delegation can run in a directory of its own.
212
+
213
+ `cwd` names an absolute path the run should use instead of the session's working directory — the shape a
214
+ post-deploy smoke test needs, where the run may write its artifacts but the repository must stay clean.
215
+
216
+ The path must be absolute, must exist, and must be a directory; anything else is refused with a message naming
217
+ the problem, rather than a run that quietly happens somewhere unexpected. It is a working directory and not a
218
+ sandbox boundary: what a run may touch remains the permission mode's decision.
219
+
220
+ Naming a directory also starts a fresh Codex thread, because a thread belongs to the directory it was created
221
+ in — continuing one elsewhere would be continuing a conversation about different files. `cwd` is therefore
222
+ incompatible with `threadMode: session`'s reuse, and the log says which directory each run used.
223
+
224
+ Requested while retiring a skill whose two jobs this plugin now covers: dispatching to Codex, and getting
225
+ screenshots back — which the skill could not do, and which is why its instructions required artifacts to land on
226
+ disk instead.
227
+
228
+ ## 0.3.3
229
+
230
+
231
+ A delegation now has a deadline, because one without it is invisible when it stalls.
232
+
233
+ `runTimeoutMs` bounds one whole delegation, defaulting to ten minutes and disabled by `0`. When the deadline
234
+ passes, the run is cancelled, the child process is torn down, and the result carries
235
+ `codex-pro: the delegation exceeded its 600000 ms deadline and was cancelled` rather than nothing at all.
236
+
237
+ The harness's own vocabulary has no `timeout` stop reason, so the provider path reports a cancelled run as
238
+ `aborted` while the diagnostic carries the reason; this plugin's own tool reports `timeout` and formats the
239
+ message itself.
240
+
241
+ Found in a real session: a screenshot delegation had been running for seven minutes at 0% CPU with one
242
+ established connection to a local proxy, no rollout written, and nothing anywhere in the log to say so. The
243
+ proxy turned out to be healthy — the stall was in the streaming request — which is precisely why the deadline
244
+ matters more than the diagnosis: whatever the cause, the wait now ends with a reason.
245
+
246
+ Verified live: a three-second deadline cancelled a run at 3.1 s, returned the diagnostic, and left no child
247
+ process behind.
248
+
249
+ ## 0.3.2
250
+
251
+
252
+ A background delegation no longer loses its images.
253
+
254
+ `run_in_background` returns a job id, and everything read back through `job_output` is text by contract, so the
255
+ image blocks a foreground call returns were simply dropped — silently, and with no trace of where the picture
256
+ went. A screenshot taken by a background delegation is still a file on this host, so the text now names it:
257
+ `[1 image: /Users/…/shot.png]`. A foreground call is unchanged and still delivers the image itself; `render` no
258
+ longer repeats the count, because the text already carries it.
259
+
260
+ Found by looking at a real session rather than at the code: a screenshot delegation had been started in the
261
+ background, and there was no path in the answer it would eventually produce.
262
+
263
+ ## 0.3.1
264
+
265
+
266
+ The image guard was too strict, and it would have hidden the feature it was added for.
267
+
268
+ 0.3.0 refused an image whenever the calling route did not **report** `image` among its input modalities, and it
269
+ failed closed: a route it could not resolve was treated as a route that cannot take images. The default
270
+ `deepseek-flash` entry declares `['text', 'image']`, so a session that could display screenshots would instead
271
+ have been told `[image not delivered: …]` for every one of them.
272
+
273
+ The rule is now the harness's own — an image is refused only when the route **declares** modalities and `image`
274
+ is not among them — and an unresolvable route delivers the image rather than withholding it. The route lookup
275
+ also gained the fallback `dsh-plugin-lcu` uses, so a session header without a model still resolves.
276
+
277
+ The rule is a pure function, `routeRefusesImages`, so the boundary is covered by tests instead of by whichever
278
+ session happens to be running.
279
+
280
+ ## 0.3.0
281
+
282
+
283
+ Images a delegation produces now come back.
284
+
285
+ The app-server reports them two ways and both are captured. `imageView` names a file on this host — the bytes
286
+ are never inlined, because the host that asked for the work is expected to read the file itself — while a
287
+ computer-use screenshot arrives as an image content block inside an MCP tool result. The plugin reads or decodes
288
+ whichever it gets, hands the bytes to the harness's attachment store, and returns image blocks beside the text,
289
+ so the model sees a picture instead of a description of one.
290
+
291
+ An image is only delivered when the calling Agent's model route reports `image` among its input modalities, the
292
+ same guard `dsh-plugin-lcu` applies to its screenshots. Everything else — no store, an unreadable file, over
293
+ 20 MB, an unsupported type, a route that cannot take images — becomes a text note. None of it can fail the
294
+ delegation: the answer the run produced always survives.
295
+
296
+ Verified against a real app-server through this package's own code: asked to open a file by path, Codex read the
297
+ providers listed on the screenshot aloud, and the run reported one captured image with its host path.
298
+
299
+ Sending images *in* is not implemented. The protocol accepts `input_image`, `local_image`, `image_url` and
300
+ audio, but this tool still sends text only; naming a path in the prompt remains the working route, and both
301
+ READMEs now document what each side actually supports.
302
+
303
+ ## 0.2.2
304
+
305
+
306
+ **`session` mode no longer collides with itself.** A thread carries one turn at a time, so two delegations sent
307
+ together from one session both reached for the remembered thread and the app-server refused the second with
308
+ `thread-store conflict: … already has an active writer`. The plugin now tracks which threads its Agent is
309
+ delegating in and checks before it starts: a remembered thread in use is skipped, the call gets a thread of its
310
+ own, and the skip is logged. Parallel work keeps running, and the mode falls back to `persistent` — which is
311
+ what that shape of work needs anyway — instead of failing and retrying.
312
+
313
+ The decision is a pure function, `chooseThread`, so it is covered by tests rather than by an app-server. An id
314
+ the caller passed explicitly is never skipped: continuing that thread was the request, and running somewhere
315
+ else would answer a different question.
316
+
317
+ ## 0.2.1
318
+
319
+
320
+ `apply` now records the thread mode and the originator, so the log says which lifetime is in force without
321
+ anyone reading the profile to find out.
322
+
323
+ **The session-mode retry is narrowed to the failure it was meant for.** It wrapped every delegation, so a turn
324
+ that failed for its own reasons was retried as a fresh thread — paying for the same work twice and hiding the
325
+ real failure behind a second attempt. It now applies only to a resume the app-server refused.
326
+
327
+ **A concurrency limit, measured rather than assumed.** Two delegations sent at once to one thread collide: the
328
+ app-server answers `thread-store conflict: … already has an active writer` and the second fails, while
329
+ `ephemeral` runs the same pair independently. `session` is therefore the wrong mode for parallel work, and both
330
+ READMEs now say so.
331
+
332
+ ## 0.2.0
333
+
334
+
335
+ A delegation can now outlive its run.
336
+
337
+ **Thread lifetime is a choice, not a constant.** Every delegation used to open an ephemeral thread, which the
338
+ app-server deletes when the connection ends — nothing to list, nothing to continue. `threadMode` now has three
339
+ settings: `ephemeral` keeps that behaviour and stays the default; `persistent` gives each delegation a durable
340
+ thread; `session` reuses one durable thread for the whole Agent session, so ten delegations leave one thread
341
+ rather than ten and each call after the first continues the same conversation.
342
+
343
+ **A durable thread is one the Codex CLI and the Codex application can see.** Verified against a real
344
+ app-server: the thread is written to `~/.codex/sessions/`, appears in `thread/list`, and can be continued with
345
+ `thread/resume`. The application's own list is the narrow part — its client filters by a single hardcoded
346
+ originator value, `Codex Desktop`, so `originator` exists to set that and defaults to the value that works.
347
+ Overriding it trades application visibility for an honest name; the CLI lists the thread either way.
348
+
349
+ **Threads are named, because the originator cannot say where they came from.** A thread from this provider has
350
+ to claim to be `Codex Desktop` to be listed at all, so `thread/name/set` carries the identification instead:
351
+ a persistent thread is named `DSH · <the call's description>`, which is what a person sees in the list.
352
+
353
+ **The model can control it per call.** The tool gained `thread_mode` and `thread_id`, and a persistent result
354
+ ends with the thread's id so a follow-up call can continue it. Resuming ignores `model` and `reasoning_effort`:
355
+ both are `thread/start` parameters and a resumed thread keeps the ones it was created with, while the per-turn
356
+ `effort` still applies.
357
+
358
+ **Why it is worth the change beyond convenience:** a resumed thread keeps the same prompt prefix, so the
359
+ endpoint's cache keeps hitting — measured on the Codex side at 93–99% of input tokens, against 0% for the same
360
+ work driven through a plan-usage route that refuses every cache control.
361
+
362
+ A thread with no turn yet is not resumable — the app-server answers `no rollout found` — so a thread becomes
363
+ continuable only after its first completed turn. A remembered session thread that has gone is replaced with a
364
+ fresh one; an id the caller passed explicitly is reported as a failure instead, because continuing it was the
365
+ whole request.
366
+
367
+ ## 0.1.1
368
+
369
+
370
+ Documentation and packaging; no behaviour change.
371
+
372
+ The published `files` list named only `lib` and the patch, so an installed copy shipped **no licence and no
373
+ readme** — npm's own defaults covered neither once `files` was set. It now carries the licence, the readme, this
374
+ changelog and the Chinese page.
375
+
376
+ Joins a closing sentence that a blank line had split in two, and removes a `helper` entry from `files` that
377
+ named a directory this package does not have.
378
+
379
+ ## 0.1.0
380
+
381
+ First release.
382
+
383
+ **A Codex delegation that can carry a model and a reasoning effort per call** — the two things
384
+ `@deepseek-ai/dsh-subagent-codex` cannot express. The Codex protocol supports both
385
+ (`ThreadStartParams.reasoningEffort`, `TurnStartParams.effort`); the official provider never sends them, and its
386
+ schema exposes neither, so a caller told to use a specific model and thinking level has nowhere to put either.
387
+
388
+ **Execution is a port of the official app-server adapter** (`src/wire.ts`, `src/run.ts`) — the initialize
389
+ handshake, the ephemeral thread, thread/turn association including notifications that arrive before
390
+ `turn/start` returns, unattended approval decisions, and terminal-answer selection — with `reasoningEffort` added
391
+ to `thread/start` and `effort` added to `turn/start`. The two literals appear nowhere in the official adapter.
392
+
393
+ **The tool is registered by this plugin itself**, on `agent/created`, into that Agent's own context, which keeps
394
+ the harness's preset-row machinery out of the path. Because the tool name is fixed, the official
395
+ `tool-subagent-codex` row stays disabled in those presets: two rows registering the same name in one scope
396
+ collide, and the second registration throws while its tool silently never appears.
397
+
398
+ **Defaults are deliberately absent.** What the call names is what runs; when it names neither, the choice stays
399
+ with Codex's own `~/.codex/config.toml`. The Host's `subagent-model-selection` setting is not consulted — it
400
+ governs a DSH catalog route billed as tokens, not a Codex model id under the CLI's own subscription.
401
+
402
+ **Background runs report progress.** `run_in_background` appends the child's completed commands, file changes,
403
+ and `commentary` messages to the job's output ring, so `job_output` shows how a long delegation is going.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ckanner
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.