@toddzheng024/dscode-bundle 0.3.0 → 0.5.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/THIRD_PARTY_NOTICES.md +15 -0
- package/cordis.patch.yml +5 -3
- package/package.json +14 -1
- package/plugins/clipboard-image/clipboard-image.swift +56 -0
- package/plugins/clipboard-image/index.mjs +70 -0
- package/plugins/code-review/git.mjs +95 -0
- package/plugins/code-review/index.mjs +88 -0
- package/plugins/dscode/index.mjs +17 -3
- package/plugins/email/cli.mjs +32 -0
- package/plugins/email/contacts.mjs +36 -0
- package/plugins/email/gmail-oauth.mjs +69 -0
- package/plugins/email/gmail-store.mjs +2 -0
- package/plugins/email/gmail.mjs +194 -0
- package/plugins/email/imap.mjs +136 -0
- package/plugins/email/inbox.d.mts +25 -0
- package/plugins/email/inbox.mjs +76 -0
- package/plugins/email/smtp.mjs +69 -0
- package/plugins/email/store.mjs +32 -0
- package/plugins/email-tools/index.mjs +44 -0
- package/plugins/session-metrics/index.mjs +6 -2
- package/plugins/session-metrics/rate.mjs +62 -0
- package/plugins/session-metrics/view.mjs +15 -9
- package/plugins/tui-tools/doctor-cli.mjs +22 -0
- package/plugins/tui-tools/doctor.mjs +141 -0
- package/plugins/tui-tools/index.mjs +14 -6
- package/plugins/ultra/policy.mjs +12 -1
- package/plugins/worktree-subagent/worktree.mjs +50 -0
- package/presets/dscode/agent.cordis.yml +7 -2
- package/vendor/deepseek/index.js +12 -2
- package/vendor/subagent/index.js +29 -9
- package/vendor/subagent-core/LICENSE +21 -0
- package/vendor/subagent-core/index.js +3232 -0
- package/vendor/subagent-core/invariant.js +76 -0
- package/vendor/subagent-core/typert.host.d.ts +3 -0
- package/vendor/subagent-core/typert.host.js +964 -0
- package/vendor/subagent-core/typert.remote-client.d.ts +27 -0
- package/vendor/subagent-core/typert.remote-client.js +160 -0
- package/vendor/subagent-core/types/assistant-output.d.ts +48 -0
- package/vendor/subagent-core/types/assistant-output.js +73 -0
- package/vendor/subagent-core/types/catalog.d.ts +77 -0
- package/vendor/subagent-core/types/catalog.js +103 -0
- package/vendor/subagent-core/types/child-agent.d.ts +150 -0
- package/vendor/subagent-core/types/child-agent.js +207 -0
- package/vendor/subagent-core/types/client.d.ts +8 -0
- package/vendor/subagent-core/types/client.js +7 -0
- package/vendor/subagent-core/types/continuation-activation.d.ts +251 -0
- package/vendor/subagent-core/types/continuation-activation.js +663 -0
- package/vendor/subagent-core/types/continuation-messages.d.ts +62 -0
- package/vendor/subagent-core/types/continuation-messages.js +102 -0
- package/vendor/subagent-core/types/continuation.d.ts +124 -0
- package/vendor/subagent-core/types/continuation.js +455 -0
- package/vendor/subagent-core/types/control-types.d.ts +146 -0
- package/vendor/subagent-core/types/control-types.js +9 -0
- package/vendor/subagent-core/types/control.d.ts +71 -0
- package/vendor/subagent-core/types/control.js +116 -0
- package/vendor/subagent-core/types/depth.d.ts +31 -0
- package/vendor/subagent-core/types/depth.js +39 -0
- package/vendor/subagent-core/types/descriptor.d.ts +144 -0
- package/vendor/subagent-core/types/descriptor.js +193 -0
- package/vendor/subagent-core/types/error.d.ts +11 -0
- package/vendor/subagent-core/types/error.js +14 -0
- package/vendor/subagent-core/types/inbox.d.ts +43 -0
- package/vendor/subagent-core/types/inbox.js +61 -0
- package/vendor/subagent-core/types/index.d.ts +316 -0
- package/vendor/subagent-core/types/index.js +511 -0
- package/vendor/subagent-core/types/internal.d.ts +58 -0
- package/vendor/subagent-core/types/internal.js +58 -0
- package/vendor/subagent-core/types/invariant.d.ts +13 -0
- package/vendor/subagent-core/types/invariant.js +91 -0
- package/vendor/subagent-core/types/lifecycle.d.ts +113 -0
- package/vendor/subagent-core/types/lifecycle.js +178 -0
- package/vendor/subagent-core/types/list-children.d.ts +65 -0
- package/vendor/subagent-core/types/list-children.js +381 -0
- package/vendor/subagent-core/types/out-of-process.d.ts +118 -0
- package/vendor/subagent-core/types/out-of-process.js +219 -0
- package/vendor/subagent-core/types/projection-types.d.ts +74 -0
- package/vendor/subagent-core/types/projection-types.js +7 -0
- package/vendor/subagent-core/types/projection.d.ts +95 -0
- package/vendor/subagent-core/types/projection.js +151 -0
- package/vendor/subagent-core/types/run-settlement.d.ts +17 -0
- package/vendor/subagent-core/types/run-settlement.js +70 -0
- package/vendor/subagent-core/types/types.d.ts +377 -0
- package/vendor/subagent-core/types/types.js +19 -0
- package/vendor/subagent-driver/LICENSE +21 -0
- package/vendor/subagent-driver/index.js +255 -0
- package/vendor/subagent-driver/types/index.d.ts +33 -0
- package/vendor/subagent-driver/types/structured.d.ts +42 -0
- package/vendor/subagent-fork/LICENSE +21 -0
- package/vendor/subagent-fork/index.js +61 -0
- package/vendor/subagent-fork/types/index.d.ts +20 -0
- package/vendor/subagent-spawn/LICENSE +21 -0
- package/vendor/subagent-spawn/index.js +45 -0
- package/vendor/subagent-spawn/types/index.d.ts +19 -0
- package/vendor/terminal/LICENSE +21 -0
- package/vendor/terminal/index.js +1013 -0
- package/vendor/terminal/types/config.d.ts +71 -0
- package/vendor/terminal/types/index.d.ts +36 -0
- package/vendor/terminal/types/sanitize.d.ts +47 -0
- package/vendor/terminal/types/session.d.ts +87 -0
- package/vendor/tui/dscode-clipboard-image/clipboard-image.swift +56 -0
- package/vendor/tui/dscode-clipboard-image/index.mjs +70 -0
- package/vendor/tui/dscode-email/cli.mjs +32 -0
- package/vendor/tui/dscode-email/contacts.mjs +36 -0
- package/vendor/tui/dscode-email/gmail-oauth.mjs +69 -0
- package/vendor/tui/dscode-email/gmail-store.mjs +2 -0
- package/vendor/tui/dscode-email/gmail.mjs +194 -0
- package/vendor/tui/dscode-email/imap.mjs +136 -0
- package/vendor/tui/dscode-email/inbox.d.mts +25 -0
- package/vendor/tui/dscode-email/inbox.mjs +76 -0
- package/vendor/tui/dscode-email/smtp.mjs +69 -0
- package/vendor/tui/dscode-email/store.mjs +32 -0
- package/vendor/tui/dscode-email.mjs +69 -0
- package/vendor/tui/index.mjs +473 -82
package/vendor/tui/index.mjs
CHANGED
|
@@ -1,3 +1,256 @@
|
|
|
1
|
+
import { readClipboardImage as dscodeReadClipboardImage } from "./dscode-clipboard-image/index.mjs";
|
|
2
|
+
// dscode-clipboard-image-v1
|
|
3
|
+
// dscode-large-paste-v1
|
|
4
|
+
function collapseLargePaste(text, draft, pastes) {
|
|
5
|
+
const safe = text.replaceAll('\r\n', '\n').replaceAll('\r', '\n').replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/gu, '').replaceAll('\t', ' ');
|
|
6
|
+
const count = [...safe].length;
|
|
7
|
+
if (count <= LARGE_PASTE_CHARS) return safe;
|
|
8
|
+
// Keep an executable-looking first line visible to the command router.
|
|
9
|
+
if (draft.trim() === '' && /^\s*[!/]/u.test(safe)) return safe;
|
|
10
|
+
const base = `[Pasted Content ${count} chars]`;
|
|
11
|
+
let marker = base;
|
|
12
|
+
for (let suffix = 2; draft.includes(marker) || pastes.has(marker); suffix++) marker = `${base} #${suffix}`;
|
|
13
|
+
pastes.set(marker, safe);
|
|
14
|
+
return marker;
|
|
15
|
+
}
|
|
16
|
+
function expandLargePastes(value, pastes) {
|
|
17
|
+
const markers = [...pastes.keys()].sort((left, right) => right.length - left.length);
|
|
18
|
+
let expanded = '';
|
|
19
|
+
let offset = 0;
|
|
20
|
+
while (offset < value.length) {
|
|
21
|
+
let found = -1;
|
|
22
|
+
let match;
|
|
23
|
+
for (const marker of markers) {
|
|
24
|
+
const at = value.indexOf(marker, offset);
|
|
25
|
+
if (at >= 0 && (found < 0 || at < found)) {
|
|
26
|
+
found = at;
|
|
27
|
+
match = marker;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (match === undefined) break;
|
|
31
|
+
expanded += value.slice(offset, found) + pastes.get(match);
|
|
32
|
+
offset = found + match.length;
|
|
33
|
+
}
|
|
34
|
+
return expanded + value.slice(offset);
|
|
35
|
+
}
|
|
36
|
+
function pasteAtomicEdit(before, edit, pastes) {
|
|
37
|
+
let prefix = 0;
|
|
38
|
+
while (prefix < before.length && prefix < edit.value.length && before[prefix] === edit.value[prefix]) prefix++;
|
|
39
|
+
let suffix = 0;
|
|
40
|
+
while (suffix < before.length - prefix && suffix < edit.value.length - prefix && before[before.length - suffix - 1] === edit.value[edit.value.length - suffix - 1]) suffix++;
|
|
41
|
+
let from = prefix, to = before.length - suffix;
|
|
42
|
+
const inserted = edit.value.slice(prefix, edit.value.length - suffix);
|
|
43
|
+
let touched = false;
|
|
44
|
+
const originalPastes = new Map(pastes);
|
|
45
|
+
for (const marker of pastes.keys()) {
|
|
46
|
+
const start = before.indexOf(marker);
|
|
47
|
+
if (start < 0) continue;
|
|
48
|
+
const end = start + marker.length;
|
|
49
|
+
if (from < end && to > start || from === to && from > start && from < end) {
|
|
50
|
+
from = Math.min(from, start);
|
|
51
|
+
to = Math.max(to, end);
|
|
52
|
+
pastes.delete(marker);
|
|
53
|
+
touched = true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (touched) edit = { ...edit, value: before.slice(0, from) + inserted + before.slice(to), cursor: from + inserted.length,
|
|
57
|
+
killed: edit.killed === undefined ? undefined : expandLargePastes(before.slice(from, to), originalPastes) };
|
|
58
|
+
for (const marker of pastes.keys()) if (!edit.value.includes(marker) && before.includes(marker)) pastes.delete(marker);
|
|
59
|
+
return edit;
|
|
60
|
+
}
|
|
61
|
+
function pasteCursorEdge(value, previous, next, pastes) {
|
|
62
|
+
for (const marker of pastes.keys()) {
|
|
63
|
+
const start = value.indexOf(marker);
|
|
64
|
+
if (start < 0) continue;
|
|
65
|
+
const end = start + marker.length;
|
|
66
|
+
if (next > start && next < end) return next < previous ? start : end;
|
|
67
|
+
}
|
|
68
|
+
return next;
|
|
69
|
+
}
|
|
70
|
+
const LARGE_PASTE_CHARS = 200;
|
|
71
|
+
// dscode-user-background-v1
|
|
72
|
+
function userBackgroundRows(rows, columns, measure) {
|
|
73
|
+
const width = Math.max(1, Math.floor(columns));
|
|
74
|
+
return rows.map(row => {
|
|
75
|
+
const used = row.segments.reduce((sum, segment) => sum + measure(segment.text), 0);
|
|
76
|
+
return {
|
|
77
|
+
...row,
|
|
78
|
+
background: 'user',
|
|
79
|
+
segments: [...row.segments, { text: ' '.repeat(Math.max(0, width - used)), style: 'plain' }],
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
// dscode-turn-divider-v1
|
|
84
|
+
function turnDividedLines(entry, columns, rendered, remaining) {
|
|
85
|
+
if (entry?.turnEnded !== true || (rendered.length > 0 && rendered.length >= remaining)) return rendered;
|
|
86
|
+
const width = Math.max(1, Math.min(72, columns - 6));
|
|
87
|
+
return [...rendered, { segments: [{ text: ` ${'─'.repeat(width)}`, style: 'dim' }] }];
|
|
88
|
+
}
|
|
89
|
+
// dscode-scroll-v1
|
|
90
|
+
function transcriptWindow(lines, rows, offset) {
|
|
91
|
+
if (rows <= 0) return [];
|
|
92
|
+
const end = Math.max(0, lines.length - Math.max(0, offset));
|
|
93
|
+
return lines.slice(Math.max(0, end - rows), end);
|
|
94
|
+
}
|
|
95
|
+
function mouseWheelDirection(unit) {
|
|
96
|
+
const match = /^\x1b\[<(\d+);\d+;\d+([Mm])$/.exec(unit);
|
|
97
|
+
if (!match) return null;
|
|
98
|
+
if (match[2] !== 'M') return 0;
|
|
99
|
+
const button = Number(match[1]) & ~(4 | 8 | 16);
|
|
100
|
+
return button === 64 ? 1 : button === 65 ? -1 : 0;
|
|
101
|
+
}
|
|
102
|
+
const DSCODE_MOUSE_ENABLE = "\x1b[?1000h\x1b[?1006h";
|
|
103
|
+
const DSCODE_MOUSE_DISABLE = "\x1b[?1006l\x1b[?1000l";
|
|
104
|
+
const dscodeWheelListeners = new Set();
|
|
105
|
+
function dscodeHandleMouseUnit(unit) {
|
|
106
|
+
const direction = mouseWheelDirection(unit);
|
|
107
|
+
if (direction === null) return false;
|
|
108
|
+
if (direction !== 0) for (const listener of dscodeWheelListeners) listener(direction);
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
// dscode-interrupt-v1
|
|
112
|
+
function ctrlCAction(armed, { interrupt, busy, preparingImages, active, hasDraft }) {
|
|
113
|
+
if (armed) return 'quit';
|
|
114
|
+
if (interrupt() || busy) return 'interrupt';
|
|
115
|
+
if (preparingImages) return 'cancel-prepare';
|
|
116
|
+
if (!active) return 'wait';
|
|
117
|
+
return hasDraft ? 'clear-draft' : 'quit';
|
|
118
|
+
}
|
|
119
|
+
// dscode-welcome-scroll-v1
|
|
120
|
+
function welcomeVisibleRows(capacity, maximum, demand, canScroll = true) {
|
|
121
|
+
if (!canScroll || capacity < maximum) return maximum;
|
|
122
|
+
return Math.max(0, Math.min(maximum, capacity - demand));
|
|
123
|
+
}
|
|
124
|
+
// dscode-email-v4
|
|
125
|
+
import { createImapConnector as dscodeCreateImapConnector } from "./dscode-email/imap.mjs";
|
|
126
|
+
import { createGmailConnector as dscodeCreateGmailConnector } from "./dscode-email/gmail.mjs";
|
|
127
|
+
import { createEmailInbox as dscodeCreateEmailInbox, emailKey as dscodeEmailKey, emailPrompt as dscodeEmailPrompt, emailText as dscodeEmailText } from "./dscode-email/inbox.mjs";
|
|
128
|
+
function DscodeImapSetup({ connector, back, done }) {
|
|
129
|
+
const [values, setValues] = (0, import_react.useState)(() => {
|
|
130
|
+
const saved = connector.status();
|
|
131
|
+
return [saved.account || '', saved.host || 'imap.gmail.com', String(saved.port || 993), saved.mailbox || 'INBOX', ''];
|
|
132
|
+
});
|
|
133
|
+
const [step, setStep] = (0, import_react.useState)(0);
|
|
134
|
+
const [error, setError] = (0, import_react.useState)('');
|
|
135
|
+
const [busy, setBusy] = (0, import_react.useState)(false);
|
|
136
|
+
const operation = (0, import_react.useRef)(null);
|
|
137
|
+
(0, import_react.useEffect)(() => () => operation.current?.abort(), []);
|
|
138
|
+
const names = ['Email address', 'IMAP host', 'TLS port', 'Mailbox folder', 'Application password'];
|
|
139
|
+
useStableInput((input, key) => {
|
|
140
|
+
if (key.escape || key.ctrl && input === 'c') { operation.current?.abort(); setValues([]); back(); return; }
|
|
141
|
+
if (operation.current) return;
|
|
142
|
+
if (key.return) {
|
|
143
|
+
if (!values[step]?.trim()) { setError('This field is required.'); return; }
|
|
144
|
+
if (step < 4) { setStep(step + 1); setError(''); return; }
|
|
145
|
+
const [account, host, port, mailbox, password] = values;
|
|
146
|
+
const controller = new AbortController(); operation.current = controller;
|
|
147
|
+
setValues(current => current.map((value, index) => index === 4 ? '' : value)); setBusy(true); setError('');
|
|
148
|
+
Promise.resolve().then(() => connector.connect({ account, host, port, mailbox, password }, { signal: controller.signal })).then(result => {
|
|
149
|
+
if (controller.signal.aborted) return;
|
|
150
|
+
if (result.busy) { setError('Another session is syncing. Retry shortly.'); return; }
|
|
151
|
+
done();
|
|
152
|
+
}, reason => { if (!controller.signal.aborted) setError(reason.message); }).finally(() => {
|
|
153
|
+
operation.current = null; if (!controller.signal.aborted) setBusy(false);
|
|
154
|
+
});
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (key.tab) { setStep(current => (current + (key.shift ? 4 : 1)) % 5); setError(''); return; }
|
|
158
|
+
if (key.ctrl && input === 'u') { setValues(current => current.map((value, index) => index === step ? '' : value)); return; }
|
|
159
|
+
if (key.backspace || key.delete) { setValues(current => current.map((value, index) => index === step ? [...value].slice(0, -1).join('') : value)); return; }
|
|
160
|
+
if (key.ctrl || key.meta || !input) return;
|
|
161
|
+
const pasted = stripPasteMarkers(input).replace(/[\x00-\x1f\x7f]/g, '');
|
|
162
|
+
setValues(current => current.map((value, index) => index === step ? (value + pasted).slice(0, 1024) : value));
|
|
163
|
+
});
|
|
164
|
+
const text = (value, props = {}) => (0, import_react.createElement)(Text, { wrap: 'truncate-end', ...props }, value);
|
|
165
|
+
return (0, import_react.createElement)(Box, { flexDirection: 'column' },
|
|
166
|
+
text('Connect IMAP · ' + (step + 1) + '/5', { bold: true }),
|
|
167
|
+
text(busy ? 'Connecting securely…' : names[step] + ' › ' + (step === 4 ? values[step] ? '••••••••' : '' : values[step])),
|
|
168
|
+
text(error || (step === 4 ? 'Gmail: use an app password from 2-Step Verification.' : 'Enter keeps defaults · Ctrl+U clears'), { dimColor: !error, color: error ? 'red' : undefined }),
|
|
169
|
+
text('Enter next/connect · Tab edit · Esc cancel', { dimColor: true }));
|
|
170
|
+
}
|
|
171
|
+
function DscodeEmailPanel({ columns, rows, pick, close, gmail, imap }) {
|
|
172
|
+
const [snapshot, setSnapshot] = (0, import_react.useState)({ emails: [], rejected: 0 });
|
|
173
|
+
const [error, setError] = (0, import_react.useState)('');
|
|
174
|
+
const [selected, setSelected] = (0, import_react.useState)(null);
|
|
175
|
+
const [offset, setOffset] = (0, import_react.useState)(0);
|
|
176
|
+
const [preview, setPreview] = (0, import_react.useState)(false);
|
|
177
|
+
const [gmailStatus, setGmailStatus] = (0, import_react.useState)(() => gmail.status());
|
|
178
|
+
const [imapStatus, setImapStatus] = (0, import_react.useState)(() => imap.status());
|
|
179
|
+
const [setup, setSetup] = (0, import_react.useState)(false);
|
|
180
|
+
const [connecting, setConnecting] = (0, import_react.useState)(false);
|
|
181
|
+
const operation = (0, import_react.useRef)(null);
|
|
182
|
+
(0, import_react.useEffect)(() => () => operation.current?.abort(), []);
|
|
183
|
+
const inbox = (0, import_react.useMemo)(() => dscodeCreateEmailInbox(), []);
|
|
184
|
+
const refresh = () => {
|
|
185
|
+
try { setSnapshot(inbox.list()); setGmailStatus(gmail.status()); setImapStatus(imap.status()); }
|
|
186
|
+
catch { setError('Could not read inbox. Press r to retry.'); }
|
|
187
|
+
};
|
|
188
|
+
(0, import_react.useEffect)(() => {
|
|
189
|
+
refresh();
|
|
190
|
+
const timer = setInterval(refresh, 2000);
|
|
191
|
+
return () => clearInterval(timer);
|
|
192
|
+
}, [inbox]);
|
|
193
|
+
const emails = snapshot.emails;
|
|
194
|
+
const index = Math.max(0, emails.findIndex(mail => dscodeEmailKey(mail) === selected));
|
|
195
|
+
const mail = emails[index];
|
|
196
|
+
(0, import_react.useEffect)(() => {
|
|
197
|
+
if (mail) setSelected(dscodeEmailKey(mail));
|
|
198
|
+
}, [mail && dscodeEmailKey(mail)]);
|
|
199
|
+
const height = Math.max(3, rows);
|
|
200
|
+
const contentRows = Math.max(1, height - 4);
|
|
201
|
+
const wide = columns >= 64;
|
|
202
|
+
const listWidth = wide ? Math.max(26, Math.floor(columns * 0.4)) : columns;
|
|
203
|
+
const previewWidth = wide ? Math.max(1, columns - listWidth - 1) : columns;
|
|
204
|
+
const clean = value => dscodeEmailText(value).replace(/\n/g, ' ');
|
|
205
|
+
const bodyLines = mail ? wrapText(dscodeEmailText(mail.body), Math.max(1, previewWidth - 2), 'wrap').split('\n') : [];
|
|
206
|
+
useStableInput((input, key) => {
|
|
207
|
+
if (setup) return;
|
|
208
|
+
if (key.escape || key.ctrl && input === 'c') { close(); return; }
|
|
209
|
+
if (input === 'i' && !operation.current) { setSetup(true); setError(''); return; }
|
|
210
|
+
if (input === 'g' || input === 'r') {
|
|
211
|
+
if (operation.current) return;
|
|
212
|
+
const controller = new AbortController(); operation.current = controller;
|
|
213
|
+
setError(''); setConnecting(input === 'g');
|
|
214
|
+
const action = input === 'g' ? gmail.connect({ signal: controller.signal }) : (imapStatus.connected ? imap : gmail).sync({ force: true, signal: controller.signal });
|
|
215
|
+
Promise.resolve(action).then(result => {
|
|
216
|
+
if (!controller.signal.aborted) { if (result.busy) setError('Gmail is busy in another session. Retry shortly.'); refresh(); }
|
|
217
|
+
}, reason => { if (!controller.signal.aborted) setError(reason.message); }).finally(() => {
|
|
218
|
+
operation.current = null;
|
|
219
|
+
if (!controller.signal.aborted) setConnecting(false);
|
|
220
|
+
});
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (key.tab) { setPreview(current => !current); return; }
|
|
224
|
+
if (!mail) return;
|
|
225
|
+
if (key.upArrow || key.downArrow) {
|
|
226
|
+
const next = Math.max(0, Math.min(emails.length - 1, index + (key.upArrow ? -1 : 1)));
|
|
227
|
+
setSelected(dscodeEmailKey(emails[next])); setOffset(0); return;
|
|
228
|
+
}
|
|
229
|
+
if (key.pageDown || key.pageUp) {
|
|
230
|
+
setOffset(current => Math.max(0, Math.min(Math.max(0, bodyLines.length - contentRows + 2), current + (key.pageUp ? -1 : 1) * Math.max(1, contentRows - 2)))); return;
|
|
231
|
+
}
|
|
232
|
+
if (key.return) pick(mail);
|
|
233
|
+
});
|
|
234
|
+
if (setup) return (0, import_react.createElement)(Box, { height, overflow: 'hidden', flexDirection: 'column' },
|
|
235
|
+
(0, import_react.createElement)(DscodeImapSetup, { connector: imap, back: () => setSetup(false), done: () => { setSetup(false); refresh(); } }));
|
|
236
|
+
const text = (value, extra = {}) => (0, import_react.createElement)(Text, { wrap: 'truncate-end', ...extra }, value);
|
|
237
|
+
const start = Math.max(0, index - contentRows + 1);
|
|
238
|
+
const list = (0, import_react.createElement)(Box, { width: listWidth, flexDirection: 'column', overflow: 'hidden' },
|
|
239
|
+
text('Email · newest updates first', { bold: true }),
|
|
240
|
+
...emails.slice(start, start + contentRows).map((entry, i) => text(
|
|
241
|
+
(start + i === index ? '› ' : ' ') + entry.updatedAt.slice(5, 16).replace('T', ' ') + ' ' + clean(entry.subject),
|
|
242
|
+
{ key: dscodeEmailKey(entry), color: start + i === index ? 'cyan' : undefined })),
|
|
243
|
+
!mail ? text(error || 'No emails received.') : null);
|
|
244
|
+
return (0, import_react.createElement)(Box, { flexDirection: 'column', height, overflow: 'hidden' },
|
|
245
|
+
text(imapStatus.connected ? imapStatus.error || 'IMAP · ' + clean(imapStatus.account) + ' · ' + clean(imapStatus.mailbox) : connecting ? 'Gmail · Complete Google login in your browser · Esc cancels' : gmailStatus.error || (gmailStatus.connected ? 'Gmail · ' + clean(gmailStatus.account) + (gmailStatus.lastSyncAt ? ' · synced ' + new Date(gmailStatus.lastSyncAt).toLocaleTimeString() : ' · waiting for new mail') : 'Email not connected · i IMAP · g Google OAuth'), { dimColor: true }),
|
|
246
|
+
(0, import_react.createElement)(Box, { flexDirection: 'row', height: Math.max(1, height - 2) },
|
|
247
|
+
wide || preview ? (0, import_react.createElement)(Box, { width: previewWidth, marginRight: wide ? 1 : 0, flexDirection: 'column', overflow: 'hidden' },
|
|
248
|
+
text(mail ? clean(mail.subject) : 'Email preview', { bold: true }),
|
|
249
|
+
text(mail ? 'From: ' + clean(mail.from) : 'Waiting for a connector', { dimColor: true }),
|
|
250
|
+
...bodyLines.slice(offset, offset + Math.max(1, contentRows - 1)).map((line, i) => text(line, { key: i }))) : null,
|
|
251
|
+
wide || !preview ? list : null),
|
|
252
|
+
text(error || (snapshot.rejected ? snapshot.rejected + ' invalid records skipped · ' : '') + (wide ? '↑↓ select · Enter steer · Esc · PgUp/Dn · i IMAP · g OAuth · r sync' : '↑↓ Enter · Tab · i IMAP · r sync'), { dimColor: true }));
|
|
253
|
+
}
|
|
1
254
|
// dscode-effort-bar-v6
|
|
2
255
|
// dscode-welcome-v1
|
|
3
256
|
function welcomePath(path, width) {
|
|
@@ -18,7 +271,7 @@ function visibleSettledLines(entries, settled, budget, columns, showReasoning, r
|
|
|
18
271
|
const chunks = [];
|
|
19
272
|
let remaining = budget;
|
|
20
273
|
for (let index = settled - 1; index >= 0 && remaining > 0; index--) {
|
|
21
|
-
const lines = renderEntry(entries[index], Math.max(10, columns - 2), showReasoning);
|
|
274
|
+
const lines = turnDividedLines(entries[index], columns, renderEntry(entries[index], Math.max(10, columns - 2), showReasoning), remaining);
|
|
22
275
|
const kept = lines.slice(-remaining);
|
|
23
276
|
if (kept.length) {
|
|
24
277
|
chunks.unshift(kept);
|
|
@@ -29,6 +282,40 @@ function visibleSettledLines(entries, settled, budget, columns, showReasoning, r
|
|
|
29
282
|
}
|
|
30
283
|
// dscode-style-v1
|
|
31
284
|
|
|
285
|
+
|
|
286
|
+
// dscode-tps-colors-v1
|
|
287
|
+
function dscodeTpsTone(rate) {
|
|
288
|
+
if (!Number.isFinite(rate) || rate < 0) return null;
|
|
289
|
+
if (rate < 75) return "yellow";
|
|
290
|
+
if (rate < 150) return "green";
|
|
291
|
+
if (rate <= 250) return "blue";
|
|
292
|
+
return "purple";
|
|
293
|
+
}
|
|
294
|
+
function dscodeTpsInkColor(tone) {
|
|
295
|
+
const palette = getPalette();
|
|
296
|
+
if (tone === "yellow") return inkColor(palette.warn);
|
|
297
|
+
if (tone === "green") return inkColor(palette.success);
|
|
298
|
+
if (tone === "blue") return inkColor(palette.brandBright);
|
|
299
|
+
if (tone === "purple") return inkColor(getTheme() === "light" ? [126, 34, 206] : [192, 132, 252]);
|
|
300
|
+
return void 0;
|
|
301
|
+
}
|
|
302
|
+
function dscodeTelemetryParts(value) {
|
|
303
|
+
const result = [];
|
|
304
|
+
for (const [index, part] of value.split(" | ").entries()) {
|
|
305
|
+
if (index > 0) result.push({ text: " | ", tone: null });
|
|
306
|
+
const prefix = part.startsWith("current: ") ? "current: " : part.startsWith("average: ") ? "average: " : "";
|
|
307
|
+
if (!prefix || !part.endsWith(" tps")) { result.push({ text: part, tone: null }); continue; }
|
|
308
|
+
const display = part.slice(prefix.length, -4);
|
|
309
|
+
const rate = Number(display.startsWith("~") ? display.slice(1) : display);
|
|
310
|
+
result.push({ text: prefix, tone: null }, { text: display + " tps", tone: display && dscodeTpsTone(rate) });
|
|
311
|
+
}
|
|
312
|
+
return result;
|
|
313
|
+
}
|
|
314
|
+
function dscodeTelemetryNodes(value, key) {
|
|
315
|
+
return dscodeTelemetryParts(value).map((part, index) => (0, import_react.createElement)(Text,
|
|
316
|
+
{ key: key + "p" + index, color: dscodeTpsInkColor(part.tone) }, part.text));
|
|
317
|
+
}
|
|
318
|
+
|
|
32
319
|
function dscodeActivity(entries, streaming) {
|
|
33
320
|
const running = entries.filter(entry => entry.kind === "tool" && entry.state === "running");
|
|
34
321
|
const tool = running.at(-1);
|
|
@@ -110,7 +397,8 @@ function dscodeChatLines(entry, columns) {
|
|
|
110
397
|
if (!entry.text && !entry.interrupted) return [];
|
|
111
398
|
entry = { ...entry, reasoning: "" };
|
|
112
399
|
}
|
|
113
|
-
|
|
400
|
+
const rows = transcriptEntryLines(entry, columns, false, false, false);
|
|
401
|
+
return entry.kind === "user" && !entry.notice ? userBackgroundRows(rows, columns, visibleColumns) : rows;
|
|
114
402
|
}
|
|
115
403
|
import { n as __require, r as __toESM, t as __commonJSMin } from "./rolldown-runtime-CMFfr-1z.mjs";
|
|
116
404
|
import { a as inkColor, c as chalk, i as getTheme, n as dim, o as parseThemeName, r as getPalette, s as setTheme } from "./theme-DCT8Y2xf.mjs";
|
|
@@ -25744,9 +26032,18 @@ function replayProjectEvent(acc, event) {
|
|
|
25744
26032
|
acc.busy = false;
|
|
25745
26033
|
acc.busySince = 0;
|
|
25746
26034
|
for (const entry of appended) appendReplayEntry(acc, entry);
|
|
25747
|
-
|
|
25748
|
-
|
|
25749
|
-
|
|
26035
|
+
for (let index = acc.entries.length - 1; index >= 0; index--) {
|
|
26036
|
+
const entry = acc.entries[index];
|
|
26037
|
+
if (entry === void 0 || entry.kind === "pending") continue;
|
|
26038
|
+
if (entry.turnEnded !== true) {
|
|
26039
|
+
acc.entries[index] = { ...entry, turnEnded: true };
|
|
26040
|
+
acc.ops += 1;
|
|
26041
|
+
}
|
|
26042
|
+
break;
|
|
26043
|
+
}
|
|
26044
|
+
return true;
|
|
26045
|
+
}
|
|
26046
|
+
case "llm/retry": {
|
|
25750
26047
|
const data = event.data;
|
|
25751
26048
|
acc.streaming = "";
|
|
25752
26049
|
acc.streamingReasoning = "";
|
|
@@ -28223,7 +28520,7 @@ function cacheHitPercent(usage) {
|
|
|
28223
28520
|
return usage.inputTokens === 0 ? null : Math.round(usage.cacheReadTokens / usage.inputTokens * 1e3) / 10;
|
|
28224
28521
|
}
|
|
28225
28522
|
/** Separator between trailing state spans. */
|
|
28226
|
-
const STATUS_ITEM_SEPARATOR = "
|
|
28523
|
+
const STATUS_ITEM_SEPARATOR = " | ";
|
|
28227
28524
|
/** The Codex-style mode cycle hint appended to the permission badge. */
|
|
28228
28525
|
const STATUS_CYCLE_HINT = " (shift+tab to cycle)";
|
|
28229
28526
|
/** Occupancy at which the usage readout flips from brand blue to amber. */
|
|
@@ -28438,7 +28735,7 @@ function safe(text) {
|
|
|
28438
28735
|
/** Dim junction separator span inside a cluster. */
|
|
28439
28736
|
function sep() {
|
|
28440
28737
|
return {
|
|
28441
|
-
text: "
|
|
28738
|
+
text: " | ",
|
|
28442
28739
|
tone: "label"
|
|
28443
28740
|
};
|
|
28444
28741
|
}
|
|
@@ -28469,7 +28766,7 @@ function buildCandidates(facts, stats, busy, enabled, contextWidth) {
|
|
|
28469
28766
|
if (model !== "" && enabled.has("model")) {
|
|
28470
28767
|
const effort = safe(facts.effort ?? stats.reasoningEffort);
|
|
28471
28768
|
push({
|
|
28472
|
-
text: effort === "" ? model : `${model}
|
|
28769
|
+
text: effort === "" ? model : `${model} | ${effort}`,
|
|
28473
28770
|
tone: "model"
|
|
28474
28771
|
});
|
|
28475
28772
|
}
|
|
@@ -28666,7 +28963,7 @@ function layoutStatusBar(facts, stats, columns, options = {}) {
|
|
|
28666
28963
|
const budget = Math.max(1, Math.floor(columns) - WIDTH_SAFETY);
|
|
28667
28964
|
const maxContextWidth = Math.max(CONTEXT_MIN_WIDTH, Math.min(budget, Math.floor(options.contextWidth ?? 24)));
|
|
28668
28965
|
const { left, right, badge, row2 } = buildCandidates(facts, stats, busy, enabled, maxContextWidth);
|
|
28669
|
-
const groupSeparator = visibleColumns("
|
|
28966
|
+
const groupSeparator = visibleColumns(" | ");
|
|
28670
28967
|
const itemSeparator = visibleColumns(STATUS_ITEM_SEPARATOR);
|
|
28671
28968
|
const position = new Map(items.map((id, index) => [id, index]));
|
|
28672
28969
|
const byPosition = (a, b) => (position.get(a.id) ?? Number.MAX_SAFE_INTEGER) - (position.get(b.id) ?? Number.MAX_SAFE_INTEGER);
|
|
@@ -28767,7 +29064,7 @@ function layoutStatusBar(facts, stats, columns, options = {}) {
|
|
|
28767
29064
|
};
|
|
28768
29065
|
}
|
|
28769
29066
|
const row2Kept = [...orderedRow2];
|
|
28770
|
-
const row2Budget = Math.max(0, budget -
|
|
29067
|
+
const row2Budget = Math.max(0, budget - 1 - (facts.telemetry ? visibleColumns(facts.telemetry) + 3 : 0));
|
|
28771
29068
|
const row2Width = () => joinWidth(row2Kept.map((entry) => spansWidth(entry.group.spans)), groupSeparator);
|
|
28772
29069
|
while (row2Width() > row2Budget && row2Kept.length > 0) {
|
|
28773
29070
|
let dropIndex = 0;
|
|
@@ -31522,6 +31819,7 @@ function readSettledRowCap() {
|
|
|
31522
31819
|
const SYNCHRONIZED_UPDATE_END = "\x1B[?2026l";
|
|
31523
31820
|
/** One source of truth for TUI-owned slash commands in completion and `/help`. */
|
|
31524
31821
|
const LOCAL_COMMANDS = [
|
|
31822
|
+
{ label: "/email", description: "browse email and steer into this session" },
|
|
31525
31823
|
{ label: "/login", description: "save a DeepSeek API key locally" },
|
|
31526
31824
|
// dscode: startup command discovery
|
|
31527
31825
|
{"label":"/status","description":"session, model, permissions and usage"},
|
|
@@ -31872,8 +32170,10 @@ function lineStyleProps(style) {
|
|
|
31872
32170
|
function StyledRows({ lines }) {
|
|
31873
32171
|
return (0, import_react.createElement)(Box, { flexDirection: "column" }, ...lines.map((line, index) => (0, import_react.createElement)(Text, {
|
|
31874
32172
|
key: index,
|
|
31875
|
-
|
|
31876
|
-
|
|
32173
|
+
wrap: "truncate-end",
|
|
32174
|
+
backgroundColor: line.background === "user" ? inkColor(getPalette().composerBand) : void 0,
|
|
32175
|
+
color: line.background === "user" ? inkColor(getPalette().text) : void 0
|
|
32176
|
+
}, line.segments.length === 0 ? " " : line.segments.map((segment, at) => (0, import_react.createElement)(Text, {
|
|
31877
32177
|
key: at,
|
|
31878
32178
|
...lineStyleProps(segment.style)
|
|
31879
32179
|
}, segment.text)))));
|
|
@@ -31945,7 +32245,7 @@ function Header({ cwd = "", model = "", effort = "" }) {
|
|
|
31945
32245
|
if (!full) return (0, import_react.createElement)(Box, { flexDirection: "column", paddingX: 2, marginBottom: 1 },
|
|
31946
32246
|
(0, import_react.createElement)(Text, { wrap: "truncate-end" },
|
|
31947
32247
|
(0, import_react.createElement)(Text, { color: inkColor(getPalette().brandBright), bold: true }, "❄ DSCODE"),
|
|
31948
|
-
(0, import_react.createElement)(Text, { color: inkColor(getPalette().dim) }, " v0.
|
|
32248
|
+
(0, import_react.createElement)(Text, { color: inkColor(getPalette().dim) }, " v0.5.0")),
|
|
31949
32249
|
(0, import_react.createElement)(Text, { wrap: "truncate-end" }, truncateColumns(modelName + " · " + effortName, width)),
|
|
31950
32250
|
(0, import_react.createElement)(Text, { color: inkColor(getPalette().dim), wrap: "truncate-end" }, welcomePath(cwd, width)));
|
|
31951
32251
|
return (0, import_react.createElement)(Box, { flexDirection: "column", width, borderStyle: "round", borderColor: inkColor(getPalette().brand), paddingX: 1, marginBottom: 1 },
|
|
@@ -31964,7 +32264,7 @@ function Header({ cwd = "", model = "", effort = "" }) {
|
|
|
31964
32264
|
(0, import_react.createElement)(Box, { flexDirection: "column", width: detailsWidth, marginTop: 2 },
|
|
31965
32265
|
(0, import_react.createElement)(Text, { color: inkColor(getPalette().text), bold: true }, "DSCODE"),
|
|
31966
32266
|
(0, import_react.createElement)(Text, { color: inkColor(getPalette().brandDeep) }, "────────────"),
|
|
31967
|
-
(0, import_react.createElement)(Text, { color: inkColor(getPalette().dim) }, "v0.
|
|
32267
|
+
(0, import_react.createElement)(Text, { color: inkColor(getPalette().dim) }, "v0.5.0"),
|
|
31968
32268
|
(0, import_react.createElement)(Text, { wrap: "truncate-end" }, truncateColumns("model " + modelName, detailsWidth)),
|
|
31969
32269
|
(0, import_react.createElement)(Text, { wrap: "truncate-end" }, truncateColumns("effort " + effortName, detailsWidth)),
|
|
31970
32270
|
(0, import_react.createElement)(Text, null, " "),
|
|
@@ -32175,7 +32475,7 @@ function deepseekWaveHues(tier) {
|
|
|
32175
32475
|
function StatusLine({ facts, stats, busy, columns, items }) {
|
|
32176
32476
|
const [, refreshMetrics] = (0, import_react.useState)(0);
|
|
32177
32477
|
(0, import_react.useEffect)(() => { const timer = setInterval(() => refreshMetrics(n => n + 1), 1000); return () => clearInterval(timer); }, []);
|
|
32178
|
-
facts = { ...facts, telemetry: columns >=
|
|
32478
|
+
facts = { ...facts, telemetry: columns >= 48 ? dscodeFooterFor(facts.fullSessionId, stats, Math.max(1, Math.min(columns - 8, Math.max(40, Math.floor(columns * 0.8) - 4)))) : "" };
|
|
32179
32479
|
const layout = (0, import_react.useMemo)(() => layoutStatusBar(facts, stats, Math.max(8, columns - 2), {
|
|
32180
32480
|
busy,
|
|
32181
32481
|
items,
|
|
@@ -32206,7 +32506,7 @@ function StatusLine({ facts, stats, busy, columns, items }) {
|
|
|
32206
32506
|
if (groupIndex > 0) leftParts.push((0, import_react.createElement)(Text, {
|
|
32207
32507
|
key: key + "gs" + groupIndex,
|
|
32208
32508
|
color: inkColor(getPalette().dim)
|
|
32209
|
-
}, "
|
|
32509
|
+
}, " | "));
|
|
32210
32510
|
group.spans.forEach((span, spanIndex) => {
|
|
32211
32511
|
leftParts.push((0, import_react.createElement)(Text, {
|
|
32212
32512
|
key: key + "g" + groupIndex + "s" + spanIndex,
|
|
@@ -32216,6 +32516,7 @@ function StatusLine({ facts, stats, busy, columns, items }) {
|
|
|
32216
32516
|
});
|
|
32217
32517
|
});
|
|
32218
32518
|
const rightParts = [];
|
|
32519
|
+
if (key === "s2" && row.left.length > 0 && row.right.length > 0) rightParts.push((0, import_react.createElement)(Text, { key: key + "divider", color: inkColor(getPalette().dim) }, "| "));
|
|
32219
32520
|
row.right.forEach((span, index) => {
|
|
32220
32521
|
if (index > 0) rightParts.push((0, import_react.createElement)(Text, {
|
|
32221
32522
|
key: key + "rs" + index,
|
|
@@ -32225,7 +32526,7 @@ function StatusLine({ facts, stats, busy, columns, items }) {
|
|
|
32225
32526
|
key: key + "r" + index,
|
|
32226
32527
|
wrap: "truncate-end",
|
|
32227
32528
|
...statusToneProps(span.tone)
|
|
32228
|
-
}, span.text));
|
|
32529
|
+
}, key === "s2" && index === 0 ? dscodeTelemetryNodes(span.text, key + "r" + index) : span.text));
|
|
32229
32530
|
});
|
|
32230
32531
|
if (row.hint) rightParts.push((0, import_react.createElement)(Text, {
|
|
32231
32532
|
key: key + "hint",
|
|
@@ -33689,7 +33990,7 @@ function HelpPanel({ descriptors, skills, commandError, skillError, onClose }) {
|
|
|
33689
33990
|
key: "key-cancel",
|
|
33690
33991
|
dimColor: true,
|
|
33691
33992
|
wrap: "truncate-end"
|
|
33692
|
-
}, "
|
|
33993
|
+
}, " ctrl+c stop running turn · ctrl+c again exit · ctrl+d exit"),
|
|
33693
33994
|
(0, import_react.createElement)(Text, {
|
|
33694
33995
|
key: "key-queue",
|
|
33695
33996
|
dimColor: true,
|
|
@@ -34209,7 +34510,7 @@ function CompletionMenu({ active, mention, index, rows, error }) {
|
|
|
34209
34510
|
* While a modal (approval / question / model panel) owns the keys, the
|
|
34210
34511
|
* box passes every key through untouched.
|
|
34211
34512
|
*/
|
|
34212
|
-
function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, skills, dispatch, steer, interrupt, quit, openLogin, openModel, openEffort, openHelp, openMode, openPermission, openResume, openPlugin, openJobs, openStatusline, openTheme, openHistory, openAgents, openSubagent, openTodos, openDelete, openDiff, reviewChanges, deleteConfirm, confirmDelete, cancelDelete, createSession, forkSession, cancelSessionSwitch, notify, applyEditorKeys, hasNotice, dismissNotice, toggleReasoning, openVerbose, clearView, refresh, loadMentions, inspectImages, prepareImages, inspectFiles, prepareFiles, cyclePermission, exportTranscript, renameTitle, copyLastResponse, recallSpace, recordLocal, recordHistory, queued, cancelQueued, historyFill, historyConsumed, animations, applyAnimations, waveTier, waveStyle, maxRows, onEditorRows, onMenuRows, sessionKey }) {
|
|
34513
|
+
function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, skills, dispatch, steer, interrupt, quit, openEmail, emailFill, emailConsumed, openLogin, openModel, openEffort, openHelp, openMode, openPermission, openResume, openPlugin, openJobs, openStatusline, openTheme, openHistory, openAgents, openSubagent, openTodos, openDelete, openDiff, reviewChanges, deleteConfirm, confirmDelete, cancelDelete, createSession, forkSession, cancelSessionSwitch, notify, applyEditorKeys, hasNotice, dismissNotice, toggleReasoning, openVerbose, clearView, refresh, loadMentions, inspectImages, prepareImages, inspectFiles, prepareFiles, readClipboardImage, cyclePermission, exportTranscript, renameTitle, copyLastResponse, recallSpace, recordLocal, recordHistory, queued, cancelQueued, historyFill, historyConsumed, animations, applyAnimations, waveTier, waveStyle, maxRows, onEditorRows, onMenuRows, onTranscriptScroll, sessionKey }) {
|
|
34213
34514
|
const columns = useStdout().stdout?.columns ?? 80;
|
|
34214
34515
|
const inputTerminalRows = useStdout().stdout?.rows ?? 30;
|
|
34215
34516
|
const dscodeImeStdout = useStdout().stdout;
|
|
@@ -34226,6 +34527,8 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34226
34527
|
const [cursor, setCursor] = (0, import_react.useState)(0);
|
|
34227
34528
|
const valueRef = (0, import_react.useRef)(value);
|
|
34228
34529
|
const cursorRef = (0, import_react.useRef)(cursor);
|
|
34530
|
+
const pendingPastesRef = (0, import_react.useRef)(new Map());
|
|
34531
|
+
const ctrlCArmedRef = (0, import_react.useRef)(false);
|
|
34229
34532
|
valueRef.current = value;
|
|
34230
34533
|
cursorRef.current = cursor;
|
|
34231
34534
|
const [draftImages, setDraftImages] = (0, import_react.useState)([]);
|
|
@@ -34242,6 +34545,16 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34242
34545
|
prepareEpochRef.current += 1;
|
|
34243
34546
|
prepareAbortRef.current?.abort();
|
|
34244
34547
|
}, []);
|
|
34548
|
+
|
|
34549
|
+
(0, import_react.useEffect)(() => {
|
|
34550
|
+
if (!emailFill) return;
|
|
34551
|
+
if (emailFill.sessionKey === sessionKey) {
|
|
34552
|
+
const next = valueRef.current + (valueRef.current ? "\n\n" : "") + sanitizeDraftText(emailFill.text);
|
|
34553
|
+
valueRef.current = next; cursorRef.current = next.length;
|
|
34554
|
+
setValue(next); setCursor(next.length); setDismissedMenuValue(void 0);
|
|
34555
|
+
}
|
|
34556
|
+
emailConsumed();
|
|
34557
|
+
}, [emailFill, sessionKey, emailConsumed]);
|
|
34245
34558
|
const killRef = (0, import_react.useRef)("");
|
|
34246
34559
|
const preferredColumnRef = (0, import_react.useRef)(null);
|
|
34247
34560
|
const editorScrollRef = (0, import_react.useRef)(0);
|
|
@@ -34259,6 +34572,7 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34259
34572
|
(0, import_react.useEffect)(() => {
|
|
34260
34573
|
if (historyFill === void 0) return;
|
|
34261
34574
|
const safe = sanitizeDraftText(historyFill.text);
|
|
34575
|
+
pendingPastesRef.current.clear();
|
|
34262
34576
|
draftImagesRef.current = [];
|
|
34263
34577
|
setDraftImages([]);
|
|
34264
34578
|
draftFilesRef.current = [];
|
|
@@ -34295,6 +34609,9 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34295
34609
|
return next.length === current.length ? current : next;
|
|
34296
34610
|
});
|
|
34297
34611
|
}, [value]);
|
|
34612
|
+
(0, import_react.useEffect)(() => {
|
|
34613
|
+
for (const marker of pendingPastesRef.current.keys()) if (!value.includes(marker)) pendingPastesRef.current.delete(marker);
|
|
34614
|
+
}, [value]);
|
|
34298
34615
|
(0, import_react.useEffect)(() => {
|
|
34299
34616
|
if (stdin === void 0) return;
|
|
34300
34617
|
const originalRead = stdin.read.bind(stdin);
|
|
@@ -34340,11 +34657,12 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34340
34657
|
const uniqueImageMarker = (name, source, reserved = [], kind = "image") => {
|
|
34341
34658
|
const safeName = singleLineText(sanitizeDraftText(name));
|
|
34342
34659
|
const label = kind === "file" ? "file" : "image";
|
|
34343
|
-
|
|
34660
|
+
// dscode-image-marker-v1
|
|
34661
|
+
let marker = source === "mention" ? `@${safeName}` : kind === "image" ? "[Image 1]" : `[${label}: ${safeName}]`;
|
|
34344
34662
|
let suffix = 2;
|
|
34345
34663
|
const taken = (candidate) => valueRef.current.includes(candidate) || draftImagesRef.current.some((image) => image.marker === candidate) || draftFilesRef.current.some((file) => file.marker === candidate) || reserved.includes(candidate);
|
|
34346
34664
|
while (taken(marker)) {
|
|
34347
|
-
marker = source === "mention" ? `@${safeName} (${suffix})` : `[${label}: ${safeName} ${suffix}]`;
|
|
34665
|
+
marker = source === "mention" ? `@${safeName} (${suffix})` : kind === "image" ? `[Image ${suffix}]` : `[${label}: ${safeName} ${suffix}]`;
|
|
34348
34666
|
suffix += 1;
|
|
34349
34667
|
}
|
|
34350
34668
|
return marker;
|
|
@@ -34367,9 +34685,7 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34367
34685
|
* durable image blocks, files ride the 0.1.5 file blocks, and both register
|
|
34368
34686
|
* visible draft markers anchored at the drop point.
|
|
34369
34687
|
*/
|
|
34370
|
-
const insertDroppedAttachments = (imagePaths, filePaths) => {
|
|
34371
|
-
const originalValue = valueRef.current;
|
|
34372
|
-
const originalCursor = cursorRef.current;
|
|
34688
|
+
const insertDroppedAttachments = (imagePaths, filePaths, originalValue = valueRef.current, originalCursor = cursorRef.current) => {
|
|
34373
34689
|
const total = imagePaths.length + filePaths.length;
|
|
34374
34690
|
if (total === 0) return;
|
|
34375
34691
|
notify(`checking ${total} attachment${total === 1 ? "" : "s"}…`);
|
|
@@ -34554,6 +34870,7 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34554
34870
|
};
|
|
34555
34871
|
/** Apply one editor edit: draft, cursor, kill buffer, menu reset. */
|
|
34556
34872
|
const applyEdit = (edit) => {
|
|
34873
|
+
edit = pasteAtomicEdit(valueRef.current, edit, pendingPastesRef.current);
|
|
34557
34874
|
if (edit.killed !== void 0 && edit.killed !== "") killRef.current = edit.killed;
|
|
34558
34875
|
valueRef.current = edit.value;
|
|
34559
34876
|
cursorRef.current = edit.cursor;
|
|
@@ -34568,6 +34885,7 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34568
34885
|
const moveCursorTo = (next) => {
|
|
34569
34886
|
resetCursorBlink();
|
|
34570
34887
|
if (next === cursorRef.current) return;
|
|
34888
|
+
next = pasteCursorEdge(valueRef.current, cursorRef.current, next, pendingPastesRef.current);
|
|
34571
34889
|
cursorRef.current = next;
|
|
34572
34890
|
setCursor(next);
|
|
34573
34891
|
preferredColumnRef.current = null;
|
|
@@ -34578,23 +34896,24 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34578
34896
|
let nextCursor = cursorRef.current;
|
|
34579
34897
|
for (const token of tokens) {
|
|
34580
34898
|
if (token.kind === "text") {
|
|
34581
|
-
const edit = insertText(nextValue, nextCursor, token.text);
|
|
34899
|
+
const edit = pasteAtomicEdit(nextValue, insertText(nextValue, nextCursor, collapseLargePaste(token.text, nextValue, pendingPastesRef.current)), pendingPastesRef.current);
|
|
34582
34900
|
nextValue = edit.value;
|
|
34583
34901
|
nextCursor = edit.cursor;
|
|
34584
34902
|
continue;
|
|
34585
34903
|
}
|
|
34586
34904
|
if (token.kind === "home") {
|
|
34587
|
-
nextCursor = moveToLineStart(nextValue, nextCursor, false);
|
|
34905
|
+
nextCursor = pasteCursorEdge(nextValue, nextCursor, moveToLineStart(nextValue, nextCursor, false), pendingPastesRef.current);
|
|
34588
34906
|
continue;
|
|
34589
34907
|
}
|
|
34590
34908
|
if (token.kind === "end") {
|
|
34591
|
-
nextCursor = moveToLineEnd(nextValue, nextCursor, false);
|
|
34909
|
+
nextCursor = pasteCursorEdge(nextValue, nextCursor, moveToLineEnd(nextValue, nextCursor, false), pendingPastesRef.current);
|
|
34592
34910
|
continue;
|
|
34593
34911
|
}
|
|
34594
34912
|
const edit = token.kind === "delete-backward" ? deleteBackward(nextValue, nextCursor) : token.kind === "delete-word-backward" ? deleteWordBackward(nextValue, nextCursor) : token.kind === "delete-forward" ? deleteForward(nextValue, nextCursor) : deleteWordForward(nextValue, nextCursor);
|
|
34595
|
-
|
|
34596
|
-
|
|
34597
|
-
|
|
34913
|
+
const atomic = pasteAtomicEdit(nextValue, edit, pendingPastesRef.current);
|
|
34914
|
+
if (atomic.killed !== void 0 && atomic.killed !== "") killRef.current = atomic.killed;
|
|
34915
|
+
nextValue = atomic.value;
|
|
34916
|
+
nextCursor = atomic.cursor;
|
|
34598
34917
|
}
|
|
34599
34918
|
valueRef.current = nextValue;
|
|
34600
34919
|
cursorRef.current = nextCursor;
|
|
@@ -34621,8 +34940,9 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34621
34940
|
const preferred = preferredColumnRef.current ?? caretSite(model, currentCursor).column;
|
|
34622
34941
|
const next = moveCursorVertically(model, currentCursor, preferred, direction);
|
|
34623
34942
|
if (next !== currentCursor) {
|
|
34624
|
-
|
|
34625
|
-
|
|
34943
|
+
const edge = pasteCursorEdge(currentValue, currentCursor, next, pendingPastesRef.current);
|
|
34944
|
+
cursorRef.current = edge;
|
|
34945
|
+
setCursor(edge);
|
|
34626
34946
|
resetCursorBlink();
|
|
34627
34947
|
preferredColumnRef.current = preferred;
|
|
34628
34948
|
return;
|
|
@@ -34643,10 +34963,29 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34643
34963
|
resetCursorBlink();
|
|
34644
34964
|
};
|
|
34645
34965
|
useStableInput((input, key) => {
|
|
34646
|
-
|
|
34647
|
-
|
|
34648
|
-
|
|
34649
|
-
|
|
34966
|
+
if (!active && !(key.ctrl && input === "c")) { ctrlCArmedRef.current = false; return; }
|
|
34967
|
+
const liveValue = valueRef.current;
|
|
34968
|
+
const liveCursor = cursorRef.current;
|
|
34969
|
+
if (key.ctrl && input === "c") {
|
|
34970
|
+
const repeated = ctrlCArmedRef.current;
|
|
34971
|
+
const action = ctrlCAction(ctrlCArmedRef.current, { interrupt, busy, preparingImages, active: active && deleteConfirm === void 0, hasDraft: liveValue !== "" });
|
|
34972
|
+
ctrlCArmedRef.current = action !== "quit";
|
|
34973
|
+
if (action === "quit") quit(repeated);
|
|
34974
|
+
else if (action === "cancel-prepare") cancelImageSubmission();
|
|
34975
|
+
else if (action === "wait" && deleteConfirm !== void 0) cancelDelete();
|
|
34976
|
+
else if (action === "clear-draft") {
|
|
34977
|
+
pendingPastesRef.current.clear();
|
|
34978
|
+
valueRef.current = ""; cursorRef.current = 0;
|
|
34979
|
+
setValue(""); setCursor(0); resetCursorBlink();
|
|
34980
|
+
draftImagesRef.current = []; setDraftImages([]);
|
|
34981
|
+
draftFilesRef.current = []; setDraftFiles([]);
|
|
34982
|
+
setCompletionIndex(0); setDismissedMenuValue(void 0);
|
|
34983
|
+
}
|
|
34984
|
+
return;
|
|
34985
|
+
}
|
|
34986
|
+
ctrlCArmedRef.current = false;
|
|
34987
|
+
if (key.pageUp || key.pageDown) { onTranscriptScroll?.(key.pageUp ? 1 : -1, true); return; }
|
|
34988
|
+
if (preparingImages) {
|
|
34650
34989
|
if (key.escape || key.ctrl && input === "c") cancelImageSubmission();
|
|
34651
34990
|
return;
|
|
34652
34991
|
}
|
|
@@ -34669,27 +35008,16 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34669
35008
|
toggleReasoning();
|
|
34670
35009
|
return;
|
|
34671
35010
|
}
|
|
35011
|
+
if ((key.ctrl || key.meta) && input === "v") {
|
|
35012
|
+
const atValue = liveValue, atCursor = liveCursor;
|
|
35013
|
+
notify("reading clipboard image…");
|
|
35014
|
+
readClipboardImage().then(path => insertDroppedAttachments([path], [], atValue, atCursor), reason => notify(reason instanceof Error ? reason.message : String(reason), "warning"));
|
|
35015
|
+
return;
|
|
35016
|
+
}
|
|
34672
35017
|
if (key.ctrl && input === "o") {
|
|
34673
35018
|
openVerbose();
|
|
34674
35019
|
return;
|
|
34675
35020
|
}
|
|
34676
|
-
if (key.ctrl && input === "c") {
|
|
34677
|
-
if (busy) interrupt();
|
|
34678
|
-
else if (liveValue !== "") {
|
|
34679
|
-
valueRef.current = "";
|
|
34680
|
-
cursorRef.current = 0;
|
|
34681
|
-
setValue("");
|
|
34682
|
-
setCursor(0);
|
|
34683
|
-
resetCursorBlink();
|
|
34684
|
-
draftImagesRef.current = [];
|
|
34685
|
-
setDraftImages([]);
|
|
34686
|
-
draftFilesRef.current = [];
|
|
34687
|
-
setDraftFiles([]);
|
|
34688
|
-
setCompletionIndex(0);
|
|
34689
|
-
setDismissedMenuValue(void 0);
|
|
34690
|
-
} else quit();
|
|
34691
|
-
return;
|
|
34692
|
-
}
|
|
34693
35021
|
if (key.ctrl && input === "d") {
|
|
34694
35022
|
if (liveValue !== "") {
|
|
34695
35023
|
applyEdit(deleteForward(liveValue, liveCursor));
|
|
@@ -34732,8 +35060,16 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34732
35060
|
return;
|
|
34733
35061
|
}
|
|
34734
35062
|
}
|
|
34735
|
-
const
|
|
34736
|
-
|
|
35063
|
+
const expandedValue = expandLargePastes(liveValue, pendingPastesRef.current);
|
|
35064
|
+
const trimmed = expandedValue.trim();
|
|
35065
|
+
const text = submissionPayload(expandedValue);
|
|
35066
|
+
if (/^\/email(?:\s|$)/.test(trimmed)) {
|
|
35067
|
+
if (trimmed !== "/email") { notify("Use /email to open the inbox.", "warning"); return; }
|
|
35068
|
+
valueRef.current = ""; cursorRef.current = 0;
|
|
35069
|
+
setValue(""); setCursor(0); setCompletionIndex(0); setDismissedMenuValue(void 0);
|
|
35070
|
+
recall.current = beginRecall(recallSpace, "");
|
|
35071
|
+
openEmail(); return;
|
|
35072
|
+
}
|
|
34737
35073
|
if (/^\/login(?:\s|$)/.test(trimmed)) {
|
|
34738
35074
|
valueRef.current = ""; cursorRef.current = 0;
|
|
34739
35075
|
setValue(""); setCursor(0); setCompletionIndex(0); setDismissedMenuValue(void 0);
|
|
@@ -34758,6 +35094,7 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34758
35094
|
if (controller.signal.aborted || prepareEpochRef.current !== epoch) return;
|
|
34759
35095
|
prepareAbortRef.current = void 0;
|
|
34760
35096
|
setPreparingImages(false);
|
|
35097
|
+
pendingPastesRef.current.clear();
|
|
34761
35098
|
valueRef.current = "";
|
|
34762
35099
|
cursorRef.current = 0;
|
|
34763
35100
|
setValue("");
|
|
@@ -34785,6 +35122,7 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34785
35122
|
});
|
|
34786
35123
|
return;
|
|
34787
35124
|
}
|
|
35125
|
+
pendingPastesRef.current.clear();
|
|
34788
35126
|
valueRef.current = "";
|
|
34789
35127
|
cursorRef.current = 0;
|
|
34790
35128
|
setValue("");
|
|
@@ -34831,7 +35169,8 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
34831
35169
|
return;
|
|
34832
35170
|
}
|
|
34833
35171
|
if (text === "/review" || text.startsWith("/review ")) {
|
|
34834
|
-
|
|
35172
|
+
// dscode-review-command-v1
|
|
35173
|
+
dispatch(text);
|
|
34835
35174
|
return;
|
|
34836
35175
|
}
|
|
34837
35176
|
if (text === "/model" || text.startsWith("/model ")) {
|
|
@@ -35028,12 +35367,12 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
35028
35367
|
clearTimeout(timer);
|
|
35029
35368
|
pasteBracketCancelRef.current = void 0;
|
|
35030
35369
|
};
|
|
35031
|
-
text = text.replaceAll(PASTE_START_MARKER, "");
|
|
35370
|
+
text = text.replaceAll(`\x1b${PASTE_START_MARKER}`, "").replaceAll(PASTE_START_MARKER, "");
|
|
35032
35371
|
}
|
|
35033
35372
|
if (text.includes("[201~")) {
|
|
35034
35373
|
pasteBracketRef.current = false;
|
|
35035
35374
|
pasteBracketCancelRef.current?.();
|
|
35036
|
-
text = text.replaceAll(PASTE_END_MARKER, "");
|
|
35375
|
+
text = text.replaceAll(`\x1b${PASTE_END_MARKER}`, "").replaceAll(PASTE_END_MARKER, "");
|
|
35037
35376
|
}
|
|
35038
35377
|
if (text === "") return;
|
|
35039
35378
|
if (text.length > 1) {
|
|
@@ -35043,9 +35382,9 @@ function Input({ effortSurface, ultraPulse, active, frozen, busy, descriptors, s
|
|
|
35043
35382
|
return;
|
|
35044
35383
|
}
|
|
35045
35384
|
}
|
|
35046
|
-
applyEdit(insertText(valueRef.current, cursorRef.current, text));
|
|
35385
|
+
applyEdit(insertText(valueRef.current, cursorRef.current, collapseLargePaste(text, valueRef.current, pendingPastesRef.current)));
|
|
35047
35386
|
}
|
|
35048
|
-
},
|
|
35387
|
+
}, true);
|
|
35049
35388
|
const waveKey = waveTier !== null && waveStyle !== null ? `${waveTier}:${waveStyle}` : null;
|
|
35050
35389
|
const [wavePlayedKey, setWavePlayedKey] = (0, import_react.useState)(null);
|
|
35051
35390
|
(0, import_react.useEffect)(() => {
|
|
@@ -35317,6 +35656,18 @@ function computeSettledRows(previous, entries, settled, showReasoning, resumed,
|
|
|
35317
35656
|
}
|
|
35318
35657
|
/** The whole terminal app; state arrives via the store, output via Ink. */
|
|
35319
35658
|
function App(props) {
|
|
35659
|
+
const gmail = (0, import_react.useMemo)(() => dscodeCreateGmailConnector(), []);
|
|
35660
|
+
const imap = (0, import_react.useMemo)(() => dscodeCreateImapConnector(), []);
|
|
35661
|
+
(0, import_react.useEffect)(() => {
|
|
35662
|
+
const controller = new AbortController();
|
|
35663
|
+
const sync = () => (imap.status().connected ? imap : gmail).sync({ signal: controller.signal }).catch(() => {});
|
|
35664
|
+
sync(); const timer = setInterval(sync, 30000);
|
|
35665
|
+
return () => { clearInterval(timer); controller.abort(); };
|
|
35666
|
+
}, [gmail, imap]);
|
|
35667
|
+
const [emailOpen, setEmailOpen] = (0, import_react.useState)(false);
|
|
35668
|
+
const [emailFill, setEmailFill] = (0, import_react.useState)(void 0);
|
|
35669
|
+
const emailConsumed = (0, import_react.useCallback)(() => setEmailFill(void 0), []);
|
|
35670
|
+
(0, import_react.useEffect)(() => { setEmailOpen(false); setEmailFill(void 0); }, [props.sessionKey]);
|
|
35320
35671
|
const view = (0, import_react.useSyncExternalStore)(props.store.subscribe, props.store.getView);
|
|
35321
35672
|
useStableInput(() => {}, true);
|
|
35322
35673
|
const readDescriptors = (0, import_react.useCallback)(() => props.commands.descriptors, [props.commands]);
|
|
@@ -35554,9 +35905,10 @@ function App(props) {
|
|
|
35554
35905
|
const agentRows = (0, import_react.useSyncExternalStore)(props.subagents.subscribe, props.subagents.getSnapshot);
|
|
35555
35906
|
const approvalPending = approvalSnapshot.pending !== void 0;
|
|
35556
35907
|
const questionPending = questionSnapshot.pending !== void 0;
|
|
35557
|
-
const inputActive = deleteConfirmId !== void 0 ? !approvalPending && !questionPending : !modelOpen && !helpOpen && !modeOpen && !permissionOpen && !resumeOpen && !pluginOpen && !jobsOpen && !statuslineOpen && !themeOpen && !historyOpen && !agentsOpen && !subagentOpen && !todosOpen && !verboseOpen && diffView === void 0 && !approvalPending && !questionPending;
|
|
35908
|
+
const inputActive = deleteConfirmId !== void 0 ? !approvalPending && !questionPending : !emailOpen && !modelOpen && !helpOpen && !modeOpen && !permissionOpen && !resumeOpen && !pluginOpen && !jobsOpen && !statuslineOpen && !themeOpen && !historyOpen && !agentsOpen && !subagentOpen && !todosOpen && !verboseOpen && diffView === void 0 && !approvalPending && !questionPending;
|
|
35558
35909
|
(0, import_react.useEffect)(() => {
|
|
35559
35910
|
if (!approvalPending && !questionPending) return;
|
|
35911
|
+
setEmailOpen(false);
|
|
35560
35912
|
setModelOpen(false);
|
|
35561
35913
|
setProviderOpen(false);
|
|
35562
35914
|
setProviderAction(void 0);
|
|
@@ -35619,21 +35971,48 @@ function App(props) {
|
|
|
35619
35971
|
setMenuRows((current) => current === rows ? current : rows);
|
|
35620
35972
|
}, []);
|
|
35621
35973
|
const composerEditorCap = composerMaxRows(terminalRows);
|
|
35622
|
-
const transcriptVisible = !modelOpen && !helpOpen && !modeOpen && !permissionOpen && !resumeOpen && !pluginOpen && !jobsOpen && !statuslineOpen && !themeOpen && !historyOpen && !agentsOpen && !subagentOpen && !todosOpen && !verboseOpen && diffView === void 0 && !approvalPending && !questionPending;
|
|
35974
|
+
const transcriptVisible = !emailOpen && !modelOpen && !helpOpen && !modeOpen && !permissionOpen && !resumeOpen && !pluginOpen && !jobsOpen && !statuslineOpen && !themeOpen && !historyOpen && !agentsOpen && !subagentOpen && !todosOpen && !verboseOpen && diffView === void 0 && !approvalPending && !questionPending;
|
|
35623
35975
|
const welcomeFull = terminalRows >= 24 && terminalColumns >= 64;
|
|
35624
|
-
const
|
|
35625
|
-
|
|
35626
|
-
const
|
|
35627
|
-
const
|
|
35976
|
+
const welcomeMaxRows = welcomeFull ? 13 : terminalRows >= 10 ? 4 : 1;
|
|
35977
|
+
// The nine fixed rows belong to the composer, footer and their gutters.
|
|
35978
|
+
const transcriptCapacity = transcriptVisible ? Math.max(0, terminalRows - 9 - composerGutterRows - (composerRows - 1) - menuRows) : 0;
|
|
35979
|
+
const streamingActive = view.streaming !== "";
|
|
35980
|
+
const deepDivingVisible = busy;
|
|
35981
|
+
const allLiveLines = (0, import_react.useMemo)(() => view.entries.slice(settled).flatMap((entry) => dscodeChatLines(entry, Math.max(1, terminalColumns - 2))), [
|
|
35982
|
+
view.entries,
|
|
35983
|
+
settled,
|
|
35984
|
+
terminalColumns,
|
|
35985
|
+
showReasoning
|
|
35986
|
+
]);
|
|
35987
|
+
const allSettledLines = (0, import_react.useMemo)(() => visibleSettledLines(view.entries, settled, Infinity, terminalColumns, showReasoning, settledEntryLines), [settled, view.entries[settled - 1], terminalColumns, showReasoning]);
|
|
35988
|
+
const settledTail = allSettledLines.slice(-transcriptCapacity);
|
|
35989
|
+
const streamingDemand = streamingActive ? textLines(view.streaming.slice(-Math.max(1, terminalColumns * transcriptCapacity)), Math.max(10, terminalColumns - 2)).length : 0;
|
|
35990
|
+
const demand = settledTail.length + allLiveLines.length + streamingDemand + (busy ? 1 : 0) + (agentRows.length > 0 ? 1 : 0);
|
|
35991
|
+
const welcomeRows = welcomeVisibleRows(transcriptCapacity, welcomeMaxRows, demand, transcriptVisible);
|
|
35992
|
+
const settledBudget = transcriptVisible ? Math.max(0, transcriptCapacity - welcomeRows) : 0;
|
|
35993
|
+
const settledViewportRows = busy || streamingActive ? Math.floor(settledBudget / 3) : settledBudget;
|
|
35994
|
+
const [scrollOffset, setScrollOffset] = (0, import_react.useState)(0);
|
|
35995
|
+
const previousHistory = (0, import_react.useRef)({ sessionKey: props.sessionKey, count: allSettledLines.length });
|
|
35996
|
+
const sameHistory = previousHistory.current.sessionKey === props.sessionKey;
|
|
35997
|
+
const growth = sameHistory ? Math.max(0, allSettledLines.length - previousHistory.current.count) : 0;
|
|
35998
|
+
const maxScrollOffset = Math.max(0, allSettledLines.length - settledViewportRows);
|
|
35999
|
+
const effectiveScrollOffset = sameHistory ? Math.min(maxScrollOffset, scrollOffset === 0 ? 0 : scrollOffset + growth) : 0;
|
|
36000
|
+
(0, import_react.useEffect)(() => {
|
|
36001
|
+
previousHistory.current = { sessionKey: props.sessionKey, count: allSettledLines.length };
|
|
36002
|
+
if (scrollOffset !== effectiveScrollOffset) setScrollOffset(effectiveScrollOffset);
|
|
36003
|
+
}, [props.sessionKey, allSettledLines.length, effectiveScrollOffset]);
|
|
36004
|
+
const scrollTranscript = (direction, page = false) => {
|
|
36005
|
+
if (!transcriptVisible || settledViewportRows <= 0) return;
|
|
36006
|
+
const step = page ? Math.max(1, settledViewportRows - 1) : 3;
|
|
36007
|
+
setScrollOffset(current => Math.max(0, Math.min(maxScrollOffset, (current === scrollOffset ? effectiveScrollOffset : current) + direction * step)));
|
|
36008
|
+
};
|
|
36009
|
+
(0, import_react.useEffect)(() => {
|
|
36010
|
+
const listener = direction => scrollTranscript(direction);
|
|
36011
|
+
dscodeWheelListeners.add(listener);
|
|
36012
|
+
return () => dscodeWheelListeners.delete(listener);
|
|
36013
|
+
});
|
|
36014
|
+
const renderedSettled = transcriptWindow(allSettledLines, settledViewportRows, effectiveScrollOffset);
|
|
35628
36015
|
const dynamicRows = Math.max(0, settledBudget - settledViewportRows);
|
|
35629
|
-
const streamingActive = view.streaming !== "";
|
|
35630
|
-
const deepDivingVisible = busy;
|
|
35631
|
-
const allLiveLines = (0, import_react.useMemo)(() => view.entries.slice(settled).flatMap((entry) => dscodeChatLines(entry, Math.max(1, terminalColumns - 2))), [
|
|
35632
|
-
view.entries,
|
|
35633
|
-
settled,
|
|
35634
|
-
terminalColumns,
|
|
35635
|
-
showReasoning
|
|
35636
|
-
]);
|
|
35637
36016
|
const liveBudget = dynamicRows === 0 ? 0 : busy || streamingActive ? Math.max(1, Math.floor(dynamicRows / 3)) : Math.max(0, dynamicRows - (deepDivingVisible ? 1 : 0));
|
|
35638
36017
|
const visibleLiveLines = liveBudget === 0 ? [] : allLiveLines.slice(-liveBudget);
|
|
35639
36018
|
const streamRows = Math.max(1, dynamicRows - visibleLiveLines.length);
|
|
@@ -35652,7 +36031,7 @@ function App(props) {
|
|
|
35652
36031
|
const auditedReasoningRows = liveAudit.allocation.reasoning;
|
|
35653
36032
|
const auditedAnswerRows = liveAudit.allocation.answer;
|
|
35654
36033
|
|
|
35655
|
-
const modalVisible = modelOpen || helpOpen || modeOpen || permissionOpen || resumeOpen || pluginOpen || jobsOpen || statuslineOpen || themeOpen || historyOpen || agentsOpen || subagentOpen || todosOpen || verboseOpen && !approvalPending && !questionPending || diffView !== void 0 || approvalPending || questionPending;
|
|
36034
|
+
const modalVisible = emailOpen || modelOpen || helpOpen || modeOpen || permissionOpen || resumeOpen || pluginOpen || jobsOpen || statuslineOpen || themeOpen || historyOpen || agentsOpen || subagentOpen || todosOpen || verboseOpen && !approvalPending && !questionPending || diffView !== void 0 || approvalPending || questionPending;
|
|
35656
36035
|
const closeInspector = (0, import_react.useCallback)(() => {
|
|
35657
36036
|
setVerboseOpen(false);
|
|
35658
36037
|
}, []);
|
|
@@ -35901,7 +36280,13 @@ function App(props) {
|
|
|
35901
36280
|
});
|
|
35902
36281
|
}
|
|
35903
36282
|
return (0, import_react.createElement)(Box, { flexDirection: "column", height: Math.max(1, terminalRows - 1) },
|
|
35904
|
-
|
|
36283
|
+
welcomeRows > 0 ? (0, import_react.createElement)(Box, { height: welcomeRows, overflowY: "hidden", flexDirection: "column", justifyContent: "flex-end", flexShrink: 0 },
|
|
36284
|
+
(0, import_react.createElement)(Box, { flexShrink: 0 }, !emailOpen && terminalRows >= 10 ? (0, import_react.createElement)(Header, { cwd: props.workspaceRoot ?? props.cwd, model: modelLabel, effort: effortLabel }) : (0, import_react.createElement)(Text, { color: inkColor(getPalette().brandBright), bold: true }, "DSCODE"))) : void 0,
|
|
36285
|
+
emailOpen && !approvalPending && !questionPending ? (0, import_react.createElement)(DscodeEmailPanel, {
|
|
36286
|
+
gmail, imap, columns: terminalColumns, rows: Math.max(3, terminalRows - 8 - composerGutterRows - composerRows),
|
|
36287
|
+
close: () => setEmailOpen(false),
|
|
36288
|
+
pick: mail => { props.steer(dscodeEmailPrompt(mail), [], props.sessionKey); setEmailOpen(false); }
|
|
36289
|
+
}) : void 0,
|
|
35905
36290
|
transcriptVisible && settledViewportRows > 0 ? (0, import_react.createElement)(StyledRows, { lines: renderedSettled }) : void 0,
|
|
35906
36291
|
transcriptVisible ? (0, import_react.createElement)(Box, { flexDirection: "column" }, auditedLiveLines.length === 0 ? void 0 : (0, import_react.createElement)(StyledRows, { lines: auditedLiveLines }), view.streamingReasoning !== "" && auditedReasoningRows > 0 ? showReasoning ? (0, import_react.createElement)(StreamTail, {
|
|
35907
36292
|
text: view.streamingReasoning,
|
|
@@ -36067,7 +36452,9 @@ function App(props) {
|
|
|
36067
36452
|
steer: props.steer,
|
|
36068
36453
|
interrupt: props.interrupt,
|
|
36069
36454
|
quit: props.quit,
|
|
36070
|
-
|
|
36455
|
+
openEmail: () => setEmailOpen(true),
|
|
36456
|
+
emailFill, emailConsumed,
|
|
36457
|
+
openLogin: () => {
|
|
36071
36458
|
setProviderOpen(false); setEffortFor(void 0);
|
|
36072
36459
|
setProviderAction({ kind: "dscode-key" }); setModelOpen(true);
|
|
36073
36460
|
},
|
|
@@ -36187,7 +36574,8 @@ function App(props) {
|
|
|
36187
36574
|
waveStyle,
|
|
36188
36575
|
maxRows: composerEditorCap,
|
|
36189
36576
|
onEditorRows: handleEditorRows,
|
|
36190
|
-
onMenuRows: handleMenuRows
|
|
36577
|
+
onMenuRows: handleMenuRows,
|
|
36578
|
+
onTranscriptScroll: scrollTranscript
|
|
36191
36579
|
}), (0, import_react.createElement)(StatusLine, {
|
|
36192
36580
|
facts: {
|
|
36193
36581
|
fullSessionId: props.sessionKey,
|
|
@@ -36420,7 +36808,7 @@ function createSplitStdin(source) {
|
|
|
36420
36808
|
stalePasteTimer.unref?.();
|
|
36421
36809
|
};
|
|
36422
36810
|
const onChunk = (chunk) => {
|
|
36423
|
-
for (const unit of splitter.push(String(chunk))) stream.write(unit);
|
|
36811
|
+
for (const unit of splitter.push(String(chunk))) if (!dscodeHandleMouseUnit(unit)) stream.write(unit);
|
|
36424
36812
|
if (splitter.openPaste()) armStalePasteTimer();
|
|
36425
36813
|
else disarmStalePasteTimer();
|
|
36426
36814
|
};
|
|
@@ -36465,7 +36853,7 @@ const internals = {
|
|
|
36465
36853
|
if (process.stdin.isTTY === true) process.stdin.setRawMode?.(true);
|
|
36466
36854
|
try {
|
|
36467
36855
|
if (process.stdout.isTTY === true) process.stdout.write("\x1B[r\x1B[0m\x1B[H\x1B[2J\x1B[3J\x1B[H");
|
|
36468
|
-
process.stdout.write((keyboardEnhanced ? KEYBOARD_ENHANCE_ENABLE : "") + BRACKETED_PASTE_ENABLE + (focusReporting ? TERMINAL_FOCUS_REPORT_ENABLE : ""));
|
|
36856
|
+
process.stdout.write((keyboardEnhanced ? KEYBOARD_ENHANCE_ENABLE : "") + BRACKETED_PASTE_ENABLE + (focusReporting ? TERMINAL_FOCUS_REPORT_ENABLE : "") + (process.stdout.isTTY === true ? DSCODE_MOUSE_ENABLE : ""));
|
|
36469
36857
|
const tuiStdin = createSplitStdin(process.stdin);
|
|
36470
36858
|
const instance = render(element, {
|
|
36471
36859
|
exitOnCtrlC: false,
|
|
@@ -36478,7 +36866,7 @@ const internals = {
|
|
|
36478
36866
|
},
|
|
36479
36867
|
unmount() {
|
|
36480
36868
|
try {
|
|
36481
|
-
process.stdout.write((keyboardEnhanced ? KEYBOARD_ENHANCE_DISABLE : "") + BRACKETED_PASTE_DISABLE + (focusReporting ? TERMINAL_FOCUS_REPORT_DISABLE : ""));
|
|
36869
|
+
process.stdout.write((keyboardEnhanced ? KEYBOARD_ENHANCE_DISABLE : "") + BRACKETED_PASTE_DISABLE + (focusReporting ? TERMINAL_FOCUS_REPORT_DISABLE : "") + (process.stdout.isTTY === true ? DSCODE_MOUSE_DISABLE : ""));
|
|
36482
36870
|
} finally {
|
|
36483
36871
|
try {
|
|
36484
36872
|
instance.unmount();
|
|
@@ -36490,6 +36878,7 @@ const internals = {
|
|
|
36490
36878
|
}
|
|
36491
36879
|
};
|
|
36492
36880
|
} catch (error) {
|
|
36881
|
+
if (process.stdout.isTTY === true) process.stdout.write(DSCODE_MOUSE_DISABLE);
|
|
36493
36882
|
if (process.stdin.isTTY === true) process.stdin.setRawMode?.(false);
|
|
36494
36883
|
throw error;
|
|
36495
36884
|
}
|
|
@@ -38556,7 +38945,7 @@ async function run(ctx, startup, io) {
|
|
|
38556
38945
|
};
|
|
38557
38946
|
const mountRef = {};
|
|
38558
38947
|
let quitting = false;
|
|
38559
|
-
const quit = () => {
|
|
38948
|
+
const quit = (fast = false) => {
|
|
38560
38949
|
if (quitting) return;
|
|
38561
38950
|
quitting = true;
|
|
38562
38951
|
switchQueue.cancel();
|
|
@@ -38576,6 +38965,7 @@ async function run(ctx, startup, io) {
|
|
|
38576
38965
|
} catch (error) {
|
|
38577
38966
|
report("unmount", error);
|
|
38578
38967
|
}
|
|
38968
|
+
if (fast) setTimeout(() => process.exit(0), 250);
|
|
38579
38969
|
runQuitSequence([
|
|
38580
38970
|
...currentSession === void 0 || currentActive === void 0 ? [] : [{
|
|
38581
38971
|
name: "flush",
|
|
@@ -39283,6 +39673,7 @@ async function run(ctx, startup, io) {
|
|
|
39283
39673
|
openAuthorizationUrl,
|
|
39284
39674
|
copyTextValue: copyText,
|
|
39285
39675
|
loadMentions: (query, signal) => mentions.candidates(query, signal),
|
|
39676
|
+
readClipboardImage: dscodeReadClipboardImage,
|
|
39286
39677
|
inspectImages: (paths) => inspectImagePaths(paths, ctx.get("attachments"), session?.header.cwd ?? cwd),
|
|
39287
39678
|
prepareImages: (paths, signal) => saveImagePaths(paths, ctx.get("attachments"), signal),
|
|
39288
39679
|
inspectFiles: (paths) => inspectFilePaths(paths, ctx.get("attachments"), session?.header.cwd ?? cwd),
|