@thegitai/cli 1.0.0-preview.3 → 1.0.0-preview.31

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 (58) hide show
  1. package/README.md +39 -6
  2. package/dist/bin/ai.js +142 -383
  3. package/dist/src/agent-mode.js +1 -6
  4. package/dist/src/api/auth.js +6 -4
  5. package/dist/src/api/browser-login.js +152 -37
  6. package/dist/src/api/chat.js +258 -38
  7. package/dist/src/api/contracts.js +55 -1
  8. package/dist/src/api/default-host.js +1 -0
  9. package/dist/src/api/http.js +69 -7
  10. package/dist/src/api/models.js +19 -10
  11. package/dist/src/background-jobs.js +2 -2
  12. package/dist/src/cli-args.js +19 -5
  13. package/dist/src/core/clipboard.js +7 -13
  14. package/dist/src/core/image-limits.js +56 -0
  15. package/dist/src/core/image-path-extractor.js +70 -3
  16. package/dist/src/core/session-image-store.js +199 -0
  17. package/dist/src/executor.js +25 -3
  18. package/dist/src/help-text.js +67 -18
  19. package/dist/src/permissions.js +243 -0
  20. package/dist/src/session-safety.js +0 -12
  21. package/dist/src/session-store.js +121 -20
  22. package/dist/src/session.js +14 -3
  23. package/dist/src/signin.js +58 -0
  24. package/dist/src/tool-executor.js +11 -46
  25. package/dist/src/tools/delete-file.js +15 -3
  26. package/dist/src/tools/index.js +13 -10
  27. package/dist/src/tools/patch-file.js +12 -26
  28. package/dist/src/tools/read-image-file.js +85 -0
  29. package/dist/src/tools/replace-document-text.js +28 -18
  30. package/dist/src/tools/restore-checkpoint.js +0 -1
  31. package/dist/src/tools/run-command.js +14 -71
  32. package/dist/src/tools/run-node-script.js +12 -81
  33. package/dist/src/tools/save-generated-image.js +120 -0
  34. package/dist/src/tools/str-replace.js +12 -26
  35. package/dist/src/tools/undo-edit.js +1 -6
  36. package/dist/src/tools/write-file.js +67 -11
  37. package/dist/src/turn-failure-marker.js +11 -0
  38. package/dist/src/ui/prompt-history-store.js +1 -1
  39. package/dist/src/ui/repl.js +649 -164
  40. package/dist/src/ui/tui/bridge.js +10 -0
  41. package/dist/src/ui/tui/build-frame.js +453 -115
  42. package/dist/src/ui/tui/markdown-render.js +81 -73
  43. package/dist/src/ui/tui/shell-input.js +206 -63
  44. package/dist/src/ui/tui/terminal-theme.js +28 -0
  45. package/dist/src/ui/tui/terminal-title.js +3 -0
  46. package/dist/src/ui/tui/terminal-writes.js +48 -0
  47. package/dist/src/ui/tui/text.js +158 -4
  48. package/dist/src/ui/tui/user-input.js +568 -0
  49. package/dist/src/utils.js +9 -0
  50. package/package.json +29 -6
  51. package/dist/src/markdown-renderer.js +0 -112
  52. package/dist/src/project-index.js +0 -221
  53. package/dist/src/tools/code-intel.js +0 -472
  54. package/dist/src/tools/find-symbol.js +0 -70
  55. package/dist/src/tools/hover-symbol.js +0 -95
  56. package/dist/src/tools/list-symbols.js +0 -55
  57. package/dist/src/tools/search-code.js +0 -37
  58. package/dist/src/tools/signature-help.js +0 -118
