@antst/dashi 0.1.0-alpha.17 → 0.1.0-alpha.19

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 (55) hide show
  1. package/README.md +6 -6
  2. package/package.json +38 -39
  3. package/lib/application.d.ts +0 -45
  4. package/lib/application.js +0 -273
  5. package/lib/at-trigger.d.ts +0 -8
  6. package/lib/at-trigger.js +0 -13
  7. package/lib/catalogs.d.ts +0 -28
  8. package/lib/catalogs.js +0 -308
  9. package/lib/clipboard-image.d.ts +0 -3
  10. package/lib/clipboard-image.js +0 -74
  11. package/lib/completion-trigger.d.ts +0 -6
  12. package/lib/completion-trigger.js +0 -19
  13. package/lib/diff-view.d.ts +0 -5
  14. package/lib/diff-view.js +0 -24
  15. package/lib/external-editor.d.ts +0 -3
  16. package/lib/external-editor.js +0 -39
  17. package/lib/help.d.ts +0 -2
  18. package/lib/help.js +0 -6
  19. package/lib/history-records.d.ts +0 -4
  20. package/lib/history-records.js +0 -14
  21. package/lib/image-input.d.ts +0 -8
  22. package/lib/image-input.js +0 -37
  23. package/lib/index.d.ts +0 -4
  24. package/lib/index.js +0 -329
  25. package/lib/input.d.ts +0 -17
  26. package/lib/input.js +0 -267
  27. package/lib/memory.d.ts +0 -3
  28. package/lib/memory.js +0 -27
  29. package/lib/mouse-input.d.ts +0 -1
  30. package/lib/mouse-input.js +0 -6
  31. package/lib/presentation.d.ts +0 -9
  32. package/lib/presentation.js +0 -54
  33. package/lib/renderer.d.ts +0 -21
  34. package/lib/renderer.js +0 -491
  35. package/lib/rewind.d.ts +0 -26
  36. package/lib/rewind.js +0 -107
  37. package/lib/session-export.d.ts +0 -3
  38. package/lib/session-export.js +0 -27
  39. package/lib/session-list.d.ts +0 -15
  40. package/lib/session-list.js +0 -65
  41. package/lib/session-runtime.d.ts +0 -49
  42. package/lib/session-runtime.js +0 -1455
  43. package/lib/shell-command.d.ts +0 -10
  44. package/lib/shell-command.js +0 -66
  45. package/lib/state.d.ts +0 -517
  46. package/lib/state.js +0 -678
  47. package/lib/terminal-guard.d.ts +0 -14
  48. package/lib/terminal-guard.js +0 -76
  49. package/lib/tool-presentation.d.ts +0 -14
  50. package/lib/tool-presentation.js +0 -156
  51. package/lib/transcript.d.ts +0 -12
  52. package/lib/transcript.js +0 -323
  53. package/lib/tui-root.d.ts +0 -20
  54. package/lib/tui-root.js +0 -25
  55. package/validated-dsh-versions.json +0 -3
