@indianic/dialout 1.10.0 → 1.11.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.
- package/dist/ai-adapters/claude.d.ts.map +1 -1
- package/dist/ai-adapters/claude.js +18 -1
- package/dist/ai-adapters/claude.js.map +1 -1
- package/node_modules/@indianic/dialout-shared/dist/ai-chat-prefs.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/ai-chat-prefs.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/ai-chat-prefs.test.js +38 -0
- package/node_modules/@indianic/dialout-shared/dist/attachments.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/attachments.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/attachments.test.js +31 -0
- package/node_modules/@indianic/dialout-shared/dist/chat-blocks.d.ts +1 -0
- package/node_modules/@indianic/dialout-shared/dist/chat-blocks.d.ts.map +1 -1
- package/node_modules/@indianic/dialout-shared/dist/chat-blocks.js +1 -1
- package/node_modules/@indianic/dialout-shared/dist/chat-blocks.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/chat-blocks.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/chat-blocks.test.js +67 -0
- package/node_modules/@indianic/dialout-shared/dist/command-filter.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/command-filter.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/command-filter.test.js +63 -0
- package/node_modules/@indianic/dialout-shared/dist/composer-behaviour.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/composer-behaviour.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/composer-behaviour.test.js +27 -0
- package/node_modules/@indianic/dialout-shared/dist/event-merge.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/event-merge.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/event-merge.test.js +42 -0
- package/node_modules/@indianic/dialout-shared/dist/events.d.ts +1 -0
- package/node_modules/@indianic/dialout-shared/dist/events.d.ts.map +1 -1
- package/node_modules/@indianic/dialout-shared/dist/index.d.ts +2 -1
- package/node_modules/@indianic/dialout-shared/dist/index.d.ts.map +1 -1
- package/node_modules/@indianic/dialout-shared/dist/index.js +7 -1
- package/node_modules/@indianic/dialout-shared/dist/notify.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/notify.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/notify.test.js +51 -0
- package/node_modules/@indianic/dialout-shared/dist/pane-prompt.d.ts +17 -0
- package/node_modules/@indianic/dialout-shared/dist/pane-prompt.d.ts.map +1 -1
- package/node_modules/@indianic/dialout-shared/dist/pane-prompt.js +27 -0
- package/node_modules/@indianic/dialout-shared/dist/pane-prompt.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/pane-prompt.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/pane-prompt.test.js +184 -0
- package/node_modules/@indianic/dialout-shared/dist/scroll-pin.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/scroll-pin.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/scroll-pin.test.js +21 -0
- package/node_modules/@indianic/dialout-shared/dist/thinking.d.ts +9 -0
- package/node_modules/@indianic/dialout-shared/dist/thinking.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/thinking.js +38 -0
- package/node_modules/@indianic/dialout-shared/dist/thinking.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/thinking.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/thinking.test.js +30 -0
- package/node_modules/@indianic/dialout-shared/dist/tmux-prefs.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/tmux-prefs.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/tmux-prefs.test.js +95 -0
- package/node_modules/@indianic/dialout-shared/dist/tool-appearance.test.d.ts +2 -0
- package/node_modules/@indianic/dialout-shared/dist/tool-appearance.test.d.ts.map +1 -0
- package/node_modules/@indianic/dialout-shared/dist/tool-appearance.test.js +38 -0
- package/node_modules/@indianic/dialout-shared/package.json +2 -2
- package/node_modules/@indianic/dialout-shared/src/chat-blocks.ts +2 -2
- package/node_modules/@indianic/dialout-shared/src/events.ts +5 -1
- package/node_modules/@indianic/dialout-shared/src/index.ts +2 -1
- package/node_modules/@indianic/dialout-shared/src/pane-prompt.test.ts +23 -1
- package/node_modules/@indianic/dialout-shared/src/pane-prompt.ts +27 -0
- package/node_modules/@indianic/dialout-shared/src/thinking.test.ts +32 -0
- package/node_modules/@indianic/dialout-shared/src/thinking.ts +32 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/ai-adapters/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,SAAS,CAAC;AA6BtD,eAAO,MAAM,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../src/ai-adapters/claude.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAoB,MAAM,SAAS,CAAC;AA6BtD,eAAO,MAAM,aAAa,EAAE,SA0E3B,CAAC"}
|
|
@@ -69,9 +69,26 @@ exports.claudeAdapter = {
|
|
|
69
69
|
ok: !block.is_error, preview: (0, types_1.preview)(textOf(block.content)), at,
|
|
70
70
|
});
|
|
71
71
|
break;
|
|
72
|
+
// Claude Code runs adaptive thinking with a `clear_thinking_20251015`
|
|
73
|
+
// context edit, so the words are stripped from the persisted history
|
|
74
|
+
// and a signed, empty block is left behind — 515 of 615 blocks in one
|
|
75
|
+
// measured session. `redacted_thinking` carries `data` rather than
|
|
76
|
+
// text and is never readable. Either way the record itself still says
|
|
77
|
+
// how long the turn spent thinking, so the row reports the duration
|
|
78
|
+
// instead of rendering as an empty disclosure.
|
|
72
79
|
case 'thinking':
|
|
73
|
-
|
|
80
|
+
case 'redacted_thinking': {
|
|
81
|
+
const text = block.type === 'thinking' ? String(block.thinking || '').trim() : '';
|
|
82
|
+
const ms = typeof rec.thinkingDurationMs === 'number' && rec.thinkingDurationMs > 0
|
|
83
|
+
? rec.thinkingDurationMs
|
|
84
|
+
: 0;
|
|
85
|
+
if (!text && !ms)
|
|
86
|
+
break;
|
|
87
|
+
// `ms` is left off entirely rather than sent as undefined: these
|
|
88
|
+
// cross a socket, and most records carry no duration.
|
|
89
|
+
events.push(ms ? { kind: 'thinking', text, ms, id, at } : { kind: 'thinking', text, id, at });
|
|
74
90
|
break;
|
|
91
|
+
}
|
|
75
92
|
default: {
|
|
76
93
|
// Includes 'text' and any block type a future release introduces.
|
|
77
94
|
// Rendering it as text keeps a new vendor format readable instead of
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/ai-adapters/claude.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/ai-adapters/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-chat-prefs.test.d.ts","sourceRoot":"","sources":["../src/ai-chat-prefs.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const ai_chat_prefs_1 = require("./ai-chat-prefs");
|
|
5
|
+
(0, vitest_1.beforeEach)(() => {
|
|
6
|
+
const store = {};
|
|
7
|
+
vitest_1.vi.stubGlobal('window', {
|
|
8
|
+
localStorage: {
|
|
9
|
+
getItem: (k) => (k in store ? store[k] : null),
|
|
10
|
+
setItem: (k, v) => { store[k] = v; },
|
|
11
|
+
removeItem: (k) => { delete store[k]; },
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
(0, vitest_1.describe)('ai-chat-prefs', () => {
|
|
16
|
+
(0, vitest_1.it)('defaults to hidden and round-trips', () => {
|
|
17
|
+
(0, vitest_1.expect)((0, ai_chat_prefs_1.getFunctionKeysVisible)()).toBe(false);
|
|
18
|
+
(0, ai_chat_prefs_1.setFunctionKeysVisible)(true);
|
|
19
|
+
(0, vitest_1.expect)((0, ai_chat_prefs_1.getFunctionKeysVisible)()).toBe(true);
|
|
20
|
+
(0, ai_chat_prefs_1.setFunctionKeysVisible)(false);
|
|
21
|
+
(0, vitest_1.expect)((0, ai_chat_prefs_1.getFunctionKeysVisible)()).toBe(false);
|
|
22
|
+
});
|
|
23
|
+
// Server render has no window at all; reading must not throw.
|
|
24
|
+
(0, vitest_1.it)('returns the default when there is no window', () => {
|
|
25
|
+
vitest_1.vi.stubGlobal('window', undefined);
|
|
26
|
+
(0, vitest_1.expect)((0, ai_chat_prefs_1.getFunctionKeysVisible)()).toBe(false);
|
|
27
|
+
});
|
|
28
|
+
(0, vitest_1.it)('survives a localStorage that throws (private mode, blocked storage)', () => {
|
|
29
|
+
vitest_1.vi.stubGlobal('window', {
|
|
30
|
+
localStorage: {
|
|
31
|
+
getItem: () => { throw new Error('blocked'); },
|
|
32
|
+
setItem: () => { throw new Error('blocked'); },
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
(0, vitest_1.expect)((0, ai_chat_prefs_1.getFunctionKeysVisible)()).toBe(false);
|
|
36
|
+
(0, vitest_1.expect)(() => (0, ai_chat_prefs_1.setFunctionKeysVisible)(true)).not.toThrow();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attachments.test.d.ts","sourceRoot":"","sources":["../src/attachments.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const attachments_1 = require("./attachments");
|
|
5
|
+
const P1 = '/Users/me/.dialout/attachments/2026-10-21/a1b2c3d4-shot.png';
|
|
6
|
+
const P2 = '/Users/me/.dialout/attachments/2026-10-21/0f0f0f0f-spec.pdf';
|
|
7
|
+
(0, vitest_1.describe)('attachments', () => {
|
|
8
|
+
(0, vitest_1.it)('makes names safe for disk and for a CLI line', () => {
|
|
9
|
+
(0, vitest_1.expect)((0, attachments_1.safeAttachmentName)('Screen Shot 2026-10-21 at 3.04 PM.PNG')).toBe('Screen-Shot-2026-10-21-at-3.04-PM.png');
|
|
10
|
+
(0, vitest_1.expect)((0, attachments_1.safeAttachmentName)('../../etc/passwd')).toBe('passwd');
|
|
11
|
+
(0, vitest_1.expect)((0, attachments_1.safeAttachmentName)('.env')).toBe('env');
|
|
12
|
+
(0, vitest_1.expect)((0, attachments_1.safeAttachmentName)('')).toBe('file');
|
|
13
|
+
(0, vitest_1.expect)((0, attachments_1.safeAttachmentName)('a'.repeat(200) + '.jpeg').length).toBeLessThanOrEqual(80);
|
|
14
|
+
(0, vitest_1.expect)((0, attachments_1.safeAttachmentName)('résumé (final).pdf')).toBe('resume-final.pdf');
|
|
15
|
+
});
|
|
16
|
+
(0, vitest_1.it)('references files the way each CLI reads them, on one line', () => {
|
|
17
|
+
(0, vitest_1.expect)((0, attachments_1.composeWithAttachments)('claude', 'Fix this\nlayout', [P1])).toBe(`Fix this layout @${P1}`);
|
|
18
|
+
(0, vitest_1.expect)((0, attachments_1.composeWithAttachments)('codex', 'Look', [P1, P2])).toBe(`Look (attached: ${P1}, ${P2})`);
|
|
19
|
+
(0, vitest_1.expect)((0, attachments_1.composeWithAttachments)('claude', '', [P1])).toBe(`@${P1}`);
|
|
20
|
+
(0, vitest_1.expect)((0, attachments_1.composeWithAttachments)('grok', 'hi', [])).toBe('hi');
|
|
21
|
+
});
|
|
22
|
+
(0, vitest_1.it)('turns references back into chips, leaving other paths alone', () => {
|
|
23
|
+
const a = (0, attachments_1.splitAttachments)((0, attachments_1.composeWithAttachments)('claude', 'Fix /src/app.ts please', [P1, P2]));
|
|
24
|
+
(0, vitest_1.expect)(a.text).toBe('Fix /src/app.ts please');
|
|
25
|
+
(0, vitest_1.expect)(a.files.map((f) => [f.name, f.image])).toEqual([['shot.png', true], ['spec.pdf', false]]);
|
|
26
|
+
const b = (0, attachments_1.splitAttachments)((0, attachments_1.composeWithAttachments)('codex', 'Look', [P1]));
|
|
27
|
+
(0, vitest_1.expect)(b.text).toBe('Look');
|
|
28
|
+
(0, vitest_1.expect)(b.files[0].path).toBe(P1);
|
|
29
|
+
(0, vitest_1.expect)((0, attachments_1.splitAttachments)('nothing here (attached: soon)').text).toBe('nothing here (attached: soon)');
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat-blocks.d.ts","sourceRoot":"","sources":["../src/chat-blocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAM,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAK,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,EAAE,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"chat-blocks.d.ts","sourceRoot":"","sources":["../src/chat-blocks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAExC,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,OAAO,GAAG,IAAI,CAAC;IACnB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,MAAM,SAAS,GACjB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAM,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GACnE;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,IAAI,EAAE,OAAO,CAAC;IAAK,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,EAAE,CAAA;CAAE,GACrD;IAAE,IAAI,EAAE,UAAU,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7D;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAI,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAIvD,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,SAAS,EAAE,CA0D1D;AAKD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,OAAO,CAE9D"}
|
|
@@ -47,7 +47,7 @@ function groupEvents(events) {
|
|
|
47
47
|
return; // orphan result: drop it rather than invent a row
|
|
48
48
|
}
|
|
49
49
|
if (e.kind === 'thinking') {
|
|
50
|
-
blocks.push({ kind: 'thinking', key, text: e.text || '' });
|
|
50
|
+
blocks.push({ kind: 'thinking', key, text: e.text || '', ms: e.ms });
|
|
51
51
|
return;
|
|
52
52
|
}
|
|
53
53
|
if (e.kind === 'state') {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-blocks.test.d.ts","sourceRoot":"","sources":["../src/chat-blocks.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const chat_blocks_1 = require("./chat-blocks");
|
|
5
|
+
const call = (id, name) => ({ kind: 'tool_call', id, name, summary: `${name} thing` });
|
|
6
|
+
const result = (forId, ok = true) => ({ kind: 'tool_result', forId, ok, preview: 'line1\nline2' });
|
|
7
|
+
const msg = (role, text, id = text) => ({ kind: 'message', role, text, id });
|
|
8
|
+
(0, vitest_1.describe)('groupEvents', () => {
|
|
9
|
+
(0, vitest_1.it)('merges consecutive tool calls into one block', () => {
|
|
10
|
+
const blocks = (0, chat_blocks_1.groupEvents)([call('a', 'Read'), call('b', 'Bash')]);
|
|
11
|
+
(0, vitest_1.expect)(blocks).toHaveLength(1);
|
|
12
|
+
(0, vitest_1.expect)(blocks[0].kind).toBe('tools');
|
|
13
|
+
if (blocks[0].kind === 'tools')
|
|
14
|
+
(0, vitest_1.expect)(blocks[0].items).toHaveLength(2);
|
|
15
|
+
});
|
|
16
|
+
(0, vitest_1.it)('splits tool blocks when a message comes between them', () => {
|
|
17
|
+
const blocks = (0, chat_blocks_1.groupEvents)([
|
|
18
|
+
call('a', 'Read'), msg('assistant', 'hello'), call('b', 'Bash'),
|
|
19
|
+
]);
|
|
20
|
+
(0, vitest_1.expect)(blocks.map((b) => b.kind)).toEqual(['tools', 'assistant', 'tools']);
|
|
21
|
+
});
|
|
22
|
+
(0, vitest_1.it)('attaches a result to its call by forId', () => {
|
|
23
|
+
const blocks = (0, chat_blocks_1.groupEvents)([call('a', 'Read'), call('b', 'Bash'), result('a', false)]);
|
|
24
|
+
if (blocks[0].kind !== 'tools')
|
|
25
|
+
throw new Error('expected tools');
|
|
26
|
+
(0, vitest_1.expect)(blocks[0].items[0].ok).toBe(false);
|
|
27
|
+
(0, vitest_1.expect)(blocks[0].items[0].resultLines).toBe(2);
|
|
28
|
+
(0, vitest_1.expect)(blocks[0].items[1].ok).toBe(null); // no result yet
|
|
29
|
+
});
|
|
30
|
+
// A result whose call was never seen must not crash or invent a row.
|
|
31
|
+
(0, vitest_1.it)('ignores an orphan result', () => {
|
|
32
|
+
(0, vitest_1.expect)((0, chat_blocks_1.groupEvents)([result('nope')])).toHaveLength(0);
|
|
33
|
+
});
|
|
34
|
+
(0, vitest_1.it)('keeps a lone tool call', () => {
|
|
35
|
+
const blocks = (0, chat_blocks_1.groupEvents)([call('a', 'Read')]);
|
|
36
|
+
(0, vitest_1.expect)(blocks).toHaveLength(1);
|
|
37
|
+
});
|
|
38
|
+
(0, vitest_1.it)('collapses repeated identical statuses to one divider', () => {
|
|
39
|
+
const blocks = (0, chat_blocks_1.groupEvents)([
|
|
40
|
+
{ kind: 'state', status: 'working' },
|
|
41
|
+
{ kind: 'state', status: 'working' },
|
|
42
|
+
{ kind: 'state', status: 'waiting_approval' },
|
|
43
|
+
]);
|
|
44
|
+
(0, vitest_1.expect)(blocks.map((b) => b.kind)).toEqual(['status', 'status']);
|
|
45
|
+
if (blocks[1].kind === 'status')
|
|
46
|
+
(0, vitest_1.expect)(blocks[1].status).toBe('waiting_approval');
|
|
47
|
+
});
|
|
48
|
+
(0, vitest_1.it)('separates user and assistant messages into their own blocks', () => {
|
|
49
|
+
const blocks = (0, chat_blocks_1.groupEvents)([msg('user', 'hi'), msg('assistant', 'hello')]);
|
|
50
|
+
(0, vitest_1.expect)(blocks.map((b) => b.kind)).toEqual(['user', 'assistant']);
|
|
51
|
+
});
|
|
52
|
+
(0, vitest_1.it)('gives every block a stable unique key', () => {
|
|
53
|
+
const blocks = (0, chat_blocks_1.groupEvents)([msg('user', 'hi'), call('a', 'Read'), call('b', 'Bash')]);
|
|
54
|
+
const keys = blocks.map((b) => b.key);
|
|
55
|
+
(0, vitest_1.expect)(new Set(keys).size).toBe(keys.length);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
(0, vitest_1.describe)('toolGroupStartsOpen', () => {
|
|
59
|
+
const item = (ok) => ({ id: 'x', name: 'Bash', summary: '', ok, resultPreview: null, resultLines: null });
|
|
60
|
+
(0, vitest_1.it)('is closed for successes and calls still running', () => {
|
|
61
|
+
(0, vitest_1.expect)((0, chat_blocks_1.toolGroupStartsOpen)([item(true), item(null)])).toBe(false);
|
|
62
|
+
(0, vitest_1.expect)((0, chat_blocks_1.toolGroupStartsOpen)([])).toBe(false);
|
|
63
|
+
});
|
|
64
|
+
(0, vitest_1.it)('is open as soon as one item failed', () => {
|
|
65
|
+
(0, vitest_1.expect)((0, chat_blocks_1.toolGroupStartsOpen)([item(true), item(false)])).toBe(true);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"command-filter.test.d.ts","sourceRoot":"","sources":["../src/command-filter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const command_filter_1 = require("./command-filter");
|
|
5
|
+
const cmd = (name, source, description = '') => ({ name, source, description });
|
|
6
|
+
(0, vitest_1.describe)('commandQuery', () => {
|
|
7
|
+
(0, vitest_1.it)('opens on a lone slash', () => {
|
|
8
|
+
(0, vitest_1.expect)((0, command_filter_1.commandQuery)('/')).toBe('');
|
|
9
|
+
});
|
|
10
|
+
(0, vitest_1.it)('returns the text after the slash', () => {
|
|
11
|
+
(0, vitest_1.expect)((0, command_filter_1.commandQuery)('/comp')).toBe('comp');
|
|
12
|
+
});
|
|
13
|
+
// A slash mid-sentence is a path or a date, not a command.
|
|
14
|
+
(0, vitest_1.it)('does not open for a slash that is not first', () => {
|
|
15
|
+
(0, vitest_1.expect)((0, command_filter_1.commandQuery)('what about /tmp')).toBe(null);
|
|
16
|
+
(0, vitest_1.expect)((0, command_filter_1.commandQuery)(' /leading-space')).toBe(null);
|
|
17
|
+
});
|
|
18
|
+
(0, vitest_1.it)('closes once the command is complete', () => {
|
|
19
|
+
(0, vitest_1.expect)((0, command_filter_1.commandQuery)('/compact now')).toBe(null);
|
|
20
|
+
});
|
|
21
|
+
(0, vitest_1.it)('is closed for ordinary text and for empty input', () => {
|
|
22
|
+
(0, vitest_1.expect)((0, command_filter_1.commandQuery)('')).toBe(null);
|
|
23
|
+
(0, vitest_1.expect)((0, command_filter_1.commandQuery)('hello')).toBe(null);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
(0, vitest_1.describe)('rankCommands', () => {
|
|
27
|
+
const all = [
|
|
28
|
+
cmd('code-review:code-review', 'plugin', 'Review a PR'),
|
|
29
|
+
cmd('compact', 'builtin', 'Compact conversation history'),
|
|
30
|
+
cmd('commit-commands:clean_gone', 'plugin', 'Delete merged branches'),
|
|
31
|
+
cmd('seo', 'user', 'SEO Machine'),
|
|
32
|
+
cmd('deploy', 'project', 'Ship it'),
|
|
33
|
+
];
|
|
34
|
+
(0, vitest_1.it)('puts a name prefix match above a name substring above a description match', () => {
|
|
35
|
+
const names = (0, command_filter_1.rankCommands)(all, 'co').map((c) => c.name);
|
|
36
|
+
(0, vitest_1.expect)(names[0]).toBe('compact'); // prefix on the bare name
|
|
37
|
+
(0, vitest_1.expect)(names).toContain('code-review:code-review');
|
|
38
|
+
(0, vitest_1.expect)(names).not.toContain('seo');
|
|
39
|
+
});
|
|
40
|
+
// 52 of 81 commands are plugin-namespaced, so the prefix has to be searchable
|
|
41
|
+
// or half the list is unreachable by typing.
|
|
42
|
+
(0, vitest_1.it)('matches the plugin namespace as well as the command name', () => {
|
|
43
|
+
const names = (0, command_filter_1.rankCommands)(all, 'commit').map((c) => c.name);
|
|
44
|
+
(0, vitest_1.expect)(names).toContain('commit-commands:clean_gone');
|
|
45
|
+
});
|
|
46
|
+
(0, vitest_1.it)('matches a word in the description', () => {
|
|
47
|
+
const names = (0, command_filter_1.rankCommands)(all, 'branches').map((c) => c.name);
|
|
48
|
+
(0, vitest_1.expect)(names).toEqual(['commit-commands:clean_gone']);
|
|
49
|
+
});
|
|
50
|
+
// Plugins outnumber the user's own commands 52:29, so a purely alphabetical
|
|
51
|
+
// sort buries the ones they wrote.
|
|
52
|
+
(0, vitest_1.it)('breaks ties by source, user first and plugin last', () => {
|
|
53
|
+
const tie = [cmd('zzz', 'plugin'), cmd('zzz2', 'user'), cmd('zzz3', 'project')];
|
|
54
|
+
(0, vitest_1.expect)((0, command_filter_1.rankCommands)(tie, 'zzz').map((c) => c.source)).toEqual(['user', 'project', 'plugin']);
|
|
55
|
+
});
|
|
56
|
+
(0, vitest_1.it)('an empty query returns everything, still ranked by source', () => {
|
|
57
|
+
(0, vitest_1.expect)((0, command_filter_1.rankCommands)(all, '')).toHaveLength(5);
|
|
58
|
+
(0, vitest_1.expect)((0, command_filter_1.rankCommands)(all, '')[0].source).toBe('user');
|
|
59
|
+
});
|
|
60
|
+
(0, vitest_1.it)('is case insensitive', () => {
|
|
61
|
+
(0, vitest_1.expect)((0, command_filter_1.rankCommands)(all, 'SEO').map((c) => c.name)).toEqual(['seo']);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"composer-behaviour.test.d.ts","sourceRoot":"","sources":["../src/composer-behaviour.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const composer_behaviour_1 = require("./composer-behaviour");
|
|
5
|
+
const k = (key, shiftKey = false) => ({ key, shiftKey });
|
|
6
|
+
(0, vitest_1.describe)('shouldSubmitOnEnter', () => {
|
|
7
|
+
(0, vitest_1.it)('sends on Enter where there is a real keyboard', () => {
|
|
8
|
+
(0, vitest_1.expect)((0, composer_behaviour_1.shouldSubmitOnEnter)(k('Enter'), false)).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
// On a touch device the on-screen Enter is conventionally a newline, and a
|
|
11
|
+
// stray one would fire a half-typed message.
|
|
12
|
+
(0, vitest_1.it)('never sends on Enter on a coarse pointer', () => {
|
|
13
|
+
(0, vitest_1.expect)((0, composer_behaviour_1.shouldSubmitOnEnter)(k('Enter'), true)).toBe(false);
|
|
14
|
+
});
|
|
15
|
+
(0, vitest_1.it)('Shift+Enter is always a newline', () => {
|
|
16
|
+
(0, vitest_1.expect)((0, composer_behaviour_1.shouldSubmitOnEnter)(k('Enter', true), false)).toBe(false);
|
|
17
|
+
(0, vitest_1.expect)((0, composer_behaviour_1.shouldSubmitOnEnter)(k('Enter', true), true)).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
(0, vitest_1.it)('ignores every other key', () => {
|
|
20
|
+
for (const key of ['a', 'Escape', 'Tab', 'NumpadEnter']) {
|
|
21
|
+
(0, vitest_1.expect)((0, composer_behaviour_1.shouldSubmitOnEnter)(k(key), false)).toBe(false);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
(0, vitest_1.it)('exposes the media query it is paired with', () => {
|
|
25
|
+
(0, vitest_1.expect)(composer_behaviour_1.COARSE_POINTER_QUERY).toBe('(pointer: coarse)');
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-merge.test.d.ts","sourceRoot":"","sources":["../src/event-merge.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const event_merge_1 = require("./event-merge");
|
|
5
|
+
const ev = (n) => ({ kind: 'message', role: 'user', text: `m${n}`, id: `m${n}` });
|
|
6
|
+
const range = (a, b) => Array.from({ length: b - a }, (_, i) => ev(a + i));
|
|
7
|
+
const texts = (s) => s.events.map((e) => e.text);
|
|
8
|
+
(0, vitest_1.describe)('mergeEvents', () => {
|
|
9
|
+
(0, vitest_1.it)('replay replaces, so a reconnect never duplicates history', () => {
|
|
10
|
+
let s = (0, event_merge_1.mergeEvents)(event_merge_1.EMPTY_TRANSCRIPT, range(250, 450), { replay: true, firstSeq: 250, earlier: 250 });
|
|
11
|
+
s = (0, event_merge_1.mergeEvents)(s, range(250, 450), { replay: true, firstSeq: 250, earlier: 250 });
|
|
12
|
+
(0, vitest_1.expect)(s.events).toHaveLength(200);
|
|
13
|
+
(0, vitest_1.expect)(s).toMatchObject({ firstSeq: 250, earlier: 250 });
|
|
14
|
+
});
|
|
15
|
+
(0, vitest_1.it)('history prepends only what is not held', () => {
|
|
16
|
+
let s = (0, event_merge_1.mergeEvents)(event_merge_1.EMPTY_TRANSCRIPT, range(250, 450), { replay: true, firstSeq: 250, earlier: 250 });
|
|
17
|
+
s = (0, event_merge_1.mergeEvents)(s, range(50, 250), { history: true, firstSeq: 50, earlier: 50 });
|
|
18
|
+
(0, vitest_1.expect)(texts(s)[0]).toBe('m50');
|
|
19
|
+
(0, vitest_1.expect)(s.events).toHaveLength(400);
|
|
20
|
+
// The same page again (double tap, or another device) changes nothing.
|
|
21
|
+
(0, vitest_1.expect)((0, event_merge_1.mergeEvents)(s, range(50, 250), { history: true, firstSeq: 50, earlier: 50 })).toBe(s);
|
|
22
|
+
// An overlapping page keeps only the older part.
|
|
23
|
+
s = (0, event_merge_1.mergeEvents)(s, range(0, 100), { history: true, firstSeq: 0, earlier: 0 });
|
|
24
|
+
(0, vitest_1.expect)(texts(s).slice(0, 51)).toEqual(range(0, 51).map((e) => e.text));
|
|
25
|
+
(0, vitest_1.expect)(s.events).toHaveLength(450);
|
|
26
|
+
(0, vitest_1.expect)(s.earlier).toBe(0);
|
|
27
|
+
});
|
|
28
|
+
(0, vitest_1.it)('live appends and trims overlap with the tail', () => {
|
|
29
|
+
let s = (0, event_merge_1.mergeEvents)(event_merge_1.EMPTY_TRANSCRIPT, range(0, 3), { replay: true, firstSeq: 0, earlier: 0 });
|
|
30
|
+
s = (0, event_merge_1.mergeEvents)(s, range(2, 5), { firstSeq: 2 });
|
|
31
|
+
(0, vitest_1.expect)(texts(s)).toEqual(['m0', 'm1', 'm2', 'm3', 'm4']);
|
|
32
|
+
(0, vitest_1.expect)((0, event_merge_1.mergeEvents)(s, range(3, 5), { firstSeq: 3 })).toBe(s);
|
|
33
|
+
});
|
|
34
|
+
(0, vitest_1.it)('an agent without paging is a plain append', () => {
|
|
35
|
+
let s = (0, event_merge_1.mergeEvents)(event_merge_1.EMPTY_TRANSCRIPT, range(0, 2));
|
|
36
|
+
s = (0, event_merge_1.mergeEvents)(s, range(2, 3));
|
|
37
|
+
(0, vitest_1.expect)(texts(s)).toEqual(['m0', 'm1', 'm2']);
|
|
38
|
+
(0, vitest_1.expect)(s.firstSeq).toBeNull();
|
|
39
|
+
// A history page cannot be placed without numbering, so it is ignored.
|
|
40
|
+
(0, vitest_1.expect)((0, event_merge_1.mergeEvents)(s, range(0, 1), { history: true, firstSeq: 0 })).toBe(s);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,eAAe,GAAG,kBAAkB,GAAG,MAAM,CAAC;AAEjF,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,SAAS,CAAC;IAAK,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3F;IAAE,IAAI,EAAE,WAAW,CAAC;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GACjG;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,eAAe,GAAG,kBAAkB,GAAG,MAAM,CAAC;AAEjF,MAAM,MAAM,OAAO,GACf;IAAE,IAAI,EAAE,SAAS,CAAC;IAAK,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3F;IAAE,IAAI,EAAE,WAAW,CAAC;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GACjG;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAKjF;IAAE,IAAI,EAAE,UAAU,CAAC;IAAI,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,IAAI,EAAE,OAAO,CAAC;IAAO,MAAM,EAAE,QAAQ,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE3D,MAAM,WAAW,SAAS;IAExB,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,OAAO,EAAE,CAAC;IAErC,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAAC;CACvC;AAKD,eAAO,MAAM,aAAa,OAAO,CAAC;AAElC,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5C"}
|
|
@@ -23,8 +23,9 @@ export type { TmuxPrefs, TmuxStatusPrefs } from './tmux-prefs';
|
|
|
23
23
|
export { DEFAULT_TMUX_PREFS, STATUS_TOKENS, MAX_STATUS_TEMPLATE, compileStatusTemplate, isValidStatusTemplate, isValidTmuxColor, resolveTmuxPrefs, } from './tmux-prefs';
|
|
24
24
|
export type { TranscriptState, EventsMeta } from './event-merge';
|
|
25
25
|
export { EMPTY_TRANSCRIPT, mergeEvents } from './event-merge';
|
|
26
|
+
export { thinkingDuration, thinkingLabel } from './thinking';
|
|
26
27
|
export type { PanePrompt, PanePromptOption, PromptKey } from './pane-prompt';
|
|
27
|
-
export { PROMPT_KEYS, detectPanePrompt, isSafeKeyList, promptKeys } from './pane-prompt';
|
|
28
|
+
export { PROMPT_KEYS, detectPanePrompt, freeTextRow, isFreeTextOption, isSafeKeyList, promptKeys, promptMoveKeys } from './pane-prompt';
|
|
28
29
|
export type { AttachmentRef } from './attachments';
|
|
29
30
|
export { ATTACHMENT_DIR, ATTACHMENT_MAX_BYTES, ATTACHMENT_MAX_FILES, composeWithAttachments, isImageName, safeAttachmentName, splitAttachments, } from './attachments';
|
|
30
31
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAElD,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAElE,YAAY,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAClD,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE9F,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAElF,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE9D,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEjF,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAErG,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAExH,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,kBAAkB,EAAE,aAAa,EAAE,mBAAmB,EACtD,qBAAqB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,gBAAgB,GACjF,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE9D,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAElD,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAElE,YAAY,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAClD,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE9F,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAElF,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAEjE,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE9D,YAAY,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE9D,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEjF,YAAY,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAErG,YAAY,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAExH,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/D,OAAO,EACL,kBAAkB,EAAE,aAAa,EAAE,mBAAmB,EACtD,qBAAqB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,gBAAgB,GACjF,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC7D,YAAY,EAAE,UAAU,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAExI,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EACL,cAAc,EAAE,oBAAoB,EAAE,oBAAoB,EAC1D,sBAAsB,EAAE,WAAW,EAAE,kBAAkB,EAAE,gBAAgB,GAC1E,MAAM,eAAe,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.splitAttachments = exports.safeAttachmentName = exports.isImageName = exports.composeWithAttachments = exports.ATTACHMENT_MAX_FILES = exports.ATTACHMENT_MAX_BYTES = exports.ATTACHMENT_DIR = exports.promptKeys = exports.isSafeKeyList = exports.detectPanePrompt = exports.PROMPT_KEYS = exports.mergeEvents = exports.EMPTY_TRANSCRIPT = exports.resolveTmuxPrefs = exports.isValidTmuxColor = exports.isValidStatusTemplate = exports.compileStatusTemplate = exports.MAX_STATUS_TEMPLATE = exports.STATUS_TOKENS = exports.DEFAULT_TMUX_PREFS = exports.renderTerminalName = exports.factsFromSession = exports.TERMINAL_NAME_TOKENS = exports.DEFAULT_TERMINAL_TEMPLATE = exports.setFunctionKeysVisible = exports.getFunctionKeysVisible = exports.FUNCTION_KEYS_PREF = exports.shouldSubmitOnEnter = exports.COARSE_POINTER_QUERY = exports.rankCommands = exports.commandQuery = exports.toolAppearance = exports.toolClass = exports.shouldFollow = exports.PIN_THRESHOLD_PX = exports.toolGroupStartsOpen = exports.groupEvents = exports.shouldNotifyPrompt = exports.shouldNotifyAi = exports.NOTIFY_COOLDOWN_MS = exports.REPLAY_LIMIT = exports.isPermissionMode = exports.PERMISSION_MODES = exports.preview = exports.PREVIEW_LIMIT = void 0;
|
|
3
|
+
exports.splitAttachments = exports.safeAttachmentName = exports.isImageName = exports.composeWithAttachments = exports.ATTACHMENT_MAX_FILES = exports.ATTACHMENT_MAX_BYTES = exports.ATTACHMENT_DIR = exports.promptMoveKeys = exports.promptKeys = exports.isSafeKeyList = exports.isFreeTextOption = exports.freeTextRow = exports.detectPanePrompt = exports.PROMPT_KEYS = exports.thinkingLabel = exports.thinkingDuration = exports.mergeEvents = exports.EMPTY_TRANSCRIPT = exports.resolveTmuxPrefs = exports.isValidTmuxColor = exports.isValidStatusTemplate = exports.compileStatusTemplate = exports.MAX_STATUS_TEMPLATE = exports.STATUS_TOKENS = exports.DEFAULT_TMUX_PREFS = exports.renderTerminalName = exports.factsFromSession = exports.TERMINAL_NAME_TOKENS = exports.DEFAULT_TERMINAL_TEMPLATE = exports.setFunctionKeysVisible = exports.getFunctionKeysVisible = exports.FUNCTION_KEYS_PREF = exports.shouldSubmitOnEnter = exports.COARSE_POINTER_QUERY = exports.rankCommands = exports.commandQuery = exports.toolAppearance = exports.toolClass = exports.shouldFollow = exports.PIN_THRESHOLD_PX = exports.toolGroupStartsOpen = exports.groupEvents = exports.shouldNotifyPrompt = exports.shouldNotifyAi = exports.NOTIFY_COOLDOWN_MS = exports.REPLAY_LIMIT = exports.isPermissionMode = exports.PERMISSION_MODES = exports.preview = exports.PREVIEW_LIMIT = void 0;
|
|
4
4
|
var events_1 = require("./events");
|
|
5
5
|
Object.defineProperty(exports, "PREVIEW_LIMIT", { enumerable: true, get: function () { return events_1.PREVIEW_LIMIT; } });
|
|
6
6
|
Object.defineProperty(exports, "preview", { enumerable: true, get: function () { return events_1.preview; } });
|
|
@@ -48,11 +48,17 @@ Object.defineProperty(exports, "resolveTmuxPrefs", { enumerable: true, get: func
|
|
|
48
48
|
var event_merge_1 = require("./event-merge");
|
|
49
49
|
Object.defineProperty(exports, "EMPTY_TRANSCRIPT", { enumerable: true, get: function () { return event_merge_1.EMPTY_TRANSCRIPT; } });
|
|
50
50
|
Object.defineProperty(exports, "mergeEvents", { enumerable: true, get: function () { return event_merge_1.mergeEvents; } });
|
|
51
|
+
var thinking_1 = require("./thinking");
|
|
52
|
+
Object.defineProperty(exports, "thinkingDuration", { enumerable: true, get: function () { return thinking_1.thinkingDuration; } });
|
|
53
|
+
Object.defineProperty(exports, "thinkingLabel", { enumerable: true, get: function () { return thinking_1.thinkingLabel; } });
|
|
51
54
|
var pane_prompt_1 = require("./pane-prompt");
|
|
52
55
|
Object.defineProperty(exports, "PROMPT_KEYS", { enumerable: true, get: function () { return pane_prompt_1.PROMPT_KEYS; } });
|
|
53
56
|
Object.defineProperty(exports, "detectPanePrompt", { enumerable: true, get: function () { return pane_prompt_1.detectPanePrompt; } });
|
|
57
|
+
Object.defineProperty(exports, "freeTextRow", { enumerable: true, get: function () { return pane_prompt_1.freeTextRow; } });
|
|
58
|
+
Object.defineProperty(exports, "isFreeTextOption", { enumerable: true, get: function () { return pane_prompt_1.isFreeTextOption; } });
|
|
54
59
|
Object.defineProperty(exports, "isSafeKeyList", { enumerable: true, get: function () { return pane_prompt_1.isSafeKeyList; } });
|
|
55
60
|
Object.defineProperty(exports, "promptKeys", { enumerable: true, get: function () { return pane_prompt_1.promptKeys; } });
|
|
61
|
+
Object.defineProperty(exports, "promptMoveKeys", { enumerable: true, get: function () { return pane_prompt_1.promptMoveKeys; } });
|
|
56
62
|
var attachments_1 = require("./attachments");
|
|
57
63
|
Object.defineProperty(exports, "ATTACHMENT_DIR", { enumerable: true, get: function () { return attachments_1.ATTACHMENT_DIR; } });
|
|
58
64
|
Object.defineProperty(exports, "ATTACHMENT_MAX_BYTES", { enumerable: true, get: function () { return attachments_1.ATTACHMENT_MAX_BYTES; } });
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notify.test.d.ts","sourceRoot":"","sources":["../src/notify.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const notify_1 = require("./notify");
|
|
5
|
+
// This is the logic most capable of annoying someone into turning
|
|
6
|
+
// notifications off, so every rule gets a case.
|
|
7
|
+
(0, vitest_1.describe)('shouldNotifyAi', () => {
|
|
8
|
+
const NOW = 1_000_000;
|
|
9
|
+
(0, vitest_1.it)('fires when a working session starts waiting for input', () => {
|
|
10
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyAi)('working', 'waiting_input', undefined, NOW)).toBe(true);
|
|
11
|
+
});
|
|
12
|
+
(0, vitest_1.it)('fires when a working session starts waiting for approval', () => {
|
|
13
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyAi)('working', 'waiting_approval', undefined, NOW)).toBe(true);
|
|
14
|
+
});
|
|
15
|
+
(0, vitest_1.it)('stays silent while the status is unchanged', () => {
|
|
16
|
+
// Without this the agent's five-second poll would re-notify forever.
|
|
17
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyAi)('waiting_input', 'waiting_input', undefined, NOW)).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
(0, vitest_1.it)('stays silent for a session seen for the first time', () => {
|
|
20
|
+
// It was probably already sitting there before anyone subscribed;
|
|
21
|
+
// announcing it would mean a burst on every reconnect.
|
|
22
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyAi)(undefined, 'waiting_input', undefined, NOW)).toBe(false);
|
|
23
|
+
});
|
|
24
|
+
(0, vitest_1.it)('stays silent when a session goes back to working', () => {
|
|
25
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyAi)('waiting_input', 'working', undefined, NOW)).toBe(false);
|
|
26
|
+
});
|
|
27
|
+
(0, vitest_1.it)('stays silent when a session merely goes idle', () => {
|
|
28
|
+
// Idle is not "your turn" — nobody needs waking for it.
|
|
29
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyAi)('working', 'idle', undefined, NOW)).toBe(false);
|
|
30
|
+
});
|
|
31
|
+
(0, vitest_1.it)('does not fire on idle -> waiting_input', () => {
|
|
32
|
+
// Only work that was actually running is worth being pulled back to.
|
|
33
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyAi)('idle', 'waiting_input', undefined, NOW)).toBe(false);
|
|
34
|
+
});
|
|
35
|
+
(0, vitest_1.it)('respects the cooldown so a run of short tool calls cannot spam', () => {
|
|
36
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyAi)('working', 'waiting_input', NOW - 30_000, NOW)).toBe(false);
|
|
37
|
+
});
|
|
38
|
+
(0, vitest_1.it)('fires again once the cooldown has passed', () => {
|
|
39
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyAi)('working', 'waiting_input', NOW - 200_000, NOW)).toBe(true);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
(0, vitest_1.describe)('shouldNotifyPrompt', () => {
|
|
43
|
+
(0, vitest_1.it)('fires for a new question, not on first sight, not twice, not inside the cooldown', () => {
|
|
44
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyPrompt)(undefined, 'a', undefined, 1000)).toBe(false);
|
|
45
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyPrompt)(null, 'a', undefined, 1000)).toBe(true);
|
|
46
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyPrompt)('a', 'a', undefined, 1000)).toBe(false);
|
|
47
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyPrompt)('a', null, undefined, 1000)).toBe(false);
|
|
48
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyPrompt)('a', 'b', 1000, 1000 + notify_1.NOTIFY_COOLDOWN_MS - 1)).toBe(false);
|
|
49
|
+
(0, vitest_1.expect)((0, notify_1.shouldNotifyPrompt)('a', 'b', 1000, 1000 + notify_1.NOTIFY_COOLDOWN_MS)).toBe(true);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -43,4 +43,21 @@ export declare function isSafeKeyList(keys: unknown): keys is string[];
|
|
|
43
43
|
* multi-select row Enter toggles it; the menu stays up and is re-read.
|
|
44
44
|
*/
|
|
45
45
|
export declare function promptKeys(p: PanePrompt, n: number): string[];
|
|
46
|
+
/**
|
|
47
|
+
* A row that takes typed text rather than being an answer itself: Claude
|
|
48
|
+
* Code's "Type something." / an "Other" row. Picking it with Enter answers
|
|
49
|
+
* with nothing, so the card asks for the text first.
|
|
50
|
+
*/
|
|
51
|
+
export declare function isFreeTextOption(label: string): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Keys that put the cursor on row `n` without choosing it. For a free-text
|
|
54
|
+
* row: move there, then the text is typed and Enter pressed (as one message).
|
|
55
|
+
*/
|
|
56
|
+
export declare function promptMoveKeys(p: PanePrompt, n: number): string[];
|
|
57
|
+
/**
|
|
58
|
+
* The free-text row's number, or 0 if the menu has none. A TUI echoes what is
|
|
59
|
+
* typed in place of that row's label, so a row that already holds text no
|
|
60
|
+
* longer matches — which is correct: it is mid-answer, not an empty invitation.
|
|
61
|
+
*/
|
|
62
|
+
export declare function freeTextRow(p: PanePrompt): number;
|
|
46
63
|
//# sourceMappingURL=pane-prompt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pane-prompt.d.ts","sourceRoot":"","sources":["../src/pane-prompt.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,EAAE,EAAE,MAAM,CAAC;IACX,mFAAmF;IACnF,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,mEAAmE;IACnE,KAAK,EAAE,OAAO,CAAC;IACf,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,QAAQ,EAAE,OAAO,CAAC;CACnB;AA6GD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAuChE;AAED,yEAAyE;AACzE,eAAO,MAAM,WAAW,sGAAuG,CAAC;AAChI,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,kGAAkG;AAClG,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,EAAE,CAG7D;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAK7D"}
|
|
1
|
+
{"version":3,"file":"pane-prompt.d.ts","sourceRoot":"","sources":["../src/pane-prompt.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,gBAAgB;IAC/B,oCAAoC;IACpC,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,kEAAkE;IAClE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CACzB;AAED,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,EAAE,EAAE,MAAM,CAAC;IACX,mFAAmF;IACnF,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,mEAAmE;IACnE,KAAK,EAAE,OAAO,CAAC;IACf,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IACf,yEAAyE;IACzE,QAAQ,EAAE,OAAO,CAAC;CACnB;AA6GD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAuChE;AAED,yEAAyE;AACzE,eAAO,MAAM,WAAW,sGAAuG,CAAC;AAChI,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,kGAAkG;AAClG,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,MAAM,EAAE,CAG7D;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAK7D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,CAGjD"}
|
|
@@ -17,6 +17,9 @@ exports.PROMPT_KEYS = void 0;
|
|
|
17
17
|
exports.detectPanePrompt = detectPanePrompt;
|
|
18
18
|
exports.isSafeKeyList = isSafeKeyList;
|
|
19
19
|
exports.promptKeys = promptKeys;
|
|
20
|
+
exports.isFreeTextOption = isFreeTextOption;
|
|
21
|
+
exports.promptMoveKeys = promptMoveKeys;
|
|
22
|
+
exports.freeTextRow = freeTextRow;
|
|
20
23
|
// Box-drawing borders some CLIs draw around a prompt: stripped before parsing,
|
|
21
24
|
// keeping the indentation inside the box (it tells options from their hints).
|
|
22
25
|
const BORDER_LEFT = /^\s*[│┃║] ?/u;
|
|
@@ -225,3 +228,27 @@ function promptKeys(p, n) {
|
|
|
225
228
|
const move = to > from ? Array(to - from).fill('Down') : Array(from - to).fill('Up');
|
|
226
229
|
return [...move, 'Enter'];
|
|
227
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* A row that takes typed text rather than being an answer itself: Claude
|
|
233
|
+
* Code's "Type something." / an "Other" row. Picking it with Enter answers
|
|
234
|
+
* with nothing, so the card asks for the text first.
|
|
235
|
+
*/
|
|
236
|
+
function isFreeTextOption(label) {
|
|
237
|
+
return /^(type something|type your own|other|something else)\.?(\s*\(.*\))?$/i.test(label.trim());
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Keys that put the cursor on row `n` without choosing it. For a free-text
|
|
241
|
+
* row: move there, then the text is typed and Enter pressed (as one message).
|
|
242
|
+
*/
|
|
243
|
+
function promptMoveKeys(p, n) {
|
|
244
|
+
return promptKeys(p, n).slice(0, -1);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* The free-text row's number, or 0 if the menu has none. A TUI echoes what is
|
|
248
|
+
* typed in place of that row's label, so a row that already holds text no
|
|
249
|
+
* longer matches — which is correct: it is mid-answer, not an empty invitation.
|
|
250
|
+
*/
|
|
251
|
+
function freeTextRow(p) {
|
|
252
|
+
const row = p.options.find((o) => o.checked === null && isFreeTextOption(o.label));
|
|
253
|
+
return row ? row.n : 0;
|
|
254
|
+
}
|