codexteer 0.16.0 → 0.17.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.
- package/CHANGELOG.md +10 -2
- package/README.md +35 -10
- package/docs/distribution.md +27 -7
- package/docs/thread-create-native-investigation.md +136 -0
- package/docs/thread-create.md +115 -0
- package/package.json +4 -2
- package/src/cli.mjs +40 -4
- package/src/connection.mjs +11 -4
- package/src/creation-verification.mjs +16 -0
- package/src/distribution.mjs +4 -4
- package/src/help.mjs +29 -12
- package/src/native-command.mjs +92 -0
- package/src/native-rpc.mjs +103 -0
- package/src/native-worker.mjs +25 -0
- package/src/projects.mjs +79 -0
- package/src/prompt.mjs +12 -5
- package/src/runtime.mjs +4 -2
- package/src/socket-endpoint.mjs +40 -0
- package/src/standalone-create.mjs +134 -0
- package/src/supervise.mjs +14 -9
- package/src/thread-create.mjs +127 -0
- package/src/wrapper.mjs +68 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
3
|
+
## 0.17.0 — 未公開
|
|
4
4
|
|
|
5
|
+
- `projects list`と`thread create --project`を追加しました。プロジェクト名と初回指示だけで作成でき、既存チャット・`CODEX_THREAD_ID`・中継AIは不要です。App Serverで作成・Desktop購読・初回配送を行い、新規チャット自身の実在IDからnative RPCで所属登録し、全フォルダと初回指示を照合します。明示的な`--context-thread`は任意で、従来のnative直接作成を使います。配送不明・部分成功を保持し、自動再作成・再送を行いません。
|
|
6
|
+
|
|
7
|
+
- 内部RPCエラー(`-32603`など)では作成・配送が実行済みの可能性を保持し、`unknown`として記録します。メソッド・引数エラー(`-32601`/`-32602`)だけを実行前の拒否として区別し、自動再作成・再送は行いません。
|
|
8
|
+
|
|
9
|
+
## 0.16.0 — 2026-09-21公開
|
|
10
|
+
|
|
11
|
+
- `supervise`と`supervise prompt`に`--use-path-cli`を追加しました。指定時はPATH上の`codexteer`を使うコマンドを本文に出し、CLIのコピー・NodeとCODEX_HOMEの固定を行いません。監督ID・接続方式と既存の監督制御は維持します。既定は従来どおり保存済みCLIを使います。
|
|
12
|
+
- Codex同梱CLI 0.155系列が作る保護ソケットへの公式シンボリックリンクに対応し、`desktop start`・共有接続・観測専用接続が`RUNTIME_UNSAFE`等で拒否される問題を修正しました。固定ディレクトリ、パスのハッシュ、所有者、権限、実ソケットを検証し、任意のリンクは引き続き拒否します。起動済みwrapperも更新後のCLIから利用でき、保存済み監督CLIにはプロンプトの再生成・監督の再起動で反映します。
|
|
5
13
|
- `watch --stream`の既定を`digest`へ変更します。通常の進捗は20秒のsettle、読み取り専用コマンドなどは最長10分の保留でまとめ、ユーザー入力・注意状態・ターン・質問・読み取り専用以外の失敗は即時通知します。`--notify all`を明示すると従来の即時出力に戻せます。単発の`watch`と保存済みCLIの動作は変わりません。
|
|
6
14
|
- `--settle-ms`と`--max-hold-ms`で待ち時間を調整できます。初回の読み取りは基準として扱い、実行中コマンドの出力だけの更新ではsettleを延長しません。保留分は接続断・終了時にも排出し、ページ途中の場合だけ`has_more:true`を保持します。200件/64KBはページ読了後の排出目安です。
|
|
7
|
-
- 監督プロンプトを方針先頭の8
|
|
15
|
+
- 監督プロンプトを方針先頭の8節へ整理し、既定方針に設計上の責務と作業の焦点を追加します。設計上の責務では、事実・計算・判定を設計がどの層やシステムの担当と定めているかを先に確認し、別の層での検算や再計算など、同じ事実の持ち主が二つになる実装を観測します。基準は複数のリポジトリにまたがる設計の全体とし、分担が示されていない場合は推測せずユーザーに確認します。開始時の`help monitor`の重複読み取りをなくし、通知の読み方・無操作時の応答・Monitor期限切れ・議論の送信を明示します。生成する監視コマンドは`--notify digest`を明示します。
|
|
8
16
|
|
|
9
17
|
## 0.15.1 — 未公開
|
|
10
18
|
|
package/README.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# codexteer
|
|
2
2
|
|
|
3
|
+
登録済みプロジェクトへの初回指示付きチャット作成は、`projects list`と`thread create --project`で行えます。プロジェクト名と指示だけで使え、既存チャットや中継AIは不要です。Desktopのnative RPCで所属を登録し、複数フォルダや重複フォルダを持つ「競馬」も、所属・全フォルダ・初回指示を照合します。[使い方と実機検証](docs/thread-create.md)
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
codexteer projects list --json
|
|
7
|
+
codexteer thread create --project '競馬' \
|
|
8
|
+
--title '関連リポジトリの調査' '関連リポジトリを読み、結果を報告してください' --json
|
|
9
|
+
```
|
|
10
|
+
|
|
3
11
|
普段のCodex Desktopを使いながら、別のAIが進捗を観測し、根拠を伴って実行途中に軌道修正を伝えるためのmacOS用CLIです。ターミナルからの単発送信にも使えます。
|
|
4
12
|
|
|
5
13
|
## 導入
|
|
@@ -10,7 +18,7 @@ macOS、Node.js 20以降とnpm、`/Applications/ChatGPT.app`にインストー
|
|
|
10
18
|
|
|
11
19
|
リポジトリのcloneやグローバルインストールなしで実行できます。npmパッケージ名とCLI名は`codexteer`です。
|
|
12
20
|
|
|
13
|
-
|
|
21
|
+
npm公開済みの最新版は`0.16.0`です。このブランチは、プロジェクト名と初回指示だけでチャットを作成できるマイナー更新`0.17.0`を準備します。公開前に使う場合は「ソースから導入する」の手順で導入してください。変更点は[CHANGELOG](CHANGELOG.md)を参照してください。
|
|
14
22
|
|
|
15
23
|
```bash
|
|
16
24
|
npx -y codexteer --version
|
|
@@ -28,10 +36,10 @@ npx -y codexteer doctor --json
|
|
|
28
36
|
<details>
|
|
29
37
|
<summary>特定のバージョンで実行する場合(任意)</summary>
|
|
30
38
|
|
|
31
|
-
不具合の切り分けや、同じ版で監督を開始し直したい場合は、パッケージ名に`@バージョン`を付けられます。`0.
|
|
39
|
+
不具合の切り分けや、同じ版で監督を開始し直したい場合は、パッケージ名に`@バージョン`を付けられます。`0.17.0`の公開後にその版を選ぶ場合は、次のように指定します。
|
|
32
40
|
|
|
33
41
|
```bash
|
|
34
|
-
npx -y codexteer@0.
|
|
42
|
+
npx -y codexteer@0.17.0 supervise <thread-id>
|
|
35
43
|
```
|
|
36
44
|
|
|
37
45
|
</details>
|
|
@@ -73,6 +81,8 @@ codexteer doctor --json
|
|
|
73
81
|
|
|
74
82
|
`desktop start`は実行ファイルと依存を`CODEX_HOME/codex-steer/runtimes/<version>-<sha256>`へ検証して配置し、そのwrapperからDesktopを起動します。元のリポジトリやnpxキャッシュに依存せず、起動後のhelperも同じ保存先を使います。配置済みの版は自動削除・上書きしません。
|
|
75
83
|
|
|
84
|
+
Codex同梱CLI 0.155系列の保護ソケット形式にも対応します。従来の実ソケットに加え、公式の固定ディレクトリとパスハッシュに一致するリンクだけを、所有者・権限・リンク先の種別を検証して利用します。旧CLIで`RUNTIME_UNSAFE`が出た場合、ソース導入先を更新すれば、すでに稼働しているwrapperへの接続も修復できます。保存済みCLIを使う監督には、監督の再起動またはプロンプトの再生成で更新を反映してください。
|
|
85
|
+
|
|
76
86
|
監督AIが使うCLIの参照先については、次の監督手順を参照してください。MITライセンス、保存先の検証・復旧と公開手順は[配布ドキュメント](docs/distribution.md)にまとめています。
|
|
77
87
|
|
|
78
88
|
## 使い方
|
|
@@ -113,7 +123,7 @@ codexteer supervise <thread-id> "セキュリティの問題だけを私へ報
|
|
|
113
123
|
|
|
114
124
|
上書きは今回の生成・起動だけに適用し、次回の既定設定や保存したCLIには書き込みません。改行・空白・プレースホルダーに見える文字も指定文のまま本文に含めます。空文字・空白だけのメッセージはエラーです。呼び出し元のシェルで一つの引数として引用してください。`$`やバッククォートを文字として含めるときは、シェルが展開しない引用方法を使ってください。
|
|
115
125
|
|
|
116
|
-
|
|
126
|
+
既定では両方とも、起動したCLI本体と依存を`CODEX_HOME/codex-steer/runtimes/<version>-<sha256>`へ検証して保存し、そのコピーへの実行コマンドを監督プロンプトに埋め込みます。監督役に渡す切り替えオプションは不要です。npxのキャッシュが新版に更新された場合や、ソース導入先を`git pull`・削除した場合も、開始済みの監督は保存した内容を使い続けます。
|
|
117
127
|
|
|
118
128
|
実行コマンドには、生成時に検証した`CODEX_HOME`の実体パス、監督ごとの`--supervisor` ID、選択した`--connection`も埋め込みます。先頭の指定とオプションを全て保持してください。貼り付け先の環境変数が未設定・別設定でも、生成元の接続先と履歴を使います。同じPCで使い、監督中は保存したコピーを保持してください。新しいCLIや別のプロファイルに切り替えるときは、その環境から監督を起動し直すか、プロンプトを生成し直します。同じ版・同じ内容のコピーは検証して再利用し、内容が変われば別の保存先を作ります。既存のコピーは自動削除・上書きしません。
|
|
119
129
|
|
|
@@ -121,6 +131,15 @@ Node本体はコピーせず、開始時の実体への絶対パスとNodeバー
|
|
|
121
131
|
|
|
122
132
|
起動時にバージョンを指定するかどうかに関係なく、監督用CLIの保存処理は同じです。キャッシュの動作と保存処理の詳細は[配布ドキュメント](docs/distribution.md#監督役が使うcli)を参照してください。
|
|
123
133
|
|
|
134
|
+
絶対パスを埋め込まず、PATH上の`codexteer`をプロンプトで案内するには、`--use-path-cli`を指定します。
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
codexteer supervise <thread-id> --use-path-cli
|
|
138
|
+
codexteer supervise prompt <thread-id> --use-path-cli
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
この場合の実行例は`codexteer --supervisor '<SESSION-ID>' --connection shared read <thread-id> --json`の形式です。CLIのコピー・Nodeの固定・`CODEX_HOME`の埋め込みを行わず、実行環境のPATHと`CODEX_HOME`を使います。CLIの更新は次の実行から反映されます。監督ID・接続方式・一時停止等の制御は維持するため、対象Desktopと同じプロファイルで実行してください。直接起動時も同じプロンプトを渡し、登録と終了時の停止を行います。`--agent`・監督方針・`--connection desktop`と併用でき、エージェント用の`--`区切りより前に指定します。`supervise prompt --json`の`data.cli_mode`は`path`、`data.deployment`と`data.node`は`null`です。指定しなければ`cli_mode`は`saved`で、従来の保存済みCLIを使います。
|
|
142
|
+
|
|
124
143
|
モデルなどClaude側の起動引数は、`--`の後ろへ渡します。
|
|
125
144
|
|
|
126
145
|
```bash
|
|
@@ -224,7 +243,7 @@ codexteer supervise <thread-id> --agent codex --connection desktop
|
|
|
224
243
|
|
|
225
244
|
直接接続で使えるのは観測です。送信・新規ターン・撤回送信・UI送信は`DESKTOP_READ_ONLY`で拒否します。送信は既存のshared方式を明示して使ってください。生成する監督プロンプトも接続方式を保持し、desktopでは観測専用の手順を使います。`doctor`は読み取り成功から送信・画面表示・承認継続の対応を推測しません。
|
|
226
245
|
|
|
227
|
-
詳細は`help connection`を参照してください。今回の開発環境にはこのソケットがなく、実Desktopへの直接接続は未検証です。読み取り・エンドポイント検査・送信拒否は隔離したUnixソケットの模擬サーバーで検証しています。同梱Codex CLI 0.
|
|
246
|
+
詳細は`help connection`を参照してください。今回の開発環境にはこのソケットがなく、実Desktopへの直接接続は未検証です。読み取り・エンドポイント検査・送信拒否は隔離したUnixソケットの模擬サーバーで検証しています。同梱Codex CLI 0.155.0-alpha.16.3を一時プロファイルとローカルの偽モデルで動かし、保護ソケットへのリンクを使って合成履歴を読む検証も通過しました(`npm run test:connection`)。実Desktopの画面表示・承認継続の確認とは区別しています。
|
|
228
247
|
|
|
229
248
|
### タスクを探して送信する
|
|
230
249
|
|
|
@@ -325,6 +344,9 @@ codexteer supervise prompt codex://threads/<thread-id>
|
|
|
325
344
|
# 標準の監督方針を置き換えて本文を生成
|
|
326
345
|
codexteer supervise prompt <thread-id> "監督方針を指定するメッセージ"
|
|
327
346
|
|
|
347
|
+
# PATH上のcodexteerを案内する本文を生成
|
|
348
|
+
codexteer supervise prompt <thread-id> --use-path-cli
|
|
349
|
+
|
|
328
350
|
# JSONで対象IDと本文を取得
|
|
329
351
|
codexteer supervise prompt <thread-id> --json
|
|
330
352
|
|
|
@@ -332,9 +354,11 @@ codexteer supervise prompt <thread-id> --json
|
|
|
332
354
|
codexteer help supervise prompt
|
|
333
355
|
```
|
|
334
356
|
|
|
335
|
-
`supervise prompt`は、ClaudeやCodexなどの監督役(オーケストレーター)へ渡す初期プロンプトを生成します。対象ID
|
|
357
|
+
`supervise prompt`は、ClaudeやCodexなどの監督役(オーケストレーター)へ渡す初期プロンプトを生成します。対象IDと引数を検証し、既定ではCLI一式を内容ハッシュ別の保存先へ配置・検証してから、正規化したIDと保存先を本文へ埋め込みます。保存・検証に失敗した場合は本文を出力せず、直接起動の場合も監督エージェントを起動しません。Desktopの起動・接続、履歴取得、送信、監督エージェントの起動は行いません。タスクの存在と接続は監督開始時に確認します。本文には観測・根拠付き介入・結果確認・停止までの手順を含みます。
|
|
358
|
+
|
|
359
|
+
既定の各コマンドは開始時のNodeと保存したCLIの絶対パスを使うため、本文を貼り付ける先のPATHに`codexteer`がなくても実行できます。先頭の`CODEX_HOME='…'`で生成元のプロファイルを指定します。相対パスやシンボリックリンクで指定していたホームも、検証した実体への絶対パスを使います。空白や引用符を含むパスはシェル引数として引用します。本文に埋め込むパスに改行等の制御文字があれば、本文を出力する前に`SUPERVISION_PATH_UNSAFE`で拒否します。`CODEX_HOME`指定・引用・`--require-node-version`を含め、実行コマンドをそのまま使ってください。別のPCや別のプロファイルを監督する場合は、そこで本文を生成し直してください。
|
|
336
360
|
|
|
337
|
-
|
|
361
|
+
`--use-path-cli`を指定すると、本文はPATH上の`codexteer`を使い、CLIの保存や絶対パスの埋め込みを省略します。接続先と履歴は実行環境の`CODEX_HOME`に従います。
|
|
338
362
|
|
|
339
363
|
通常出力は末尾改行付きの本文のみです。`--json`では既存CLIと同じ形式で返します。
|
|
340
364
|
|
|
@@ -345,11 +369,12 @@ codexteer help supervise prompt
|
|
|
345
369
|
"data": {
|
|
346
370
|
"thread_id": "01a04373-3770-71e0-a2e3-a3c196f5f5b1",
|
|
347
371
|
"prompt": "対象IDと保存したCLIの実行コマンドを含む監督プロンプト本文…",
|
|
372
|
+
"cli_mode": "saved",
|
|
348
373
|
"deployment": {
|
|
349
374
|
"codex_home": "/Users/me/.codex",
|
|
350
|
-
"directory": "/Users/me/.codex/codex-steer/runtimes/0.
|
|
351
|
-
"wrapper_path": "/Users/me/.codex/codex-steer/runtimes/0.
|
|
352
|
-
"version": "0.
|
|
375
|
+
"directory": "/Users/me/.codex/codex-steer/runtimes/0.17.0-<sha256>",
|
|
376
|
+
"wrapper_path": "/Users/me/.codex/codex-steer/runtimes/0.17.0-<sha256>/bin/codexteer-wrapper.mjs",
|
|
377
|
+
"version": "0.17.0",
|
|
353
378
|
"sha256": "<sha256>",
|
|
354
379
|
"reused": false
|
|
355
380
|
},
|
package/docs/distribution.md
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# 配布と永続実行
|
|
2
2
|
|
|
3
3
|
パッケージ名は `codexteer`、CLI名は `codexteer`、ライセンスはMITです。
|
|
4
|
-
旧npmパッケージは`@vinhphatfsg/codex-steer`です。`codexteer@0.
|
|
4
|
+
旧npmパッケージは`@vinhphatfsg/codex-steer`です。`codexteer@0.16.0`は公開済みで、このブランチはプロジェクトチャット作成を追加するマイナー更新`0.17.0`を準備します。GitHubのPR作成・マージはnpm公開を行う操作ではありません。公開時は`npm whoami`でnpm側のユーザーを確認してください。
|
|
5
5
|
`package.json` は `private` を持たず、`publishConfig` でnpm公式レジストリへのpublic公開を指定しています。公開可能な設定であることと、実際に公開済みであることは別です。
|
|
6
6
|
|
|
7
7
|
公開後の基本的な実行形式は次のとおりです。通常はバージョン指定なしで使えます。監督開始後は保存したCLIを使い続けるため、監督中の一貫性を保つために版を明示する必要はありません。起動側と操作側の製品バージョンも、必要な通信仕様が対応していれば異なっていても使えます。
|
|
8
|
-
以下の監督機能は公開済みの0.15.0から利用できます。0.16.0
|
|
8
|
+
以下の監督機能は公開済みの0.15.0から利用できます。0.16.0では通知集約と監督プロンプトを改善しました。0.17.0のチャット作成機能は公開準備中のため、公開前はこのブランチをソースから導入してください。`-y` はnpmの取得確認を省略します。
|
|
9
9
|
|
|
10
10
|
```text
|
|
11
11
|
npx -y codexteer desktop start
|
|
@@ -25,6 +25,10 @@ CLIはDesktopを自動終了しません。
|
|
|
25
25
|
|
|
26
26
|
## 監督役が使うCLI
|
|
27
27
|
|
|
28
|
+
既定は以下の保存済みCLI方式です。`supervise <THREAD> --use-path-cli`または`supervise prompt <THREAD> --use-path-cli`を指定すると、本文はPATH上の`codexteer`を使います。このモードではCLIを保存せず、本文は現在実行中のCLIから生成します。Nodeのパス・版・CODEX_HOMEを埋め込まず、各コマンドは実行環境のPATHとCODEX_HOMEに従います。更新されたCLIは次の実行から使われます。対象Desktopと同じプロファイルで実行してください。--supervisor・--connectionと監督の登録・停止・送信制御は維持します。本文だけの生成はファイルを書き込まず、直接起動では現在のプロファイルを検証・準備して監督を登録します。JSONの`cli_mode`は`path`、`deployment`と`node`は`null`です。既定方式では`cli_mode`は`saved`です。
|
|
29
|
+
|
|
30
|
+
以下は`--use-path-cli`を指定しない場合の動作です。
|
|
31
|
+
|
|
28
32
|
`0.14.1`以降の`supervise`と`supervise prompt`は、開始時のCLI本体と依存を内容ハッシュ別の永続配置へコピーし、その保存先を使う実行コマンドを本文に埋め込みます。npxで取得したパッケージもソースのチェックアウトも、同じ保存・検証・生成処理を使います。起動経路を推測する環境変数や切り替えオプションは不要です。本文の生成処理自体も保存したCLI一式から読み込みます。
|
|
29
33
|
|
|
30
34
|
両形式で対象IDの後ろに任意の`MESSAGE`を一つの引数として渡せます。省略時は保存したCLIの標準方針を使い、指定時は標準方針全体をその文に置き換えます。必須の共通テンプレートは保存したCLIから常に生成し、対象・実行コマンド・操作時の確認を保ちます。指定文は生成・起動ごとの入力で、永続配置のファイルやマニフェストへ書き込まず、内容ハッシュにも含めません。同じCLIなら異なる方針でも保存先を検証して再利用します。空文字・空白だけの文は保存処理前に`INVALID_SUPERVISION_POLICY`で拒否します。本文の文字列はテンプレートやシェルとして評価しません。
|
|
@@ -64,7 +68,7 @@ README、CHANGELOG、MIT LICENSE、package.jsonに加え、依存する `ws` と
|
|
|
64
68
|
|
|
65
69
|
## 永続配置
|
|
66
70
|
|
|
67
|
-
`desktop start` は呼び出したパッケージの実行用ファイルを、次の場所へコピーしてからDesktopを起動します。`supervise`と`supervise prompt
|
|
71
|
+
`desktop start` は呼び出したパッケージの実行用ファイルを、次の場所へコピーしてからDesktopを起動します。`supervise`と`supervise prompt`も、`--use-path-cli`を指定しない場合は同じ配置処理を使い、監督役が使うコピーを準備します。
|
|
68
72
|
|
|
69
73
|
```text
|
|
70
74
|
<canonical CODEX_HOME>/codex-steer/runtimes/<version>-<sha256>/
|
|
@@ -175,7 +179,7 @@ npxから模擬Claudeと模擬Codexを起動して保存したCLIへの参照を
|
|
|
175
179
|
|
|
176
180
|
レビュー・検証を終えた版を、npm側の公開権限を持つアカウントで公開します。手動公開には2FAを有効にしたアカウントを使ってください。
|
|
177
181
|
|
|
178
|
-
公開済みのパッケージ名とバージョンの組み合わせは再公開できません。既存の`codexteer@0.
|
|
182
|
+
公開済みのパッケージ名とバージョンの組み合わせは再公開できません。既存の`codexteer@0.16.0`は変更せず、今回の配布物は`codexteer@0.17.0`として準備します。公開は別途実行します。削除しても同じ名前・版番号の組み合わせを再利用できません。[npm publishの仕様](https://docs.npmjs.com/cli/v11/commands/npm-publish/)
|
|
179
183
|
|
|
180
184
|
```bash
|
|
181
185
|
npm login
|
|
@@ -184,11 +188,11 @@ npm run test:package
|
|
|
184
188
|
npm publish --access public
|
|
185
189
|
```
|
|
186
190
|
|
|
187
|
-
公開後は、公開した版と起動コマンドの登録を確認します。次は0.
|
|
191
|
+
公開後は、公開した版と起動コマンドの登録を確認します。次は0.17.0を公開した場合の例です。
|
|
188
192
|
|
|
189
193
|
```bash
|
|
190
|
-
npm view codexteer@0.
|
|
191
|
-
npx -y codexteer@0.
|
|
194
|
+
npm view codexteer@0.17.0 version bin --json
|
|
195
|
+
npx -y codexteer@0.17.0 --version
|
|
192
196
|
```
|
|
193
197
|
|
|
194
198
|
`EPRIVATE`はリポジトリの`package.json`に公開禁止設定が残っていることを示します。`--access public`はその禁止を解除しません。
|
|
@@ -213,3 +217,19 @@ npx -y codexteer@0.16.0 --version
|
|
|
213
217
|
`--connection desktop`は既存の`CODEX_HOME/app-server-control/app-server-control.sock`へ読み取り専用で接続します。ホームは所有者一致かつgroup/other書込不可、制御ディレクトリとソケットは所有者専用に限定します。接続前後・各API要求でendpointを検査し、ロード済み対象だけを読み取ります。明示的な選択であり、自動検出による接続切り替え・daemon起動・Desktop再起動はしません。送信機能の診断は`unsupported`、`source: observation-only`です。実機での送信・UI表示・承認継続は未検証のまま残します。
|
|
214
218
|
|
|
215
219
|
開発用の`npm run test:connection`は、Desktop同梱CLIを一時プロファイルのUnixソケットで起動し、ローカル偽モデルで作った合成履歴の読み取りを確認します。実Desktopへの接続・設定変更や外部モデル利用は行いません。`npm run test:protocol`は既存wrapper・偽Desktopとの送信と承認経路、`npm run test:package`は実tarball・オフラインnpx・偽Claude/Codexの起動と、別CODEX_HOME・キャッシュ削除後の観測/送信・pause/resume・重複拒否を確認します。これらの隔離検証から実Desktopの表示や直接接続での承認往復まで保証するものではありません。
|
|
220
|
+
|
|
221
|
+
## 0.17.0の公開候補
|
|
222
|
+
|
|
223
|
+
`package.json`と`package-lock.json`の版を0.17.0に揃えています。0.16.0はnpm registryで公開済みであることを確認し、同じ版への上書き公開は行いません。`projects list`と`thread create --project`、Desktopの所属登録、全フォルダと初回指示の照合を追加します。既存のruntime protocolとcapability契約はv1を維持します。
|
|
224
|
+
|
|
225
|
+
公開前に構文・全回帰・tarballとoffline install・npm/npx・publish dry-runを確認します。公開するファイルを固定する場合は、検証済みtarballのSHA-256を照合してから同じtarballを公開してください。PRのReady化やバージョン更新だけではnpmへ公開されません。
|
|
226
|
+
|
|
227
|
+
2026-10-15 JSTの公開候補で、次を確認しました。
|
|
228
|
+
|
|
229
|
+
- `npm ci --offline --ignore-scripts --no-audit --no-fund`、`npm run check`、`git diff --check`が成功。
|
|
230
|
+
- `node --test --test-concurrency=1`は294件成功、失敗・skipなし。内部RPCエラーによる結果不明の回帰試験を含みます。
|
|
231
|
+
- `npm run test:package`が成功。73ファイルのtarball、offline install、npm exec/npx、保存CLI、混在バージョン、publish dry-runを確認。
|
|
232
|
+
- `npm run test:protocol`と`npm run test:connection`が成功。実同梱CLIと偽Desktop・ローカル偽モデルの隔離試験で、実ユーザーのタスクには送信していません。
|
|
233
|
+
- 0.17.0候補CLIから`CODEX_THREAD_ID`なしで「競馬」へのdry-runが成功。7フォルダ、standalone経路、同梱schemaとnative catalogを確認し、チャット・指示・receiptは作成していません。
|
|
234
|
+
|
|
235
|
+
実Desktopでの作成・所属とCLI終了後の手動承認は[チャット作成の実測記録](thread-create.md)を参照してください。PR確定前の開発作業ツリーで記録した過去の件数と、今回のPRだけを含む294件・73ファイルは検証範囲が異なります。npm公開・Gitタグ作成はこの準備に含みません。
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# 中継AIなしのDesktopチャット作成経路の調査
|
|
2
|
+
|
|
3
|
+
実装・直接作成・承認往復の後続結果は[現在の運用と実機検証](thread-create.md)を参照。以下は実装前の調査時点の記録です。
|
|
4
|
+
|
|
5
|
+
調査日: 2026-10-14 JST。対象はインストール済みDesktop `26.1007.30912` (build `20156`, bundle ID `com.openai.codex`) と同梱CLI `0.162.0-alpha.17.2`。この調査ではチャット作成、指示送信、所属変更、Desktop再起動、実装の置換を行っていない。
|
|
6
|
+
|
|
7
|
+
## 結論と検証の境界
|
|
8
|
+
|
|
9
|
+
モデル推論を伴わずにDesktopのnative toolを実行できる接続経路がある。認証されたnative RPCの `tools/list` に `create_thread`、`move_thread_to_project`、`list_projects` が存在し、`tools/call` で `list_projects` を実行できた。追加のAIターンや中継指示は不要だった。
|
|
10
|
+
|
|
11
|
+
native `create_thread` はDesktop内でプロジェクトの全フォルダを解決し、スケジュールと同じ `threadProjectAssignments.setAssignment` を使って所属を保存する。実装候補は既存Desktop wrapperからこのnative toolを直接呼ぶ方法である。ただし、今回の直接RPC検証は読み取りまで。直接RPCによる作成、所属の実機反映、初回指示、CLI終了後の承認往復は未検証であり、現行のAI中継実装はまだ置換していない。
|
|
12
|
+
|
|
13
|
+
以前の「複数フォルダ・重複フォルダにはAI中継が必要」という判断は、native RPCの直接呼出しを調べきる前だった。native RPCの存在と読み取り実測により、その判断は修正する必要がある。
|
|
14
|
+
|
|
15
|
+
## スケジュールが正しい所属になる理由
|
|
16
|
+
|
|
17
|
+
スケジュールの `Ll` は新しいthreadを作成した後、初回ターン開始前にDesktopの所属サービスを呼ぶ。
|
|
18
|
+
|
|
19
|
+
```js
|
|
20
|
+
await threadProjectAssignments.setAssignment({
|
|
21
|
+
threadId,
|
|
22
|
+
assignment: { projectKind: "local", projectId: project.projectId },
|
|
23
|
+
});
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Desktopの所属ストアは `thread-project-assignments` / `projectless-thread-ids` であり、更新時に `thread-project-memberships-updated` を通知する。App Serverのcanonical `projectId` だけを設定する経路と一致しないため、同じcwdを持つ「競馬」と `prediction_model` で分類の差が生じていた。直接global stateを書き換える方法は採用しない。Desktop自身も汎用 `set-global-state` によるこの所属ストアの変更を拒否している。
|
|
27
|
+
|
|
28
|
+
native toolの作成処理は次の経路を通る。
|
|
29
|
+
|
|
30
|
+
1. `create_thread` handler (`execution-fde3a4937b6a.js` の `sp`) が引数を検証し、Desktopのチャット作成処理へ渡す。
|
|
31
|
+
2. `sso` → `MZr` が指定したDesktopプロジェクトIDからcwd、全workspace roots、`projectAssignment` を取得する。
|
|
32
|
+
3. `HGi` → manager `startConversation` → `zln` がthreadを作成し、初回ターン前のcallbackで `saveThreadProjectAssignment` を呼ぶ。
|
|
33
|
+
4. このcallbackはDesktop hostの `threadProjectAssignments.setAssignment` を呼び、所属ストアと表示へ反映する。callbackがない構成でも `threadWorkspaceStorage.setProjectAssignment` が同サービスを呼ぶ。
|
|
34
|
+
5. Desktopが初回指示とターン開始を担当する。明示的なsourceThreadIdがあるnative toolでは指示が `codex_delegation` として保存される。
|
|
35
|
+
|
|
36
|
+
`CAr` はプロジェクト内の手動表示順を保存する処理であり、所属登録の本体ではない。所属登録は上記の `setAssignment`。
|
|
37
|
+
|
|
38
|
+
native `move_thread_to_project` もDesktopのsidebar移動処理から所属サービスの `setMembership` を呼ぶ。これは既存のApp Server作成経路に所属登録だけ追加する候補だが、作成と移動の部分成功や初回ターンの順序を別に管理する必要がある。
|
|
39
|
+
|
|
40
|
+
## native RPCと認証
|
|
41
|
+
|
|
42
|
+
Desktopは子プロセスに `CODEX_APP_TOOLS_PIPE_PATH` を渡す。既存shared wrapperがこの値を継承していることを、選択中wrapperの環境の該当キーだけを読み取って確認した。環境全体や秘密値は出力していない。
|
|
43
|
+
|
|
44
|
+
native pipeはUnix domain socket。macOSでは長さ4バイトのnative endian (今回LE) + UTF-8 JSONのframeを使い、frame上限は8 MiB。newline JSONのApp Server protocolとは別物である。socketは所有者専用で、接続時にnativeのsocket peer認証が行われる。既存wrapperはDesktop同梱の署名付きNodeを直接使う。認証を無効化・迂回する方法は使っていない。
|
|
45
|
+
|
|
46
|
+
native serverの `Vae` は `tools/call` を `callDynamicAppTool` に渡す。mainのdispatcherは準備済みDesktop windowを選び、rendererの `canCallTool` / `dispatchToolCall` がnative handlerを実行する。ここに中継AIの推論はない。
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"id": "request-uuid",
|
|
51
|
+
"jsonrpc": "2.0",
|
|
52
|
+
"method": "tools/call",
|
|
53
|
+
"params": {
|
|
54
|
+
"arguments": {},
|
|
55
|
+
"callerSource": "codex",
|
|
56
|
+
"callId": "unique-call-uuid",
|
|
57
|
+
"hostId": "local",
|
|
58
|
+
"namespace": "codex_app",
|
|
59
|
+
"threadId": "existing-caller-thread-id",
|
|
60
|
+
"turnId": "actual-stored-caller-turn-id",
|
|
61
|
+
"tool": "list_projects"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`threadId` / `turnId` は呼出し元の監査・関連付け用contextであり、モデルを起動するための指示ではない。今回のprobeは実在するチャットとその保存済みターンだけを使用した。架空IDは使用していない。rendererは呼出し元threadを読み込めることを確認し、callIdの実行claimを取る。idleの保存済みターンを使った読み取りも成功したが、作成toolで同じcontextが使えるかは未検証。
|
|
67
|
+
|
|
68
|
+
`taskProject/assign` という別RPCもあるが、これはWorkのlocal executorの実在environmentIdとthreadのenvironment一致が必要な経路である。通常のCodexチャットに `environmentId: "local"` を付ければ使えるAPIではない。この候補では使用しない。
|
|
69
|
+
|
|
70
|
+
## 読み取りの実測
|
|
71
|
+
|
|
72
|
+
一時probe `/private/tmp/codexteer-native-read-probe.mjs` を同梱Node `/Applications/ChatGPT.app/Contents/Resources/cua_node/bin/node` で実行した。選択中shared runtimeのプロセス確認とローカルIPC読み取りのみ、sandbox外で実施した。
|
|
73
|
+
|
|
74
|
+
| 確認 | 結果 |
|
|
75
|
+
| --- | --- |
|
|
76
|
+
| `tools/list` (`threadStartKind: all`) | 57 native tools。作成・所属移動・プロジェクト一覧のschemaを取得 |
|
|
77
|
+
| `tools/call list_projects`、現在の実在activeターン | `success: true`、23プロジェクト |
|
|
78
|
+
| 同呼出し、既存idleチャットの保存済みcompletedターン | `success: true`、23プロジェクト |
|
|
79
|
+
| idleチャットの後続読取り | idle、latest turnは同じcompletedターン、turn数4。新しいターンは発生していない |
|
|
80
|
+
|
|
81
|
+
idle contextは既存検証チャット `01a135bf-1087-7902-8b78-0fb683b025d6`、保存済みターン `01a135cb-47ba-73a0-befe-6eb41452655e`。現在のcontextはthread `01a135a4-c1ea-7081-be4c-3c5ab7b11193`、turn `01a135d2-9375-78f0-8f39-ced3c29a5d98`。
|
|
82
|
+
|
|
83
|
+
native一覧は次のDesktop IDを返した。作成先にはnative一覧のIDを使う。App Serverのcanonical IDと混ぜない。
|
|
84
|
+
|
|
85
|
+
| label | projectKind | Desktop projectId |
|
|
86
|
+
| --- | --- | --- |
|
|
87
|
+
| codex-steer | local | `8b8c19b2-5a36-4683-8b2f-28a489e03724` |
|
|
88
|
+
| 競馬 | local | `ad16728e-81d9-499f-81c8-fdf13f0f9d89` |
|
|
89
|
+
| prediction_model | local | `cad845a7-dfb1-45b8-8503-b9aca1ee89d6` |
|
|
90
|
+
| 競馬 | chatgpt | `g-p-69379d229d7081918b1efb6f5c107d17` |
|
|
91
|
+
|
|
92
|
+
localの「競馬」と `prediction_model` は両方ともpathが `/Users/phat/Desktop/app_race-calc_h/prediction_model` だが、IDは異なる。同名ChatGPTプロジェクトも存在するので、プロジェクト解決ではkindとIDを確認する。
|
|
93
|
+
|
|
94
|
+
## codexteerへの組込み候補
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
terminal CLI → 共有App Serverのcommand/exec
|
|
98
|
+
→ 固定の署名付きNode helper(thread/turnやモデル推論なし)
|
|
99
|
+
→ Desktop native RPC tools/call create_thread
|
|
100
|
+
→ Desktopでproject roots解決・setAssignment・初回ターン開始
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
実装時には、wrapper自身のnative接続では署名情報検証に失敗することを確認したため、既存App Serverの正規の子としてhelperを起動する経路を採用した。command/execは独立したコマンド実行APIで、チャットやAIターンを作らない。matching CLI schemaで対応を確認し、固定の署名付きNodeとhelperに限定する。詳細と実測は現在の運用文書を参照。
|
|
104
|
+
|
|
105
|
+
端末からの呼出しには実在するcaller contextの明示または確実な解決が必要である。context用チャットのモデル起動や追加ターンは不要な見込みだが、作成toolで検証してから契約にする。現在の `--via-thread` のようなAIへのメッセージ配送は廃止候補となる。
|
|
106
|
+
|
|
107
|
+
nativeの作成引数は以下で、promptと指定プロジェクトをそのまま渡せる。
|
|
108
|
+
|
|
109
|
+
```json
|
|
110
|
+
{
|
|
111
|
+
"prompt": "initial instruction",
|
|
112
|
+
"title": "optional title",
|
|
113
|
+
"target": {
|
|
114
|
+
"type": "project",
|
|
115
|
+
"projectId": "Desktop projectId",
|
|
116
|
+
"environment": { "type": "local" }
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
モデル・thinkingはnative schemaの対応範囲内で指定可能。cwd・sandbox・approval policy等を任意に上書きする引数はこのnative toolにないため、既存CLIのオプションをそのまま対応済みとは扱わない。native経路でDesktopの設定を使うか、所属移動だけを使う別経路が必要。
|
|
122
|
+
|
|
123
|
+
組込み後の必須検証は、単一フォルダと「競馬」の全7フォルダ、共有cwdでの正しいDesktop所属、初回指示の完全一致、短命CLI終了後のDesktop承認継続・承認往復、途中失敗の同一attemptでの照合である。tool callIdがあることを作成のidempotency保証と解釈せず、不明結果を自動再送しない。
|
|
124
|
+
|
|
125
|
+
native RPCはこのDesktop内部のversion依存interfaceであり、公開App Server互換契約ではない。wrapperのcapabilityとnative schema/接続を確認し、未対応なら作成前に止める。AI中継へ自動fallbackしない。稼働中wrapperへコードを追加するには対応版で起動し直す必要があるが、この調査では再起動していない。
|
|
126
|
+
|
|
127
|
+
## 調査に使用したインストール済みコード
|
|
128
|
+
|
|
129
|
+
ASARは読み取り専用で展開し、bundleや署名は変更していない。minified名はこのbuildに限る。
|
|
130
|
+
|
|
131
|
+
| ASAR resource | SHA-256 |
|
|
132
|
+
| --- | --- |
|
|
133
|
+
| `.vite/build/main-CqEoQDOU.js` | `09d19386e1f23cf4ccbc950fc40d85a1e8a064a08be588b2a4be6a89f6ada9e6` |
|
|
134
|
+
| `webview/assets/app-initial-6350d04672d0.js` | `604b5d2de4fbb41f3d0dc5b3662129c558e1c7b8aac8cc87225286f58dcfaf8f` |
|
|
135
|
+
| `webview/assets/app-shared-8bd9d0399038.js` | `607ad0866dd25ed3764711b4467a9b60708353a599485b5249ff4cbe0e870245` |
|
|
136
|
+
| `webview/assets/execution-fde3a4937b6a.js` | `5c300497b7331bfa317231251e1097385405b70f2746b1fe8959c74e56735811` |
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Desktopプロジェクトにチャットを直接作成する
|
|
2
|
+
|
|
3
|
+
`projects list`でローカルプロジェクトを確認し、`thread create`で初回指示付きのチャットを作成します。Desktopのnative RPCを使い、中継AIは実装から削除しました。「競馬」のような複数フォルダ・共有フォルダを持つプロジェクトにも対応します。
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
codexteer projects list --json
|
|
7
|
+
codexteer thread create --project '競馬' \
|
|
8
|
+
--title '関連リポジトリの調査' '関連リポジトリを読み、結果を報告してください' --json
|
|
9
|
+
codexteer thread create --project '競馬' \
|
|
10
|
+
--dry-run '調査してください' --json
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**プロジェクト名と初回指示だけで作成できます。`--context-thread`も`CODEX_THREAD_ID`も不要です。** 既存チャットがないプロジェクトでも使えます。既存チャットを探したり、別のAIを起動したりせず、作成したチャット自身の実在thread/turn IDでnative所属登録を呼びます。
|
|
14
|
+
|
|
15
|
+
`--context-thread`を明示した場合だけ、その既存チャットの保存済みターンを関連付けてnative `create_thread`を呼びます。idleでも使用できます。呼出し元への送信や追加のAIターンはありません。省略時は環境変数`CODEX_THREAD_ID`も参照せず、独立した作成になります。
|
|
16
|
+
|
|
17
|
+
プロジェクト名は完全一致で選び、同名なら`projects list`のIDを指定します。App Serverのcanonical IDとDesktop IDは読取り専用の対応表・native一覧で照合します。同名のChatGPTプロジェクトは選択しません。cwdだけで所属を推測しません。
|
|
18
|
+
|
|
19
|
+
## 作成と所属登録
|
|
20
|
+
|
|
21
|
+
標準経路は次のとおりです。
|
|
22
|
+
|
|
23
|
+
```text
|
|
24
|
+
terminal CLI → App Server thread/start(選択プロジェクトの全フォルダ)
|
|
25
|
+
→ Desktopの長期接続で購読 → turn/start(初回指示を1回だけ送信)
|
|
26
|
+
→ 共有App Serverのcommand/exec(追加のthread/turnを作らないAPI)
|
|
27
|
+
→ 固定の署名付きNode helper(read-only sandbox)
|
|
28
|
+
→ native tools/call move_thread_to_project(新規チャット自身)
|
|
29
|
+
→ Desktopの所属サービスで登録・表示更新
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
App Serverはnative操作用にcodexteer同梱の固定helperだけを起動します。native引数は所有者専用の一時JSONファイルで渡し、shellやargvへ埋め込みません。helperの許可操作はcatalog、list_projects、ローカルcreate_thread、新規チャット自身のmove_thread_to_projectだけです。新規チャットの初回処理以外のモデル推論は発生しません。
|
|
33
|
+
|
|
34
|
+
作成前に、実行中サーバーと同じ同梱CLIからcommand/execとread-only sandboxのschemaを確認します。helperはDesktopのpeer認証を通過する署名付きApp Serverの正規の子として実行されます。Unix socketへ接続するためsandboxのnetworkAccessはtrueですが、helperにHTTP/DNSや外部サービスへの接続処理はありません。認証チェックや署名は変更しません。
|
|
35
|
+
|
|
36
|
+
codexteerは選択プロジェクトからプライマリcwdと全workspace rootsを解決します。名前とcanonical所属をAPIで保存し、Desktopの購読を確立します。初回指示の前に範囲と空の履歴を確認します。初回受付後、Desktopのnative所属サービスを呼び、スケジュールと同じ所属ストアと表示へ反映します。作成応答だけを成功の証拠にせず、保存されたDesktop所属、canonical projectId、全フォルダ、userMessageとして保存された初回指示の完全一致とタイトルを照合します。関連付けを明示したnative作成の場合は、`codex_delegation`の呼出し元IDと本文を含むliteral全文を比較します。XMLとして解釈しません。
|
|
37
|
+
|
|
38
|
+
受付が履歴の永続化より早い場合は、最大5秒間、読取りだけで反映を待ちます。作成や初回ターンを再実行しません。standaloneではcanonical所属をthread/startで指定し、購読前にmetadata APIでも保存します。関連付けを明示したnative作成では必要に応じてmetadata APIでcanonical所属を登録します。Desktopの状態ファイル・DBを直接書き換えません。
|
|
39
|
+
|
|
40
|
+
CLI終了後の承認はDesktopが担当します。codexteerは承認を自動回答しません。
|
|
41
|
+
|
|
42
|
+
## 設定と接続の制約
|
|
43
|
+
|
|
44
|
+
- `--title`、`--model`、`--thinking`を明示指定できます。standaloneで指定しないモデル・権限・承認はプロジェクトのApp Server設定に従います。他チャットの設定を継承しません。関連付けを明示した場合はDesktopのnative作成規則に従います。
|
|
45
|
+
- standaloneで`--title`を省略すると、初回指示の空白をまとめた先頭80文字を名前にします。タイトル生成用のAIは起動しません。対象サーバーでは未使用の空チャットをDesktopが購読するために、先に名前を保存して履歴を永続化する必要があります。
|
|
46
|
+
- cwd・permissions・sandbox・approval policy・approvals reviewerの上書きはnative schemaにないため、指定すると作成前に拒否します。
|
|
47
|
+
- `--via-thread`のAI中継経路は削除しました。自動fallbackもありません。
|
|
48
|
+
- 対応先は登録済みローカルプロジェクトです。worktree、remote、ChatGPT cloudは未対応です。
|
|
49
|
+
- `--timeout-ms`は各RPCの待機期限で、既定120000、1000〜600000です。
|
|
50
|
+
- `--dry-run`は接続・プロジェクト・native schemaを読み、チャット・指示・receiptを作りません。
|
|
51
|
+
|
|
52
|
+
native RPCはDesktop内部のversion依存APIです。この実装の実測はDesktop `26.1007.30912`と`26.1007.71326` / 同梱CLI `0.162.0-alpha.17.2`です。未対応schema、unsafe socket、変更されたendpoint、認証拒否では止めます。
|
|
53
|
+
|
|
54
|
+
wrapperはnative endpointを所有者専用runtimeに公開します。公開されていない旧wrapperでは、選択済み・所有者検証済みPIDと同梱Node実行ファイルを確認し、継承環境のnative endpointだけを取得します。環境全体を出力・保存しません。
|
|
55
|
+
|
|
56
|
+
作成処理は既存の共有App Serverのcommand/execを使うため、専用control serviceの追加・native_tools_rpcフラグ・追加のDesktop再起動を必要としません。wrapper自身からnative接続する旧経路と、外部Nodeがnative workerを直接起動する経路は削除しました。通常の`codexteer`コマンドがそのまま使えます。
|
|
57
|
+
|
|
58
|
+
`--dry-run`でもschemaと要求JSONの一時ファイルを作成・削除します。チャット、追加AIターン、永続receiptは作りません。
|
|
59
|
+
|
|
60
|
+
## 配送不明と部分成功
|
|
61
|
+
|
|
62
|
+
作成前に`CODEX_HOME/codex-steer/creations/<attempt_id>.json`を所有者専用で保存します。standaloneのschemaは3、`creation_mode`は`standalone`、外部`context_thread_id`と`context_turn_id`はnullです。`native_context_*`は新規チャット自身の実在IDです。`native_call_id`は所属登録のcall IDでattempt IDと一致します。初回指示のSHA-256、所属ID、rootと名前を記録します。standaloneでは省略時の名前が初回指示の先頭80文字になるため、JSON出力・receiptの`title`にもこの文字列が含まれます。指示全文の専用フィールドやAI中継用のmessages journalは作りません。
|
|
63
|
+
|
|
64
|
+
- `creation_status: created`は既に子チャットが存在することを示します。照合失敗でも同じIDを調べ、作成を再実行しません。
|
|
65
|
+
- `sent: true` / `delivery_status: accepted`は初回ターンの受付です。後続の所属登録・照合やreceipt保存が失敗しても、この受付を取り消しません。standaloneでは所属登録前に指示が開始するため、所属登録失敗もcreated/acceptedとして保持します。
|
|
66
|
+
- `creation_status: unknown` / `dispatching`は未作成の証拠ではありません。接続断・時間切れ・不明応答で自動再送しません。
|
|
67
|
+
- `verification_status: verified`と所属・初回指示の個別verifiedが、照合完了の証拠です。
|
|
68
|
+
- 最終receipt保存だけ失敗した場合は`receipt_update_required`を返します。受付済み操作を再送可能な失敗に変換しません。
|
|
69
|
+
|
|
70
|
+
## 実機検証 (2026-10-14 JST)
|
|
71
|
+
|
|
72
|
+
- 直接作成と承認: `01a135f5-85aa-7410-a0cf-1a0eed53037f`、attempt `b7479787-a995-4566-a1d0-5f05a8bc6035`。native CLIは終了済みでもDesktopで`waitingOnApproval`が継続。Desktop一覧のprojectIdは「競馬」の`ad16728e-81d9-499f-81c8-fdf13f0f9d89`。初回commentaryに`CODEXTEER_NATIVE_INITIAL_INSTRUCTION_OK`。
|
|
73
|
+
- ユーザーの「今回だけ承認」後、`printf CODEXTEER_NATIVE_APPROVAL_OK`がexit 0、最終応答`CODEXTEER_NATIVE_APPROVAL_ROUNDTRIP_OK`を確認。
|
|
74
|
+
- この最初の試行は受付直後の履歴照合が早すぎ、CLIがcreated/acceptedの部分成功を返した。反映待ちを修正し、同じ子ID・同じattemptを読み取り照合してreceiptを確定。再作成・再送していない。
|
|
75
|
+
- 修正後CLI全体: `01a135f9-3974-7983-a756-5d6b31968fd0`、attempt `daf87c13-7df3-45b0-acb6-4e7ea56f32ef`。Desktop所属・canonical所属・7フォルダ・初回指示・タイトルの照合を完了しexit 0。最終応答`CODEXTEER_NATIVE_CREATE_VERIFIED`。
|
|
76
|
+
- contextは`01a135b4-b84b-7530-9c25-5bde83077c9e`の既存completedターン。終了後もidle、turn数1、latest turnは`01a135b4-bac5-7f62-9014-d109c5a37b92`。中継AIターンは発生していない。
|
|
77
|
+
- 稼働中wrapperを中断しないため、実Desktopの作成試験は同梱NodeでCLIを直接実行した。当時のcontrol経路はローカルsocket試験までで、その後の実機確認で修正しました。現行経路と結果は次節を参照。
|
|
78
|
+
|
|
79
|
+
これらは特定Desktop/CLIの実測で、将来のリリースや全承認種別の認定ではありません。[調査時の経路とコード根拠](thread-create-native-investigation.md)も参照してください。
|
|
80
|
+
|
|
81
|
+
## 再起動後の通常CLI検証 (2026-10-15 JST)
|
|
82
|
+
|
|
83
|
+
Desktop `26.1007.71326` / 同梱CLI `0.162.0-alpha.17.2`で実測しました。
|
|
84
|
+
|
|
85
|
+
- 最初の再起動後、旧native_tools_rpc:1のwrapper自身の接続は`missing-code-signing-identity`で拒否され、dry-runで停止。チャットは作成していません。
|
|
86
|
+
- 接続元の起動経路を修正し、既存App Serverのcommand/execから固定の署名付きhelperをread-only sandboxで起動する方式に切り替えました。追加の再起動なしで通常CLIのdry-runが成功しました。
|
|
87
|
+
- 通常の`codexteer thread create --project 競馬 --context-thread ...`がexit 0。作成IDは`01a13e01-2d5a-7bc2-a752-dbdddda9d1ea`、attemptは`68b4064b-eabc-444b-8607-935e66ebbb62`です。Desktop一覧の「競馬」所属、canonical所属、7フォルダ、タイトル、初回指示を全てverifiedで返しました。
|
|
88
|
+
- 初回commentaryに`CODEXTEER_STANDARD_CLI_INITIAL_OK`、printfがexit 0、最終応答`CODEXTEER_STANDARD_CLI_ROUNDTRIP_OK`。この時のDesktop設定はauto_reviewでした。
|
|
89
|
+
- 手動承認は同じ検証チャットだけをapprovalsReviewer:user / on-request / read-onlyへ変更した後続ターン`01a13e03-559a-7f12-9d9f-2d7650c52ae8`で確認しました。他チャットやプロジェクト設定は変更していません。
|
|
90
|
+
- このターンの短命senderは`2026-10-15T05:22:48.359Z`に終了し、その後もDesktopのwaitingOnApprovalが継続。ユーザーの「今回だけ承認」後、`printf CODEXTEER_STANDARD_CLI_HUMAN_APPROVAL_OK`がexit 0、最終応答`CODEXTEER_STANDARD_CLI_HUMAN_ROUNDTRIP_OK`を確認しました。
|
|
91
|
+
- 呼出し元`01a135b4-b84b-7530-9c25-5bde83077c9e`は元のcompletedターン1件のままです。中継AIや追加ターンは発生していません。
|
|
92
|
+
|
|
93
|
+
## 回帰・配布検証
|
|
94
|
+
|
|
95
|
+
native直接作成の時点では`npm run check`成功、`node --test --test-concurrency=1`は320件中318成功・2skip・失敗0。配布テストもPASSで、76ファイルのpack、publish dry-run、offline install、npm/npx起動を確認しました。公開は行っていません。
|
|
96
|
+
|
|
97
|
+
並列実行では既存checkpointのファイル監視テストが一度失敗しました。同テストの単独実行と全体の逐次実行は成功しています。今回のnative helper関連テストは全て成功しています。
|
|
98
|
+
|
|
99
|
+
## 呼出し元なし・最小引数での検証 (2026-10-15 JST)
|
|
100
|
+
|
|
101
|
+
`env -u CODEX_THREAD_ID codexteer thread create --project 競馬 '初回指示' --json`で実測しました。`--context-thread`、`--title`、モデル・権限上書きは指定していません。
|
|
102
|
+
|
|
103
|
+
- 最終CLIはexit 0。threadは`01a13e22-e9db-71a3-b0d2-703586bf84d5`、attemptは`ed2dc9ec-ac30-445c-9586-dbfcd336179e`。Desktopの「競馬」所属、canonical所属、全7フォルダ、初回指示と名前がverifiedです。
|
|
104
|
+
- `context_thread_id` / `context_turn_id`はnull。native所属登録のcontextは新規thread自身と、その実際の初回ターン`01a13e22-ebfa-7541-b7a1-789676672435`です。既存チャットの読取りやAIターンは不要です。
|
|
105
|
+
- 初回ターンはcompleted、最終応答`CODEXTEER_PROJECT_PROMPT_ONLY_FINAL_OK`。初回指示は通常のuserMessageとして完全一致し、作成時に開始したターンはこの1件だけです。
|
|
106
|
+
- タイトル未指定の試験で、初回ターン前の未保存チャットはDesktop購読やmetadata保存を拒否される条件が見つかりました。名前を先にAPIで保存し、canonical所属を保存してから購読するよう修正しました。途中の2試行はcreated/not_sentのreceiptを保持しています。`95bdf33c-7580-40da-90e2-a2882f4b83af`は履歴0件を確認してアーカイブしました。`cf88c307-7e8d-4140-a074-ed25fa551916`は作成後の読取りをAPIが拒否したため状態を断定せず、receiptを保持しています。いずれも初回指示の送信前で停止し、再送していません。
|
|
107
|
+
- 承認試験は同じ最終チャットの後続ターン`01a13e23-e670-7e60-8107-5317fbbca458`のみをuser/on-request/read-onlyにして実施。作成時のDesktop購読を再利用し、新たな購読は行っていません。短命senderは`2026-10-15T05:58:22.584Z`に終了し、その後もDesktopでwaitingOnApprovalが継続しました。ユーザーの「今回だけ承認」後、`printf CODEXTEER_STANDALONE_HUMAN_APPROVAL_OK`がexit 0、最終応答`CODEXTEER_STANDALONE_HUMAN_ROUNDTRIP_OK`、ターンcompletedを確認しました。所属・7フォルダ・初回指示も再照合し、同じattemptのreceiptをhuman_approval_roundtrip:verifiedへ更新しました。
|
|
108
|
+
- 全体の逐次テストは327件中325成功・2skip・失敗0、`npm run check`と`git diff --check`も成功しました。sandbox内のNode 25によるUnix socket試験は実行環境のassertで終了したため、ローカルsocketを許可した環境で実行・確認しました。
|
|
109
|
+
- 更新後の配布テストもPASS。77ファイルのpack、publish dry-run、offline install、npm exec/npx、保存CLIと混在バージョンの回帰を確認しました。公開は行っていません。
|
|
110
|
+
|
|
111
|
+
## PRレビューでの修正 (0.17.0公開候補)
|
|
112
|
+
|
|
113
|
+
内部RPCエラーを実際の`RpcFailure`型で模擬すると、処理が実行された可能性があっても`not_created` / `not_sent`になる問題が再現しました。内部エラー(`-32603`など)は`unknown`を保持し、メソッド・引数エラー(`-32601` / `-32602`)だけを実行前の拒否として扱うよう修正しています。standaloneの作成・初回配送、native helperと明示的context作成の回帰テストを追加しました。未確認の操作を自動再実行する処理は追加していません。
|
|
114
|
+
|
|
115
|
+
公開前の全回帰で、既存のcheckpoint試験がmacOSの監視通知の到着順に依存して失敗することを変更前のmainでも確認しました。edit-and-restore試験は監視イベントまたはスナップショットのメタデータ差分で対象ファイルの変更が検出されたことを確認し、無効化されるという契約を維持しています。checkpointの実装は変更していません。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codexteer",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.0",
|
|
4
4
|
"description": "Send steering messages to running Codex Desktop threads from a terminal.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
"scripts/*.applescript",
|
|
32
32
|
"assets/send-pururu.wav",
|
|
33
33
|
"CHANGELOG.md",
|
|
34
|
-
"docs/distribution.md"
|
|
34
|
+
"docs/distribution.md",
|
|
35
|
+
"docs/thread-create.md",
|
|
36
|
+
"docs/thread-create-native-investigation.md"
|
|
35
37
|
],
|
|
36
38
|
"bundleDependencies": [
|
|
37
39
|
"ws"
|
package/src/cli.mjs
CHANGED
|
@@ -15,6 +15,8 @@ import { prepareSupervisorPrompt, superviseAgent } from "./supervise.mjs";
|
|
|
15
15
|
import { supervisorId, registerSupervisor, getSupervisor, assertSupervisor, controlSupervisor, supervisorStatus, listSupervisors } from "./supervision.mjs";
|
|
16
16
|
import { createFinding, findingStatus, listFindings, resolveFinding, dismissFinding, reopenFinding, evaluateFinding, findingStats } from "./findings.mjs";
|
|
17
17
|
import { connectionMode, observationConnection, desktopReadOnly } from "./connection.mjs";
|
|
18
|
+
import { listProjects } from "./projects.mjs";
|
|
19
|
+
import { createProjectThread } from "./thread-create.mjs";
|
|
18
20
|
|
|
19
21
|
const DEFAULT_SEND_BACKEND = "app-server";
|
|
20
22
|
|
|
@@ -32,6 +34,9 @@ function fail(error, json) {
|
|
|
32
34
|
message_id: error.message_id, client_message_id: error.client_message_id, journal_update_required: error.journal_update_required,
|
|
33
35
|
existing_message_id: error.existing_message_id,
|
|
34
36
|
supervision_update_required: error.supervision_update_required,
|
|
37
|
+
receipt_path: error.receipt_path,
|
|
38
|
+
creation_status: error.creation_status, attempt_id: error.attempt_id, receipt_update_required: error.receipt_update_required,
|
|
39
|
+
native_call_id: error.native_call_id,
|
|
35
40
|
} }));
|
|
36
41
|
else console.error(`codexteer: ${message}`);
|
|
37
42
|
process.exitCode = 1;
|
|
@@ -182,9 +187,10 @@ export async function main(argv) {
|
|
|
182
187
|
if (command === "supervise" && args[0] === "prompt") {
|
|
183
188
|
args.shift();
|
|
184
189
|
const agent = takeOption(args, "--agent", "claude");
|
|
190
|
+
const usePathCli = takeFlag(args, "--use-path-cli");
|
|
185
191
|
if (args.length < 1 || args.length > 2 || args.some(arg => arg.startsWith("--"))) throw new Error("Expected: supervise prompt <THREAD> [MESSAGE]. See codexteer help supervise prompt.");
|
|
186
192
|
if (supervisor) throw new Error("A supervisor cannot generate a replacement session.");
|
|
187
|
-
const data = await prepareSupervisorPrompt(args[0], args[1], { agent, connection });
|
|
193
|
+
const data = await prepareSupervisorPrompt(args[0], args[1], { agent, connection, usePathCli });
|
|
188
194
|
success("supervise.prompt", data, json);
|
|
189
195
|
if (!json) console.log(data.prompt);
|
|
190
196
|
return;
|
|
@@ -196,8 +202,9 @@ export async function main(argv) {
|
|
|
196
202
|
const ownArgs = separator < 0 ? args : args.slice(0, separator);
|
|
197
203
|
const agentArgs = separator < 0 ? [] : args.slice(separator + 1);
|
|
198
204
|
const agent = takeOption(ownArgs, "--agent", "claude");
|
|
199
|
-
|
|
200
|
-
|
|
205
|
+
const usePathCli = takeFlag(ownArgs, "--use-path-cli");
|
|
206
|
+
if (ownArgs.length < 1 || ownArgs.length > 2 || ownArgs.some(arg => arg.startsWith("--"))) throw new Error("Expected: supervise <THREAD> [MESSAGE] [--agent claude|codex] [--use-path-cli] [-- <AGENT-ARGS...>].");
|
|
207
|
+
process.exitCode = await superviseAgent(ownArgs[0], { agent, agentArgs, policy: ownArgs[1], connection, usePathCli });
|
|
201
208
|
return;
|
|
202
209
|
}
|
|
203
210
|
if (command === "resource") {
|
|
@@ -368,6 +375,15 @@ export async function main(argv) {
|
|
|
368
375
|
return;
|
|
369
376
|
}
|
|
370
377
|
|
|
378
|
+
if (command === "projects") {
|
|
379
|
+
if (connection === "desktop") throw desktopReadOnly();
|
|
380
|
+
if (args.shift() !== "list" || args.length) throw new Error("Expected: codexteer projects list");
|
|
381
|
+
const projects = await listProjects();
|
|
382
|
+
success("projects.list", { projects, count: projects.length }, json);
|
|
383
|
+
if (!json) for (const project of projects) console.log(`${project.project_id} ${project.name}\n${project.roots.map(root => ` ${root}`).join("\n")}`);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
|
|
371
387
|
if (command === "threads") {
|
|
372
388
|
if (args.shift() !== "list") throw new Error("Expected: codexteer threads list");
|
|
373
389
|
const limit = Number.parseInt(takeOption(args, "--limit", "20"), 10);
|
|
@@ -383,7 +399,27 @@ export async function main(argv) {
|
|
|
383
399
|
}
|
|
384
400
|
|
|
385
401
|
if (command === "thread") {
|
|
386
|
-
|
|
402
|
+
const action = args.shift();
|
|
403
|
+
if (action === "create") {
|
|
404
|
+
if (connection === "desktop") throw desktopReadOnly();
|
|
405
|
+
if (supervisor) throw Object.assign(new Error("Managed supervision is bound to its existing task. Run thread create without --supervisor under the user's delegated creation scope."), { code: "SUPERVISOR_CONTROL_FORBIDDEN" });
|
|
406
|
+
const selector = takeOption(args, "--project", undefined);
|
|
407
|
+
const options = { title: takeOption(args, "--title", undefined), cwd: takeOption(args, "--cwd", undefined), model: takeOption(args, "--model", undefined),
|
|
408
|
+
permissions: takeOption(args, "--permissions", undefined), sandbox: takeOption(args, "--sandbox", undefined),
|
|
409
|
+
approvalPolicy: takeOption(args, "--approval-policy", undefined), approvalsReviewer: takeOption(args, "--approvals-reviewer", undefined), dryRun: takeFlag(args, "--dry-run"),
|
|
410
|
+
contextThread: takeOption(args, "--context-thread", undefined), thinking: takeOption(args, "--thinking", undefined), timeoutMs: takeOption(args, "--timeout-ms", undefined) };
|
|
411
|
+
if (options.timeoutMs !== undefined) {
|
|
412
|
+
options.timeoutMs = Number(options.timeoutMs);
|
|
413
|
+
}
|
|
414
|
+
const literal = args.indexOf("--");
|
|
415
|
+
if (args.slice(0, literal < 0 ? args.length : literal).some(arg => arg.startsWith("--"))) throw new Error("Unknown thread create option. Use -- before an instruction starting with --.");
|
|
416
|
+
const message = readMessage(args);
|
|
417
|
+
const data = await createProjectThread(selector, message, options);
|
|
418
|
+
success("thread.create", data, json);
|
|
419
|
+
if (!json) console.log(options.dryRun ? `Dry run: ${data.project_name} (${data.cwd}), ${data.message_characters} characters.` : `Created ${data.deep_link} in ${data.project_name}; initial instruction accepted${data.turn_id ? ` (turn ${data.turn_id})` : ""}.`);
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
if (action !== "resolve") throw new Error("Expected: codexteer thread create|resolve. See help thread.");
|
|
387
423
|
if (args.length !== 1) throw new Error("thread resolve requires exactly one thread ID or URL.");
|
|
388
424
|
const threadId = normalizeThreadId(args[0]);
|
|
389
425
|
const data = { thread_id: threadId, deep_link: threadDeepLink(threadId) };
|