@agents-ensemble/cli 0.6.4 → 0.7.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.
Files changed (86) hide show
  1. package/README.md +36 -3
  2. package/config.example.yaml +13 -0
  3. package/dist/async-operator-input.js +1 -1
  4. package/dist/async-operator-input.js.map +1 -1
  5. package/dist/display/session-display-reducer.d.ts.map +1 -1
  6. package/dist/display/session-display-reducer.js +0 -11
  7. package/dist/display/session-display-reducer.js.map +1 -1
  8. package/dist/inline-markdown.d.ts +3 -1
  9. package/dist/inline-markdown.d.ts.map +1 -1
  10. package/dist/inline-markdown.js +232 -33
  11. package/dist/inline-markdown.js.map +1 -1
  12. package/dist/issue-command.d.ts.map +1 -1
  13. package/dist/issue-command.js +8 -4
  14. package/dist/issue-command.js.map +1 -1
  15. package/dist/prompt-operator-input.d.ts +1 -1
  16. package/dist/prompt-operator-input.d.ts.map +1 -1
  17. package/dist/prompt-operator-input.js +1 -1
  18. package/dist/prompt-operator-input.js.map +1 -1
  19. package/dist/session-log-lines.d.ts.map +1 -1
  20. package/dist/session-log-lines.js +64 -8
  21. package/dist/session-log-lines.js.map +1 -1
  22. package/dist/session-sinks.d.ts.map +1 -1
  23. package/dist/session-sinks.js +2 -10
  24. package/dist/session-sinks.js.map +1 -1
  25. package/dist/tui/activity-log.d.ts +8 -0
  26. package/dist/tui/activity-log.d.ts.map +1 -1
  27. package/dist/tui/activity-log.js +16 -0
  28. package/dist/tui/activity-log.js.map +1 -1
  29. package/dist/tui/compute-operator-input-cursor-y.d.ts +4 -0
  30. package/dist/tui/compute-operator-input-cursor-y.d.ts.map +1 -1
  31. package/dist/tui/compute-operator-input-cursor-y.js +4 -2
  32. package/dist/tui/compute-operator-input-cursor-y.js.map +1 -1
  33. package/dist/tui/create-issue-session-tui-host.d.ts.map +1 -1
  34. package/dist/tui/create-issue-session-tui-host.js +44 -8
  35. package/dist/tui/create-issue-session-tui-host.js.map +1 -1
  36. package/dist/tui/create-issue-session-tui-host.test.js +19 -5
  37. package/dist/tui/create-issue-session-tui-host.test.js.map +1 -1
  38. package/dist/tui/issue-session-tui-stream.d.ts +6 -1
  39. package/dist/tui/issue-session-tui-stream.d.ts.map +1 -1
  40. package/dist/tui/issue-session-tui-stream.js +55 -17
  41. package/dist/tui/issue-session-tui-stream.js.map +1 -1
  42. package/dist/tui/issue-session-tui-stream.test.js +345 -11
  43. package/dist/tui/issue-session-tui-stream.test.js.map +1 -1
  44. package/dist/tui/issue-session-tui.d.ts +11 -5
  45. package/dist/tui/issue-session-tui.d.ts.map +1 -1
  46. package/dist/tui/issue-session-tui.js +60 -30
  47. package/dist/tui/issue-session-tui.js.map +1 -1
  48. package/dist/tui/issue-session-tui.test.js +268 -30
  49. package/dist/tui/issue-session-tui.test.js.map +1 -1
  50. package/dist/tui/open-questions-pane.d.ts.map +1 -1
  51. package/dist/tui/open-questions-pane.js +30 -12
  52. package/dist/tui/open-questions-pane.js.map +1 -1
  53. package/dist/tui/pane-layout.d.ts +22 -0
  54. package/dist/tui/pane-layout.d.ts.map +1 -0
  55. package/dist/tui/pane-layout.js +74 -0
  56. package/dist/tui/pane-layout.js.map +1 -0
  57. package/dist/tui/stream-scrollback.d.ts +29 -0
  58. package/dist/tui/stream-scrollback.d.ts.map +1 -0
  59. package/dist/tui/stream-scrollback.js +35 -0
  60. package/dist/tui/stream-scrollback.js.map +1 -0
  61. package/dist/tui/titled-border-pane.d.ts +2 -1
  62. package/dist/tui/titled-border-pane.d.ts.map +1 -1
  63. package/dist/tui/titled-border-pane.js +2 -2
  64. package/dist/tui/titled-border-pane.js.map +1 -1
  65. package/dist/tui/tui-layout-constants.d.ts +11 -6
  66. package/dist/tui/tui-layout-constants.d.ts.map +1 -1
  67. package/dist/tui/tui-layout-constants.js +11 -6
  68. package/dist/tui/tui-layout-constants.js.map +1 -1
  69. package/dist/tui/tui-resize-recovery.d.ts +24 -0
  70. package/dist/tui/tui-resize-recovery.d.ts.map +1 -0
  71. package/dist/tui/tui-resize-recovery.js +34 -0
  72. package/dist/tui/tui-resize-recovery.js.map +1 -0
  73. package/dist/tui/tui-terminal-size.d.ts +45 -0
  74. package/dist/tui/tui-terminal-size.d.ts.map +1 -0
  75. package/dist/tui/tui-terminal-size.js +195 -0
  76. package/dist/tui/tui-terminal-size.js.map +1 -0
  77. package/dist/tui/tui-view-model.d.ts +2 -0
  78. package/dist/tui/tui-view-model.d.ts.map +1 -1
  79. package/dist/tui/tui-view-model.js +7 -0
  80. package/dist/tui/tui-view-model.js.map +1 -1
  81. package/dist/tui/wrap-text-to-width.d.ts.map +1 -1
  82. package/dist/tui/wrap-text-to-width.js +4 -1
  83. package/dist/tui/wrap-text-to-width.js.map +1 -1
  84. package/docs/config.md +67 -3
  85. package/docs/settings.md +17 -4
  86. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"issue-session-tui-stream.d.ts","sourceRoot":"","sources":["../../src/tui/issue-session-tui-stream.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AA0B7E,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,8BAA8B,CAAC;AAMtC,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,YAAY,CAAC;IACxB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B,KAAK,IAAI,CAAC;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAkCD,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,aAAsB,GACvB,EAAE,0BAA0B,2CA+K5B"}
