throughline 0.10.15 → 0.10.16

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 CHANGED
@@ -10,6 +10,14 @@ shipped to npm but were not individually tagged on GitHub.
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [0.10.16] — 2026-09-07
14
+
15
+ ### 修正
16
+
17
+ - WindowsのDesktop引き継ぎで、稼働中のアプリが使うCodex実行ファイルを選ぶようにした。
18
+ PATH上の古いCodexがデスクトップ版の設定を読めず、新規タスクの作成に失敗する問題を修正した。
19
+ - 引き継ぎ結果へCodex実行元を表示する。アプリの実体を特定できない場合は理由を出して停止する。
20
+
13
21
  ## [0.10.15] — 2026-09-06
14
22
 
15
23
  ### Fixed
@@ -1449,7 +1457,8 @@ two attempts, instrument first instead of patching again.
1449
1457
 
1450
1458
  ---
1451
1459
 
1452
- [Unreleased]: https://github.com/kitepon/Throughline/compare/v0.10.15...HEAD
1460
+ [Unreleased]: https://github.com/kitepon/Throughline/compare/v0.10.16...HEAD
1461
+ [0.10.16]: https://github.com/kitepon/Throughline/compare/v0.10.15...v0.10.16
1453
1462
  [0.10.15]: https://github.com/kitepon/Throughline/compare/v0.10.14...v0.10.15
1454
1463
  [0.10.14]: https://github.com/kitepon/Throughline/compare/v0.10.13...v0.10.14
1455
1464
  [0.10.13]: https://github.com/kitepon/Throughline/compare/v0.10.12...v0.10.13
package/README.md CHANGED
@@ -638,6 +638,10 @@ opens the new task in Codex Desktop when invoked there, while preserving the
638
638
  existing VS Code and CLI routes. The result reports both the requested and
639
639
  resolved host. The installed `$throughline` skill passes the current Codex
640
640
  surface explicitly so a persistent shell or PTY cannot redirect the handoff.
641
+ WindowsのDesktop引き継ぎは、稼働中のCodex Desktopが使う実行ファイルを選びます。
642
+ PATH上の別バージョンによる設定読取りエラーを避け、選んだ実行元を結果へ表示します。
643
+ Desktopを起動してから実行してください。実行ファイルが見つからない場合や、異なる実行ファイルの
644
+ Desktopが複数稼働している場合は理由を出して停止します。明示した`--codex-app-server-bin`は優先します。
641
645
  The
642
646
  individual commands remain available: validate the fresh-thread handoff with
643
647
  `throughline codex-handoff-smoke --session codex:<thread-id>`, optionally audit
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "throughline",
3
- "version": "0.10.15",
3
+ "version": "0.10.16",
4
4
  "type": "module",
5
5
  "description": "Persistent memory hooks for Claude Code, Codex, Grok, and Cursor (/clear-safe context compression)",
