zames_pro 2.74.0 → 2.75.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +24 -0
- package/dist/attachments.js +6 -1
- package/dist/commands.js +0 -1
- package/dist/config.js +7 -7
- package/dist/i18n/common.js +0 -8
- package/dist/i18n/config.js +0 -1
- package/dist/i18n/help.js +8 -4
- package/dist/i18n/qwen.js +0 -4
- package/dist/i18n/self-review.js +2 -18
- package/dist/i18n/spinner.js +5 -0
- package/dist/index.js +30 -43
- package/dist/input/suggest.js +19 -4
- package/dist/theme.js +9 -0
- package/dist/tui/ConfigMenu.js +44 -11
- package/dist/tui/FullScreenApp.js +44 -11
- package/dist/tui/InputLine.js +52 -19
- package/dist/tui/SelectList.js +6 -2
- package/dist/tui/StatusBar.js +66 -36
- package/dist/tui/TuiApp.js +3 -2
- package/dist/tui/TuiEditor.js +44 -4
- package/dist/tui/edit.js +21 -1
- package/dist/tui/keys.js +46 -2
- package/dist/tui/store.js +1 -1
- package/dist/tui/useMouseWheel.js +80 -29
- package/dist/tui/widgets.js +6 -1
- package/package.json +2 -1
- package/scripts/ctd-live-driver.mts +51 -0
- package/scripts/ctd-live.tsx +33 -0
- package/scripts/escd-live-driver.mts +37 -0
- package/scripts/inline-status-driver.mts +31 -0
- package/scripts/inline-status.tsx +33 -0
- package/scripts/mouse-churn.mts +34 -0
- package/scripts/qwen-models-smoke.mts +117 -0
- package/scripts/ru-shot.mts +20 -0
- package/scripts/tui-comp-shot.mts +63 -0
- package/scripts/tui-components.tsx +62 -0
- package/scripts/tui-config-driver.mts +82 -0
- package/scripts/tui-config-probe.tsx +74 -0
- package/scripts/tui-edit-driver.mts +100 -0
- package/scripts/tui-edit-probe.tsx +38 -0
- package/scripts/tui-editor-probe.tsx +24 -0
- package/scripts/tui-input-driver.mts +54 -0
- package/scripts/tui-input-shot.tsx +59 -0
- package/scripts/tui-log-driver.mts +35 -0
- package/scripts/tui-log-shot.tsx +48 -0
- package/scripts/tui-longpaste-driver.mts +56 -0
- package/scripts/tui-longpaste.tsx +35 -0
- package/scripts/tui-manyselect-shot.mts +34 -0
- package/scripts/tui-manyselect.tsx +17 -0
- package/scripts/tui-mouse-churn-probe.tsx +28 -0
- package/scripts/tui-paste-driver.mts +88 -0
- package/scripts/tui-paste-kinds.tsx +76 -0
- package/scripts/tui-pastetest.mts +38 -0
- package/scripts/tui-repro.tsx +64 -0
- package/scripts/tui-resize.mts +70 -0
- package/scripts/tui-scroll-driver.mts +53 -0
- package/scripts/tui-scroll-probe.tsx +46 -0
- package/scripts/tui-shot.mts +106 -0
- package/scripts/tui-status-driver.mts +24 -0
- package/scripts/tui-status-shot.tsx +27 -0
- package/scripts/tui-submit.tsx +57 -0
- package/scripts/tui-wheel-driver.mts +61 -0
- package/scripts/tui-wheel-probe.tsx +48 -0
- package/scripts/tui-widgets-driver.mts +20 -0
- package/scripts/tui-widgets.tsx +44 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// Minimal probe: mount the REAL FullScreenApp with a store whose submit
|
|
2
|
+
// callback logs what it receives. Used to verify the bracketed-paste ->
|
|
3
|
+
// [Pasted lines#N] -> expandPastes path end to end.
|
|
4
|
+
|
|
5
|
+
import React from 'react'
|
|
6
|
+
import fs from 'node:fs'
|
|
7
|
+
import { render } from 'ink'
|
|
8
|
+
import { TuiStore } from '../src/tui/store.js'
|
|
9
|
+
import { FullScreenApp } from '../src/tui/FullScreenApp.js'
|
|
10
|
+
import { initialEditState } from '../src/tui/edit.js'
|
|
11
|
+
import { expandPastes } from '../src/input/layout.js'
|
|
12
|
+
|
|
13
|
+
const LOG = process.env.PROBE_SUBMIT_LOG || '/tmp/paste-submit.log'
|
|
14
|
+
const store = new TuiStore()
|
|
15
|
+
store.set({
|
|
16
|
+
title: 'probe',
|
|
17
|
+
version: '0',
|
|
18
|
+
workdir: '/tmp',
|
|
19
|
+
prompt: '> ',
|
|
20
|
+
locale: 'en',
|
|
21
|
+
commands: [],
|
|
22
|
+
edit: { ...initialEditState(), buf: '' },
|
|
23
|
+
})
|
|
24
|
+
const inputProps = {
|
|
25
|
+
onSubmit: (text: string) => {
|
|
26
|
+
// Mirrors TuiEditor.handleSubmit: expand the paste markers from the
|
|
27
|
+
// CURRENT store snapshot, which is what the agent actually receives.
|
|
28
|
+
const expanded = expandPastes(store.getSnapshot().pastes, text)
|
|
29
|
+
fs.appendFileSync(
|
|
30
|
+
LOG,
|
|
31
|
+
'SUBMIT=' + JSON.stringify(expanded) + String.fromCharCode(10),
|
|
32
|
+
)
|
|
33
|
+
},
|
|
34
|
+
onEscape: () => {},
|
|
35
|
+
onCtrlC: () => {},
|
|
36
|
+
onCopyCode: () => {},
|
|
37
|
+
onAttach: () => null,
|
|
38
|
+
onClipboard: () => Promise.resolve(null),
|
|
39
|
+
onHistoryChange: () => {},
|
|
40
|
+
onClearScreen: () => {},
|
|
41
|
+
attachments: [],
|
|
42
|
+
onPastesChange: (p: unknown) => {
|
|
43
|
+
// Mirrors TuiEditor.buildInputProps: the adapter writes the paste list
|
|
44
|
+
// BACK into the store, which is what handleSubmit reads to expand markers.
|
|
45
|
+
store.set({ pastes: p as never })
|
|
46
|
+
fs.appendFileSync(
|
|
47
|
+
LOG,
|
|
48
|
+
'PASTES=' + JSON.stringify(p) + String.fromCharCode(10),
|
|
49
|
+
)
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
render(<FullScreenApp store={store} inputProps={inputProps} />, {
|
|
53
|
+
exitOnCtrlC: false,
|
|
54
|
+
patchConsole: false,
|
|
55
|
+
alternateScreen: true,
|
|
56
|
+
})
|
|
57
|
+
setInterval(() => {}, 1 << 30)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Drive scripts/tui-wheel-probe.tsx under a pty and send REAL SGR wheel events
|
|
2
|
+
// (mouse reporting must be on for these to arrive; the probe sets nothing, so
|
|
3
|
+
// this also proves the SCROLL mode sequences are emitted). Prints the buffer
|
|
4
|
+
// and scroll transitions the probe logged: the buffer must NEVER change and
|
|
5
|
+
// the scroll must INCREASE on wheel-up.
|
|
6
|
+
import { spawn } from 'node:child_process'
|
|
7
|
+
import fs from 'node:fs'
|
|
8
|
+
import path from 'node:path'
|
|
9
|
+
|
|
10
|
+
const ESC = String.fromCharCode(27)
|
|
11
|
+
const LOG = '/tmp/wheel-probe.log'
|
|
12
|
+
const SCROLL = process.argv.includes('--scroll')
|
|
13
|
+
// SGR wheel-up = Cb 64, wheel-down = 65: ESC [ < 64 ; col ; row M
|
|
14
|
+
try {
|
|
15
|
+
fs.unlinkSync(LOG)
|
|
16
|
+
} catch {
|
|
17
|
+
/* ignore */
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const child = spawn(
|
|
21
|
+
'script',
|
|
22
|
+
['-qec', 'npx tsx scripts/tui-wheel-probe.tsx', '/dev/null'],
|
|
23
|
+
{
|
|
24
|
+
cwd: path.resolve('.'),
|
|
25
|
+
env: {
|
|
26
|
+
...process.env,
|
|
27
|
+
COLUMNS: '80',
|
|
28
|
+
LINES: '24',
|
|
29
|
+
PROBE_WHEEL_LOG: LOG,
|
|
30
|
+
...(SCROLL ? { PROBE_MOUSE_SCROLL: '1' } : {}),
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
)
|
|
34
|
+
child.stdout.on('data', () => {})
|
|
35
|
+
child.stderr.on('data', () => {})
|
|
36
|
+
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
// Five wheel-up notches.
|
|
39
|
+
for (let i = 0; i < 5; i++) {
|
|
40
|
+
child.stdin.write(ESC + '[<64;10;10M')
|
|
41
|
+
setTimeout(() => {}, 50)
|
|
42
|
+
}
|
|
43
|
+
setTimeout(() => child.kill('SIGTERM'), 800)
|
|
44
|
+
}, 6000)
|
|
45
|
+
|
|
46
|
+
child.on('close', () => {
|
|
47
|
+
let lines: string[] = []
|
|
48
|
+
try {
|
|
49
|
+
lines = fs.readFileSync(LOG, 'utf-8').trim().split(String.fromCharCode(10))
|
|
50
|
+
} catch {
|
|
51
|
+
/* ignore */
|
|
52
|
+
}
|
|
53
|
+
const parsed = lines.map(
|
|
54
|
+
(l) => JSON.parse(l) as { buf: string; scroll: number },
|
|
55
|
+
)
|
|
56
|
+
const bufs = [...new Set(parsed.map((p) => p.buf))]
|
|
57
|
+
const scrolls = parsed.map((p) => p.scroll)
|
|
58
|
+
console.log('BUFS=' + JSON.stringify(bufs))
|
|
59
|
+
console.log('SCROLLS=' + JSON.stringify(scrolls))
|
|
60
|
+
process.exit(0)
|
|
61
|
+
})
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// Mount the REAL TuiEditor with a NON-EMPTY input history and a long log, so a
|
|
2
|
+
// pty can send real SGR wheel events and the probe can log whether the INPUT
|
|
3
|
+
// BUFFER or the LOG scroll offset changed. This distinguishes the two failure
|
|
4
|
+
// modes the operator kept hitting: wheel must scroll the LOG (SCROLL mode) and
|
|
5
|
+
// must NEVER touch the input history.
|
|
6
|
+
|
|
7
|
+
import fs from 'node:fs'
|
|
8
|
+
import { TuiEditor } from '../src/tui/TuiEditor.js'
|
|
9
|
+
|
|
10
|
+
const LOG = process.env.PROBE_WHEEL_LOG || '/tmp/wheel-probe.log'
|
|
11
|
+
fs.writeFileSync(LOG, '')
|
|
12
|
+
|
|
13
|
+
const ed = new TuiEditor({
|
|
14
|
+
prompt: '> ',
|
|
15
|
+
commands: [],
|
|
16
|
+
locale: 'en',
|
|
17
|
+
alternateScreen: true,
|
|
18
|
+
})
|
|
19
|
+
ed.onSubmit = () => {}
|
|
20
|
+
ed.onAttach = () => null
|
|
21
|
+
ed.onClipboard = () => Promise.resolve(null)
|
|
22
|
+
// Mouse-wheel scroll of the log is opt-in (config.ui.mouseScroll). Set it from
|
|
23
|
+
// the env so the driver can exercise BOTH modes on a real pty.
|
|
24
|
+
ed.setHeader?.({ mouseScroll: process.env.PROBE_MOUSE_SCROLL === '1' })
|
|
25
|
+
|
|
26
|
+
// A non-empty history: a wheel-to-history bug would replace the empty buffer
|
|
27
|
+
// with one of these lines.
|
|
28
|
+
const snap = ed.store.getSnapshot()
|
|
29
|
+
ed.store.set({
|
|
30
|
+
edit: { ...snap.edit, history: ['OLD_COMMAND_ONE', 'OLD_COMMAND_TWO'] },
|
|
31
|
+
scroll: 0,
|
|
32
|
+
})
|
|
33
|
+
// A tall log so there is something to scroll.
|
|
34
|
+
for (let i = 0; i < 40; i++) ed.printAbove('log line ' + i)
|
|
35
|
+
|
|
36
|
+
const report = (): void => {
|
|
37
|
+
const s = ed.store.getSnapshot()
|
|
38
|
+
fs.appendFileSync(
|
|
39
|
+
LOG,
|
|
40
|
+
JSON.stringify({ buf: s.edit.buf, scroll: s.scroll }) +
|
|
41
|
+
String.fromCharCode(10),
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
ed.store.subscribe(report)
|
|
45
|
+
report()
|
|
46
|
+
|
|
47
|
+
ed.start()
|
|
48
|
+
setInterval(() => {}, 1 << 30)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { Term } from '../test/vt100.mts'
|
|
4
|
+
const NL = String.fromCharCode(10)
|
|
5
|
+
const term = new Term(16, 60)
|
|
6
|
+
const child = spawn(
|
|
7
|
+
'script',
|
|
8
|
+
['-qec', 'npx tsx scripts/tui-widgets.tsx', '/dev/null'],
|
|
9
|
+
{
|
|
10
|
+
cwd: path.resolve('.'),
|
|
11
|
+
env: { ...process.env, COLUMNS: '60', LINES: '16' },
|
|
12
|
+
},
|
|
13
|
+
)
|
|
14
|
+
child.stdout.on('data', (d) => term.write(d.toString('utf-8')))
|
|
15
|
+
child.stderr.on('data', (d) => term.write(d.toString('utf-8')))
|
|
16
|
+
setTimeout(() => {
|
|
17
|
+
process.stdout.write(term.render() + NL)
|
|
18
|
+
child.kill('SIGTERM')
|
|
19
|
+
}, 5000)
|
|
20
|
+
child.on('close', () => process.exit(0))
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { render, Box, Text } from 'ink'
|
|
3
|
+
import {
|
|
4
|
+
Checkbox,
|
|
5
|
+
Select,
|
|
6
|
+
Panel,
|
|
7
|
+
HintBar,
|
|
8
|
+
CodeBlock,
|
|
9
|
+
} from '../src/tui/widgets.js'
|
|
10
|
+
render(
|
|
11
|
+
React.createElement(
|
|
12
|
+
Box,
|
|
13
|
+
{ flexDirection: 'column' },
|
|
14
|
+
React.createElement(
|
|
15
|
+
Text,
|
|
16
|
+
null,
|
|
17
|
+
'Checkbox: ',
|
|
18
|
+
React.createElement(Checkbox, { checked: true, focused: true }),
|
|
19
|
+
' ',
|
|
20
|
+
React.createElement(Checkbox, { checked: false, focused: false }),
|
|
21
|
+
),
|
|
22
|
+
React.createElement(
|
|
23
|
+
Text,
|
|
24
|
+
null,
|
|
25
|
+
'Select: ',
|
|
26
|
+
React.createElement(Select, { value: 'qwen3.7-plus', focused: true }),
|
|
27
|
+
),
|
|
28
|
+
React.createElement(
|
|
29
|
+
Panel,
|
|
30
|
+
{ title: 'Панель', subtitle: '2', width: 50 },
|
|
31
|
+
React.createElement(Text, null, 'содержимое'),
|
|
32
|
+
),
|
|
33
|
+
React.createElement(HintBar, {
|
|
34
|
+
hints: [
|
|
35
|
+
['↑/↓', 'выбор'],
|
|
36
|
+
['Enter', 'ok'],
|
|
37
|
+
['Esc', 'отмена'],
|
|
38
|
+
],
|
|
39
|
+
}),
|
|
40
|
+
React.createElement(CodeBlock, { code: 'const a = 1', lang: 'ts' }),
|
|
41
|
+
),
|
|
42
|
+
{ exitOnCtrlC: false, patchConsole: false },
|
|
43
|
+
)
|
|
44
|
+
setInterval(() => {}, 1 << 30)
|