package/lib/index.js DELETED
@@ -1,329 +0,0 @@
1
- import { readFileSync, realpathSync } from 'node:fs';
2
- import { createRequire } from 'node:module';
3
- import { dirname, resolve } from 'node:path';
4
- import { exitOnStdinEnd } from '@deepseek-ai/dsh-cmdline';
5
- import { createTerminalShell } from './application.js';
6
- import { sessionOverlay } from './catalogs.js';
7
- import { readClipboardImage } from './clipboard-image.js';
8
- import { editDraftExternally } from './external-editor.js';
9
- import { FLAG_HELP, VERSION_LINE } from './help.js';
10
- import { formatSessionList, isSessionId, parseSessionListArgs, sessionMatches, sessionNotFound, } from './session-list.js';
11
- import { createSessionRuntime, LaunchArgumentError, } from './session-runtime.js';
12
- import { TuiRoot } from './tui-root.js';
13
- export const name = 'dashi';
14
- export const inject = [
15
- 'agentPresets', 'agents', 'attachments', 'authorization', 'cmdlineArgs', 'commands', 'credentials', 'fs', 'jobs', 'loader', 'permissionPresets', 'subagents',
16
- 'pluginInventory', 'sessionController', 'sandboxPolicy', 'sessionProjections', 'sessionQuery', 'sessions', 'settings', 'shell', 'skills', 'systemPrompt', 'tools',
17
- ];
18
- const validatedVersions = JSON.parse(readFileSync(new URL('../validated-dsh-versions.json', import.meta.url), 'utf8'));
19
- function parseArgs(args) {
20
- let accessible = false;
21
- let argumentError;
22
- let agentPreset, sessionId;
23
- let forkSession = false;
24
- let inline = true;
25
- let name;
26
- let effort;
27
- let model;
28
- let permission;
29
- let provider;
30
- let tools;
31
- let disallowedTools;
32
- let resume;
33
- let resumeAll = false;
34
- let resumePicker = false;
35
- let systemPrompt, appendSystemPrompt;
36
- let useContinue = false;
37
- let verbose = false;
38
- const images = [];
39
- const prompt = [];
40
- for (let index = 0; index < args.length; index++) {
41
- const argument = args[index];
42
- if (argument === '--accessible')
43
- accessible = true;
44
- else if (argument === '--inline')
45
- inline = true;
46
- else if (argument === '--fullscreen')
47
- inline = false;
48
- else if (['--name', '-n', '--agent', '--image', '--effort', '--model', '--permission', '--provider', '--tools', '--disallowedTools',
49
- '--system-prompt', '--system-prompt-file', '--append-system-prompt', '--append-system-prompt-file',
50
- '--session-id'].includes(argument ?? '')) {
51
- const value = args[++index];
52
- if (value === undefined || value === '')
53
- return undefined;
54
- if (argument === '--name' || argument === '-n')
55
- name = value;
56
- else if (argument === '--agent')
57
- agentPreset = value;
58
- else if (argument === '--image')
59
- images.push(value);
60
- else if (argument === '--effort')
61
- effort = value;
62
- else if (argument === '--model')
63
- model = value;
64
- else if (argument === '--permission')
65
- permission = value;
66
- else if (argument === '--session-id')
67
- sessionId = value;
68
- else if (argument === '--tools' || argument === '--disallowedTools') {
69
- const names = value.split(',').map(name => name.trim());
70
- if (names.includes(''))
71
- return undefined;
72
- if (argument === '--tools')
73
- tools = names;
74
- else
75
- disallowedTools = names;
76
- }
77
- else if (argument?.includes('system-prompt') === true) {
78
- let text = value;
79
- if (argument.endsWith('-file')) {
80
- try {
81
- text = readFileSync(value, 'utf8');
82
- }
83
- catch (error) {
84
- argumentError = error instanceof Error ? error.message : String(error);
85
- }
86
- }
87
- if (argument.startsWith('--append'))
88
- appendSystemPrompt = text;
89
- else
90
- systemPrompt = text;
91
- }
92
- else
93
- provider = value;
94
- }
95
- else if (argument === '--resume' || argument === '-r') {
96
- const value = args[index + 1];
97
- if (value === '')
98
- return undefined;
99
- if (value === undefined || value.startsWith('-'))
100
- resumePicker = true;
101
- else
102
- resume = args[++index];
103
- }
104
- else if (argument === '--all')
105
- resumeAll = true;
106
- else if (argument === '--continue' || argument === '-c')
107
- useContinue = true;
108
- else if (argument === '--fork-session')
109
- forkSession = true;
110
- else if (argument === '--verbose')
111
- verbose = true;
112
- else if (argument === '--yolo' || argument === '--dangerously-skip-permissions') {
113
- permission = 'danger-full-access';
114
- }
115
- else if (argument?.startsWith('-') === true)
116
- return undefined;
117
- else if (argument !== undefined)
118
- prompt.push(argument);
119
- }
120
- if (resume !== undefined && (resumePicker || useContinue) || resumePicker && useContinue
121
- || name !== undefined && (resume !== undefined || resumePicker || useContinue)
122
- || resumeAll && resume === undefined && !resumePicker || resumeAll && useContinue
123
- || provider !== undefined && model === undefined
124
- || sessionId !== undefined && (!isSessionId(sessionId) || resume !== undefined || resumePicker || useContinue)
125
- || agentPreset !== undefined && (resume !== undefined || resumePicker || useContinue)
126
- || forkSession && resume === undefined && !resumePicker && !useContinue)
127
- return undefined;
128
- return {
129
- accessible,
130
- ...(argumentError === undefined ? {} : { argumentError }),
131
- ...(appendSystemPrompt === undefined ? {} : { appendSystemPrompt }),
132
- continue: useContinue,
133
- ...(agentPreset === undefined ? {} : { agentPreset }), forkSession, inline,
134
- resumeAll,
135
- resumePicker,
136
- ...(images.length === 0 ? {} : { images }),
137
- ...(effort === undefined ? {} : { effort }),
138
- ...(model === undefined ? {} : { model }),
139
- ...(name === undefined ? {} : { name }),
140
- ...(permission === undefined ? {} : { permission }),
141
- ...(prompt.length === 0 ? {} : { prompt: prompt.join(' ') }),
142
- ...(provider === undefined ? {} : { provider }),
143
- ...(tools === undefined ? {} : { tools }),
144
- ...(disallowedTools === undefined ? {} : { disallowedTools }),
145
- ...(resume === undefined ? {} : { resume }), ...(sessionId === undefined ? {} : { sessionId }),
146
- ...(systemPrompt === undefined ? {} : { systemPrompt }), verbose,
147
- };
148
- }
149
- function packageVersion(path) {
150
- const manifest = JSON.parse(readFileSync(path, 'utf8'));
151
- return typeof manifest.version === 'string' ? manifest.version : 'unknown';
152
- }
153
- function runningDshVersions() {
154
- try {
155
- const entry = realpathSync(process.argv[1] ?? '');
156
- const manifest = resolve(dirname(entry), '../package.json');
157
- const version = packageVersion(manifest);
158
- try {
159
- return [version, packageVersion(createRequire(manifest).resolve('@deepseek-ai/dsh-base/package.json'))];
160
- }
161
- catch {
162
- return [version, 'unknown'];
163
- }
164
- }
165
- catch {
166
- return ['unknown', 'unknown'];
167
- }
168
- }
169
- function warnDshVersion() {
170
- const [version, baseVersion] = runningDshVersions();
171
- if (baseVersion !== version) {
172
- process.stderr.write(`dashi: warning: DSH ${version} loads @deepseek-ai/dsh-base ${baseVersion}; versions must match\n`);
173
- }
174
- if (!validatedVersions.includes(version)) {
175
- process.stderr.write(`dashi: warning: DSH ${version} is not validated; validated: ${validatedVersions.join(', ')}\n`);
176
- }
177
- }
178
- function installSessionList(ctx, options, ready, exit) {
179
- const abort = new AbortController();
180
- let listing;
181
- const announce = ready.onReady(() => {
182
- warnDshVersion();
183
- listing = ctx.sessionController.list({}, abort.signal).then(({ items }) => {
184
- const cwd = options.all ? undefined : resolve(options.cwd ?? process.cwd());
185
- process.stdout.write(`${formatSessionList(items, cwd, options.json)}\n`);
186
- exit(0);
187
- }).catch((error) => {
188
- process.stderr.write(`dashi: sessions list failed: ${error instanceof Error ? error.message : String(error)}\n`);
189
- exit(1);
190
- });
191
- });
192
- ctx.effect(() => async () => {
193
- announce();
194
- abort.abort();
195
- await listing;
196
- }, 'dashi.sessions-list');
197
- }
198
- export function apply(ctx) {
199
- const exit = ctx.get('appExit');
200
- const ready = ctx.get('appReady');
201
- const cmdline = ctx.get('cmdlineArgs');
202
- if (exit === undefined || ready === undefined || cmdline === undefined) {
203
- throw new Error('dashi: the launcher must provide ctx.appExit, ctx.appReady, and ctx.cmdlineArgs');
204
- }
205
- const args = cmdline.get();
206
- if (args.length === 1 && (args[0] === '--help' || args[0] === '-h')) {
207
- process.stdout.write(`${VERSION_LINE}\n\nUsage: dashi [options] [prompt]\n\n${FLAG_HELP.join('\n')}\n`);
208
- exit(0);
209
- return;
210
- }
211
- if (args[0] === 'sessions') {
212
- const options = parseSessionListArgs(args);
213
- if (options === undefined) {
214
- process.stderr.write(`dashi: unsupported arguments: ${args.join(' ')}\n`);
215
- exit(2);
216
- return;
217
- }
218
- installSessionList(ctx, options, ready, exit);
219
- return;
220
- }
221
- const parsed = parseArgs(args);
222
- if (parsed === undefined) {
223
- process.stderr.write(`dashi: unsupported arguments: ${args.join(' ')}\n`);
224
- exit(2);
225
- return;
226
- }
227
- const tuiRoot = new TuiRoot(ctx);
228
- let shell;
229
- let runtime;
230
- let boot;
231
- const stdoutError = (error) => { void shell?.fail(error); };
232
- process.stdout.on('error', stdoutError);
233
- const changed = ctx.on('tui/root-changed', (_previous, current) => {
234
- if (current === undefined)
235
- shell?.dispatch({ type: 'root-cleared' });
236
- });
237
- const announce = ready.onReady(() => {
238
- warnDshVersion();
239
- boot = (async () => {
240
- if (parsed.argumentError !== undefined)
241
- throw new LaunchArgumentError(parsed.argumentError);
242
- const cwd = process.cwd();
243
- const makeRuntime = (options) => createSessionRuntime(ctx, options, tuiRoot, action => { shell?.dispatch(action); }, {
244
- cancel: id => { shell?.cancelDecision(id); },
245
- request: decision => shell?.requestDecision(decision)
246
- ?? Promise.reject(new Error('dashi terminal is not ready')),
247
- });
248
- const sendPrompt = () => {
249
- if (parsed.prompt !== undefined)
250
- shell?.dispatch({ type: 'composer-changed', text: parsed.prompt });
251
- if (parsed.prompt !== undefined)
252
- shell?.dispatch({ type: 'submit' });
253
- };
254
- let pickerItems = parsed.resumePicker
255
- ? (await ctx.sessionController.list({}, new AbortController().signal)).items : undefined;
256
- if (parsed.resume !== undefined && !isSessionId(parsed.resume)) {
257
- const matches = sessionMatches((await ctx.sessionController.list({}, new AbortController().signal)).items, parsed.resume, parsed.resumeAll ? undefined : cwd);
258
- const [match] = matches;
259
- if (match === undefined)
260
- throw sessionNotFound(parsed.resume);
261
- if (matches.length > 1)
262
- pickerItems = matches;
263
- else
264
- runtime = await makeRuntime({ ...parsed, cwd, resume: String(match.sessionId) });
265
- }
266
- else if (!parsed.resumePicker)
267
- runtime = await makeRuntime({ ...parsed, cwd });
268
- const initial = runtime;
269
- shell = createTerminalShell({
270
- accessible: parsed.accessible,
271
- activateOverlay: async (value) => {
272
- if (runtime !== undefined)
273
- return runtime.activate(value);
274
- if (value.kind !== 'resume')
275
- return;
276
- runtime = await makeRuntime({ ...parsed, continue: false, cwd, resume: value.sessionId });
277
- shell?.dispatch({ type: 'root-bound', cells: runtime.initialCells, hasMore: runtime.initialHasMore,
278
- prompts: runtime.initialPrompts, root: runtime.root });
279
- for (const attachment of runtime.initialAttachments)
280
- shell?.dispatch({ type: 'attachment-added', attachment });
281
- runtime.start();
282
- sendPrompt();
283
- },
284
- attach: path => runtime?.attach(path) ?? Promise.resolve(undefined),
285
- beforeExit: () => runtime?.shutdown() ?? Promise.resolve(),
286
- complete: (query, caret) => runtime?.complete(query, caret) ?? Promise.resolve([]),
287
- cwd,
288
- cyclePermission: () => runtime?.cyclePermission() ?? Promise.resolve(),
289
- exit,
290
- externalEdit: editDraftExternally,
291
- ...(initial === undefined ? {} : {
292
- initialAttachments: initial.initialAttachments, initialCells: initial.initialCells, initialHasMore: initial.initialHasMore,
293
- initialPrompts: initial.initialPrompts, initialRoot: initial.root,
294
- }),
295
- ...(parsed.verbose ? { initialToolMode: 'expanded' } : {}),
296
- inline: parsed.inline || parsed.accessible,
297
- interrupt: () => { runtime?.interrupt(); },
298
- loadHistory: rootId => runtime?.loadHistory(rootId) ?? Promise.resolve(),
299
- onReleased: () => { process.stdout.write(`${runtime?.summary ?? ''}\n`); },
300
- pasteImage: readClipboardImage,
301
- search: (query, rootId) => runtime?.search(query, rootId) ?? Promise.resolve(),
302
- statusLine: () => runtime?.statusLine,
303
- submit: (text, mode, attachments) => runtime?.submit(text, mode, attachments),
304
- });
305
- shell.start();
306
- if (pickerItems !== undefined) {
307
- shell.dispatch({ type: 'open-overlay', overlay: sessionOverlay(pickerItems, '', parsed.resumeAll ? undefined : cwd) });
308
- }
309
- else {
310
- runtime?.start();
311
- sendPrompt();
312
- }
313
- })().catch(async (error) => {
314
- process.stderr.write(`dashi: startup failed: ${error instanceof Error ? error.message : String(error)}\n`);
315
- await runtime?.shutdown();
316
- await shell?.dispose();
317
- exit(error instanceof LaunchArgumentError ? 2 : 1);
318
- });
319
- });
320
- ctx.effect(() => async () => {
321
- announce();
322
- changed();
323
- await boot;
324
- await runtime?.shutdown();
325
- await shell?.dispose();
326
- process.stdout.off('error', stdoutError);
327
- }, 'dashi.profile-boot');
328
- exitOnStdinEnd(ctx, 'dashi.stdin');
329
- }
package/lib/input.d.ts DELETED
@@ -1,17 +0,0 @@
1
- import { type TUI } from '@earendil-works/pi-tui';
2
- import { type ComposerCursor, type UiAction, type ViewState } from './state.js';
3
- export interface InputBindings {
4
- readonly dispatch: (action: UiAction) => void;
5
- readonly insertNewline?: () => void;
6
- readonly insertText?: (text: string) => void;
7
- readonly readComposerCursor?: () => ComposerCursor;
8
- readonly readState: () => ViewState;
9
- }
10
- export declare function droppedPaths(data: string, cwd: string, inspect?: (path: string) => {
11
- isDirectory(): boolean;
12
- }): {
13
- readonly images: readonly string[];
14
- readonly text: string;
15
- } | undefined;
16
- export declare function caretOffset(text: string, cursor: ComposerCursor): number;
17
- export declare function installInput(tui: TUI, bindings: InputBindings): () => void;
package/lib/input.js DELETED
@@ -1,267 +0,0 @@
1
- import { statSync } from 'node:fs';
2
- import { isAbsolute, relative, resolve, sep } from 'node:path';
3
- import { formatFileMention } from '@deepseek-ai/dsh-file-reference/grammar';
4
- import { isKeyRelease, matchesKey } from '@earendil-works/pi-tui';
5
- import { isImagePath } from './image-input.js';
6
- import { PAGE_CELLS } from './state.js';
7
- export function droppedPaths(data, cwd, inspect = statSync) {
8
- const [start, end] = ['\u001B[200~', '\u001B[201~'];
9
- if (!data.startsWith(start) || !data.endsWith(end))
10
- return undefined;
11
- const token = /(?:[^\s'\\]+|'[^']*'|\\[\s\S])+/gu;
12
- const source = data.slice(start.length, -end.length);
13
- const chunks = source.match(token) ?? [];
14
- if (chunks.length === 0 || source.replace(token, '').trim() !== '')
15
- return undefined;
16
- const paths = chunks.map(chunk => chunk.replace(/'([^']*)'|\\([\s\S])/gu, (_match, quoted, escaped) => quoted ?? escaped ?? ''));
17
- try {
18
- const entries = paths.map(value => {
19
- const absolute = resolve(cwd, value);
20
- const directory = inspect(absolute).isDirectory();
21
- if (!directory && isImagePath(absolute))
22
- return { absolute };
23
- const local = relative(resolve(cwd), absolute);
24
- const mention = formatFileMention({ kind: directory ? 'directory' : 'file', path: local !== '' && !isAbsolute(local) && local !== '..' && !local.startsWith(`..${sep}`) ? local : absolute }, false);
25
- if (mention === undefined)
26
- throw new Error('path cannot be mentioned');
27
- return { absolute, mention };
28
- });
29
- const mentions = entries.flatMap(entry => entry.mention === undefined ? [] : [entry.mention]);
30
- return { images: entries.flatMap(entry => entry.mention === undefined ? [entry.absolute] : []), text: mentions.length === 0 ? '' : `${mentions.join(' ')} ` };
31
- }
32
- catch {
33
- return undefined;
34
- }
35
- }
36
- export function caretOffset(text, cursor) {
37
- const lines = text.split('\n');
38
- let offset = 0;
39
- for (let line = 0; line < cursor.line; line++)
40
- offset += (lines[line]?.length ?? 0) + 1;
41
- return Math.min(text.length, offset + cursor.col);
42
- }
43
- export function installInput(tui, bindings) {
44
- return tui.addInputListener((data) => {
45
- if (data.includes('\u001B[200~')) {
46
- const state = bindings.readState();
47
- const decision = state.decisions[0];
48
- const question = decision?.kind === 'question' ? decision.questions[decision.index] : undefined;
49
- const customQuestion = question !== undefined && decision?.kind === 'question'
50
- && decision.cursor === question.options.length;
51
- const completion = state.overlay?.kind === 'list' && state.overlay.purpose === 'completion';
52
- const dropped = decision === undefined && state.overlay === undefined && state.search === undefined && droppedPaths(data, state.root?.cwd ?? state.cwd);
53
- if (dropped) {
54
- bindings.insertText?.(dropped.text);
55
- for (const path of dropped.images)
56
- bindings.dispatch({ type: 'attachment-path', path });
57
- return { consume: true };
58
- }
59
- return customQuestion || state.search !== undefined || completion
60
- || decision === undefined && state.overlay === undefined ? undefined : { consume: true };
61
- }
62
- if (isKeyRelease(data))
63
- return { consume: true };
64
- const state = bindings.readState();
65
- const ctrlC = matchesKey(data, 'ctrl+c');
66
- const ctrlD = matchesKey(data, 'ctrl+d');
67
- if ((state.rewindArmed && !matchesKey(data, 'escape')) || (state.exitArmed && !ctrlC && !ctrlD)) {
68
- bindings.dispatch({ type: 'disarm-exit' });
69
- }
70
- if (ctrlC) {
71
- bindings.dispatch({ type: 'ctrl-c' });
72
- return { consume: true };
73
- }
74
- const decision = bindings.readState().decisions[0];
75
- if (decision !== undefined) {
76
- const question = decision.kind === 'question' ? decision.questions[decision.index] : undefined;
77
- const custom = question !== undefined && decision.cursor === question.options.length;
78
- if (matchesKey(data, 'escape'))
79
- bindings.dispatch({ type: 'decision-cancel' });
80
- else if (matchesKey(data, 'up'))
81
- bindings.dispatch({ type: 'decision-move', offset: -1 });
82
- else if (matchesKey(data, 'down'))
83
- bindings.dispatch({ type: 'decision-move', offset: 1 });
84
- else if (matchesKey(data, 'enter'))
85
- bindings.dispatch({ type: 'decision-submit' });
86
- else if (custom)
87
- return undefined;
88
- else if (matchesKey(data, 'space'))
89
- bindings.dispatch({ type: 'decision-toggle' });
90
- else {
91
- for (let number = 1; number <= 9; number++) {
92
- if (!matchesKey(data, String(number)))
93
- continue;
94
- bindings.dispatch({ type: 'decision-number', number });
95
- break;
96
- }
97
- }
98
- return { consume: true };
99
- }
100
- if (matchesKey(data, 'f1')) {
101
- bindings.dispatch({ type: 'help' });
102
- return { consume: true };
103
- }
104
- const search = bindings.readState().search;
105
- if (search !== undefined) {
106
- if (matchesKey(data, 'escape'))
107
- bindings.dispatch({ type: 'search-close' });
108
- else if (matchesKey(data, 'enter') || matchesKey(data, 'down')) {
109
- bindings.dispatch({ type: 'search-move', offset: 1 });
110
- }
111
- else if (matchesKey(data, 'shift+enter') || matchesKey(data, 'up')) {
112
- bindings.dispatch({ type: 'search-move', offset: -1 });
113
- }
114
- else
115
- return undefined;
116
- return { consume: true };
117
- }
118
- if (matchesKey(data, 'ctrl+f')) {
119
- bindings.dispatch({ type: 'search-open', scope: 'transcript' });
120
- return { consume: true };
121
- }
122
- if (matchesKey(data, 'ctrl+b')) {
123
- bindings.dispatch({ type: 'open-details' });
124
- return { consume: true };
125
- }
126
- if (matchesKey(data, 'shift+tab')) {
127
- bindings.dispatch({ type: 'cycle-permission' });
128
- return { consume: true };
129
- }
130
- const overlay = bindings.readState().overlay;
131
- if (overlay !== undefined) {
132
- if (matchesKey(data, 'escape'))
133
- bindings.dispatch({ type: 'overlay-close' });
134
- else if (overlay.kind === 'history' && matchesKey(data, 'up'))
135
- bindings.dispatch({ type: 'history-move', offset: -1 });
136
- else if (overlay.kind === 'history' && matchesKey(data, 'down'))
137
- bindings.dispatch({ type: 'history-move', offset: 1 });
138
- else if (overlay.kind === 'history' && matchesKey(data, '/'))
139
- bindings.dispatch({ type: 'search-open', scope: 'history' });
140
- else if (overlay.kind === 'history' && matchesKey(data, 'y'))
141
- bindings.dispatch({ type: 'history-copy' });
142
- else if (overlay.kind === 'info' && matchesKey(data, 'pageUp'))
143
- bindings.dispatch({ type: 'overlay-move', offset: -PAGE_CELLS });
144
- else if (overlay.kind === 'info' && matchesKey(data, 'pageDown'))
145
- bindings.dispatch({ type: 'overlay-move', offset: PAGE_CELLS });
146
- else if (matchesKey(data, 'up'))
147
- bindings.dispatch({ type: 'overlay-move', offset: -1 });
148
- else if (matchesKey(data, 'down'))
149
- bindings.dispatch({ type: 'overlay-move', offset: 1 });
150
- else if (matchesKey(data, 'ctrl+o'))
151
- bindings.dispatch({ type: 'toggle-tool-mode' });
152
- else if (matchesKey(data, 'enter'))
153
- bindings.dispatch({ type: 'overlay-submit', execute: true });
154
- else if (matchesKey(data, 'tab'))
155
- bindings.dispatch({ type: 'overlay-submit' });
156
- else if (overlay.kind === 'list' && overlay.purpose === 'completion') {
157
- bindings.dispatch({ type: 'overlay-close' });
158
- return undefined;
159
- }
160
- else {
161
- for (let number = 1; number <= 9; number++) {
162
- if (!matchesKey(data, String(number)))
163
- continue;
164
- bindings.dispatch({ type: 'overlay-number', number });
165
- break;
166
- }
167
- }
168
- return { consume: true };
169
- }
170
- if (matchesKey(data, 'ctrl+v')) {
171
- bindings.dispatch({ type: 'clipboard-paste' });
172
- return { consume: true };
173
- }
174
- if (matchesKey(data, 'pageUp')) {
175
- bindings.dispatch(bindings.readState().inline
176
- ? { type: 'open-history' }
177
- : { type: 'scroll', direction: 'page-up' });
178
- return { consume: true };
179
- }
180
- if (matchesKey(data, 'pageDown')) {
181
- bindings.dispatch({ type: 'scroll', direction: 'page-down' });
182
- return { consume: true };
183
- }
184
- if (matchesKey(data, 'ctrl+home')) {
185
- bindings.dispatch(bindings.readState().inline
186
- ? { type: 'open-history' }
187
- : { type: 'scroll', direction: 'home' });
188
- return { consume: true };
189
- }
190
- if (matchesKey(data, 'ctrl+end')) {
191
- bindings.dispatch({ type: 'scroll', direction: 'end' });
192
- return { consume: true };
193
- }
194
- if (matchesKey(data, 'tab')) {
195
- const state = bindings.readState();
196
- const cursor = bindings.readComposerCursor?.() ?? { col: state.composer.length, line: 0 };
197
- bindings.dispatch({ type: 'request-completion', caret: caretOffset(state.composer, cursor) });
198
- return { consume: true };
199
- }
200
- if (matchesKey(data, 'ctrl+r')) {
201
- bindings.dispatch({ type: 'request-search' });
202
- return { consume: true };
203
- }
204
- if (matchesKey(data, 'up') && !bindings.readState().composer.includes('\n')) {
205
- bindings.dispatch({ type: 'recall-move', offset: -1 });
206
- return { consume: true };
207
- }
208
- if (matchesKey(data, 'down') && bindings.readState().recall !== undefined) {
209
- bindings.dispatch({ type: 'recall-move', offset: 1 });
210
- return { consume: true };
211
- }
212
- if (matchesKey(data, 'ctrl+o')) {
213
- bindings.dispatch({ type: 'toggle-tool-mode' });
214
- return { consume: true };
215
- }
216
- if (matchesKey(data, 'ctrl+t')) {
217
- bindings.dispatch({ type: 'toggle-send-mode' });
218
- return { consume: true };
219
- }
220
- if (matchesKey(data, 'ctrl+s')) {
221
- const state = bindings.readState();
222
- bindings.dispatch({
223
- type: 'stash-toggle', cursor: bindings.readComposerCursor?.() ?? { col: state.composer.length, line: 0 },
224
- });
225
- return { consume: true };
226
- }
227
- if (matchesKey(data, 'ctrl+g')) {
228
- bindings.dispatch({ type: 'external-edit' });
229
- return { consume: true };
230
- }
231
- if (matchesKey(data, 'backspace')) {
232
- const state = bindings.readState();
233
- if (state.composer === '' && state.attachments.length > 0) {
234
- bindings.dispatch({ type: 'attachment-remove', index: state.attachments.length - 1 });
235
- return { consume: true };
236
- }
237
- }
238
- if (data === '\n' || matchesKey(data, 'ctrl+j')
239
- || matchesKey(data, 'shift+enter') || matchesKey(data, 'alt+enter')) {
240
- bindings.insertNewline?.();
241
- return { consume: true };
242
- }
243
- if (matchesKey(data, 'enter')) {
244
- bindings.dispatch({ type: 'submit' });
245
- return { consume: true };
246
- }
247
- if (ctrlD && bindings.readState().composer === '') {
248
- bindings.dispatch({ type: 'ctrl-d' });
249
- return { consume: true };
250
- }
251
- if (matchesKey(data, 'ctrl+l')) {
252
- bindings.dispatch({ type: 'redraw' });
253
- return { consume: true };
254
- }
255
- if (matchesKey(data, 'ctrl+z')) {
256
- bindings.dispatch({ type: 'suspend' });
257
- return { consume: true };
258
- }
259
- if (matchesKey(data, 'escape')) {
260
- bindings.dispatch({ type: 'escape' });
261
- return { consume: true };
262
- }
263
- if (bindings.readState().exitArmed)
264
- bindings.dispatch({ type: 'disarm-exit' });
265
- return undefined;
266
- });
267
- }
package/lib/memory.d.ts DELETED
@@ -1,3 +0,0 @@
1
- import type { Agent } from '@deepseek-ai/dsh-agent';
2
- import type { Overlay } from './state.js';
3
- export declare function memoryOverlay(agent: Agent): Overlay;
package/lib/memory.js DELETED
@@ -1,27 +0,0 @@
1
- import { resolve } from 'node:path';
2
- import { resolveDshHome } from '@deepseek-ai/dsh-home-paths';
3
- export function memoryOverlay(agent) {
4
- const cwd = agent.session.header.cwd ?? process.cwd();
5
- let root = cwd;
6
- const active = new Map();
7
- for (const seq of agent.session.surface.nodes) {
8
- const event = agent.session.eventAt(seq);
9
- if (event?.type !== 'user/message' || event.data.source.kind !== 'agent-instructions')
10
- continue;
11
- const source = event.data.source, identity = source.baselineIdentity === undefined
12
- ? undefined : JSON.parse(source.baselineIdentity);
13
- if (typeof identity?.projectRoot === 'string')
14
- root = resolve(cwd, identity.projectRoot);
15
- for (const change of source.changes) {
16
- if (change.action === 'remove')
17
- active.delete(change.scope);
18
- else
19
- active.set(change.scope, { path: change.path, scope: change.scope.split('\0')[0] ?? change.scope });
20
- }
21
- }
22
- return { cursor: 0, kind: 'list', options: [...active.values()].map(item => {
23
- const homePath = /^(?:~\/\.dsh|\$DSH_HOME)\/(.*)$/u.exec(item.path)?.[1];
24
- return { detail: `scope ${item.scope}`, label: item.path,
25
- value: { kind: 'open-file', path: resolve(homePath === undefined ? root : resolveDshHome(), homePath ?? item.path) } };
26
- }), purpose: 'memory', title: 'Memory' };
27
- }
@@ -1 +0,0 @@
1
- export declare function filterWheelInput(data: string): -3 | 3 | string;
@@ -1,6 +0,0 @@
1
- export function filterWheelInput(data) {
2
- if (!data.startsWith('\u001B[<'))
3
- return data;
4
- const match = /^(64|65);\d+;\d+M$/u.exec(data.slice(3));
5
- return match?.[1] === '64' ? 3 : match?.[1] === '65' ? -3 : data;
6
- }
@@ -1,9 +0,0 @@
1
- import type { Context } from '@deepseek-ai/cordis';
2
- import type { SessionJob } from '@deepseek-ai/dsh-api-session-controller';
3
- import type { SessionId } from '@deepseek-ai/dsh-session';
4
- import type { JobView, SubagentView } from './state.js';
5
- /** Web-equivalent context occupancy; undefined until both DSH projection fields exist. */
6
- export declare function contextPercent(value: unknown): number | undefined;
7
- export declare function jobViews(jobs: readonly SessionJob[]): readonly JobView[];
8
- /** Read DSH's direct-child catalog and projection-backed summary facts. */
9
- export declare function subagentViews(ctx: Context, parentId: SessionId, signal: AbortSignal): Promise<readonly SubagentView[]>;