@@ -0,0 +1,48 @@
1
+ const MAX_CAPTURED_CHARS = 1_000_000;
2
+ let restore = null;
3
+ let captured = [];
4
+ let capturedChars = 0;
5
+ function chunkToString(chunk, encoding) {
6
+ if (typeof chunk === 'string')
7
+ return chunk;
8
+ if (chunk instanceof Uint8Array) {
9
+ return Buffer.from(chunk).toString(typeof encoding === 'string' ? encoding : 'utf8');
10
+ }
11
+ return String(chunk ?? '');
12
+ }
13
+ export function captureTerminalWrites() {
14
+ if (restore)
15
+ return;
16
+ const streams = [process.stdout, process.stderr];
17
+ const originals = streams.map((stream) => stream.write.bind(stream));
18
+ for (const stream of streams) {
19
+ stream.write = (chunk, encoding, callback) => {
20
+ if (capturedChars < MAX_CAPTURED_CHARS) {
21
+ const text = chunkToString(chunk, encoding);
22
+ captured.push(text);
23
+ capturedChars += text.length;
24
+ }
25
+ const done = typeof encoding === 'function' ? encoding : callback;
26
+ if (typeof done === 'function')
27
+ done();
28
+ return true;
29
+ };
30
+ }
31
+ restore = () => {
32
+ streams.forEach((stream, index) => {
33
+ stream.write = originals[index];
34
+ });
35
+ };
36
+ }
37
+ export function releaseTerminalWrites() {
38
+ if (!restore)
39
+ return;
40
+ restore();
41
+ restore = null;
42
+ if (captured.length > 0) {
43
+ const text = captured.join('');
44
+ captured = [];
45
+ capturedChars = 0;
46
+ process.stderr.write(text);
47
+ }
48
+ }
@@ -1,5 +1,14 @@
1
+ const CSI_PATTERN = /\u001B\[[0-9;?]*[ -\/]*[@-~]/g;
2
+ const OSC_PATTERN = /\u001B\][^\u0007\u001B]*(?:\u0007|\u001B\\)?/g;
3
+ const CONTROL_CHAR_PATTERN = /[\u0000-\u0008\u000B-\u001F\u007F]/g;
4
+ export function stripControlCharacters(text) {
5
+ return String(text ?? '')
6
+ .replace(OSC_PATTERN, '')
7
+ .replace(CSI_PATTERN, '')
8
+ .replace(CONTROL_CHAR_PATTERN, '');
9
+ }
1
10
  export function span(text, style = {}) {
2
- return { text, ...style };
11
+ return { text: stripControlCharacters(text), ...style };
3
12
  }