6
6
  "keywords": [
@@ -9,6 +9,7 @@ import { sameProjectPath } from '../project-path.mjs';
9
9
  import { shQuote } from '../os/shell.mjs';
10
10
  import { openUrlWithOsHandler } from '../os/open-url.mjs';
11
11
  import { runTerminalDoScript } from '../os/macos-terminal.mjs';
12
+ import { resolveCodexRuntime } from '../os/codex-runtime.mjs';
12
13
 
13
14
  async function readStdin() {
14
15
  let raw = '';
@@ -242,6 +243,7 @@ function renderTextResult(result) {
242
243
  lines.push(` execute: ${result.execute ? 'yes' : 'no'}`);
243
244
  lines.push(` open requested: ${result.requestedOpenHost ?? result.openHost}`);
244
245
  lines.push(` open resolved: ${result.resolvedOpenHost ?? result.open?.host ?? result.openHost}`);
246
+ if (result.runtime) lines.push(` Codex実行元: ${result.runtime.command} (${result.runtime.source})`);
245
247
  lines.push(` handoff smoke: ${result.handoffSmoke.status}`);
246
248
  lines.push(` prompt chars: ${result.handoffSmoke.promptChars}/${result.handoffSmoke.maxPromptChars}`);
247
249
  lines.push(` model prompt: ${result.modelPromptChars}`);
@@ -452,11 +454,16 @@ export async function run(args) {
452
454
  }
453
455
 
454
456
  if (parsed.execute && result.status === 'ready') {
457
+ const runtime = resolveCodexRuntime({
458
+ host: result.resolvedOpenHost,
459
+ override: parsed.codexAppServerBin,
460
+ });
461
+ result.runtime = runtime;
455
462
  const startResult = await runCodexNewThreadHandoff({
456
463
  cwd: process.cwd(),
457
464
  prompt: handoffPrompt,
458
- command: parsed.codexAppServerBin ?? 'codex',
459
- commandArgs: parsed.codexAppServerBin ? [] : ['app-server', '--listen', 'stdio://'],
465
+ command: runtime.command,
466
+ commandArgs: runtime.commandArgs,
460
467
  timeoutMs: parsed.timeoutMs,
461
468
  requestTimeoutMs: parsed.requestTimeoutMs,
462
469
  waitForTurn: false,
@@ -310,6 +310,9 @@ test('codex-handoff-start execute creates a new app-server thread and can skip o
310
310
  assert.equal(payload.startThreadManually, false);
311
311
  assert.equal(payload.newThread.threadId, '019e2000-0000-7000-8000-000000000001');
312
312
  assert.equal(payload.newThread.delivery, 'developer-item');
313
+ assert.equal(payload.runtime.command, script);
314
+ assert.equal(payload.runtime.source, 'explicit');
315
+ assert.deepEqual(payload.runtime.commandArgs, []);
313
316
  assert.equal(payload.newThread.injectSent, true);
314
317
  assert.equal(payload.newThread.turnStatus, 'not-started');
315
318
  assert.equal(payload.open.status, 'skipped');
@@ -0,0 +1,36 @@
1
+ import { spawnPortableSync } from './portable-spawn-sync.mjs';
2
+
3
+ function discoverWindowsDesktopCodex() {
4
+ const result = spawnPortableSync('pwsh.exe', ['-NoLogo', '-NoProfile', '-NonInteractive', '-Command', `
5
+ $ErrorActionPreference = 'Stop'
6
+ $processes = @(Get-CimInstance Win32_Process)
7
+ $paths = @($processes | Where-Object { $_.Name -eq 'codex.exe' } | ForEach-Object {
8
+ $child = $_
9
+ $parent = $processes | Where-Object { $_.ProcessId -eq $child.ParentProcessId }
10
+ if ($parent.ExecutablePath -match '[\\\\/]OpenAI\\.Codex_[^\\\\/]+[\\\\/]app[\\\\/]ChatGPT\\.exe$' -and $child.ExecutablePath) {
11
+ $child.ExecutablePath
12
+ }
13
+ })
14
+ ConvertTo-Json -InputObject $paths -Compress
15
+ `], { encoding: 'utf8', timeout: 15000 });
16
+ if (result.error || result.status !== 0) {
17
+ throw new Error(`Codex Desktopの実行ファイルを取得できません: ${result.error?.message ?? result.stderr.trim()}`);
18
+ }
19
+ return JSON.parse(result.stdout.trim());
20
+ }
21
+
22
+ export function resolveCodexRuntime({ host, override = null, platform = process.platform,
23
+ discover = discoverWindowsDesktopCodex } = {}) {
24
+ if (override) return { command: override, commandArgs: [], source: 'explicit' };
25
+ const commandArgs = ['app-server', '--listen', 'stdio://'];
26
+ if (platform !== 'win32' || host !== 'desktop') {
27
+ return { command: 'codex', commandArgs, source: 'path' };
28
+ }
29
+ const candidates = [...new Set(discover())];
30
+ if (candidates.length !== 1) {
31
+ throw new Error(candidates.length === 0
32
+ ? '稼働中のCodex Desktopの実行ファイルが見つかりません。アプリを起動してから再実行してください。'
33
+ : '複数のCodex Desktop実行ファイルが稼働しています。使用するアプリだけを残して再実行してください。');
34
+ }
35
+ return { command: candidates[0], commandArgs, source: 'desktop-process' };
36
+ }
@@ -0,0 +1,31 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { resolveCodexRuntime } from './codex-runtime.mjs';
4
+
5
+ test('Windows Desktopは稼働中アプリのCodexを使う', () => {
6
+ const runtime = resolveCodexRuntime({ platform: 'win32', host: 'desktop',
7
+ discover: () => ['C:\\Codex\\codex.exe', 'C:\\Codex\\codex.exe'] });
8
+ assert.equal(runtime.command, 'C:\\Codex\\codex.exe');
9
+ assert.deepEqual(runtime.commandArgs, ['app-server', '--listen', 'stdio://']);
10
+ assert.equal(runtime.source, 'desktop-process');
11
+ });
12
+
13
+ test('明示したapp-serverはDesktopの探索より優先する', () => {
14
+ const runtime = resolveCodexRuntime({ platform: 'win32', host: 'desktop', override: 'fake.mjs',
15
+ discover: () => { throw new Error('探索してはいけない'); } });
16
+ assert.equal(runtime.command, 'fake.mjs');
17
+ assert.deepEqual(runtime.commandArgs, []);
18
+ });
19
+
20
+ test('対象外のOSとhostは従来のCodexを使う', () => {
21
+ for (const [platform, host] of [['darwin', 'desktop'], ['win32', 'cli'], ['win32', 'vscode']]) {
22
+ assert.equal(resolveCodexRuntime({ platform, host }).command, 'codex');
23
+ }
24
+ });
25
+
26
+ test('Desktopの実体がない場合や複数ある場合は古いCLIへ切り替えない', () => {
27
+ for (const candidates of [[], ['C:\\one\\codex.exe', 'C:\\two\\codex.exe']]) {
28
+ assert.throws(() => resolveCodexRuntime({ platform: 'win32', host: 'desktop',
29
+ discover: () => candidates }), /Codex Desktop/);
30
+ }
31
+ });