zames_pro 2.75.4 → 2.75.6

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 (79) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +12 -6
  3. package/dist/agent-loop.js +61 -1
  4. package/dist/browser.js +40 -8
  5. package/dist/commands.js +0 -1
  6. package/dist/config.js +8 -3
  7. package/dist/deepseek-ui.js +1 -3
  8. package/dist/i18n/common.js +13 -16
  9. package/dist/i18n/config.js +2 -2
  10. package/dist/i18n/help.js +6 -10
  11. package/dist/i18n/spinner.js +16 -5
  12. package/dist/index.js +0 -49
  13. package/dist/net-capture.js +43 -11
  14. package/dist/provider-handoff.js +0 -4
  15. package/dist/qwen-ui.js +0 -8
  16. package/dist/run-task.js +24 -1
  17. package/dist/shell.js +0 -6
  18. package/dist/system-prompt.js +52 -2
  19. package/dist/tools.js +33 -0
  20. package/dist/tui/AskQuestion.js +108 -0
  21. package/dist/tui/FullScreenApp.js +2 -1
  22. package/dist/tui/InputLine.js +0 -3
  23. package/dist/tui/StatusBar.js +5 -10
  24. package/dist/tui/TuiEditor.js +0 -43
  25. package/dist/tui/keys.js +0 -2
  26. package/dist/tui/run-ask.js +22 -0
  27. package/dist/tui/store.js +0 -2
  28. package/dist/tui/widgets.js +3 -9
  29. package/package.json +3 -2
  30. package/scripts/build-readme.mts +0 -101
  31. package/scripts/changelog-draft.mts +0 -93
  32. package/scripts/clean-dist.mts +0 -17
  33. package/scripts/coverage-gate.mts +0 -112
  34. package/scripts/ctd-live-driver.mts +0 -51
  35. package/scripts/ctd-live.tsx +0 -33
  36. package/scripts/escd-live-driver.mts +0 -37
  37. package/scripts/eslint-ts6.mts +0 -58
  38. package/scripts/inline-status-driver.mts +0 -31
  39. package/scripts/inline-status.tsx +0 -33
  40. package/scripts/mouse-churn.mts +0 -34
  41. package/scripts/qwen-models-smoke.mts +0 -117
  42. package/scripts/qwen-smoke.mts +0 -221
  43. package/scripts/release.mts +0 -199
  44. package/scripts/render-demo.mts +0 -154
  45. package/scripts/render-how-it-works.mts +0 -229
  46. package/scripts/ru-shot.mts +0 -20
  47. package/scripts/self-smoke.mts +0 -309
  48. package/scripts/tui-comp-shot.mts +0 -63
  49. package/scripts/tui-components.tsx +0 -62
  50. package/scripts/tui-config-driver.mts +0 -82
  51. package/scripts/tui-config-probe.tsx +0 -74
  52. package/scripts/tui-edit-driver.mts +0 -100
  53. package/scripts/tui-edit-probe.tsx +0 -38
  54. package/scripts/tui-editor-probe.tsx +0 -24
  55. package/scripts/tui-input-driver.mts +0 -54
  56. package/scripts/tui-input-shot.tsx +0 -59
  57. package/scripts/tui-log-driver.mts +0 -35
  58. package/scripts/tui-log-shot.tsx +0 -48
  59. package/scripts/tui-longpaste-driver.mts +0 -56
  60. package/scripts/tui-longpaste.tsx +0 -35
  61. package/scripts/tui-manyselect-shot.mts +0 -34
  62. package/scripts/tui-manyselect.tsx +0 -17
  63. package/scripts/tui-mouse-churn-probe.tsx +0 -28
  64. package/scripts/tui-paste-driver.mts +0 -88
  65. package/scripts/tui-paste-kinds.tsx +0 -76
  66. package/scripts/tui-pastetest.mts +0 -38
  67. package/scripts/tui-probe.tsx +0 -62
  68. package/scripts/tui-repro.tsx +0 -64
  69. package/scripts/tui-resize.mts +0 -70
  70. package/scripts/tui-scroll-driver.mts +0 -53
  71. package/scripts/tui-scroll-probe.tsx +0 -46
  72. package/scripts/tui-shot.mts +0 -106
  73. package/scripts/tui-status-driver.mts +0 -24
  74. package/scripts/tui-status-shot.tsx +0 -27
  75. package/scripts/tui-submit.tsx +0 -57
  76. package/scripts/tui-wheel-driver.mts +0 -61
  77. package/scripts/tui-wheel-probe.tsx +0 -48
  78. package/scripts/tui-widgets-driver.mts +0 -20
  79. package/scripts/tui-widgets.tsx +0 -44
