throughline 0.4.6 → 0.4.8

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.
@@ -1,6 +1,6 @@
1
1
  import { test } from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
- import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
3
+ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
4
4
  import { tmpdir } from 'node:os';
5
5
  import { join } from 'node:path';
6
6
 
@@ -22,6 +22,8 @@ const {
22
22
  setMeasuredColumns,
23
23
  withLiveActivity,
24
24
  resolveMonitorUsage,
25
+ discoverCodexSessionStates,
26
+ mergeCodexDiscoveredStates,
25
27
  } = _internal;
26
28
 
27
29
  // state-file は projectPath を resolve + lowercase 正規化する。
@@ -244,6 +246,73 @@ test('resolveMonitorUsage: live Codex rollout overrides stale Stop snapshot', ()
244
246
  }
245
247
  });
246
248
 
249
+ test('discoverCodexSessionStates: finds Codex rollout without a monitor state file', () => {
250
+ const home = mkdtempSync(join(tmpdir(), 'tl-monitor-codex-home-'));
251
+ const project = mkdtempSync(join(tmpdir(), 'tl-monitor-codex-project-'));
252
+ const oldHome = process.env.CODEX_HOME;
253
+ try {
254
+ process.env.CODEX_HOME = home;
255
+ const threadId = '019e085c-d3b9-7b43-8445-0efe32416e3d';
256
+ const dir = join(home, 'sessions', '2026', '05', '09');
257
+ mkdirSync(dir, { recursive: true });
258
+ const rollout = join(dir, `rollout-2026-05-09T01-12-41-${threadId}.jsonl`);
259
+ writeFileSync(
260
+ rollout,
261
+ JSON.stringify({
262
+ type: 'session_meta',
263
+ payload: {
264
+ id: threadId,
265
+ cwd: project,
266
+ source: 'vscode',
267
+ cli_version: '0.129.0-alpha.15',
268
+ },
269
+ }) + '\n',
270
+ );
271
+
272
+ const states = discoverCodexSessionStates({ all: false, session: null }, project);
273
+
274
+ assert.equal(states.length, 1);
275
+ assert.equal(states[0].sessionId, `codex:${threadId}`);
276
+ assert.equal(states[0].host, 'codex');
277
+ assert.equal(states[0].projectPath, normalizeProjectPath(project));
278
+ assert.equal(states[0].rolloutPath, rollout);
279
+ assert.equal(states[0].discoveredFrom, 'codex-rollout-discovery');
280
+ } finally {
281
+ if (oldHome === undefined) delete process.env.CODEX_HOME;
282
+ else process.env.CODEX_HOME = oldHome;
283
+ rmSync(home, { recursive: true, force: true });
284
+ rmSync(project, { recursive: true, force: true });
285
+ }
286
+ });
287
+
288
+ test('mergeCodexDiscoveredStates: discovered rollout updates an existing Codex state entry', () => {
289
+ const existing = {
290
+ sessionId: 'codex:thread-a',
291
+ host: 'codex',
292
+ projectPath: CWD_FOO,
293
+ transcriptPath: null,
294
+ rolloutPath: '/old/rollout.jsonl',
295
+ updatedAt: 100,
296
+ usage: { tokens: 1 },
297
+ };
298
+ const discovered = {
299
+ sessionId: 'codex:thread-a',
300
+ host: 'codex',
301
+ projectPath: CWD_FOO,
302
+ transcriptPath: null,
303
+ rolloutPath: '/new/rollout.jsonl',
304
+ updatedAt: 200,
305
+ discoveredFrom: 'codex-rollout-discovery',
306
+ };
307
+
308
+ const states = mergeCodexDiscoveredStates([existing], [discovered]);
309
+
310
+ assert.equal(states.length, 1);
311
+ assert.equal(states[0].rolloutPath, '/new/rollout.jsonl');
312
+ assert.equal(states[0].updatedAt, 200);
313
+ assert.deepEqual(states[0].usage, { tokens: 1 });
314
+ });
315
+
247
316
  // ─── cellWidth ─────────────────────────────────────────────────────
248
317
 
249
318
  test('cellWidth: ASCII は 1 セル', () => {
@@ -451,7 +520,18 @@ test('formatLine: Codex estimated usage は host と est marker を表示する'
451
520
  assert.ok(out.includes('codex est win?'));
452
521
  });
453
522
 
454
- test('formatLine: Codex live turn usage transient output marker を表示する', () => {
523
+ test('formatLine: Codex session idhost prefix を外して 8 桁表示する', () => {
524
+ const args = makeLineArgs(0.5);
525
+ args.state.host = 'codex';
526
+ args.state.sessionId = 'codex:019e085c-d3b9-7b43-8445-0efe32416e3d';
527
+
528
+ const out = stripColors(formatLine(args));
529
+
530
+ assert.ok(out.includes('019e085c'), `expected raw Codex short id in output: ${out}`);
531
+ assert.ok(!out.includes('codex:01'), `did not expect prefixed short id in output: ${out}`);
532
+ });
533
+
534
+ test('formatLine: Codex live turn usage は transient output marker を表示しない', () => {
455
535
  const args = makeLineArgs(0.5);
456
536
  args.state.host = 'codex';
457
537
  args.usage = {
@@ -469,7 +549,8 @@ test('formatLine: Codex live turn usage は transient output marker を表示す
469
549
  const out = stripColors(formatLine(args));
470
550
  assert.ok(out.includes('Codex'));
471
551
  assert.ok(out.includes('101.2k / 200.0k'));
472
- assert.ok(out.includes('gpt-5.5 live+1.2k'));
552
+ assert.ok(out.includes('gpt-5.5'));
553
+ assert.ok(!out.includes('live+'));
473
554
  });
474
555
 
475
556
  test('formatLine: 70% 以上で "!" マーカーと弱めの文言', () => {