throughline 0.3.4 → 0.3.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "throughline",
3
- "version": "0.3.4",
3
+ "version": "0.3.5",
4
4
  "type": "module",
5
5
  "description": "Claude Code hooks plugin for structured context compression (/clear-safe persistent memory)",
6
6
  "keywords": [
@@ -263,11 +263,15 @@ function formatLine({ state, usage, isActive, now = Date.now() }) {
263
263
  const modelCol = usage?.model ? color(ANSI.dim, usage.model) : color(ANSI.dim, '(未取得)');
264
264
  // 最終更新からの経過: 表示が「止まって見える」とき、それが idle なのか障害なのかを
265
265
  // 即座に判別できるようにする。updatedAt は state.writeSessionState 時の Date.now()。
266
- const ago = typeof state.updatedAt === 'number'
267
- ? color(ANSI.dim, `(${formatTimeAgo(now - state.updatedAt)})`)
266
+ // 位置は session id の直後(左寄せ固定幅)。狭いターミナルでもモデル名より先に
267
+ // 切れない位置に置くのと、縦の視線移動で「どれが最新更新か」を把握しやすくするため。
268
+ const agoText = typeof state.updatedAt === 'number'
269
+ ? formatTimeAgo(now - state.updatedAt)
268
270
  : '';
271
+ // 8 セル固定: "just now" が最長 (8 セル)、"99d ago" は 7 セル。括弧なしで OK
272
+ const agoCol = color(ANSI.dim, padCellsEnd(agoText, 8));
269
273
 
270
- return `${marker} ${projectCol} ${idCol} ${barCol} ${tokCol} ${remCol} ${modelCol} ${ago}${warn}`;
274
+ return `${marker} ${projectCol} ${idCol} ${agoCol} ${barCol} ${tokCol} ${remCol} ${modelCol}${warn}`;
271
275
  }
272
276
 
273
277
  // --- フィルタ ---
@@ -395,12 +395,30 @@ test('formatLine: updatedAt から経過時間が表示される', () => {
395
395
  };
396
396
  args.state.updatedAt = now - 3 * 60 * 1000; // 3 分前
397
397
  const out = stripColors(formatLine(args));
398
- assert.ok(out.includes('(3m ago)'), `expected "(3m ago)" in output: ${out}`);
398
+ assert.ok(out.includes('3m ago'), `expected "3m ago" in output: ${out}`);
399
399
  });
400
400
 
401
- test('formatLine: updatedAt が無ければ ago 表示は出ない', () => {
401
+ test('formatLine: updatedAt が無ければ ago テキストは空', () => {
402
402
  const args = makeLineArgs(0.5);
403
403
  delete args.state.updatedAt;
404
404
  const out = stripColors(formatLine(args));
405
405
  assert.ok(!out.includes('ago'));
406
+ assert.ok(!out.includes('just now'));
407
+ });
408
+
409
+ test('formatLine: ago は session id のすぐ右に配置される(狭幅でも切れない位置)', () => {
410
+ const now = Date.now();
411
+ const args = {
412
+ ...makeLineArgs(0.5),
413
+ now,
414
+ };
415
+ args.state.updatedAt = now - 5 * 60 * 1000; // 5m
416
+ const out = stripColors(formatLine(args));
417
+ // shortId と 5m ago の位置関係: shortId が先、ago がその後、bar (█ or ░) がさらに後
418
+ const idPos = out.indexOf('abc12345');
419
+ const agoPos = out.indexOf('5m ago');
420
+ const barPos = out.search(/[█░]/);
421
+ assert.ok(idPos >= 0 && agoPos >= 0 && barPos >= 0, 'all fields present');
422
+ assert.ok(idPos < agoPos, 'shortId before ago');
423
+ assert.ok(agoPos < barPos, 'ago before bar');
406
424
  });