@@ -1,82 +0,0 @@
1
- // Drive scripts/tui-config-probe.tsx under a pty: send keys one at a time,
2
- // screenshot the VT100 grid at the end, and print the probe's set/reset log.
3
- // Used by test/tui-pty-render.test.ts to pin the config-menu regressions
4
- // (the stale value after a toggle, and the overflowing block at a small
5
- // terminal).
6
- import { spawn } from 'node:child_process'
7
- import fs from 'node:fs'
8
- import path from 'node:path'
9
- import { Term } from '../test/vt100.mts'
10
-
11
- const ESC = String.fromCharCode(27)
12
- const NL = String.fromCharCode(10)
13
-
14
- function arg(name: string, def = ''): string {
15
- const hit = process.argv.find((a) => a.startsWith('--' + name + '='))
16
- return hit ? hit.slice(name.length + 3) : def
17
- }
18
- const cols = Number(arg('cols', '90'))
19
- const rows = Number(arg('rows', '30'))
20
- const keys = arg('keys', '')
21
- .split(',')
22
- .filter((s) => s.length > 0)
23
- .map((s) =>
24
- s === 'RIGHT'
25
- ? ESC + '[C'
26
- : s === 'LEFT'
27
- ? ESC + '[D'
28
- : s === 'DOWN'
29
- ? ESC + '[B'
30
- : s === 'UP'
31
- ? ESC + '[A'
32
- : s === 'ENTER'
33
- ? String.fromCharCode(13)
34
- : s,
35
- )
36
-
37
- const LOG = '/tmp/config-probe.log'
38
- try {
39
- fs.unlinkSync(LOG)
40
- } catch {
41
- /* ignore */
42
- }
43
-
44
- const term = new Term(rows, cols)
45
- const child = spawn(
46
- 'script',
47
- ['-qec', 'npx tsx scripts/tui-config-probe.tsx', '/dev/null'],
48
- {
49
- cwd: path.resolve('.'),
50
- env: {
51
- ...process.env,
52
- COLUMNS: String(cols),
53
- LINES: String(rows),
54
- PROBE_CONFIG_LOG: LOG,
55
- },
56
- },
57
- )
58
- child.stdout.on('data', (d) => term.write(d.toString('utf-8')))
59
- child.stderr.on('data', (d) => term.write(d.toString('utf-8')))
60
-
61
- let i = 0
62
- const tick = (): void => {
63
- if (i < keys.length) {
64
- child.stdin.write(keys[i])
65
- i++
66
- setTimeout(tick, 220)
67
- } else {
68
- setTimeout(() => {
69
- process.stdout.write('===SCREEN===' + NL)
70
- process.stdout.write(term.render() + NL)
71
- process.stdout.write('===LOG===' + NL)
72
- try {
73
- process.stdout.write(fs.readFileSync(LOG, 'utf-8'))
74
- } catch {
75
- /* ignore */
76
- }
77
- child.kill('SIGTERM')
78
- }, 500)
79
- }
80
- }
81
- setTimeout(tick, 5000)
82
- child.on('close', () => process.exit(0))
@@ -1,74 +0,0 @@
1
- // Mount the REAL Ink config menu with the REAL schema and callbacks so a pty
2
- // run can screenshot it and drive it (toggle a boolean, cycle an enum, open an
3
- // edit prompt) — the menu is otherwise only reachable from a live agent.
4
-
5
- import React from 'react'
6
- import fs from 'node:fs'
7
- import { render } from 'ink'
8
- import { ConfigMenuApp } from '../src/tui/ConfigMenu.js'
9
- import {
10
- CONFIG_SCHEMA,
11
- DEFAULTS,
12
- validateConfigValue,
13
- type ConfigField,
14
- } from '../src/config.js'
15
- import { translate } from '../src/i18n.js'
16
-
17
- const LOG = process.env.PROBE_CONFIG_LOG || '/tmp/config-probe.log'
18
- // A tiny in-memory config so get/set/reset are real (validate + default).
19
- function getByPath(obj: Record<string, unknown>, path: string): unknown {
20
- return path
21
- .split('.')
22
- .reduce<unknown>(
23
- (o, k) => (o == null ? undefined : (o as Record<string, unknown>)[k]),
24
- obj,
25
- )
26
- }
27
- function setByPath(path: string, value: unknown): void {
28
- const parts = path.split('.')
29
- let o: Record<string, unknown> = cfg
30
- for (let i = 0; i < parts.length - 1; i++) {
31
- o[parts[i]] = o[parts[i]] ?? {}
32
- o = o[parts[i]] as Record<string, unknown>
33
- }
34
- o[parts[parts.length - 1]] = value
35
- }
36
- const cfg: Record<string, unknown> = {}
37
- // Seed a few NESTED values so toggling is observable (the menu reads through
38
- // getByPath, which walks the path — a flat key would never be found).
39
- setByPath('ui.locale', 'ru')
40
- setByPath('ui.tui', true)
41
- setByPath('ui.alternateScreen', true)
42
- setByPath('ui.mouseScroll', false)
43
- setByPath('maxIterations', 0)
44
- setByPath('headless', true)
45
- setByPath('provider', 'deepseek')
46
-
47
- const log = (line: string): void => {
48
- fs.appendFileSync(LOG, line + String.fromCharCode(10))
49
- }
50
-
51
- render(
52
- React.createElement(ConfigMenuApp, {
53
- fields: CONFIG_SCHEMA,
54
- t: translate('ru'),
55
- get: (p: string) => getByPath(cfg, p),
56
- getDefault: (p: string) =>
57
- getByPath(DEFAULTS as unknown as Record<string, unknown>, p),
58
- set: (field: ConfigField, raw: string) => {
59
- const v = validateConfigValue(field, raw)
60
- setByPath(field.path, v)
61
- log('SET ' + field.path + '=' + JSON.stringify(v))
62
- },
63
- reset: (field: ConfigField) => {
64
- setByPath(
65
- field.path,
66
- getByPath(DEFAULTS as unknown as Record<string, unknown>, field.path),
67
- )
68
- log('RESET ' + field.path)
69
- },
70
- onExit: () => log('EXIT'),
71
- }),
72
- { exitOnCtrlC: false, patchConsole: false },
73
- )
74
- setInterval(() => {}, 1 << 30)
@@ -1,100 +0,0 @@
1
- // Drive scripts/tui-edit-probe.tsx under a pty with a scripted key sequence,
2
- // then print the LAST buffer state the probe logged.
3
- import { spawn } from 'node:child_process'
4
- import fs from 'node:fs'
5
- import path from 'node:path'
6
-
7
- const ESC = String.fromCharCode(27)
8
- const LOG = '/tmp/edit-probe.log'
9
-
10
- function arg(name: string, def = ''): string {
11
- const hit = process.argv.find((a) => a.startsWith('--' + name + '='))
12
- return hit ? hit.slice(name.length + 3) : def
13
- }
14
- const seed = arg('seed', '')
15
- const keys = arg('keys', '')
16
- .split(',')
17
- .filter((s) => s.length > 0)
18
- .map((s) =>
19
- s === 'CTDL'
20
- ? ESC + '[3;5~'
21
- : s === 'CTDLU'
22
- ? ESC + '[3;5u'
23
- : s === 'CTB127U'
24
- ? ESC + '[127;5u'
25
- : s === 'DELU'
26
- ? ESC + '[3u'
27
- : s === 'BSU'
28
- ? ESC + '[127u'
29
- : s === 'CTRLBS'
30
- ? ESC + String.fromCharCode(127)
31
- : s === 'CTB08'
32
- ? String.fromCharCode(8)
33
- : s === 'DEL'
34
- ? ESC + '[3~'
35
- : s === 'CTRLUNDO'
36
- ? String.fromCharCode(31)
37
- : s === 'CTRLU'
38
- ? String.fromCharCode(21)
39
- : s === 'CTRLK'
40
- ? String.fromCharCode(11)
41
- : s === 'CTRLR'
42
- ? String.fromCharCode(18)
43
- : s === 'ESCAPE'
44
- ? ESC
45
- : s === 'CTRLW'
46
- ? String.fromCharCode(23)
47
- : s === 'LEFT'
48
- ? ESC + '[D'
49
- : s === 'RIGHT'
50
- ? ESC + '[C'
51
- : s === 'UP'
52
- ? ESC + '[A'
53
- : s === 'DOWN'
54
- ? ESC + '[B'
55
- : s === 'ENTER'
56
- ? String.fromCharCode(13)
57
- : s,
58
- )
59
-
60
- const child = spawn(
61
- 'script',
62
- ['-qec', 'npx tsx scripts/tui-edit-probe.tsx', '/dev/null'],
63
- {
64
- cwd: path.resolve('.'),
65
- env: {
66
- ...process.env,
67
- COLUMNS: '80',
68
- LINES: '24',
69
- PROBE_EDIT_LOG: LOG,
70
- PROBE_EDIT_SEED: seed,
71
- },
72
- },
73
- )
74
- child.stdout.on('data', () => {})
75
- child.stderr.on('data', () => {})
76
-
77
- let i = 0
78
- const tick = (): void => {
79
- if (i < keys.length) {
80
- child.stdin.write(keys[i])
81
- i++
82
- setTimeout(tick, 200)
83
- } else {
84
- setTimeout(() => child.kill('SIGTERM'), 300)
85
- }
86
- }
87
- setTimeout(tick, 5000)
88
- child.on('close', () => {
89
- let lines: string[] = []
90
- try {
91
- lines = fs.readFileSync(LOG, 'utf-8').trim().split(String.fromCharCode(10))
92
- } catch {
93
- /* ignore */
94
- }
95
- console.log(
96
- 'SEED=' + JSON.stringify(seed) + ' KEYS=' + JSON.stringify(arg('keys', '')),
97
- )
98
- console.log('FINAL=' + (lines[lines.length - 1] || '(none)'))
99
- process.exit(0)
100
- })
@@ -1,38 +0,0 @@
1
- // Mount the REAL TuiEditor and log the editor BUFFER after every change, so a
2
- // pty driver can send keys and assert what the buffer became (word deletion,
3
- // newlines, history) instead of guessing from bytes. The log is one JSON line
4
- // per change: {buf, cursor}.
5
-
6
- import fs from 'node:fs'
7
- import { TuiEditor } from '../src/tui/TuiEditor.js'
8
-
9
- const LOG = process.env.PROBE_EDIT_LOG || '/tmp/edit-probe.log'
10
- const SEED = process.env.PROBE_EDIT_SEED || ''
11
- fs.writeFileSync(LOG, '')
12
-
13
- const ed = new TuiEditor({
14
- prompt: '> ',
15
- commands: [],
16
- locale: 'en',
17
- alternateScreen: process.env.PROBE_INLINE !== '1',
18
- })
19
- ed.onSubmit = () => {}
20
- ed.onAttach = () => null
21
- ed.onClipboard = () => Promise.resolve(null)
22
-
23
- ed.store.subscribe(() => {
24
- const s = ed.store.getSnapshot().edit
25
- fs.appendFileSync(
26
- LOG,
27
- JSON.stringify({ buf: s.buf, cursor: s.cursor }) + String.fromCharCode(10),
28
- )
29
- })
30
-
31
- ed.start()
32
- if (SEED) {
33
- // Type the seed through the store so the buffer starts non-empty.
34
- ed.store.update((snap) => ({
35
- edit: { ...snap.edit, buf: SEED, cursor: Array.from(SEED).length },
36
- }))
37
- }
38
- setInterval(() => {}, 1 << 30)
@@ -1,24 +0,0 @@
1
- // Mount the REAL TuiEditor (the adapter index.ts uses), so the pty resize test
2
- // exercises TuiEditor.installResizeHandler (unmount+remount), NOT just Ink's
3
- // built-in erase. The raw FullScreenApp probe bypasses that handler.
4
-
5
- import { TuiEditor } from '../src/tui/TuiEditor.js'
6
-
7
- const ed = new TuiEditor({
8
- prompt: '\u2794 zames_pro \u203a ',
9
- commands: [
10
- { name: '/help', description: 'show help' },
11
- { name: '/new', description: 'new chat' },
12
- ],
13
- locale: 'en',
14
- alternateScreen: true,
15
- })
16
- ed.setHeader?.({
17
- title: 'zames_pro',
18
- version: '2.74.0',
19
- workdir: '/workspaces/zames/zames_pro',
20
- })
21
- ed.start()
22
- ed.printAbove('log line one')
23
- ed.printAbove('log line two')
24
- setInterval(() => {}, 1 << 30)
@@ -1,54 +0,0 @@
1
- // Screenshot the REAL FullScreenApp input box for a given buffer/cursor, and
2
- // print the VT100 grid WITH a cursor marker (the real terminal cursor cell).
3
- import { spawn } from 'node:child_process'
4
- import path from 'node:path'
5
- import { Term } from '../test/vt100.mts'
6
-
7
- const NL = String.fromCharCode(10)
8
- function arg(name: string, def = ''): string {
9
- const hit = process.argv.find((a) => a.startsWith('--' + name + '='))
10
- return hit ? hit.slice(name.length + 3) : def
11
- }
12
- const cols = Number(arg('cols', '80'))
13
- const rows = Number(arg('rows', '24'))
14
- const buf = arg('buf', '')
15
- .replace(/\\n/g, NL)
16
- .replace(/\\t/g, String.fromCharCode(9))
17
- const cursor = arg('cursor', '')
18
-
19
- const term = new Term(rows, cols)
20
- let stderr = ''
21
- const child = spawn(
22
- 'script',
23
- ['-qec', 'npx tsx scripts/tui-input-shot.tsx', '/dev/null'],
24
- {
25
- cwd: path.resolve('.'),
26
- env: {
27
- ...process.env,
28
- COLUMNS: String(cols),
29
- LINES: String(rows),
30
- PROBE_BUF: buf,
31
- ...(cursor ? { PROBE_CURSOR: cursor } : {}),
32
- },
33
- },
34
- )
35
- child.stdout.on('data', (d) => term.write(d.toString('utf-8')))
36
- child.stderr.on('data', (d) => (stderr += d.toString('utf-8')))
37
- setTimeout(() => {
38
- const cr = term.r
39
- const cc = term.c
40
- // Mark by GRID CELL, not by string index: a wide char occupies two grid
41
- // cells, so slicing the rendered string would place the marker wrong.
42
- const grid = term.grid
43
- if (grid[cr] && grid[cr][cc] !== undefined)
44
- grid[cr][cc] = String.fromCharCode(9673)
45
- const lines = grid.map((row) => row.join('').replace(/\s+$/, ''))
46
- process.stdout.write(
47
- lines.map((l, n) => String(n).padStart(2) + '| ' + l).join(NL) + NL,
48
- )
49
- process.stdout.write('CURSOR row=' + cr + ' col=' + cc + NL)
50
- const lay = stderr.split(NL).find((l) => l.startsWith('LAYOUT'))
51
- if (lay) process.stdout.write(lay + NL)
52
- child.kill('SIGTERM')
53
- }, 5000)
54
- child.on('close', () => process.exit(0))
@@ -1,59 +0,0 @@
1
- // Mount the REAL FullScreenApp with a buffer set from env, so the input box
2
- // rendering (wrapping, cursor, CJK width, paste markers) can be screenshotted.
3
- import React from 'react'
4
- import { render } from 'ink'
5
- import { TuiStore } from '../src/tui/store.js'
6
- import { FullScreenApp } from '../src/tui/FullScreenApp.js'
7
- import { initialEditState } from '../src/tui/edit.js'
8
- import { layoutInput, inputInnerCols } from '../src/input/layout.js'
9
-
10
- const buf = process.env.PROBE_BUF || ''
11
- const cursor = process.env.PROBE_CURSOR
12
- ? Number(process.env.PROBE_CURSOR)
13
- : buf.length
14
- const store = new TuiStore()
15
- store.set({
16
- title: 'zames',
17
- version: '2.74',
18
- workdir: '/workspaces/zames/zames_pro',
19
- prompt: '\u2794 zames \u203a ',
20
- locale: 'en',
21
- commands: [],
22
- edit: { ...initialEditState(), buf, cursor },
23
- })
24
- store.pushLog('system', 'log line one')
25
- const inputProps = {
26
- onSubmit: () => {},
27
- onEscape: () => {},
28
- onCtrlC: () => {},
29
- onCopyCode: () => {},
30
- onAttach: () => null,
31
- onClipboard: () => Promise.resolve(null),
32
- onHistoryChange: () => {},
33
- onClearScreen: () => {},
34
- attachments: [],
35
- onPastesChange: () => {},
36
- }
37
- // Print the expected layout to stderr so it can be compared with the screen.
38
- const cols = Number(process.env.COLUMNS || 80)
39
- const lay = layoutInput(
40
- '\u2794 zames \u203a ',
41
- buf,
42
- cursor,
43
- inputInnerCols(cols),
44
- )
45
- process.stderr.write(
46
- 'LAYOUT rows=' +
47
- lay.rows.length +
48
- ' cursorRow=' +
49
- lay.cursorRow +
50
- ' cursorCol=' +
51
- lay.cursorCol +
52
- String.fromCharCode(10),
53
- )
54
- render(React.createElement(FullScreenApp, { store, inputProps }), {
55
- exitOnCtrlC: false,
56
- patchConsole: false,
57
- alternateScreen: true,
58
- })
59
- setInterval(() => {}, 1 << 30)
@@ -1,35 +0,0 @@
1
- // Screenshot the FullScreenApp log for a given content spec.
2
- import { spawn } from 'node:child_process'
3
- import path from 'node:path'
4
- import { Term } from '../test/vt100.mts'
5
-
6
- const NL = String.fromCharCode(10)
7
- function arg(n: string, d = ''): string {
8
- const h = process.argv.find((a) => a.startsWith('--' + n + '='))
9
- return h ? h.slice(n.length + 3) : d
10
- }
11
- const cols = Number(arg('cols', '80'))
12
- const rows = Number(arg('rows', '24'))
13
- const spec = arg('log', 'empty')
14
-
15
- const term = new Term(rows, cols)
16
- const child = spawn(
17
- 'script',
18
- ['-qec', 'npx tsx scripts/tui-log-shot.tsx', '/dev/null'],
19
- {
20
- cwd: path.resolve('.'),
21
- env: {
22
- ...process.env,
23
- COLUMNS: String(cols),
24
- LINES: String(rows),
25
- PROBE_LOG: spec,
26
- },
27
- },
28
- )
29
- child.stdout.on('data', (d) => term.write(d.toString('utf-8')))
30
- child.stderr.on('data', (d) => term.write(d.toString('utf-8')))
31
- setTimeout(() => {
32
- process.stdout.write(term.render() + NL)
33
- child.kill('SIGTERM')
34
- }, 5000)
35
- child.on('close', () => process.exit(0))
@@ -1,48 +0,0 @@
1
- // Mount the REAL FullScreenApp with a log driven by PROBE_LOG (JSON entries),
2
- // so empty/overflowing/long-wrapped logs can be screenshotted.
3
- import React from 'react'
4
- import { render } from 'ink'
5
- import { TuiStore } from '../src/tui/store.js'
6
- import { FullScreenApp } from '../src/tui/FullScreenApp.js'
7
- import { initialEditState } from '../src/tui/edit.js'
8
-
9
- const store = new TuiStore()
10
- store.set({
11
- title: 'zames',
12
- version: '2.74',
13
- workdir: '/tmp',
14
- prompt: '\u2794 zames \u203a ',
15
- locale: 'en',
16
- commands: [],
17
- edit: { ...initialEditState(), buf: '' },
18
- })
19
- const spec = process.env.PROBE_LOG || 'empty'
20
- if (spec === 'empty') {
21
- // nothing
22
- } else if (spec === 'few') {
23
- store.pushLog('user', 'hello')
24
- store.pushLog('assistant', 'hi there')
25
- } else if (spec === 'many') {
26
- for (let i = 0; i < 100; i++) store.pushLog('system', 'log line ' + i)
27
- } else if (spec === 'long') {
28
- store.pushLog('assistant', 'L'.repeat(300))
29
- store.pushLog('system', 'after long')
30
- }
31
- const inputProps = {
32
- onSubmit: () => {},
33
- onEscape: () => {},
34
- onCtrlC: () => {},
35
- onCopyCode: () => {},
36
- onAttach: () => null,
37
- onClipboard: () => Promise.resolve(null),
38
- onHistoryChange: () => {},
39
- onClearScreen: () => {},
40
- attachments: [],
41
- onPastesChange: () => {},
42
- }
43
- render(React.createElement(FullScreenApp, { store, inputProps }), {
44
- exitOnCtrlC: false,
45
- patchConsole: false,
46
- alternateScreen: true,
47
- })
48
- setInterval(() => {}, 1 << 30)
@@ -1,56 +0,0 @@
1
- // Paste a long bracketed block into the REAL TuiEditor under a pty, screenshot
2
- // the screen (marker shown), press Enter, and print the submit log.
3
- import { spawn } from 'node:child_process'
4
- import fs from 'node:fs'
5
- import path from 'node:path'
6
- import { Term } from '../test/vt100.mts'
7
- const ESC = String.fromCharCode(27)
8
- const CR = String.fromCharCode(13)
9
- const NL = String.fromCharCode(10)
10
- const LOG = '/tmp/longpaste.log'
11
- try {
12
- fs.unlinkSync(LOG)
13
- } catch {
14
- /* ignore */
15
- }
16
- const lines = Number(process.argv[2] || '25')
17
- const body = Array.from(
18
- { length: lines },
19
- (_, i) => 'line ' + i + ' of the pasted block',
20
- ).join(NL)
21
- const cols = Number(process.argv[3] || '80')
22
- const rows = Number(process.argv[4] || '24')
23
- const term = new Term(rows, cols)
24
- const child = spawn(
25
- 'script',
26
- ['-qec', 'npx tsx scripts/tui-longpaste.tsx', '/dev/null'],
27
- {
28
- cwd: path.resolve('.'),
29
- env: {
30
- ...process.env,
31
- COLUMNS: String(cols),
32
- LINES: String(rows),
33
- PROBE_PASTE_LOG: LOG,
34
- },
35
- },
36
- )
37
- child.stdout.on('data', (d) => term.write(d.toString('utf-8')))
38
- child.stderr.on('data', (d) => term.write(d.toString('utf-8')))
39
- setTimeout(() => {
40
- child.stdin.write(ESC + '[200~' + body + ESC + '[201~')
41
- setTimeout(() => {
42
- process.stdout.write('=== SCREEN (after paste) ===' + NL)
43
- process.stdout.write(term.render() + NL)
44
- child.stdin.write(CR)
45
- setTimeout(() => {
46
- process.stdout.write('=== LOG ===' + NL)
47
- try {
48
- process.stdout.write(fs.readFileSync(LOG, 'utf-8'))
49
- } catch {
50
- /* ignore */
51
- }
52
- child.kill('SIGTERM')
53
- }, 600)
54
- }, 600)
55
- }, 5000)
56
- child.on('close', () => process.exit(0))
@@ -1,35 +0,0 @@
1
- // Mount the REAL TuiEditor and log every onSubmit (the EXPANDED text), so a pty
2
- // can paste a LONG multi-line block and prove the agent receives all of it —
3
- // not the [Pasted lines#N] marker.
4
- import fs from 'node:fs'
5
- import { TuiEditor } from '../src/tui/TuiEditor.js'
6
- const LOG = process.env.PROBE_PASTE_LOG || '/tmp/longpaste.log'
7
- fs.writeFileSync(LOG, '')
8
- const ed = new TuiEditor({
9
- prompt: '> ',
10
- commands: [],
11
- locale: 'en',
12
- alternateScreen: true,
13
- })
14
- ed.onSubmit = (text: string) => {
15
- fs.appendFileSync(
16
- LOG,
17
- 'SUBMIT_LEN=' +
18
- text.length +
19
- ' LINES=' +
20
- text.split(String.fromCharCode(10)).length +
21
- String.fromCharCode(10),
22
- )
23
- fs.appendFileSync(
24
- LOG,
25
- 'HEAD=' + JSON.stringify(text.slice(0, 40)) + String.fromCharCode(10),
26
- )
27
- fs.appendFileSync(
28
- LOG,
29
- 'TAIL=' + JSON.stringify(text.slice(-40)) + String.fromCharCode(10),
30
- )
31
- }
32
- ed.onAttach = () => null
33
- ed.onClipboard = () => Promise.resolve(null)
34
- ed.start()
35
- setInterval(() => {}, 1 << 30)
@@ -1,34 +0,0 @@
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 ESC = String.fromCharCode(27)
6
- const keys = (process.argv[2] || '')
7
- .split(',')
8
- .filter(Boolean)
9
- .map((k) => (k === 'UP' ? ESC + '[A' : k === 'DOWN' ? ESC + '[B' : k))
10
- const term = new Term(20, 60)
11
- const child = spawn(
12
- 'script',
13
- ['-qec', 'npx tsx scripts/tui-manyselect.tsx', '/dev/null'],
14
- {
15
- cwd: path.resolve('.'),
16
- env: { ...process.env, COLUMNS: '60', LINES: '20' },
17
- },
18
- )
19
- child.stdout.on('data', (d) => term.write(d.toString('utf-8')))
20
- child.stderr.on('data', (d) => term.write(d.toString('utf-8')))
21
- let i = 0
22
- const tick = (): void => {
23
- if (i < keys.length) {
24
- child.stdin.write(keys[i])
25
- i++
26
- setTimeout(tick, 250)
27
- } else
28
- setTimeout(() => {
29
- process.stdout.write(term.render() + NL)
30
- child.kill('SIGTERM')
31
- }, 400)
32
- }
33
- setTimeout(tick, 4500)
34
- child.on('close', () => process.exit(0))
@@ -1,17 +0,0 @@
1
- import React from 'react'
2
- import { render } from 'ink'
3
- import { SelectList } from '../src/tui/SelectList.js'
4
- const items = Array.from({ length: 30 }, (_, i) => ({
5
- value: 'm' + i,
6
- label: 'модель-' + i,
7
- }))
8
- render(
9
- React.createElement(SelectList, {
10
- title: 'Много',
11
- items,
12
- initial: 'm15',
13
- onSelect: () => {},
14
- }),
15
- { exitOnCtrlC: false, patchConsole: false },
16
- )
17
- setInterval(() => {}, 1 << 30)