aiterm-mcp 0.52.3 → 0.53.1
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 +50 -1
- package/README.ja.md +14 -3
- package/README.md +14 -3
- package/dist/core.js +13 -8
- package/dist/harnesses/codex.js +33 -4
- package/dist/harnesses/cursor.js +5 -0
- package/dist/harnesses/grok.js +28 -3
- package/dist/index.js +5 -1
- package/docs/DESIGN.md +4 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,53 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.53.1] - 2026-10-05
|
|
11
|
+
|
|
12
|
+
### 修正
|
|
13
|
+
|
|
14
|
+
- 0.53.0で、Grokにログイン済みなのに`agent_auth`の`status`が`blocked`(認証が必要)を返す事があった。
|
|
15
|
+
`grok models`は、生きているログインでも古いtokenを取り直す回だけ`You are not authenticated.`と答える事がある
|
|
16
|
+
(macbook、Grok 1.0.46。1回目は未認証、同じ時刻に`auth.json`が更新され、2回目からは認証済み)。
|
|
17
|
+
「未認証」の答えは1回では決めず、1.5秒置いてもう1回聞く。2回とも未認証の時だけ`blocked`にする。
|
|
18
|
+
|
|
19
|
+
## [0.53.0] - 2026-10-05
|
|
20
|
+
|
|
21
|
+
### 追加
|
|
22
|
+
|
|
23
|
+
- `agent_auth`の`start`に`relogin`を足す(既定false)。trueの時は、公式の状態が認証済みでも公式ログインを開始し、
|
|
24
|
+
`session_id`付きの結果を返す(`authenticated`かつ`session_id:null`は返さない)。別のアカウントへ入り直す時と、
|
|
25
|
+
ログインの期限切れを状態から見抜けない時に使う。Aitermは資格情報を消さず、置き換えは公式CLIが行う。
|
|
26
|
+
公式CLIがログインを始めた時点で元のログインを消す事がある(Codex 0.160.0の`codex login --device-auth`は、
|
|
27
|
+
始めた時点で`auth.json`を消し、途中で`cancel`しても戻らない。期限切れのログインの写しで確認)。
|
|
28
|
+
Claude CodeとCursorは、途中で`cancel`すれば元の資格情報が残った(無効な資格情報で確認)。
|
|
29
|
+
結果の形(`aiterm.agent-auth-result.v1`)は変えていない。
|
|
30
|
+
- `agent_auth`の`status`(sessionなし)が、Grokの認証状態を答える。今までは「公式ログインsessionの終了結果で確認します」の
|
|
31
|
+
`blocked`だけだった。`grok models`が`You are not authenticated.`と答えれば`blocked`、答えなければ`authenticated`。
|
|
32
|
+
これに伴い、Grokが認証済みの時の`start`(`relogin`なし)は、何も起こさず`authenticated`を返す(今までは毎回ログインを始めていた)。
|
|
33
|
+
|
|
34
|
+
### 修正
|
|
35
|
+
|
|
36
|
+
- 期限が切れたCodexのログインを、`agent_auth`の`status`と`start`が`authenticated`と返していた(ADR 0090)。
|
|
37
|
+
`codex login status`は`auth.json`の有無だけを見て、ログインから30日でrefresh tokenが切れた後も「Logged in」と答える
|
|
38
|
+
(2026-10-05、Codex 0.160.0、BellTeamのコンテナ)。`start`は入り直しを始めず、`auth.json`の名前を手で変えるまで戻せなかった。
|
|
39
|
+
「Logged in」の時は公式App Serverへ`getAuthStatus`、`account/read`の順に聞き、`account`が`null`なら
|
|
40
|
+
`status`は`blocked`(「Codexのログインの期限が切れています」)、`start`は入り直しを始める。
|
|
41
|
+
生きているログインへ余計なtokenの取り直しはかけず、資格情報のfileも読まない。
|
|
42
|
+
App Serverがこの問い合わせを知らない旧版のCodexでは、今までどおり`codex login status`の答えに従う。
|
|
43
|
+
- Cursorの公式statusが`Logged in (unable to fetch user details)`と答える時(無効なtoken。期限切れか通信できないかは分からない)、
|
|
44
|
+
`authenticated`でなく`failed`を返す。入り直しは`relogin:true`で始められる。
|
|
45
|
+
- Grokのログインが無い・切れている時、`agent_launch`が30秒待ってから`unrecognized_screen`で返っていた。
|
|
46
|
+
Grokが起動してすぐ自分で始めるサインイン画面(`Approve in your browser to finish signing in`)を見分け、
|
|
47
|
+
すぐ`startup.status: blocked`/`reason: startup_dialog`で返す。Codexのサインイン画面も同じ`startup_dialog`のまま、
|
|
48
|
+
種別を「サインイン画面(ログインが必要)」と読む。
|
|
49
|
+
|
|
50
|
+
### 分かっている限界
|
|
51
|
+
|
|
52
|
+
- Claude Codeの期限切れは、`status`では見抜けない(`claude auth status --json`が`loggedIn:true`と答える)。
|
|
53
|
+
`agent_launch`は通り、最初のturnが認証の誤りで終わる。入り直しは`relogin:true`。
|
|
54
|
+
- Cursorのログインが無効な時、`agent_launch`はsessionを作る前に
|
|
55
|
+
「Cursor model catalog を取得できません: Error: Authentication required…」の誤りで返る(今までと同じ)。
|
|
56
|
+
|
|
10
57
|
## [0.52.3] - 2026-10-05
|
|
11
58
|
|
|
12
59
|
### 修正
|
|
@@ -2157,7 +2204,9 @@ prototype (preserved under `prototype/python/` as the porting source and referen
|
|
|
2157
2204
|
`ubuntu-latest` for Node 18/20/22, publishing to npm on `v*` tags with
|
|
2158
2205
|
provenance.
|
|
2159
2206
|
|
|
2160
|
-
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.
|
|
2207
|
+
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.53.1...HEAD
|
|
2208
|
+
[0.53.1]: https://github.com/kitepon/aiterm-mcp/compare/v0.53.0...v0.53.1
|
|
2209
|
+
[0.53.0]: https://github.com/kitepon/aiterm-mcp/compare/v0.52.3...v0.53.0
|
|
2161
2210
|
[0.52.3]: https://github.com/kitepon/aiterm-mcp/compare/v0.52.2...v0.52.3
|
|
2162
2211
|
[0.52.2]: https://github.com/kitepon/aiterm-mcp/compare/v0.52.1...v0.52.2
|
|
2163
2212
|
[0.52.1]: https://github.com/kitepon/aiterm-mcp/compare/v0.52.0...v0.52.1
|
package/README.ja.md
CHANGED
|
@@ -209,7 +209,7 @@ runtime-error store は canonical dotagents config の `collection.enabled: true
|
|
|
209
209
|
場合だけ収集し、既定OFF、network送信は行いません。tag起点CIのnpm provenance(OIDC Trusted
|
|
210
210
|
Publishing)で公開し、GitHub Release が Official MCP Registry を再登録します。
|
|
211
211
|
|
|
212
|
-
**状態:** 開発継続中 · 現行公開版 **v0.
|
|
212
|
+
**状態:** 開発継続中 · 現行公開版 **v0.53.1** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
|
|
213
213
|
|
|
214
214
|
### 更新と巻き戻し
|
|
215
215
|
|
|
@@ -561,7 +561,7 @@ Claudeの相関済み承認は既存の`claude_approval`を使う。
|
|
|
561
561
|
| `pty_list` | textと構造化したsession一覧、明示した非秘密環境変数の照会 | `env_keys?` |
|
|
562
562
|
| `pty_observe` | pane/harnessの生存、native process identity、状態と活動 | `session_id`, `cursor?` |
|
|
563
563
|
| `agent_launch` | harnessとmodelを別軸で選ぶ正規agent起動入口 | `harness`, `prompt?`, `model?`, `reasoning_effort?`, `cwd?`, `write_scope?`, `trust_project?`, `env_vars?`, `throughline_source_session?`, `throughline_supplement_file?` |
|
|
564
|
-
| `agent_auth` | 公式CLIの認証を開始・確認・取消し、公式URL・device code・入力待ちを返す | `harness`, `action`, `session_id?`, `cwd?`, `env_vars?` |
|
|
564
|
+
| `agent_auth` | 公式CLIの認証を開始・確認・取消し、公式URL・device code・入力待ちを返す | `harness`, `action`, `session_id?`, `cwd?`, `env_vars?`, `relogin?` |
|
|
565
565
|
| `agent_models` | harnessが今選べるmodelとreasoning effortを、そのharness自身の一覧からpromptを送らずに取得 | `harness`, `cwd?`, `include_hidden?` |
|
|
566
566
|
| `agent_approval` | Codexの現在の承認を検査し、単発許可・拒否を送る | `action`, `session_id`, `approval_choice?`, `observed_prompt_digest?` |
|
|
567
567
|
| `claude_agent` / `codex_agent` / `grok_agent` | deprecated互換alias(`composer_agent`は0.41.0で削除。Composerは`agent_launch`の`cursor-cli`で使う) | 旧launcher引数 |
|
|
@@ -597,7 +597,18 @@ Aitermは、既定では実行時エラーをどこへも送らない。送る
|
|
|
597
597
|
|
|
598
598
|
`agent_configure({ session_id, model?, reasoning_effort? })`はharness標準操作で起動中のClaude/Codex/Grok/Cursorを変更し、PTYと会話contextを維持する。
|
|
599
599
|
|
|
600
|
-
`agent_auth({ harness, action:"start"|"status"|"cancel", session_id?, cwd?, env_vars? })`は、各harnessの公式CLIで認証を進める。Claudeは`claude auth login`、CodexとGrokは`login --device-auth`、Cursorは`NO_OPEN_BROWSER=1 cursor-agent login`を使い、資格情報は各CLIだけが保存する。Aitermは資格情報を読取り・copy・編集せず、独自OAuthも実装しない。`remote`は他toolと同じ標準対応。
|
|
600
|
+
`agent_auth({ harness, action:"start"|"status"|"cancel", session_id?, cwd?, env_vars?, relogin? })`は、各harnessの公式CLIで認証を進める。Claudeは`claude auth login`、CodexとGrokは`login --device-auth`、Cursorは`NO_OPEN_BROWSER=1 cursor-agent login`を使い、資格情報は各CLIだけが保存する。Aitermは資格情報を読取り・copy・編集せず、独自OAuthも実装しない。`remote`は他toolと同じ標準対応。
|
|
601
|
+
|
|
602
|
+
`start`は、公式の状態が認証済みなら何も起こさず`authenticated`(`session_id:null`)を返す。`relogin:true`を付けると、認証済みに見えても公式ログインを開始し、`session_id`付きの結果を返す。別のアカウントへ入り直す時と、ログインの期限切れを状態から見抜けない時に使う。Aitermは資格情報を消さず、置き換えは公式CLIが行う。ただし、公式CLIがログインを始めた時点で元のログインを消す事がある(Codex 0.160.0の`codex login --device-auth`は、始めた時点で`auth.json`を消す。途中で`cancel`しても戻らない)。Claude CodeとCursorは、途中で`cancel`すれば元の資格情報が残る(無効な資格情報で確認)。
|
|
603
|
+
|
|
604
|
+
`status`(sessionなし)は、公式CLIに今の状態を聞く。
|
|
605
|
+
|
|
606
|
+
| harness | 聞き方 | 期限が切れたログイン |
|
|
607
|
+
|---|---|---|
|
|
608
|
+
| Codex | `codex login status`が「Logged in」の時、公式App Serverの`getAuthStatus`→`account/read` | `blocked`(`account`が`null`)。`codex login status`だけでは「Logged in」のままで見抜けない |
|
|
609
|
+
| Claude Code | `claude auth status --json` | **見抜けない**(公式の答えが`loggedIn:true`のまま)。起動は通り、最初のturnが認証の誤りで終わる |
|
|
610
|
+
| Grok | `grok models`(状態の命令は無い) | `blocked`(`You are not authenticated.`)。Grokは使えない資格情報を自分で消す |
|
|
611
|
+
| Cursor | `cursor-agent status` | `failed`(`Logged in (unable to fetch user details)`。期限切れか通信できないかは区別できない)。`relogin:true`で入り直す |
|
|
601
612
|
|
|
602
613
|
結果は`aiterm.agent-auth-result.v1`。`status`は`waiting`/`authenticated`/`blocked`/`failed`、`session_id`・`url`・`user_code`・`input_required`・`message`を返す。`start`のsession IDを保存して`status`へ渡す。公式HTTPS URLと明示device codeだけを返し、CLIの生出力・token・OAuth callback codeを結果へ載せない。`input_required:true`なら同じsessionの`pty_read(screen:true)`で公式画面を表示し、`pty_send`/`pty_key`で人の入力を中継する。
|
|
603
614
|
|
package/README.md
CHANGED
|
@@ -223,7 +223,7 @@ collection is off by default and performs no network I/O. It ships via
|
|
|
223
223
|
tag-triggered CI with npm provenance (OIDC Trusted Publishing); the GitHub
|
|
224
224
|
Release re-registers the Official MCP Registry entry.
|
|
225
225
|
|
|
226
|
-
**Status:** actively maintained · current public release **v0.
|
|
226
|
+
**Status:** actively maintained · current public release **v0.53.1** · runs on Linux · WSL2 · macOS · native Windows (tmux on POSIX, the tmux-CLI-compatible [psmux](https://github.com/psmux/psmux) on native Windows — no WSL required) · MIT · see the [CHANGELOG](CHANGELOG.md).
|
|
227
227
|
|
|
228
228
|
### Update and rollback
|
|
229
229
|
|
|
@@ -598,7 +598,7 @@ continue to use `claude_approval`.
|
|
|
598
598
|
| `pty_list` | Text and structured session list, with explicitly requested non-secret environment values | `env_keys?` |
|
|
599
599
|
| `pty_observe` | Pane/harness liveness, native process identity, state, and activity | `session_id`, `cursor?` |
|
|
600
600
|
| `agent_launch` | Canonical agent launch; harness and model are independent | `harness`, `prompt?`, `model?`, `reasoning_effort?`, `cwd?`, `write_scope?`, `trust_project?`, `env_vars?`, `throughline_source_session?`, `throughline_supplement_file?` |
|
|
601
|
-
| `agent_auth` | 公式CLIの認証を開始・確認・取消し、公式URL・device code・入力待ちを返す | `harness`, `action`, `session_id?`, `cwd?`, `env_vars?` |
|
|
601
|
+
| `agent_auth` | 公式CLIの認証を開始・確認・取消し、公式URL・device code・入力待ちを返す | `harness`, `action`, `session_id?`, `cwd?`, `env_vars?`, `relogin?` |
|
|
602
602
|
| `agent_models` | List the models and reasoning efforts a harness offers now, read from that harness's own catalog without sending a prompt | `harness`, `cwd?`, `include_hidden?` |
|
|
603
603
|
| `agent_approval` | Inspect a Codex approval and submit a one-time approval or denial | `action`, `session_id`, `approval_choice?`, `observed_prompt_digest?` |
|
|
604
604
|
| `claude_agent` / `codex_agent` / `grok_agent` | Deprecated compatibility aliases (`composer_agent` was removed in 0.41.0; run Composer with `agent_launch` on `cursor-cli`) | legacy launcher arguments |
|
|
@@ -637,7 +637,18 @@ enables collection on that host.
|
|
|
637
637
|
|
|
638
638
|
`agent_configure({ session_id, model?, reasoning_effort? })` changes a running Claude, Codex, Grok, or Cursor TUI through the harness's standard controls, preserving the PTY and conversation context.
|
|
639
639
|
|
|
640
|
-
`agent_auth({ harness, action:"start"|"status"|"cancel", session_id?, cwd?, env_vars? })`は、各harnessの公式CLIで認証を進める。Claudeは`claude auth login`、CodexとGrokは`login --device-auth`、Cursorは`NO_OPEN_BROWSER=1 cursor-agent login`を使い、資格情報は各CLIだけが保存する。Aitermは資格情報を読取り・copy・編集せず、独自OAuthも実装しない。`remote`は他toolと同じ標準対応。
|
|
640
|
+
`agent_auth({ harness, action:"start"|"status"|"cancel", session_id?, cwd?, env_vars?, relogin? })`は、各harnessの公式CLIで認証を進める。Claudeは`claude auth login`、CodexとGrokは`login --device-auth`、Cursorは`NO_OPEN_BROWSER=1 cursor-agent login`を使い、資格情報は各CLIだけが保存する。Aitermは資格情報を読取り・copy・編集せず、独自OAuthも実装しない。`remote`は他toolと同じ標準対応。
|
|
641
|
+
|
|
642
|
+
`start`は、公式の状態が認証済みなら何も起こさず`authenticated`(`session_id:null`)を返す。`relogin:true`を付けると、認証済みに見えても公式ログインを開始し、`session_id`付きの結果を返す。別のアカウントへ入り直す時と、ログインの期限切れを状態から見抜けない時に使う。Aitermは資格情報を消さず、置き換えは公式CLIが行う。ただし、公式CLIがログインを始めた時点で元のログインを消す事がある(Codex 0.160.0の`codex login --device-auth`は、始めた時点で`auth.json`を消す。途中で`cancel`しても戻らない)。Claude CodeとCursorは、途中で`cancel`すれば元の資格情報が残る(無効な資格情報で確認)。
|
|
643
|
+
|
|
644
|
+
`status`(sessionなし)は、公式CLIに今の状態を聞く。
|
|
645
|
+
|
|
646
|
+
| harness | 聞き方 | 期限が切れたログイン |
|
|
647
|
+
|---|---|---|
|
|
648
|
+
| Codex | `codex login status`が「Logged in」の時、公式App Serverの`getAuthStatus`→`account/read` | `blocked`(`account`が`null`)。`codex login status`だけでは「Logged in」のままで見抜けない |
|
|
649
|
+
| Claude Code | `claude auth status --json` | **見抜けない**(公式の答えが`loggedIn:true`のまま)。起動は通り、最初のturnが認証の誤りで終わる |
|
|
650
|
+
| Grok | `grok models`(状態の命令は無い) | `blocked`(`You are not authenticated.`)。Grokは使えない資格情報を自分で消す |
|
|
651
|
+
| Cursor | `cursor-agent status` | `failed`(`Logged in (unable to fetch user details)`。期限切れか通信できないかは区別できない)。`relogin:true`で入り直す |
|
|
641
652
|
|
|
642
653
|
結果は`aiterm.agent-auth-result.v1`。`status`は`waiting`/`authenticated`/`blocked`/`failed`、`session_id`・`url`・`user_code`・`input_required`・`message`を返す。`start`のsession IDを保存して`status`へ渡す。公式HTTPS URLと明示device codeだけを返し、CLIの生出力・token・OAuth callback codeを結果へ載せない。`input_required:true`なら同じsessionの`pty_read(screen:true)`で公式画面を表示し、`pty_send`/`pty_key`で人の入力を中継する。
|
|
643
654
|
|
package/dist/core.js
CHANGED
|
@@ -3710,11 +3710,11 @@ function authPlan(kind, phase) {
|
|
|
3710
3710
|
case "cursor": return cursorAuthPlan();
|
|
3711
3711
|
}
|
|
3712
3712
|
}
|
|
3713
|
-
function authStatus(kind, bin, cwd, env = process.env) {
|
|
3713
|
+
async function authStatus(kind, bin, cwd, env = process.env) {
|
|
3714
3714
|
switch (kind) {
|
|
3715
3715
|
case "claude": return claudeAuthStatus(bin, cwd, env);
|
|
3716
|
-
case "codex": return codexAuthStatus(bin, cwd, env);
|
|
3717
|
-
case "grok": return grokAuthStatus();
|
|
3716
|
+
case "codex": return await codexAuthStatus(bin, cwd, env);
|
|
3717
|
+
case "grok": return await grokAuthStatus(bin, cwd, env);
|
|
3718
3718
|
case "cursor": return cursorAuthStatus(bin, cwd, env);
|
|
3719
3719
|
}
|
|
3720
3720
|
}
|
|
@@ -3781,7 +3781,11 @@ function launchAuthProcess(name, meta) {
|
|
|
3781
3781
|
const cmd = ["exec", "env", ...env, shq(agentBinForPaneShell(meta.bin)), ...plan.args.map(shq)].join(" ");
|
|
3782
3782
|
send(name, `cd ${shq(paneCwdArgument(meta.cwd))} && ${cmd}`, { enter: true, force: true, raw: true });
|
|
3783
3783
|
}
|
|
3784
|
-
/**
|
|
3784
|
+
/**
|
|
3785
|
+
* 公式CLIの認証processを起動・観測する。資格情報の読取り・copy・独自OAuthは行わない。
|
|
3786
|
+
* startは、公式の状態が認証済みなら何も起こさない。`relogin`は、認証済みに見えても公式ログインを始める
|
|
3787
|
+
* (別のアカウントへ入り直す時と、期限切れを状態から見抜けない時のため)。資格情報を消すことはせず、置き換えは公式CLIが行う。
|
|
3788
|
+
*/
|
|
3785
3789
|
export async function authenticateAgent(kind, options) {
|
|
3786
3790
|
const result = (status, session, message, pane) => ({ schema: "aiterm.agent-auth-result.v1", harness: agentHarness(kind),
|
|
3787
3791
|
status, session_id: session, url: pane?.url ?? null, user_code: pane?.user_code ?? null,
|
|
@@ -3809,7 +3813,8 @@ export async function authenticateAgent(kind, options) {
|
|
|
3809
3813
|
const bin = resolveAgentBin(kind);
|
|
3810
3814
|
if (!bin)
|
|
3811
3815
|
return result("failed", null, `${agentLabel(kind)}の公式CLIが見つかりません。`);
|
|
3812
|
-
|
|
3816
|
+
// reloginは今の状態を聞かない。状態を確認できない時(failed)でも、入り直しは始められる。
|
|
3817
|
+
const before = options.relogin ? { status: "unauthenticated", message: null } : await authStatus(kind, bin, cwd);
|
|
3813
3818
|
if (before.status === "failed")
|
|
3814
3819
|
return result("failed", null, before.message);
|
|
3815
3820
|
if (before.status === "authenticated" && !before.verify_onboarding)
|
|
@@ -3837,7 +3842,7 @@ export async function authenticateAgent(kind, options) {
|
|
|
3837
3842
|
const bin = resolveAgentBin(kind);
|
|
3838
3843
|
if (!bin)
|
|
3839
3844
|
return result("failed", null, `${agentLabel(kind)}の公式CLIが見つかりません。`);
|
|
3840
|
-
const checked = authStatus(kind, bin, cwd);
|
|
3845
|
+
const checked = await authStatus(kind, bin, cwd);
|
|
3841
3846
|
return result(checked.status === "authenticated" ? "authenticated" : checked.status === "failed" ? "failed" : "blocked", null, checked.message ?? (checked.status === "unauthenticated" ? "公式CLIの認証が必要です。agent_authのstartで開始してください。" : null));
|
|
3842
3847
|
}
|
|
3843
3848
|
else {
|
|
@@ -3861,7 +3866,7 @@ export async function authenticateAgent(kind, options) {
|
|
|
3861
3866
|
if (dead === "1") {
|
|
3862
3867
|
if (exit !== "0")
|
|
3863
3868
|
return result("failed", session, `公式認証processが失敗しました(exit=${/^\d+$/.test(exit ?? "") ? exit : "unknown"})。`);
|
|
3864
|
-
const checked = authStatus(kind, meta.bin, meta.cwd, authSessionEnvironment(session, meta.env_vars));
|
|
3869
|
+
const checked = await authStatus(kind, meta.bin, meta.cwd, authSessionEnvironment(session, meta.env_vars));
|
|
3865
3870
|
if (checked.status === "failed")
|
|
3866
3871
|
return result("failed", session, checked.message);
|
|
3867
3872
|
if (checked.status === "unauthenticated")
|
|
@@ -3881,7 +3886,7 @@ export async function authenticateAgent(kind, options) {
|
|
|
3881
3886
|
if (dead !== "0")
|
|
3882
3887
|
return result("failed", session, "認証processの生存状態の形式を認識できません。");
|
|
3883
3888
|
if (pane.onboarding_complete) {
|
|
3884
|
-
const checked = authStatus(kind, meta.bin, meta.cwd, authSessionEnvironment(session, meta.env_vars));
|
|
3889
|
+
const checked = await authStatus(kind, meta.bin, meta.cwd, authSessionEnvironment(session, meta.env_vars));
|
|
3885
3890
|
if (checked.status === "authenticated")
|
|
3886
3891
|
return result("authenticated", session, null);
|
|
3887
3892
|
return result("failed", session, checked.message ?? "公式CLIのstatusが未認証です。");
|
package/dist/harnesses/codex.js
CHANGED
|
@@ -575,6 +575,9 @@ export function codexLaunchBlockingDialog(screen) {
|
|
|
575
575
|
return "directory trust確認ダイアログ";
|
|
576
576
|
if (screen.includes("Trust this folder?"))
|
|
577
577
|
return "folder trust確認ダイアログ";
|
|
578
|
+
// ログインが無い・期限が切れた時の最初の画面(Codex 0.160.0)。
|
|
579
|
+
if (screen.includes("Sign in with ChatGPT") && screen.includes("Sign in with Device Code"))
|
|
580
|
+
return "サインイン画面(ログインが必要)";
|
|
578
581
|
if (screen.includes("Press enter to continue"))
|
|
579
582
|
return "起動時ダイアログ(種別未特定)";
|
|
580
583
|
return null;
|
|
@@ -788,14 +791,40 @@ export function codexCatalogFromPages(pages) {
|
|
|
788
791
|
});
|
|
789
792
|
}
|
|
790
793
|
export function codexAuthPlan() { return { args: ["login", "--device-auth"], env: [] }; }
|
|
791
|
-
|
|
794
|
+
const CODEX_AUTH_CHECK_TIMEOUT_MS = 15_000;
|
|
795
|
+
/**
|
|
796
|
+
* `codex login status`は`auth.json`があるかだけを見る。ログインの期限が切れた後(refresh tokenの失効)も「Logged in」と答える
|
|
797
|
+
* (2026-10-05、Codex 0.160.0、ログインから30日後)。使えるログインかは、公式App Serverに聞く。
|
|
798
|
+
* `getAuthStatus`(`refreshToken:false`)は、Codex自身が要ると判断した時だけtokenを取り直す。取り直しが恒久的に失敗していると、
|
|
799
|
+
* 続く`account/read`が`account: null`を返す。Aitermは資格情報を読まず、生きているログインへ余計な取り直しもかけない。
|
|
800
|
+
*/
|
|
801
|
+
export async function codexAuthStatus(bin, cwd, env = process.env) {
|
|
792
802
|
const result = spawnAgentControlCommand(bin, ["login", "status"], cwd, { cwd, env, encoding: "utf8", timeout: 5000, maxBuffer: 64 * 1024 });
|
|
793
803
|
const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`;
|
|
794
|
-
if (!result.error && result.status === 0 && /Logged in/i.test(output))
|
|
795
|
-
return { status: "authenticated", message: null };
|
|
796
804
|
if (!result.error && /Not logged in/i.test(output))
|
|
797
805
|
return { status: "unauthenticated", message: null };
|
|
798
|
-
|
|
806
|
+
if (result.error || result.status !== 0 || !/Logged in/i.test(output))
|
|
807
|
+
return { status: "failed", message: "Codex CLIの公式認証状態を確認できません。" };
|
|
808
|
+
const parent = { thread_id: "00000000-0000-4000-8000-000000000000", codex_home: path.resolve(env.CODEX_HOME || steer.realCodexHome()) };
|
|
809
|
+
let read;
|
|
810
|
+
try {
|
|
811
|
+
read = await steer.withCodexReceiver(AITERM_PROFILE, parent, async (request) => {
|
|
812
|
+
await request("getAuthStatus", { includeToken: false, refreshToken: false });
|
|
813
|
+
return await request("account/read", { refreshToken: false });
|
|
814
|
+
}, { executable: bin, timeout_ms: CODEX_AUTH_CHECK_TIMEOUT_MS, env });
|
|
815
|
+
}
|
|
816
|
+
catch (error) {
|
|
817
|
+
// App Serverがこの問い合わせを知らない旧版は、今までどおり公式statusの答えに従う(期限切れは見抜けない)。
|
|
818
|
+
if (error instanceof steer.CodexDeliveryError && error.delivery_code === "CODEX_RECEIVER_REJECTED")
|
|
819
|
+
return { status: "authenticated", message: null };
|
|
820
|
+
return { status: "failed", message: "Codexのログインが使えるかを、公式App Serverで確認できません。" };
|
|
821
|
+
}
|
|
822
|
+
if (read?.requiresOpenaiAuth === false || (read?.account !== null && typeof read?.account === "object"))
|
|
823
|
+
return { status: "authenticated", message: null };
|
|
824
|
+
if (read?.account === null) {
|
|
825
|
+
return { status: "unauthenticated", message: "Codexのログインの期限が切れています。agent_authのstartで入り直してください。" };
|
|
826
|
+
}
|
|
827
|
+
return { status: "failed", message: "Codexの公式App Serverが返した認証状態の形式を認識できません。" };
|
|
799
828
|
}
|
|
800
829
|
export function codexAuthPane(screen) {
|
|
801
830
|
return { url: authUrl(screen, ["auth.openai.com", "auth0.openai.com", "login.openai.com"]),
|
package/dist/harnesses/cursor.js
CHANGED
|
@@ -581,6 +581,11 @@ export function cursorAuthStatus(bin, cwd, env = process.env) {
|
|
|
581
581
|
const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`;
|
|
582
582
|
if (!result.error && /not logged in|unauthenticated|sign in/i.test(output))
|
|
583
583
|
return { status: "unauthenticated", message: null };
|
|
584
|
+
// 無効なtoken(期限切れ等)の時、公式statusは「Logged in (unable to fetch user details)」と終了0で答える(2026-10-05)。
|
|
585
|
+
// 期限切れか、通信できないだけかは、この答えからは分からない。認証済みとは返さない。
|
|
586
|
+
if (!result.error && /unable to fetch user details/i.test(output)) {
|
|
587
|
+
return { status: "failed", message: "Cursorのログインを確認できません(期限切れか、通信できない状態です)。入り直す時はagent_authのstartにrelogin:trueを付けてください。" };
|
|
588
|
+
}
|
|
584
589
|
// launcherと同じ公式status契約。stderrやアカウント情報はreceiptへ載せない。
|
|
585
590
|
if (!result.error && result.status === 0)
|
|
586
591
|
return { status: "authenticated", message: null };
|
package/dist/harnesses/grok.js
CHANGED
|
@@ -355,6 +355,13 @@ export function assertGrokSandboxNotRejected(screen) {
|
|
|
355
355
|
"CLIが示した設定の問題を、その設定の管理元で修正してください。修正後はpty_closeで対象sessionを閉じ、agent_launchで起動し直してください。", 2);
|
|
356
356
|
}
|
|
357
357
|
export function grokLaunchBlockingDialog(screen) {
|
|
358
|
+
// ログインが無い・期限が切れた時、Grok 1.0.46は起動してすぐdevice codeのサインインを自分で始め、承認を待つ。
|
|
359
|
+
const signInAt = screen.lastIndexOf("Approve in your browser to finish signing in");
|
|
360
|
+
if (signInAt >= 0) {
|
|
361
|
+
const afterSignIn = screen.slice(signInAt);
|
|
362
|
+
if (afterSignIn.includes("Waiting for approval") && !/(?:^|\n)[ \t]*(?:│[ \t]*)?[❯>]/u.test(afterSignIn))
|
|
363
|
+
return "サインイン画面(ログインが必要)";
|
|
364
|
+
}
|
|
358
365
|
const trustAt = screen.lastIndexOf("Do you trust the contents of this directory?");
|
|
359
366
|
if (trustAt < 0)
|
|
360
367
|
return null;
|
|
@@ -523,9 +530,27 @@ export function createGrokAgentMetadata(kind, name, cwd, initialPrompt, authPath
|
|
|
523
530
|
return meta;
|
|
524
531
|
}
|
|
525
532
|
export function grokAuthPlan() { return { args: ["login", "--device-auth"], env: [] }; }
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
533
|
+
const GROK_AUTH_RECHECK_MS = 1500;
|
|
534
|
+
/**
|
|
535
|
+
* Grokには認証状態を答える公式commandが無い。`grok models`は、使えるログインが無い時に`You are not authenticated.`と答える
|
|
536
|
+
* (1.0.46。ログイン無しと、期限切れ・無効なtokenの両方。後者ではGrokが`auth.json`を自分で消す)。auth fileの存在は見ない。
|
|
537
|
+
* 生きているログインでも、古いtokenを取り直す回だけ「未認証」と答える事がある(2026-10-05 macbook。1回目は未認証、
|
|
538
|
+
* 同じ時刻に`auth.json`が更新され、2回目からは認証済み)。1回の「未認証」では決めず、少し置いてもう1回聞く。
|
|
539
|
+
*/
|
|
540
|
+
export async function grokAuthStatus(bin, cwd, env = process.env) {
|
|
541
|
+
for (let attempt = 0;; attempt += 1) {
|
|
542
|
+
const result = spawnAgentControlCommand(bin, ["models"], cwd, { cwd, env, encoding: "utf8", timeout: 20000, maxBuffer: 256 * 1024 });
|
|
543
|
+
const output = `${result.stdout ?? ""}\n${result.stderr ?? ""}`;
|
|
544
|
+
if (!result.error && /You are not authenticated|Not signed in/i.test(output)) {
|
|
545
|
+
if (attempt > 0)
|
|
546
|
+
return { status: "unauthenticated", message: null };
|
|
547
|
+
await new Promise(resolve => setTimeout(resolve, GROK_AUTH_RECHECK_MS));
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
if (!result.error && result.status === 0 && /Available models/i.test(output))
|
|
551
|
+
return { status: "authenticated", message: null };
|
|
552
|
+
return { status: "failed", message: "Grokの公式CLIで認証状態を確認できません。" };
|
|
553
|
+
}
|
|
529
554
|
}
|
|
530
555
|
export function grokAuthPane(screen) {
|
|
531
556
|
const url = authUrl(screen, ["auth.x.ai", "accounts.x.ai", "grok.com"]);
|
package/dist/index.js
CHANGED
|
@@ -758,13 +758,17 @@ registerRemoteAwareTool("claude_approval", {
|
|
|
758
758
|
registerRemoteAwareTool("agent_auth", {
|
|
759
759
|
description: "各harnessの公式CLI認証を開始・確認・取消する。CLIごとのコマンドと認証URL/codeの抽出はAitermが所有し、資格情報は各CLIだけが保存する。" +
|
|
760
760
|
"waitingのURL/codeを人へ表示し、input_requiredなら同じsessionのpty_send/pty_keyで公式画面へ入力する。" +
|
|
761
|
-
"authenticatedは認証の結果であり、agent_launchの起動準備完了とは別。remoteは他toolと同じ標準対応。"
|
|
761
|
+
"authenticatedは認証の結果であり、agent_launchの起動準備完了とは別。remoteは他toolと同じ標準対応。" +
|
|
762
|
+
"startは公式の状態が認証済みなら何も起こさずauthenticatedを返す。relogin:trueを付けると、認証済みに見えても公式ログインを開始する" +
|
|
763
|
+
"(別のアカウントへ入り直す時、ログインの期限切れを状態から見抜けない時)。Aitermは資格情報を消さず、置き換えは公式CLIが行う。" +
|
|
764
|
+
"Codexの公式ログインは、始めた時点で元のログインを消す(途中でcancelしても戻らない)。",
|
|
762
765
|
inputSchema: {
|
|
763
766
|
harness: z.enum(["claude-code", "codex-cli", "grok-cli", "cursor-cli"]),
|
|
764
767
|
action: z.enum(["start", "status", "cancel"]),
|
|
765
768
|
session_id: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/).optional(),
|
|
766
769
|
cwd: z.string().optional().describe("公式CLIを実行する作業ディレクトリの絶対パス"),
|
|
767
770
|
env_vars: z.array(z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/)).optional().describe("startで認証PTYへ引き継ぐ環境変数名。値はreceiptへ返さない"),
|
|
771
|
+
relogin: z.boolean().optional().describe("startで、公式の状態が認証済みでも公式ログインを開始する。既定false。trueの時、authenticatedかつsession_idがnullの結果は返さない"),
|
|
768
772
|
},
|
|
769
773
|
outputSchema: {
|
|
770
774
|
schema: z.literal("aiterm.agent-auth-result.v1"),
|
package/docs/DESIGN.md
CHANGED
|
@@ -293,7 +293,10 @@ shell、接続先、各harnessの公式CLIが所有する。
|
|
|
293
293
|
|
|
294
294
|
PTYが消失した場合は、相関記録の有無にかかわらず`status`が`failed`、`cancel`が既に終了・取消済みを示す`blocked`を返し、どちらも`session_id:null`となる。保存したsession IDを解除して`start`で再開始できる。生存中の通常PTYやharness不一致、記録の破損・読取り失敗はエラーを返す。
|
|
295
295
|
|
|
296
|
-
Claude/Codex/Cursorは公式statusを照合する。Grokは公式status command
|
|
296
|
+
Claude/Codex/Cursorは公式statusを照合する。Grokは公式status commandが無いため、`grok models`が`You are not authenticated.`と答えるかで見る(ADR 0090)。auth fileの存在は見ない。
|
|
297
|
+
Codexの`codex login status`は`auth.json`の有無だけを答え、ログインの期限が切れた後も「Logged in」を返す。「Logged in」の時は、公式App Serverへ`getAuthStatus`(`refreshToken:false`)、`account/read`の順に聞き、`account`が`null`なら未認証とする。App Serverを起こす環境は、認証sessionへ引き継いだ環境を使う。
|
|
298
|
+
Cursorの公式statusが`unable to fetch user details`を返す時は、認証済みとせず`failed`とする。Claudeの期限切れは、公式statusからは見抜けない。
|
|
299
|
+
`start`の`relogin:true`は、今の状態を聞かずに公式ログインを始める。資格情報を消す処理は持たない。Claudeはlogin完了後に同じPTYへ公式の初回TUIを用意し、初回案内の入力待ちを`blocked`/`input_required:true`へ写す。認証とlauncherの起動準備は別の結果であり、`agent_launch`のready gateを省略しない。
|
|
297
300
|
|
|
298
301
|
公開receiptは`aiterm.agent-auth-result.v1`で、公式HTTPS URLと明示device codeだけを抽出する。生の画面本文・credential・token・OAuth callback codeは含めない。人の入力は既存の`pty_send`/`pty_key`で同じPTYへ送る。`remote`は標準のremote tool中継を使い、callerはCLI commandや環境ごとの入力方言を組み立てない。
|
|
299
302
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.53.1",
|
|
4
4
|
"mcpName": "io.github.kitepon/aiterm-mcp",
|
|
5
5
|
"description": "Persistent terminal MCP with one harness-based launcher for Claude Code, Codex CLI, Grok CLI, and Cursor Agent CLI, plus durable PTYs for SSH, containers, and REPLs.",
|
|
6
6
|
"keywords": [
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
74
|
-
"aiterm-steer-delivery": "^0.2.
|
|
74
|
+
"aiterm-steer-delivery": "^0.2.1",
|
|
75
75
|
"ws": "8.21.3",
|
|
76
76
|
"zod": "^4.4.3"
|
|
77
77
|
},
|