1
+ {"version":3,"file":"issue-session-tui-stream.d.ts","sourceRoot":"","sources":["../../src/tui/issue-session-tui-stream.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AACxE,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,qBAAqB,CAAC;AA0B7E,OAAO,EAEL,KAAK,aAAa,EACnB,MAAM,8BAA8B,CAAC;AAKtC,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAGL,KAAK,qBAAqB,EAC3B,MAAM,wBAAwB,CAAC;AAEhC,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,YAAY,CAAC;IACxB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,0BAA0B,KAAK,IAAI,CAAC;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,iBAAiB,CAAC,EAAE,oBAAoB,CAAC;IACzC,+EAA+E;IAC/E,eAAe,CAAC,EAAE,qBAAqB,CAAC;CACzC;AA0CD,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,aAAsB,EACtB,iBAAiB,EACjB,eAAe,GAChB,EAAE,0BAA0B,2CA0O5B"}
@@ -13,27 +13,31 @@ import { buildActivityLogDisplayLines } from './activity-log.js';
13
13
  import { getPaneContentWidth, wrapTextToWidth } from './wrap-text-to-width.js';
14
14
  import { resolveStreamPaneHeights } from './stream-layout.js';
15
15
  import { TitledBorderPane } from './titled-border-pane.js';
16
- function useStreamContentWidth() {
16
+ import { useTuiTerminalSize, } from './tui-terminal-size.js';
17
+ import { createStreamScrollbackState, reduceStreamScrollback, } from './stream-scrollback.js';
18
+ function useStreamContentWidth(columns) {
17
19
  return getPaneContentWidth({
18
- columns: process.stdout.columns ?? 80,
20
+ columns,
19
21
  paddingX: PANE_PADDING_X,
20
22
  borderWidth: ROUND_BORDER_WIDTH,
21
23
  });
22
24
  }
23
- function useStreamActivityLogWidth() {
24
- return Math.max(1, process.stdout.columns ?? 80);
25
+ function useStreamActivityLogWidth(columns) {
26
+ return Math.max(1, columns);
25
27
  }
26
- function StaticActivityLog({ activityLog, contentWidth, }) {
27
- return (_jsx(Static, { items: activityLog, children: (entry, index) => (_jsx(Box, { flexDirection: "column", children: buildActivityLogDisplayLines([entry], contentWidth).map((line, lineIndex) => (_jsx(ActivityLogDisplayLineRow, { line: line }, `activity-line-${index}-${lineIndex}`))) }, `activity-log-${index}`)) }));
28
+ function StaticActivityLog({ activityLog, contentWidth, replayGeneration, issueLinkMode, }) {
29
+ return (_jsx(Static, { items: activityLog, children: (entry, index) => (_jsx(Box, { flexDirection: "column", children: buildActivityLogDisplayLines([entry], contentWidth).map((line, lineIndex) => (_jsx(ActivityLogDisplayLineRow, { line: line, issueLinkMode: issueLinkMode }, `activity-line-${index}-${lineIndex}`))) }, `activity-log-${index}`)) }, replayGeneration));
28
30
  }
29
- export function IssueSessionTuiStream({ viewModel, onSubmit, issueUrl, issueLinkMode = 'osc8', }) {
31
+ export function IssueSessionTuiStream({ viewModel, onSubmit, issueUrl, issueLinkMode = 'osc8', terminalSizeStore, scrollbackEvent, }) {
30
32
  const snapshot = useSyncExternalStore(viewModel.subscribe, viewModel.getSnapshot, viewModel.getSnapshot);
31
33
  const [inputValue, setInputValue] = useState('');
32
34
  const [inputDisplayLineCount, setInputDisplayLineCount] = useState(1);
33
35
  const [selectedQuestionIndex, setSelectedQuestionIndex] = useState(0);
34
- const contentWidth = useStreamContentWidth();
35
- const activityLogContentWidth = useStreamActivityLogWidth();
36
- const terminalRows = process.stdout.rows ?? 24;
36
+ const [scrollbackState, setScrollbackState] = useState(() => createStreamScrollbackState(snapshot.activityLog.length));
37
+ const terminalSize = useTuiTerminalSize(terminalSizeStore);
38
+ const { columns: terminalColumns, rows: terminalRows } = terminalSize;
39
+ const contentWidth = useStreamContentWidth(terminalColumns);
40
+ const activityLogContentWidth = useStreamActivityLogWidth(terminalColumns);
37
41
  const operatorPrompt = 'operator> ';
38
42
  const maxInputDisplayLines = computeMaxInputDisplayLines(terminalRows);
39
43
  const openQuestions = getTuiOpenQuestions(snapshot);
@@ -56,7 +60,18 @@ export function IssueSessionTuiStream({ viewModel, onSubmit, issueUrl, issueLink
56
60
  postLoopWaiting: snapshot.postLoopWaiting,
57
61
  shuttingDown: snapshot.shuttingDown,
58
62
  });
59
- const contextHintLines = operatorInputDisplay.hintLines;
63
+ const committedActivityCount = Math.min(scrollbackState.detached
64
+ ? scrollbackState.committedActivityCount
65
+ : snapshot.activityLog.length, snapshot.activityLog.length);
66
+ const pendingActivityCount = scrollbackState.detached
67
+ ? Math.max(0, snapshot.activityLog.length - committedActivityCount)
68
+ : 0;
69
+ const scrollbackHint = pendingActivityCount > 0
70
+ ? `${pendingActivityCount} 件の新着 · End で最新へ`
71
+ : undefined;
72
+ const contextHintLines = scrollbackHint
73
+ ? [scrollbackHint, ...operatorInputDisplay.hintLines]
74
+ : operatorInputDisplay.hintLines;
60
75
  const visibleInputDisplayLineCount = Math.min(inputDisplayLineCount, maxInputDisplayLines);
61
76
  const hintLineCount = contextHintLines.reduce((lineCount, line) => lineCount + wrapTextToWidth(line, contentWidth).length, 0);
62
77
  const desiredInputPaneHeight = computeInputPaneHeight({
@@ -86,16 +101,39 @@ export function IssueSessionTuiStream({ viewModel, onSubmit, issueUrl, issueLink
86
101
  useEffect(() => {
87
102
  setSelectedQuestionIndex((current) => clampOpenQuestionSelectionIndex(current, openQuestions.length));
88
103
  }, [openQuestions]);
104
+ useEffect(() => {
105
+ if (!scrollbackEvent) {
106
+ return;
107
+ }
108
+ // The prop is an edge-triggered event. A future adapter should replace it
109
+ // when it observes another viewport transition.
110
+ setScrollbackState((current) => reduceStreamScrollback(current, scrollbackEvent, snapshot.activityLog.length));
111
+ }, [scrollbackEvent]);
112
+ const dispatchScrollbackEvent = (event) => {
113
+ setScrollbackState((current) => reduceStreamScrollback(current, event, snapshot.activityLog.length));
114
+ };
89
115
  useInput((_input, key) => {
90
- if (openQuestions.length === 0 || !key.shift) {
116
+ if (openQuestions.length > 0 && key.shift) {
117
+ if (key.upArrow) {
118
+ setSelectedQuestionIndex((current) => advanceOpenQuestionSelection(current, 'up', openQuestions.length));
119
+ return;
120
+ }
121
+ if (key.downArrow) {
122
+ setSelectedQuestionIndex((current) => advanceOpenQuestionSelection(current, 'down', openQuestions.length));
123
+ return;
124
+ }
125
+ }
126
+ const scrollWithModifier = key.ctrl;
127
+ const scrollWithoutModifier = inputValue.length === 0;
128
+ if (!scrollWithModifier && !scrollWithoutModifier) {
91
129
  return;
92
130
  }
93
- if (key.upArrow) {
94
- setSelectedQuestionIndex((current) => advanceOpenQuestionSelection(current, 'up', openQuestions.length));
131
+ if (key.pageUp) {
132
+ dispatchScrollbackEvent({ type: 'detached', source: 'keyboard' });
95
133
  return;
96
134
  }
97
- if (key.downArrow) {
98
- setSelectedQuestionIndex((current) => advanceOpenQuestionSelection(current, 'down', openQuestions.length));
135
+ if (key.end) {
136
+ dispatchScrollbackEvent({ type: 'follow', source: 'keyboard' });
99
137
  }
100
138
  });
101
139
  const handleSubmit = (value) => {
@@ -112,6 +150,6 @@ export function IssueSessionTuiStream({ viewModel, onSubmit, issueUrl, issueLink
112
150
  setInputValue('');
113
151
  setInputDisplayLineCount(1);
114
152
  };
115
- return (_jsxs(_Fragment, { children: [_jsx(StaticActivityLog, { activityLog: snapshot.activityLog, contentWidth: activityLogContentWidth }), _jsxs(Box, { flexDirection: "column", width: process.stdout.columns ?? 80, height: streamPaneHeights.dynamicFrameHeight, overflowX: "visible", overflowY: "hidden", children: [operatorInputDisplay.mode === 'withQuestions' ? (_jsx(OpenQuestionsPane, { layout: streamOpenQuestionsLayout })) : null, _jsxs(TitledBorderPane, { title: INPUT_PANE_TITLE, borderStyle: "single", borderColor: INPUT_PANE_BORDER_COLOR, paddingX: PANE_PADDING_X, height: streamPaneHeights.inputPaneHeight, children: [contextHintLines.map((line, index) => (_jsx(WrappedTextLines, { text: line, width: contentWidth, color: INPUT_PANE_HINT_COLOR }, `context-hint-${index}`))), _jsx(OperatorTextArea, { value: inputValue, onChange: setInputValue, onSubmit: handleSubmit, focus: !snapshot.shuttingDown, contentWidth: contentWidth, promptPrefix: operatorPrompt, maxDisplayLines: maxInputDisplayLines, onDisplayLineCountChange: handleDisplayLineCountChange, cursorStart: cursorStart })] }), _jsx(WorkerStatusPane, { workers: snapshot.displayState.workers, dispatchHold: snapshot.displayState.dispatchHold, height: streamPaneHeights.workerPaneHeight, issueUrl: issueUrl, issueLinkMode: issueLinkMode })] })] }));
153
+ return (_jsxs(_Fragment, { children: [_jsx(StaticActivityLog, { activityLog: snapshot.activityLog.slice(0, committedActivityCount), contentWidth: activityLogContentWidth, replayGeneration: snapshot.activityLogGeneration, issueLinkMode: issueLinkMode }), _jsxs(Box, { flexDirection: "column", width: terminalColumns, height: streamPaneHeights.dynamicFrameHeight, overflowX: "visible", overflowY: "hidden", children: [operatorInputDisplay.mode === 'withQuestions' ? (_jsx(OpenQuestionsPane, { layout: streamOpenQuestionsLayout, terminalColumns: terminalColumns, issueLinkMode: issueLinkMode })) : null, _jsxs(TitledBorderPane, { title: INPUT_PANE_TITLE, borderStyle: "single", borderColor: INPUT_PANE_BORDER_COLOR, paddingX: PANE_PADDING_X, height: streamPaneHeights.inputPaneHeight, terminalColumns: terminalColumns, children: [contextHintLines.map((line, index) => (_jsx(WrappedTextLines, { text: line, width: contentWidth, color: INPUT_PANE_HINT_COLOR }, `context-hint-${index}`))), _jsx(OperatorTextArea, { value: inputValue, onChange: setInputValue, onSubmit: handleSubmit, focus: !snapshot.shuttingDown, contentWidth: contentWidth, promptPrefix: operatorPrompt, maxDisplayLines: maxInputDisplayLines, onDisplayLineCountChange: handleDisplayLineCountChange, cursorStart: cursorStart })] }), _jsx(WorkerStatusPane, { workers: snapshot.displayState.workers, dispatchHold: snapshot.displayState.dispatchHold, height: streamPaneHeights.workerPaneHeight, terminalColumns: terminalColumns, issueUrl: issueUrl, issueLinkMode: issueLinkMode })] })] }));
116
154
  }
117
155
  //# sourceMappingURL=issue-session-tui-stream.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"issue-session-tui-stream.js","sourceRoot":"","sources":["../../src/tui/issue-session-tui-stream.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"issue-session-tui-stream.js","sourceRoot":"","sources":["../../src/tui/issue-session-tui-stream.tsx"],"names":[],"mappings":"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"}
@@ -1,10 +1,42 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
3
  vi.mock('./operator-text-area.js', () => import('./operator-text-area.test-double.js'));
4
+ import { EventEmitter } from 'node:events';
5
+ import { PassThrough } from 'node:stream';
6
+ import React from 'react';
7
+ import { render as renderInk } from 'ink';
4
8
  import { cleanup, render } from 'ink-testing-library';
5
9
  import { IssueSessionTuiStream } from './issue-session-tui-stream.js';
6
10
  import { createTuiViewModel } from './tui-view-model.js';
7
11
  import { flushInkStdin, INK_TEST_KEYS } from './ink-test-keys.js';
12
+ import { createTuiResizeController, createTuiTerminalSizeStore, TUI_RESIZE_SETTLE_MS, TUI_RESIZE_SHRINK_COALESCE_MS, } from './tui-terminal-size.js';
13
+ import { createTuiResizeRecovery, TUI_FULL_REDRAW_SEQUENCE, } from './tui-resize-recovery.js';
14
+ class ResizeSource extends EventEmitter {
15
+ columns = 80;
16
+ rows = 24;
17
+ }
18
+ class FakeTtyStdout extends PassThrough {
19
+ isTTY = true;
20
+ columns = 120;
21
+ rows = 32;
22
+ }
23
+ class FakeTtyStdin extends PassThrough {
24
+ isTTY = true;
25
+ isRaw = false;
26
+ setRawMode(value) {
27
+ this.isRaw = value;
28
+ return this;
29
+ }
30
+ ref() {
31
+ return this;
32
+ }
33
+ unref() {
34
+ return this;
35
+ }
36
+ }
37
+ function waitFor(milliseconds) {
38
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
39
+ }
8
40
  function createOpenQuestion(overrides) {
9
41
  return {
10
42
  responseType: 'text',
@@ -29,6 +61,7 @@ describe('IssueSessionTuiStream', () => {
29
61
  });
30
62
  afterEach(() => {
31
63
  cleanup();
64
+ vi.useRealTimers();
32
65
  vi.restoreAllMocks();
33
66
  });
34
67
  it('renders activity as unframed static output and keeps the lower panes framed', () => {
@@ -54,7 +87,44 @@ describe('IssueSessionTuiStream', () => {
54
87
  expect(frame.indexOf('Open questions')).toBeLessThan(frame.indexOf('Operator input'));
55
88
  expect(frame.indexOf('Operator input')).toBeLessThan(frame.indexOf('Workers'));
56
89
  expect(frame).toContain('inq-1 (1/1) への回答');
57
- expect(frame).not.toContain('任意のタイミングで入力 · /exit で終了');
90
+ expect(frame).not.toContain('任意のタイミングで入力 · /reconnect で再接続 · /exit で終了');
91
+ });
92
+ it('keeps compact rows visible when long selected detail reaches the cap', async () => {
93
+ const viewModel = createTuiViewModel();
94
+ viewModel.setDisplayState({
95
+ workers: {},
96
+ conductorOutput: null,
97
+ openQuestions: [
98
+ createOpenQuestion({
99
+ id: 'inq-long',
100
+ question: `question-start ${'word '.repeat(100)}`,
101
+ context: `first-detail-start ${'context '.repeat(80)}context-tail`,
102
+ }),
103
+ createOpenQuestion({
104
+ id: 'inq-compact-1',
105
+ question: 'Second question',
106
+ context: 'second-detail',
107
+ }),
108
+ createOpenQuestion({
109
+ id: 'inq-compact-2',
110
+ question: 'Third question',
111
+ }),
112
+ ],
113
+ dispatchHold: { hold: false, heldEventCount: 0 },
114
+ });
115
+ const { stdin, lastFrame } = render(_jsx(IssueSessionTuiStream, { viewModel: viewModel, onSubmit: () => { } }));
116
+ const initialFrame = lastFrame() ?? '';
117
+ expect(initialFrame).toContain('first-detail-start');
118
+ expect(initialFrame).toContain('inq-compact-1');
119
+ expect(initialFrame).toContain('inq-compact-2');
120
+ stdin.write(INK_TEST_KEYS.shiftDownArrow);
121
+ await flushInkStdin();
122
+ const switchedFrame = lastFrame() ?? '';
123
+ expect(switchedFrame).toContain('▸ inq-compact-1');
124
+ expect(switchedFrame).toContain('second-detail');
125
+ expect(switchedFrame).toContain('inq-long');
126
+ expect(switchedFrame).toContain('inq-compact-2');
127
+ expect(switchedFrame).not.toContain('first-detail-start');
58
128
  });
59
129
  it('renders inline Markdown in static activity output', () => {
60
130
  const viewModel = createTuiViewModel();
@@ -65,6 +135,34 @@ describe('IssueSessionTuiStream', () => {
65
135
  expect(frame).not.toContain('**');
66
136
  expect(frame).not.toContain('`');
67
137
  });
138
+ it('renders nested Markdown links in stream activity and open questions', () => {
139
+ const viewModel = createTuiViewModel();
140
+ viewModel.setDisplayState({
141
+ workers: {},
142
+ conductorOutput: null,
143
+ openQuestions: [
144
+ createOpenQuestion({
145
+ id: 'inq-stream-link',
146
+ question: '- **choose** [this](https://example.com/question)',
147
+ context: 'Use `safe` [docs](https://example.com/context).',
148
+ }),
149
+ ],
150
+ dispatchHold: { hold: false, heldEventCount: 0 },
151
+ });
152
+ viewModel.appendActivityLog('conductor', '- **bold** [activity](https://example.com/activity)\n - `nested`');
153
+ const { lastFrame } = render(_jsx(IssueSessionTuiStream, { viewModel: viewModel, issueLinkMode: "osc8", onSubmit: () => { } }));
154
+ const frame = lastFrame() ?? '';
155
+ const visibleFrame = frame.replace(/\u001b\]8;;[^\u0007]*\u0007/g, '');
156
+ expect(visibleFrame).toContain('[conductor]');
157
+ expect(visibleFrame).toContain('- bold activity');
158
+ expect(visibleFrame).toContain('▸ inq-stream-link [text] - choose this');
159
+ expect(visibleFrame).toContain(' Use safe docs.');
160
+ expect(frame).toContain('\u001b]8;;https://example.com/activity\u0007');
161
+ expect(frame).toContain('\u001b]8;;https://example.com/question\u0007');
162
+ expect(frame).toContain('\u001b]8;;https://example.com/context\u0007');
163
+ expect(frame).not.toContain('**');
164
+ expect(frame).not.toContain('`');
165
+ });
68
166
  it('shows dispatch hold count in the Workers pane title', () => {
69
167
  const viewModel = createTuiViewModel();
70
168
  viewModel.setDisplayState({
@@ -82,14 +180,14 @@ describe('IssueSessionTuiStream', () => {
82
180
  const { lastFrame } = render(_jsx(IssueSessionTuiStream, { viewModel: viewModel, issueUrl: "https://github.com/otolab/agents-ensemble/issues/261", issueLinkMode: "label", onSubmit: () => { } }));
83
181
  const frame = lastFrame() ?? '';
84
182
  const operatorInputIndex = frame.indexOf('Operator input');
85
- const instructionHintIndex = frame.indexOf('追加指示を入力するか /exit で終了');
183
+ const instructionHintIndex = frame.indexOf('追加指示を入力するか /reconnect で再接続 · /exit で終了');
86
184
  const workersIndex = frame.indexOf('Workers');
87
185
  expect(operatorInputIndex).toBeGreaterThanOrEqual(0);
88
186
  expect(frame).not.toContain('Open questions');
89
187
  expect(frame).not.toContain('(未回答なし)');
90
188
  expect(instructionHintIndex).toBeGreaterThan(operatorInputIndex);
91
189
  expect(workersIndex).toBeGreaterThan(operatorInputIndex);
92
- expect(frame).toContain('追加指示を入力するか /exit で終了');
190
+ expect(frame).toContain('追加指示を入力するか /reconnect で再接続 · /exit で終了');
93
191
  expect(frame).toContain('otolab/agents-ensemble#261');
94
192
  expect(frame).not.toContain('post-loop 待機中');
95
193
  expect(Math.max(...frame.split('\n').map((line) => line.trimEnd().length))).toBeLessThanOrEqual(80);
@@ -254,7 +352,7 @@ describe('IssueSessionTuiStream', () => {
254
352
  viewModel.setPostLoopWaiting(true);
255
353
  await flushInkStdin();
256
354
  expectCanonicalIssueLink();
257
- expect(lastFrame() ?? '').toContain('追加指示を入力するか /exit で終了');
355
+ expect(lastFrame() ?? '').toContain('追加指示を入力するか /reconnect で再接続 · /exit で終了');
258
356
  viewModel.setShuttingDown(true);
259
357
  await flushInkStdin();
260
358
  expectCanonicalIssueLink();
@@ -264,7 +362,7 @@ describe('IssueSessionTuiStream', () => {
264
362
  const viewModel = createTuiViewModel();
265
363
  const { lastFrame } = render(_jsx(IssueSessionTuiStream, { viewModel: viewModel, issueUrl: "https://github.com/otolab/agents-ensemble/issues/261", issueLinkMode: "label", onSubmit: () => { } }));
266
364
  const frame = lastFrame() ?? '';
267
- expect(frame).toContain('任意のタイミングで入力 · /exit で終了');
365
+ expect(frame).toContain('任意のタイミングで入力 · /reconnect で再接続 · /exit で終了');
268
366
  expect(frame).not.toContain('自律ターン');
269
367
  });
270
368
  it('omits the open-question pane and keeps ordinary input available', async () => {
@@ -272,9 +370,9 @@ describe('IssueSessionTuiStream', () => {
272
370
  const onSubmit = vi.fn();
273
371
  const { stdin, lastFrame } = render(_jsx(IssueSessionTuiStream, { viewModel: viewModel, issueUrl: "https://github.com/otolab/agents-ensemble/issues/263", issueLinkMode: "label", onSubmit: onSubmit }));
274
372
  expect(lastFrame() ?? '').not.toContain('Open questions');
275
- expect(lastFrame() ?? '').toContain('任意のタイミングで入力 · /exit で終了');
373
+ expect(lastFrame() ?? '').toContain('任意のタイミングで入力 · /reconnect で再接続 · /exit で終了');
276
374
  expect(lastFrame() ?? '').toContain('otolab/agents-ensemble#263');
277
- expect(lastFrame() ?? '').not.toContain('otolab/agents-ensemble#263 — 任意のタイミングで入力 · /exit で終了');
375
+ expect(lastFrame() ?? '').not.toContain('otolab/agents-ensemble#263 — 任意のタイミングで入力 · /reconnect で再接続 · /exit で終了');
278
376
  stdin.write('follow-up');
279
377
  await flushInkStdin();
280
378
  stdin.write('\r');
@@ -292,6 +390,242 @@ describe('IssueSessionTuiStream', () => {
292
390
  expect(frame).toContain('[harness] first');
293
391
  expect(frame).toContain('[observation] second');
294
392
  });
393
+ it('holds new activity while detached and flushes the pending suffix once on End', async () => {
394
+ const viewModel = createTuiViewModel({ activityLogWindowSize: null });
395
+ viewModel.appendActivityLog('harness', 'committed');
396
+ const { stdin, lastFrame } = render(_jsx(IssueSessionTuiStream, { viewModel: viewModel, onSubmit: () => { } }));
397
+ stdin.write(INK_TEST_KEYS.pageUp);
398
+ await flushInkStdin();
399
+ viewModel.appendActivityLog('harness', 'pending-one');
400
+ viewModel.appendActivityLog('harness', 'pending-two');
401
+ await flushInkStdin();
402
+ const detachedFrame = lastFrame() ?? '';
403
+ expect(detachedFrame).not.toContain('[harness] pending-one');
404
+ expect(detachedFrame).not.toContain('[harness] pending-two');
405
+ expect(detachedFrame).toContain('2 件の新着 · End で最新へ');
406
+ stdin.write(INK_TEST_KEYS.end);
407
+ await flushInkStdin();
408
+ const followedFrame = lastFrame() ?? '';
409
+ expect(followedFrame).toContain('[harness] pending-one');
410
+ expect(followedFrame).toContain('[harness] pending-two');
411
+ expect((followedFrame.match(/\[harness\] pending-one/g) ?? []).length).toBe(1);
412
+ expect((followedFrame.match(/\[harness\] pending-two/g) ?? []).length).toBe(1);
413
+ expect(followedFrame).not.toContain('2 件の新着 · End で最新へ');
414
+ });
415
+ it('requires Ctrl+PgUp while input has text, matching the pane key contract', async () => {
416
+ const viewModel = createTuiViewModel({ activityLogWindowSize: null });
417
+ viewModel.appendActivityLog('harness', 'committed');
418
+ const { stdin, lastFrame } = render(_jsx(IssueSessionTuiStream, { viewModel: viewModel, onSubmit: () => { } }));
419
+ stdin.write('typed');
420
+ await flushInkStdin();
421
+ stdin.write(INK_TEST_KEYS.pageUp);
422
+ await flushInkStdin();
423
+ viewModel.appendActivityLog('harness', 'plain-page-up-followed');
424
+ await flushInkStdin();
425
+ expect(lastFrame() ?? '').toContain('[harness] plain-page-up-followed');
426
+ expect(lastFrame() ?? '').not.toContain('新着 · End で最新へ');
427
+ stdin.write(INK_TEST_KEYS.ctrlPageUp);
428
+ await flushInkStdin();
429
+ viewModel.appendActivityLog('harness', 'ctrl-page-up-pending');
430
+ await flushInkStdin();
431
+ const detachedFrame = lastFrame() ?? '';
432
+ expect(detachedFrame).toContain('typed');
433
+ expect(detachedFrame).not.toContain('[harness] ctrl-page-up-pending');
434
+ expect(detachedFrame).toContain('1 件の新着 · End で最新へ');
435
+ });
436
+ it('settles the live frame without replaying stream Static history', async () => {
437
+ vi.useFakeTimers();
438
+ const source = new ResizeSource();
439
+ const terminalSizeStore = createTuiTerminalSizeStore(source);
440
+ const viewModel = createTuiViewModel();
441
+ viewModel.appendActivityLog('harness', 'before resize');
442
+ const { lastFrame } = render(_jsx(IssueSessionTuiStream, { viewModel: viewModel, terminalSizeStore: terminalSizeStore, onSubmit: () => { } }));
443
+ const countHistory = (frame) => (frame.match(/\[harness\] before resize/g) ?? []).length;
444
+ expect(countHistory(lastFrame() ?? '')).toBe(1);
445
+ source.columns = 40;
446
+ source.rows = 12;
447
+ source.emit('resize');
448
+ await vi.advanceTimersByTimeAsync(TUI_RESIZE_SHRINK_COALESCE_MS);
449
+ const frame = lastFrame() ?? '';
450
+ expect(countHistory(frame)).toBe(1);
451
+ expect(Math.max(...frame.split('\n').map((line) => line.trimEnd().length))).toBeLessThanOrEqual(40);
452
+ terminalSizeStore.dispose();
453
+ });
454
+ it('coalesces staged same-row shrink before redrawing the stream frame', async () => {
455
+ vi.useFakeTimers();
456
+ const source = new ResizeSource();
457
+ source.columns = 120;
458
+ source.rows = 32;
459
+ const resizeController = createTuiResizeController(source);
460
+ const terminalSizeStore = resizeController.terminalSize;
461
+ const viewModel = createTuiViewModel();
462
+ viewModel.appendActivityLog('harness', 'before staged resize');
463
+ const { lastFrame } = render(_jsx(IssueSessionTuiStream, { viewModel: viewModel, terminalSizeStore: terminalSizeStore, onSubmit: () => { } }));
464
+ const initialFrame = lastFrame() ?? '';
465
+ const countHistory = (frame) => (frame.match(/\[harness\] before staged resize/g) ?? []).length;
466
+ const inkResizeNotifications = [];
467
+ const inkResizeListener = () => {
468
+ inkResizeNotifications.push({
469
+ terminalColumns: terminalSizeStore.getSnapshot().columns,
470
+ proxyColumns: resizeController.stdout.columns,
471
+ });
472
+ };
473
+ resizeController.stdout.on('resize', inkResizeListener);
474
+ const unsubscribe = terminalSizeStore.subscribe(() => {
475
+ expect(resizeController.stdout.columns).toBeGreaterThanOrEqual(terminalSizeStore.getSnapshot().columns);
476
+ });
477
+ try {
478
+ expect(countHistory(initialFrame)).toBe(1);
479
+ for (const columns of [110, 100, 90, 80, 70]) {
480
+ source.columns = columns;
481
+ source.rows = 32;
482
+ source.emit('resize');
483
+ await vi.advanceTimersByTimeAsync(TUI_RESIZE_SETTLE_MS);
484
+ expect(inkResizeNotifications).toEqual([]);
485
+ expect(lastFrame()).toBe(initialFrame);
486
+ expect(countHistory(lastFrame() ?? '')).toBe(1);
487
+ }
488
+ source.columns = 60;
489
+ source.rows = 32;
490
+ source.emit('resize');
491
+ await vi.advanceTimersByTimeAsync(TUI_RESIZE_SHRINK_COALESCE_MS);
492
+ const finalFrame = lastFrame() ?? '';
493
+ expect(inkResizeNotifications).toEqual([
494
+ { terminalColumns: 60, proxyColumns: 120 },
495
+ ]);
496
+ expect(finalFrame).not.toBe(initialFrame);
497
+ expect(countHistory(finalFrame)).toBe(1);
498
+ expect(Math.max(...finalFrame.split('\n').map((line) => line.trimEnd().length))).toBeLessThanOrEqual(60);
499
+ expect(finalFrame).toContain('Workers');
500
+ expect(finalFrame).toContain('operator>');
501
+ }
502
+ finally {
503
+ unsubscribe();
504
+ resizeController.dispose();
505
+ }
506
+ });
507
+ it('clears and replays retained stream history once per settled shrink', async () => {
508
+ const source = new FakeTtyStdout();
509
+ const stdin = new FakeTtyStdin();
510
+ const stderr = new PassThrough();
511
+ const output = [];
512
+ source.on('data', (chunk) => {
513
+ output.push(chunk.toString());
514
+ });
515
+ const viewModel = createTuiViewModel({ activityLogWindowSize: null });
516
+ viewModel.appendActivityLog('observation', 'before-resize');
517
+ let ink;
518
+ let recovery;
519
+ const resizeController = createTuiResizeController(source, TUI_RESIZE_SETTLE_MS, (event) => {
520
+ recovery?.recover(event);
521
+ });
522
+ recovery = createTuiResizeRecovery({
523
+ clearInk: () => {
524
+ ink?.clear();
525
+ },
526
+ write: (data) => {
527
+ resizeController.stdout.write(data);
528
+ },
529
+ requestActivityLogReplay: () => {
530
+ viewModel.requestActivityLogReplay();
531
+ },
532
+ });
533
+ ink = renderInk(React.createElement(IssueSessionTuiStream, {
534
+ viewModel,
535
+ terminalSizeStore: resizeController.terminalSize,
536
+ onSubmit: () => { },
537
+ }), {
538
+ stdout: resizeController.stdout,
539
+ stdin: stdin,
540
+ stderr: stderr,
541
+ alternateScreen: false,
542
+ interactive: true,
543
+ patchConsole: false,
544
+ maxFps: 60,
545
+ });
546
+ try {
547
+ await ink.waitUntilRenderFlush();
548
+ const firstOutputLength = output.join('').length;
549
+ source.columns = 60;
550
+ source.emit('resize');
551
+ await waitFor(TUI_RESIZE_SHRINK_COALESCE_MS + 80);
552
+ await ink.waitUntilRenderFlush();
553
+ const firstRecoveryOutput = output.join('').slice(firstOutputLength);
554
+ const firstResetIndex = firstRecoveryOutput.indexOf(TUI_FULL_REDRAW_SEQUENCE);
555
+ const firstMarkerIndex = firstRecoveryOutput.indexOf('[observation] before-resize');
556
+ expect(firstRecoveryOutput.split(TUI_FULL_REDRAW_SEQUENCE)).toHaveLength(2);
557
+ expect(firstResetIndex).toBeGreaterThanOrEqual(0);
558
+ expect(firstResetIndex).toBeLessThan(firstMarkerIndex);
559
+ expect(firstRecoveryOutput.match(/\[observation\] before-resize/g)).toHaveLength(1);
560
+ expect(viewModel.getSnapshot().activityLogGeneration).toBe(1);
561
+ viewModel.appendActivityLog('observation', 'after-resize');
562
+ await ink.waitUntilRenderFlush();
563
+ const secondOutputLength = output.join('').length;
564
+ source.columns = 40;
565
+ source.emit('resize');
566
+ await waitFor(TUI_RESIZE_SHRINK_COALESCE_MS + 80);
567
+ await ink.waitUntilRenderFlush();
568
+ const secondRecoveryOutput = output.join('').slice(secondOutputLength);
569
+ const secondResetIndex = secondRecoveryOutput.indexOf(TUI_FULL_REDRAW_SEQUENCE);
570
+ const secondMarkerIndex = secondRecoveryOutput.indexOf('[observation] before-resize');
571
+ expect(secondRecoveryOutput.split(TUI_FULL_REDRAW_SEQUENCE)).toHaveLength(2);
572
+ expect(secondResetIndex).toBeGreaterThanOrEqual(0);
573
+ expect(secondResetIndex).toBeLessThan(secondMarkerIndex);
574
+ expect(secondRecoveryOutput.match(/\[observation\] before-resize/g)).toHaveLength(1);
575
+ expect(secondRecoveryOutput.match(/\[observation\] after-resize/g)).toHaveLength(1);
576
+ expect(viewModel.getSnapshot().activityLogGeneration).toBe(2);
577
+ }
578
+ finally {
579
+ recovery.dispose();
580
+ ink.unmount();
581
+ await ink.waitUntilExit();
582
+ resizeController.dispose();
583
+ stdin.destroy();
584
+ stderr.destroy();
585
+ source.destroy();
586
+ }
587
+ });
588
+ it('applies a stream width increase after a pending shrink through the normal path', async () => {
589
+ vi.useFakeTimers();
590
+ const source = new ResizeSource();
591
+ source.columns = 120;
592
+ source.rows = 32;
593
+ const resizeController = createTuiResizeController(source);
594
+ const terminalSizeStore = resizeController.terminalSize;
595
+ const viewModel = createTuiViewModel();
596
+ const { lastFrame } = render(_jsx(IssueSessionTuiStream, { viewModel: viewModel, terminalSizeStore: terminalSizeStore, onSubmit: () => { } }));
597
+ const resizeNotifications = [];
598
+ resizeController.stdout.on('resize', () => {
599
+ resizeNotifications.push({
600
+ terminalColumns: terminalSizeStore.getSnapshot().columns,
601
+ proxyColumns: resizeController.stdout.columns,
602
+ });
603
+ });
604
+ try {
605
+ source.columns = 60;
606
+ source.rows = 32;
607
+ source.emit('resize');
608
+ await vi.advanceTimersByTimeAsync(TUI_RESIZE_SHRINK_COALESCE_MS);
609
+ const shrunkFrame = lastFrame() ?? '';
610
+ const shrunkWidth = Math.max(...shrunkFrame.split('\n').map((line) => line.trimEnd().length));
611
+ source.columns = 120;
612
+ source.rows = 32;
613
+ source.emit('resize');
614
+ await vi.advanceTimersByTimeAsync(TUI_RESIZE_SETTLE_MS);
615
+ const grownFrame = lastFrame() ?? '';
616
+ const grownWidth = Math.max(...grownFrame.split('\n').map((line) => line.trimEnd().length));
617
+ expect(terminalSizeStore.getSnapshot().columns).toBe(120);
618
+ expect(resizeNotifications).toEqual([
619
+ { terminalColumns: 60, proxyColumns: 120 },
620
+ { terminalColumns: 120, proxyColumns: 120 },
621
+ ]);
622
+ expect(grownFrame).not.toBe(shrunkFrame);
623
+ expect(grownWidth).toBeGreaterThan(shrunkWidth);
624
+ }
625
+ finally {
626
+ resizeController.dispose();
627
+ }
628
+ });
295
629
  it('submits input for the selected open question', async () => {
296
630
  const viewModel = createTuiViewModel();
297
631
  viewModel.setDisplayState({
@@ -342,7 +676,7 @@ describe('IssueSessionTuiStream', () => {
342
676
  const initialFrame = lastFrame() ?? '';
343
677
  expect(initialFrame).toContain('Open questions');
344
678
  expect(initialFrame).toContain('inq-resumed-1');
345
- expect(initialFrame).not.toContain('任意のタイミングで入力 · /exit で終了');
679
+ expect(initialFrame).not.toContain('任意のタイミングで入力 · /reconnect で再接続 · /exit で終了');
346
680
  if (selectedIndex === 1) {
347
681
  stdin.write(INK_TEST_KEYS.shiftDownArrow);
348
682
  await flushInkStdin();
@@ -356,16 +690,16 @@ describe('IssueSessionTuiStream', () => {
356
690
  });
357
691
  if (restoredQuestions.length === 1) {
358
692
  expect(lastFrame() ?? '').not.toContain('Open questions');
359
- expect(lastFrame() ?? '').toContain('任意のタイミングで入力 · /exit で終了');
693
+ expect(lastFrame() ?? '').toContain('任意のタイミングで入力 · /reconnect で再接続 · /exit で終了');
360
694
  }
361
695
  else {
362
696
  expect(lastFrame() ?? '').toContain('Open questions');
363
697
  expect(lastFrame() ?? '').toContain('inq-resumed-1');
364
- expect(lastFrame() ?? '').not.toContain('任意のタイミングで入力 · /exit で終了');
698
+ expect(lastFrame() ?? '').not.toContain('任意のタイミングで入力 · /reconnect で再接続 · /exit で終了');
365
699
  setOperatorQuestions([]);
366
700
  await flushInkStdin();
367
701
  expect(lastFrame() ?? '').not.toContain('Open questions');
368
- expect(lastFrame() ?? '').toContain('任意のタイミングで入力 · /exit で終了');
702
+ expect(lastFrame() ?? '').toContain('任意のタイミングで入力 · /reconnect で再接続 · /exit で終了');
369
703
  }
370
704
  });
371
705
  it('keeps Shift+arrow open-question selection in stream mode', async () => {