@giovannijecha/jecode 0.2.0 → 0.2.2
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/README.md +4 -3
- package/dist/controller.js +63 -14
- package/dist/credential-safety.js +19 -1
- package/dist/effort.js +25 -0
- package/dist/openai-account.js +10 -7
- package/dist/provider-commands.js +67 -14
- package/dist/providers/anthropic-stream.js +8 -2
- package/dist/providers/anthropic.js +21 -5
- package/dist/providers/ollama-stream.js +3 -0
- package/dist/providers/ollama.js +3 -0
- package/dist/providers/openai-codex.js +53 -10
- package/dist/providers/openai-stream.js +1 -1
- package/dist/providers/openai-wire.js +0 -5
- package/dist/providers/openai.js +34 -13
- package/dist/settings-command.js +53 -6
- package/dist/settings.js +2 -1
- package/dist/tools/args.js +4 -3
- package/dist/tools/fs.js +8 -3
- package/dist/tools/index.js +2 -2
- package/dist/tools/search.js +105 -20
- package/dist/tools/shell.js +30 -9
- package/dist/tui/app.js +17 -3
- package/dist/tui/components/messages.js +26 -5
- package/dist/tui/keys.js +33 -0
- package/dist/tui/screen.js +19 -5
- package/dist/tui/turn.js +4 -1
- package/dist/ui/width.js +41 -1
- package/package.json +1 -1
package/dist/tui/keys.js
CHANGED
|
@@ -12,6 +12,8 @@ const PASTE_END = "[201~";
|
|
|
12
12
|
// one packs the coordinates into single bytes and simply stops being able to
|
|
13
13
|
// say where the pointer is past column 223.
|
|
14
14
|
const MOUSE = /^\[<(\d+);(\d+);(\d+)([Mm])/;
|
|
15
|
+
const CSI_SEQUENCE = /^\[[0-?]*[ -/]*[@-~]/;
|
|
16
|
+
const SS3_SEQUENCE = /^O[ -~]/;
|
|
15
17
|
const BUTTONS = ["left", "middle", "right", "none"];
|
|
16
18
|
// Both the normal and the application-cursor forms, because a terminal sends
|
|
17
19
|
// either depending on the mode it thinks it is in.
|
|
@@ -59,6 +61,16 @@ export function decoder() {
|
|
|
59
61
|
if (pasting) {
|
|
60
62
|
const end = held.indexOf(ESC + PASTE_END);
|
|
61
63
|
if (end === -1) {
|
|
64
|
+
const interrupt = firstInterrupt(held);
|
|
65
|
+
if (interrupt !== -1) {
|
|
66
|
+
// A missing bracketed-paste terminator must not trap the decoder
|
|
67
|
+
// forever. Ctrl+C/Ctrl+D are emergency exits: discard the partial
|
|
68
|
+
// paste, then let the normal control-key path handle the byte.
|
|
69
|
+
held = held.slice(interrupt);
|
|
70
|
+
pasted = "";
|
|
71
|
+
pasting = false;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
62
74
|
// Hold back a possible partial terminator rather than pasting it.
|
|
63
75
|
const safe = held.length - PASTE_END.length - 1;
|
|
64
76
|
if (safe > 0) {
|
|
@@ -96,6 +108,13 @@ export function decoder() {
|
|
|
96
108
|
keys.push({ name: SEQUENCES[match], text: "", ctrl: false });
|
|
97
109
|
continue;
|
|
98
110
|
}
|
|
111
|
+
const unbound = completeTerminalSequence(rest);
|
|
112
|
+
if (unbound !== undefined) {
|
|
113
|
+
// Terminals have many optional keys and mode reports. An unbound but
|
|
114
|
+
// complete CSI/SS3 sequence is terminal protocol, never editor text.
|
|
115
|
+
held = rest.slice(unbound.length);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
99
118
|
if (!final && couldGrow(rest))
|
|
100
119
|
break;
|
|
101
120
|
held = held.slice(1);
|
|
@@ -139,6 +158,15 @@ export function decoder() {
|
|
|
139
158
|
},
|
|
140
159
|
};
|
|
141
160
|
}
|
|
161
|
+
function firstInterrupt(text) {
|
|
162
|
+
const ctrlC = text.indexOf(String.fromCharCode(3));
|
|
163
|
+
const ctrlD = text.indexOf(String.fromCharCode(4));
|
|
164
|
+
if (ctrlC === -1)
|
|
165
|
+
return ctrlD;
|
|
166
|
+
if (ctrlD === -1)
|
|
167
|
+
return ctrlC;
|
|
168
|
+
return Math.min(ctrlC, ctrlD);
|
|
169
|
+
}
|
|
142
170
|
function matchSequence(rest) {
|
|
143
171
|
for (const seq of Object.keys(SEQUENCES)) {
|
|
144
172
|
if (rest.startsWith(seq))
|
|
@@ -146,10 +174,15 @@ function matchSequence(rest) {
|
|
|
146
174
|
}
|
|
147
175
|
return undefined;
|
|
148
176
|
}
|
|
177
|
+
function completeTerminalSequence(rest) {
|
|
178
|
+
return CSI_SEQUENCE.exec(rest)?.[0] ?? SS3_SEQUENCE.exec(rest)?.[0];
|
|
179
|
+
}
|
|
149
180
|
/** Whether `rest` is still a viable prefix of something we know. */
|
|
150
181
|
function couldGrow(rest) {
|
|
151
182
|
if (PASTE_START.startsWith(rest))
|
|
152
183
|
return true;
|
|
184
|
+
if (/^\[[0-?]*[ -/]*$/.test(rest))
|
|
185
|
+
return true;
|
|
153
186
|
// A mouse report has no fixed length, so it grows until its final letter.
|
|
154
187
|
if (/^\[<?\d*;?\d*;?\d*$/.test(rest))
|
|
155
188
|
return true;
|
package/dist/tui/screen.js
CHANGED
|
@@ -37,6 +37,7 @@ const CURSOR_RESET = `${CSI}0 q`;
|
|
|
37
37
|
const SYNC_BEGIN = `${CSI}?2026h`;
|
|
38
38
|
const SYNC_END = `${CSI}?2026l`;
|
|
39
39
|
let active = false;
|
|
40
|
+
let handlersRegistered = false;
|
|
40
41
|
export function interactive() {
|
|
41
42
|
return process.stdin.isTTY === true && process.stdout.isTTY === true;
|
|
42
43
|
}
|
|
@@ -53,9 +54,7 @@ export function enter(reducedMotion = false) {
|
|
|
53
54
|
if (active)
|
|
54
55
|
return;
|
|
55
56
|
active = true;
|
|
56
|
-
|
|
57
|
-
process.on("SIGTERM", onFatalSignal);
|
|
58
|
-
process.on("SIGHUP", onFatalSignal);
|
|
57
|
+
registerProcessHandlers();
|
|
59
58
|
write(ALT_ON + WRAP_OFF + CURSOR_HIDE + (reducedMotion ? CURSOR_STEADY : CURSOR_BLOCK) + PASTE_ON + MOUSE_ON);
|
|
60
59
|
process.stdin.setRawMode(true);
|
|
61
60
|
process.stdin.setEncoding("utf8");
|
|
@@ -74,9 +73,24 @@ export function setReducedMotion(reducedMotion) {
|
|
|
74
73
|
if (active)
|
|
75
74
|
write(reducedMotion ? CURSOR_STEADY : CURSOR_BLOCK);
|
|
76
75
|
}
|
|
77
|
-
function
|
|
76
|
+
function registerProcessHandlers() {
|
|
77
|
+
if (handlersRegistered)
|
|
78
|
+
return;
|
|
79
|
+
handlersRegistered = true;
|
|
80
|
+
process.on("exit", leave);
|
|
81
|
+
process.on("uncaughtExceptionMonitor", leave);
|
|
82
|
+
process.on("SIGTERM", onSigterm);
|
|
83
|
+
process.on("SIGHUP", onSighup);
|
|
84
|
+
}
|
|
85
|
+
function onSigterm() {
|
|
86
|
+
onFatalSignal(15);
|
|
87
|
+
}
|
|
88
|
+
function onSighup() {
|
|
89
|
+
onFatalSignal(1);
|
|
90
|
+
}
|
|
91
|
+
function onFatalSignal(number) {
|
|
78
92
|
leave();
|
|
79
|
-
process.exit(
|
|
93
|
+
process.exit(128 + number);
|
|
80
94
|
}
|
|
81
95
|
export function onResize(handler) {
|
|
82
96
|
process.stdout.on("resize", handler);
|
package/dist/tui/turn.js
CHANGED
|
@@ -110,7 +110,10 @@ export function transcribe(stage) {
|
|
|
110
110
|
const block = tools.get(call.id);
|
|
111
111
|
if (block === undefined || block.kind !== "tool")
|
|
112
112
|
return;
|
|
113
|
-
|
|
113
|
+
// Explicit refusal stays a refusal. Cancellation can first settle an
|
|
114
|
+
// approval overlay as `no`, though, so its synthesized result must be
|
|
115
|
+
// allowed to reconcile that rail with the interrupted history.
|
|
116
|
+
if (block.tone === "deny" && summary !== "interrupted") {
|
|
114
117
|
stage.render(block);
|
|
115
118
|
return;
|
|
116
119
|
}
|
package/dist/ui/width.js
CHANGED
|
@@ -27,6 +27,43 @@ const WIDE = [
|
|
|
27
27
|
[0x1fa70, 0x1faff],
|
|
28
28
|
[0x20000, 0x3fffd],
|
|
29
29
|
];
|
|
30
|
+
/** Default emoji-presentation ranges below the main supplementary blocks. */
|
|
31
|
+
const EMOJI_WIDE = [
|
|
32
|
+
[0x231a, 0x231b],
|
|
33
|
+
[0x23e9, 0x23ec],
|
|
34
|
+
[0x23f0, 0x23f0],
|
|
35
|
+
[0x23f3, 0x23f3],
|
|
36
|
+
[0x25fd, 0x25fe],
|
|
37
|
+
[0x2614, 0x2615],
|
|
38
|
+
[0x2648, 0x2653],
|
|
39
|
+
[0x267f, 0x267f],
|
|
40
|
+
[0x2693, 0x2693],
|
|
41
|
+
[0x26a1, 0x26a1],
|
|
42
|
+
[0x26aa, 0x26ab],
|
|
43
|
+
[0x26bd, 0x26be],
|
|
44
|
+
[0x26c4, 0x26c5],
|
|
45
|
+
[0x26ce, 0x26ce],
|
|
46
|
+
[0x26d4, 0x26d4],
|
|
47
|
+
[0x26ea, 0x26ea],
|
|
48
|
+
[0x26f2, 0x26f3],
|
|
49
|
+
[0x26f5, 0x26f5],
|
|
50
|
+
[0x26fa, 0x26fa],
|
|
51
|
+
[0x26fd, 0x26fd],
|
|
52
|
+
[0x2705, 0x2705],
|
|
53
|
+
[0x270a, 0x270b],
|
|
54
|
+
[0x2728, 0x2728],
|
|
55
|
+
[0x274c, 0x274c],
|
|
56
|
+
[0x274e, 0x274e],
|
|
57
|
+
[0x2753, 0x2755],
|
|
58
|
+
[0x2757, 0x2757],
|
|
59
|
+
[0x2795, 0x2797],
|
|
60
|
+
[0x27b0, 0x27b0],
|
|
61
|
+
[0x27bf, 0x27bf],
|
|
62
|
+
[0x2b1b, 0x2b1c],
|
|
63
|
+
[0x2b50, 0x2b50],
|
|
64
|
+
[0x2b55, 0x2b55],
|
|
65
|
+
[0x1f1e6, 0x1f1ff],
|
|
66
|
+
];
|
|
30
67
|
/** Ranges that occupy no cell of their own: they attach to what precedes. */
|
|
31
68
|
const ZERO = [
|
|
32
69
|
[0x0300, 0x036f],
|
|
@@ -54,6 +91,7 @@ function inRanges(code, ranges) {
|
|
|
54
91
|
}
|
|
55
92
|
// The emoji presentation selector, built rather than typed: an invisible byte
|
|
56
93
|
// in source is a byte nobody reviews.
|
|
94
|
+
const VS15 = String.fromCodePoint(0xfe0e);
|
|
57
95
|
const VS16 = String.fromCodePoint(0xfe0f);
|
|
58
96
|
// Grapheme segmentation is in the standard library, so a family emoji built
|
|
59
97
|
// out of five code points and three joiners counts as the one thing the
|
|
@@ -80,9 +118,11 @@ export function charWidth(cluster) {
|
|
|
80
118
|
return 0;
|
|
81
119
|
if (inRanges(code, ZERO))
|
|
82
120
|
return 0;
|
|
121
|
+
if (cluster.includes(VS15))
|
|
122
|
+
return inRanges(code, WIDE) ? 2 : 1;
|
|
83
123
|
if (cluster.includes(VS16))
|
|
84
124
|
return 2;
|
|
85
|
-
return inRanges(code, WIDE) ? 2 : 1;
|
|
125
|
+
return inRanges(code, WIDE) || inRanges(code, EMOJI_WIDE) ? 2 : 1;
|
|
86
126
|
}
|
|
87
127
|
export function textWidth(text) {
|
|
88
128
|
let total = 0;
|