4
13
  export function line(...spans) {
5
14
  return { spans };
@@ -14,10 +23,11 @@ export function wrapText(text, width) {
14
23
  const lines = [];
15
24
  for (const rawLine of text.split('\n')) {
16
25
  let remaining = rawLine;
17
- while (remaining.length > safeWidth) {
18
- let breakAt = remaining.lastIndexOf(' ', safeWidth);
26
+ while (displayWidth(remaining) > safeWidth) {
27
+ const head = sliceToWidth(remaining, safeWidth);
28
+ let breakAt = head.lastIndexOf(' ');
19
29
  if (breakAt <= 0)
20
- breakAt = safeWidth;
30
+ breakAt = head.length;
21
31
  lines.push(remaining.slice(0, breakAt).trimEnd());
22
32
  remaining = remaining.slice(breakAt).trimStart();
23
33
  }
@@ -28,3 +38,147 @@ export function wrapText(text, width) {
28
38
  export function joinLines(blocks) {
29
39
  return blocks.flat();
30
40
  }
41
+ function isZeroWidthCodePoint(codePoint) {
42
+ return (codePoint === 0x200d ||
43
+ (codePoint >= 0x0300 && codePoint <= 0x036f) ||
44
+ (codePoint >= 0x1ab0 && codePoint <= 0x1aff) ||
45
+ (codePoint >= 0x1dc0 && codePoint <= 0x1dff) ||
46
+ (codePoint >= 0x20d0 && codePoint <= 0x20ff) ||
47
+ (codePoint >= 0xfe00 && codePoint <= 0xfe0f) ||
48
+ (codePoint >= 0xfe20 && codePoint <= 0xfe2f));
49
+ }
50
+ function isWideCodePoint(codePoint) {
51
+ return ((codePoint >= 0x1100 && codePoint <= 0x115f) ||
52
+ codePoint === 0x231a ||
53
+ codePoint === 0x231b ||
54
+ (codePoint >= 0x23e9 && codePoint <= 0x23ec) ||
55
+ codePoint === 0x23f0 ||
56
+ codePoint === 0x23f3 ||
57
+ (codePoint >= 0x25fd && codePoint <= 0x25fe) ||
58
+ (codePoint >= 0x2614 && codePoint <= 0x2615) ||
59
+ (codePoint >= 0x2648 && codePoint <= 0x2653) ||
60
+ codePoint === 0x267f ||
61
+ codePoint === 0x2693 ||
62
+ codePoint === 0x26a1 ||
63
+ (codePoint >= 0x26aa && codePoint <= 0x26ab) ||
64
+ (codePoint >= 0x26bd && codePoint <= 0x26be) ||
65
+ (codePoint >= 0x26c4 && codePoint <= 0x26c5) ||
66
+ codePoint === 0x26ce ||
67
+ codePoint === 0x26d4 ||
68
+ codePoint === 0x26ea ||
69
+ (codePoint >= 0x26f2 && codePoint <= 0x26f3) ||
70
+ codePoint === 0x26f5 ||
71
+ codePoint === 0x26fa ||
72
+ codePoint === 0x26fd ||
73
+ codePoint === 0x2705 ||
74
+ (codePoint >= 0x270a && codePoint <= 0x270b) ||
75
+ codePoint === 0x2728 ||
76
+ codePoint === 0x274c ||
77
+ codePoint === 0x274e ||
78
+ (codePoint >= 0x2753 && codePoint <= 0x2755) ||
79
+ codePoint === 0x2757 ||
80
+ (codePoint >= 0x2795 && codePoint <= 0x2797) ||
81
+ codePoint === 0x27b0 ||
82
+ codePoint === 0x27bf ||
83
+ (codePoint >= 0x2b1b && codePoint <= 0x2b1c) ||
84
+ codePoint === 0x2b50 ||
85
+ codePoint === 0x2b55 ||
86
+ (codePoint >= 0x2e80 && codePoint <= 0x303e) ||
87
+ (codePoint >= 0x3041 && codePoint <= 0x33ff) ||
88
+ (codePoint >= 0x3400 && codePoint <= 0x4dbf) ||
89
+ (codePoint >= 0x4e00 && codePoint <= 0x9fff) ||
90
+ (codePoint >= 0xa000 && codePoint <= 0xa4cf) ||
91
+ (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||
92
+ (codePoint >= 0xf900 && codePoint <= 0xfaff) ||
93
+ (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||
94
+ (codePoint >= 0xff00 && codePoint <= 0xff60) ||
95
+ (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||
96
+ (codePoint >= 0x1f300 && codePoint <= 0x1f64f) ||
97
+ (codePoint >= 0x1f680 && codePoint <= 0x1f6ff) ||
98
+ (codePoint >= 0x1f900 && codePoint <= 0x1f9ff) ||
99
+ (codePoint >= 0x1fa70 && codePoint <= 0x1faff) ||
100
+ (codePoint >= 0x20000 && codePoint <= 0x3fffd));
101
+ }
102
+ export function displayWidth(text) {
103
+ const chars = [...String(text ?? '')];
104
+ let width = 0;
105
+ for (let index = 0; index < chars.length; index++) {
106
+ const codePoint = chars[index].codePointAt(0);
107
+ if (isZeroWidthCodePoint(codePoint))
108
+ continue;
109
+ const next = chars[index + 1]?.codePointAt(0);
110
+ if (next === 0xfe0f) {
111
+ width += 2;
112
+ index++;
113
+ continue;
114
+ }
115
+ if (next === 0xfe0e) {
116
+ width += 1;
117
+ index++;
118
+ continue;
119
+ }
120
+ width += isWideCodePoint(codePoint) ? 2 : 1;
121
+ }
122
+ return width;
123
+ }
124
+ export function sliceToWidth(text, width) {
125
+ const limit = Math.max(1, Math.floor(width));
126
+ const chars = [...String(text ?? '')];
127
+ let out = '';
128
+ let used = 0;
129
+ for (let index = 0; index < chars.length; index++) {
130
+ const char = chars[index];
131
+ const next = chars[index + 1];
132
+ const selector = next === '️' || next === '︎';
133
+ const cluster = selector ? `${char}${next}` : char;
134
+ const clusterWidth = displayWidth(cluster);
135
+ if (used + clusterWidth > limit)
136
+ break;
137
+ out += cluster;
138
+ used += clusterWidth;
139
+ if (selector)
140
+ index++;
141
+ }
142
+ if (!out)
143
+ return chars[0] ?? '';
144
+ return out;
145
+ }
146
+ export function padToWidth(text, width) {
147
+ const current = displayWidth(text);
148
+ if (current >= width)
149
+ return text;
150
+ return text + ' '.repeat(width - current);
151
+ }
152
+ export function wrapToWidth(text, width) {
153
+ const limit = Math.max(1, Math.floor(width));
154
+ const out = [];
155
+ for (const rawLine of String(text ?? '').split('\n')) {
156
+ let current = '';
157
+ const flush = () => {
158
+ out.push(current);
159
+ current = '';
160
+ };
161
+ for (const token of rawLine.split(/\s+/).filter(Boolean)) {
162
+ let rest = token;
163
+ while (displayWidth(rest) > limit) {
164
+ if (current)
165
+ flush();
166
+ const head = sliceToWidth(rest, limit);
167
+ out.push(head);
168
+ rest = rest.slice(head.length);
169
+ }
170
+ if (!rest)
171
+ continue;
172
+ const candidate = current ? `${current} ${rest}` : rest;
173
+ if (displayWidth(candidate) > limit) {
174
+ flush();
175
+ current = rest;
176
+ }
177
+ else {
178
+ current = candidate;
179
+ }
180
+ }
181
+ flush();
182
+ }
183
+ return out.length > 0 ? out : [''];
184
+ }