@agi-fans/dsh-tui 0.1.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/LICENSE +21 -0
- package/README.md +13 -0
- package/lib/autocomplete.d.ts +80 -0
- package/lib/autocomplete.js +320 -0
- package/lib/autocomplete.js.map +1 -0
- package/lib/box.d.ts +79 -0
- package/lib/box.js +276 -0
- package/lib/box.js.map +1 -0
- package/lib/clipboard.d.ts +19 -0
- package/lib/clipboard.js +77 -0
- package/lib/clipboard.js.map +1 -0
- package/lib/command-integrations.d.ts +10 -0
- package/lib/command-integrations.js +49 -0
- package/lib/command-integrations.js.map +1 -0
- package/lib/command-mode.d.ts +5 -0
- package/lib/command-mode.js +73 -0
- package/lib/command-mode.js.map +1 -0
- package/lib/command-model.d.ts +5 -0
- package/lib/command-model.js +87 -0
- package/lib/command-model.js.map +1 -0
- package/lib/command-output.d.ts +6 -0
- package/lib/command-output.js +33 -0
- package/lib/command-output.js.map +1 -0
- package/lib/command-queue.d.ts +5 -0
- package/lib/command-queue.js +62 -0
- package/lib/command-queue.js.map +1 -0
- package/lib/command-registration.d.ts +5 -0
- package/lib/command-registration.js +20 -0
- package/lib/command-registration.js.map +1 -0
- package/lib/command-session.d.ts +5 -0
- package/lib/command-session.js +153 -0
- package/lib/command-session.js.map +1 -0
- package/lib/command-transcript.d.ts +5 -0
- package/lib/command-transcript.js +85 -0
- package/lib/command-transcript.js.map +1 -0
- package/lib/copy-selector.d.ts +52 -0
- package/lib/copy-selector.js +136 -0
- package/lib/copy-selector.js.map +1 -0
- package/lib/copy-targets.d.ts +34 -0
- package/lib/copy-targets.js +170 -0
- package/lib/copy-targets.js.map +1 -0
- package/lib/definition.d.ts +171 -0
- package/lib/definition.js +14 -0
- package/lib/definition.js.map +1 -0
- package/lib/editor.d.ts +66 -0
- package/lib/editor.js +365 -0
- package/lib/editor.js.map +1 -0
- package/lib/event-views.d.ts +188 -0
- package/lib/event-views.js +678 -0
- package/lib/event-views.js.map +1 -0
- package/lib/external-editor.d.ts +2 -0
- package/lib/external-editor.js +31 -0
- package/lib/external-editor.js.map +1 -0
- package/lib/history-search.d.ts +61 -0
- package/lib/history-search.js +239 -0
- package/lib/history-search.js.map +1 -0
- package/lib/history-store.d.ts +8 -0
- package/lib/history-store.js +36 -0
- package/lib/history-store.js.map +1 -0
- package/lib/hotkeys.d.ts +14 -0
- package/lib/hotkeys.js +115 -0
- package/lib/hotkeys.js.map +1 -0
- package/lib/human-interaction.d.ts +5 -0
- package/lib/human-interaction.js +8 -0
- package/lib/human-interaction.js.map +1 -0
- package/lib/image-paste.d.ts +21 -0
- package/lib/image-paste.js +277 -0
- package/lib/image-paste.js.map +1 -0
- package/lib/index.d.ts +10 -0
- package/lib/index.js +11 -0
- package/lib/index.js.map +1 -0
- package/lib/interaction-adapter.d.ts +18 -0
- package/lib/interaction-adapter.js +93 -0
- package/lib/interaction-adapter.js.map +1 -0
- package/lib/keybindings-config.d.ts +5 -0
- package/lib/keybindings-config.js +28 -0
- package/lib/keybindings-config.js.map +1 -0
- package/lib/keys.d.ts +59 -0
- package/lib/keys.js +263 -0
- package/lib/keys.js.map +1 -0
- package/lib/markdown.d.ts +13 -0
- package/lib/markdown.js +453 -0
- package/lib/markdown.js.map +1 -0
- package/lib/path-complete.d.ts +85 -0
- package/lib/path-complete.js +231 -0
- package/lib/path-complete.js.map +1 -0
- package/lib/path-mentions.d.ts +4 -0
- package/lib/path-mentions.js +50 -0
- package/lib/path-mentions.js.map +1 -0
- package/lib/project-context.d.ts +13 -0
- package/lib/project-context.js +52 -0
- package/lib/project-context.js.map +1 -0
- package/lib/project-file-search.d.ts +25 -0
- package/lib/project-file-search.js +207 -0
- package/lib/project-file-search.js.map +1 -0
- package/lib/prompt-selector.d.ts +56 -0
- package/lib/prompt-selector.js +297 -0
- package/lib/prompt-selector.js.map +1 -0
- package/lib/provider-local.d.ts +115 -0
- package/lib/provider-local.js +1760 -0
- package/lib/provider-local.js.map +1 -0
- package/lib/pwd.d.ts +13 -0
- package/lib/pwd.js +14 -0
- package/lib/pwd.js.map +1 -0
- package/lib/relative-time.d.ts +2 -0
- package/lib/relative-time.js +11 -0
- package/lib/relative-time.js.map +1 -0
- package/lib/renderer.d.ts +112 -0
- package/lib/renderer.js +181 -0
- package/lib/renderer.js.map +1 -0
- package/lib/runner.d.ts +9 -0
- package/lib/runner.js +94 -0
- package/lib/runner.js.map +1 -0
- package/lib/session-controller.d.ts +92 -0
- package/lib/session-controller.js +571 -0
- package/lib/session-controller.js.map +1 -0
- package/lib/session-runtime.d.ts +16 -0
- package/lib/session-runtime.js +17 -0
- package/lib/session-runtime.js.map +1 -0
- package/lib/settings-list.d.ts +67 -0
- package/lib/settings-list.js +380 -0
- package/lib/settings-list.js.map +1 -0
- package/lib/status-config.d.ts +32 -0
- package/lib/status-config.js +52 -0
- package/lib/status-config.js.map +1 -0
- package/lib/status-line.d.ts +41 -0
- package/lib/status-line.js +351 -0
- package/lib/status-line.js.map +1 -0
- package/lib/style.d.ts +22 -0
- package/lib/style.js +23 -0
- package/lib/style.js.map +1 -0
- package/lib/theme.d.ts +83 -0
- package/lib/theme.js +317 -0
- package/lib/theme.js.map +1 -0
- package/lib/tool-presentation.d.ts +20 -0
- package/lib/tool-presentation.js +79 -0
- package/lib/tool-presentation.js.map +1 -0
- package/lib/tool-renderers.d.ts +21 -0
- package/lib/tool-renderers.js +133 -0
- package/lib/tool-renderers.js.map +1 -0
- package/lib/tools-list.d.ts +14 -0
- package/lib/tools-list.js +61 -0
- package/lib/tools-list.js.map +1 -0
- package/lib/transcript-export.d.ts +4 -0
- package/lib/transcript-export.js +66 -0
- package/lib/transcript-export.js.map +1 -0
- package/lib/tui-settings.d.ts +20 -0
- package/lib/tui-settings.js +23 -0
- package/lib/tui-settings.js.map +1 -0
- package/lib/welcome-tips.d.ts +10 -0
- package/lib/welcome-tips.js +36 -0
- package/lib/welcome-tips.js.map +1 -0
- package/lib/width.d.ts +54 -0
- package/lib/width.js +323 -0
- package/lib/width.js.map +1 -0
- package/package.json +119 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Harness approval/question adapter mounted independently from the runner. */
|
|
2
|
+
import { bindHumanInteraction } from "./interaction-adapter.js";
|
|
3
|
+
export const name = 'omdsh-human-interaction';
|
|
4
|
+
export const inject = ['tui', 'omdshSession'];
|
|
5
|
+
export function apply(ctx) {
|
|
6
|
+
ctx.effect(() => bindHumanInteraction(ctx, ctx.tui, () => ctx.omdshSession.agent), 'omdsh human interaction');
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=human-interaction.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"human-interaction.js","sourceRoot":"","sources":["../src/human-interaction.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAM/E,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAE/D,MAAM,CAAC,MAAM,IAAI,GAAG,yBAAyB,CAAA;AAC7C,MAAM,CAAC,MAAM,MAAM,GAAG,CAAC,KAAK,EAAE,cAAc,CAAC,CAAA;AAE7C,MAAM,UAAU,KAAK,CAAC,GAAY;IAChC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,yBAAyB,CAAC,CAAA;AAC/G,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Clipboard and path image ingestion owned by the local terminal provider. */
|
|
2
|
+
import type { ImageMediaType } from '@deepseek-ai/dsh-attachment';
|
|
3
|
+
import type { TuiInputImage } from './definition.ts';
|
|
4
|
+
/** Parse a paste made entirely of supported local image paths. */
|
|
5
|
+
export declare function imagePathCandidates(text: string): string[];
|
|
6
|
+
/** Read intrinsic dimensions without decoding the complete image. */
|
|
7
|
+
export declare function probeImageDimensions(data: Uint8Array, mediaType: ImageMediaType): {
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
} | undefined;
|
|
11
|
+
/** Compact, stable composer placeholder matching OMP's image draft label. */
|
|
12
|
+
export declare function imageMarker(index: number, image: TuiInputImage): string;
|
|
13
|
+
/** Load a supported local image without exposing its path beyond the TUI boundary. */
|
|
14
|
+
export declare function readImageFile(path: string, cwd?: string): Promise<TuiInputImage | null>;
|
|
15
|
+
/** Read Finder's file-url pasteboard flavor, which `pbpaste` cannot expose. */
|
|
16
|
+
export declare function readMacClipboardFiles(): Promise<string[]>;
|
|
17
|
+
/** Best-effort native clipboard image reader; null lets text paste take over. */
|
|
18
|
+
export declare function readImageFromClipboard(): Promise<TuiInputImage | null>;
|
|
19
|
+
export type ClipboardImageReader = () => Promise<TuiInputImage | null>;
|
|
20
|
+
export type ClipboardFileReader = () => Promise<string[]>;
|
|
21
|
+
export type ImagePathReader = (path: string) => Promise<TuiInputImage | null>;
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/** Clipboard and path image ingestion owned by the local terminal provider. */
|
|
2
|
+
import { execFile } from 'node:child_process';
|
|
3
|
+
import { mkdtemp, readFile, rm } from 'node:fs/promises';
|
|
4
|
+
import { homedir, platform, tmpdir } from 'node:os';
|
|
5
|
+
import { basename, extname, resolve } from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
const MEDIA_TYPES = {
|
|
8
|
+
'.png': 'image/png',
|
|
9
|
+
'.jpg': 'image/jpeg',
|
|
10
|
+
'.jpeg': 'image/jpeg',
|
|
11
|
+
'.webp': 'image/webp',
|
|
12
|
+
'.gif': 'image/gif',
|
|
13
|
+
};
|
|
14
|
+
const CLIPBOARD_LIMIT = 64 * 1024 * 1024;
|
|
15
|
+
const EXPLICIT_PATH_PREFIX = /^(?:\/|~\/|\.{1,2}\/|file:\/\/|[A-Za-z]:[\\/]|\\\\)/u;
|
|
16
|
+
const INTERIOR_PATH_ANCHOR = /\s(?:\/|~\/|\.{1,2}\/|file:\/\/|[A-Za-z]:[\\/]|\\\\)/u;
|
|
17
|
+
function unquote(value) {
|
|
18
|
+
const first = value.at(0);
|
|
19
|
+
const last = value.at(-1);
|
|
20
|
+
if (value.length >= 2 && (first === '"' || first === "'") && last === first)
|
|
21
|
+
return value.slice(1, -1);
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
/** Parse a paste made entirely of supported local image paths. */
|
|
25
|
+
export function imagePathCandidates(text) {
|
|
26
|
+
const lines = text.replaceAll('\r\n', '\n').replaceAll('\r', '\n')
|
|
27
|
+
.split('\n')
|
|
28
|
+
.map(line => line.trim())
|
|
29
|
+
.filter(Boolean);
|
|
30
|
+
if (lines.length === 0)
|
|
31
|
+
return [];
|
|
32
|
+
const paths = [];
|
|
33
|
+
for (const line of lines) {
|
|
34
|
+
const quoted = (line.startsWith('"') && line.endsWith('"')) || (line.startsWith("'") && line.endsWith("'"));
|
|
35
|
+
if (!quoted && /(^|[^\\])\s/u.test(line)
|
|
36
|
+
&& (!EXPLICIT_PATH_PREFIX.test(line) || INTERIOR_PATH_ANCHOR.test(line.slice(1))))
|
|
37
|
+
return [];
|
|
38
|
+
let candidate = unquote(line);
|
|
39
|
+
try {
|
|
40
|
+
if (candidate.startsWith('file://'))
|
|
41
|
+
candidate = fileURLToPath(candidate);
|
|
42
|
+
else
|
|
43
|
+
candidate = candidate.replace(/\\([\\ ])/gu, '$1');
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
if (MEDIA_TYPES[extname(candidate).toLowerCase()] === undefined)
|
|
49
|
+
return [];
|
|
50
|
+
paths.push(candidate);
|
|
51
|
+
}
|
|
52
|
+
return paths;
|
|
53
|
+
}
|
|
54
|
+
function uint24le(data, offset) {
|
|
55
|
+
return (data[offset] ?? 0) | ((data[offset + 1] ?? 0) << 8) | ((data[offset + 2] ?? 0) << 16);
|
|
56
|
+
}
|
|
57
|
+
function jpegDimensions(data) {
|
|
58
|
+
if (data[0] !== 0xff || data[1] !== 0xd8)
|
|
59
|
+
return undefined;
|
|
60
|
+
let offset = 2;
|
|
61
|
+
while (offset + 8 < data.length) {
|
|
62
|
+
if (data[offset] !== 0xff) {
|
|
63
|
+
offset += 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const marker = data[offset + 1];
|
|
67
|
+
offset += 2;
|
|
68
|
+
if (marker === undefined || marker === 0xd8 || marker === 0xd9)
|
|
69
|
+
continue;
|
|
70
|
+
if (marker === 0xda)
|
|
71
|
+
break;
|
|
72
|
+
const length = ((data[offset] ?? 0) << 8) | (data[offset + 1] ?? 0);
|
|
73
|
+
if (length < 2 || offset + length > data.length)
|
|
74
|
+
break;
|
|
75
|
+
const isStartOfFrame = marker >= 0xc0 && marker <= 0xcf
|
|
76
|
+
&& marker !== 0xc4 && marker !== 0xc8 && marker !== 0xcc;
|
|
77
|
+
if (isStartOfFrame && length >= 7) {
|
|
78
|
+
const height = ((data[offset + 3] ?? 0) << 8) | (data[offset + 4] ?? 0);
|
|
79
|
+
const width = ((data[offset + 5] ?? 0) << 8) | (data[offset + 6] ?? 0);
|
|
80
|
+
if (width > 0 && height > 0)
|
|
81
|
+
return { width, height };
|
|
82
|
+
}
|
|
83
|
+
offset += length;
|
|
84
|
+
}
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
/** Read intrinsic dimensions without decoding the complete image. */
|
|
88
|
+
export function probeImageDimensions(data, mediaType) {
|
|
89
|
+
if (mediaType === 'image/png' && data.length >= 24
|
|
90
|
+
&& data[0] === 0x89 && data[1] === 0x50 && data[2] === 0x4e && data[3] === 0x47) {
|
|
91
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
92
|
+
return { width: view.getUint32(16), height: view.getUint32(20) };
|
|
93
|
+
}
|
|
94
|
+
if (mediaType === 'image/gif' && data.length >= 10) {
|
|
95
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
96
|
+
return { width: view.getUint16(6, true), height: view.getUint16(8, true) };
|
|
97
|
+
}
|
|
98
|
+
if (mediaType === 'image/jpeg')
|
|
99
|
+
return jpegDimensions(data);
|
|
100
|
+
if (mediaType === 'image/webp' && data.length >= 30
|
|
101
|
+
&& String.fromCharCode(...data.slice(0, 4)) === 'RIFF'
|
|
102
|
+
&& String.fromCharCode(...data.slice(8, 12)) === 'WEBP') {
|
|
103
|
+
const kind = String.fromCharCode(...data.slice(12, 16));
|
|
104
|
+
if (kind === 'VP8X') {
|
|
105
|
+
return { width: uint24le(data, 24) + 1, height: uint24le(data, 27) + 1 };
|
|
106
|
+
}
|
|
107
|
+
if (kind === 'VP8 ' && data.length >= 30 && data[23] === 0x9d && data[24] === 0x01 && data[25] === 0x2a) {
|
|
108
|
+
return {
|
|
109
|
+
width: ((data[26] ?? 0) | ((data[27] ?? 0) << 8)) & 0x3fff,
|
|
110
|
+
height: ((data[28] ?? 0) | ((data[29] ?? 0) << 8)) & 0x3fff,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (kind === 'VP8L' && data.length >= 25 && data[20] === 0x2f) {
|
|
114
|
+
const bits = (data[21] ?? 0) | ((data[22] ?? 0) << 8) | ((data[23] ?? 0) << 16) | ((data[24] ?? 0) << 24);
|
|
115
|
+
return { width: (bits & 0x3fff) + 1, height: ((bits >>> 14) & 0x3fff) + 1 };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
/** Compact, stable composer placeholder matching OMP's image draft label. */
|
|
121
|
+
export function imageMarker(index, image) {
|
|
122
|
+
const dimensions = image.width === undefined || image.height === undefined
|
|
123
|
+
? ''
|
|
124
|
+
: `, ${image.width}x${image.height}`;
|
|
125
|
+
return `[Image #${index + 1}${dimensions}]`;
|
|
126
|
+
}
|
|
127
|
+
/** Load a supported local image without exposing its path beyond the TUI boundary. */
|
|
128
|
+
export async function readImageFile(path, cwd = process.cwd()) {
|
|
129
|
+
const expanded = path.startsWith('~/') ? homedir() + path.slice(1) : path;
|
|
130
|
+
const absolute = resolve(cwd, expanded);
|
|
131
|
+
const mediaType = MEDIA_TYPES[extname(absolute).toLowerCase()];
|
|
132
|
+
if (mediaType === undefined)
|
|
133
|
+
return null;
|
|
134
|
+
try {
|
|
135
|
+
return { data: new Uint8Array(await readFile(absolute)), mediaType, name: basename(absolute) };
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
function execBytes(command, args) {
|
|
142
|
+
return new Promise((resolvePromise, reject) => {
|
|
143
|
+
execFile(command, [...args], { encoding: 'buffer', maxBuffer: CLIPBOARD_LIMIT, timeout: 5000 }, (error, stdout) => {
|
|
144
|
+
if (error !== null)
|
|
145
|
+
reject(error);
|
|
146
|
+
else
|
|
147
|
+
resolvePromise(new Uint8Array(stdout));
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function execText(command, args) {
|
|
152
|
+
return new Promise((resolvePromise, reject) => {
|
|
153
|
+
execFile(command, [...args], { encoding: 'utf8', maxBuffer: CLIPBOARD_LIMIT, timeout: 5000 }, (error, stdout) => {
|
|
154
|
+
if (error !== null)
|
|
155
|
+
reject(error);
|
|
156
|
+
else
|
|
157
|
+
resolvePromise(stdout);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
async function readMacClipboardImage() {
|
|
162
|
+
const dir = await mkdtemp(resolve(tmpdir(), 'omdsh-clipboard-'));
|
|
163
|
+
const tiff = resolve(dir, 'clipboard.tiff');
|
|
164
|
+
const png = resolve(dir, 'clipboard.png');
|
|
165
|
+
const script = [
|
|
166
|
+
'set imageData to the clipboard as «class TIFF»',
|
|
167
|
+
`set outputFile to open for access POSIX file ${JSON.stringify(tiff)} with write permission`,
|
|
168
|
+
'try',
|
|
169
|
+
'set eof outputFile to 0',
|
|
170
|
+
'write imageData to outputFile',
|
|
171
|
+
'on error messageText number messageNumber',
|
|
172
|
+
'close access outputFile',
|
|
173
|
+
'error messageText number messageNumber',
|
|
174
|
+
'end try',
|
|
175
|
+
'close access outputFile',
|
|
176
|
+
].join('\n');
|
|
177
|
+
try {
|
|
178
|
+
await execText('osascript', ['-e', script]);
|
|
179
|
+
await execText('sips', ['-s', 'format', 'png', tiff, '--out', png]);
|
|
180
|
+
return { data: new Uint8Array(await readFile(png)), mediaType: 'image/png', name: 'clipboard.png' };
|
|
181
|
+
}
|
|
182
|
+
catch {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
finally {
|
|
186
|
+
await rm(dir, { recursive: true, force: true });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
/** Read Finder's file-url pasteboard flavor, which `pbpaste` cannot expose. */
|
|
190
|
+
export async function readMacClipboardFiles() {
|
|
191
|
+
if (platform() !== 'darwin')
|
|
192
|
+
return [];
|
|
193
|
+
const script = [
|
|
194
|
+
'set output to ""',
|
|
195
|
+
'try',
|
|
196
|
+
'if (clipboard info for «class furl») is {} then return output',
|
|
197
|
+
'set clipboardFiles to the clipboard as «class furl»',
|
|
198
|
+
'if class of clipboardFiles is list then',
|
|
199
|
+
'repeat with clipboardFile in clipboardFiles',
|
|
200
|
+
'try',
|
|
201
|
+
'set output to output & POSIX path of clipboardFile & linefeed',
|
|
202
|
+
'end try',
|
|
203
|
+
'end repeat',
|
|
204
|
+
'else',
|
|
205
|
+
'set output to POSIX path of clipboardFiles & linefeed',
|
|
206
|
+
'end if',
|
|
207
|
+
'end try',
|
|
208
|
+
'return output',
|
|
209
|
+
].join('\n');
|
|
210
|
+
try {
|
|
211
|
+
return (await execText('osascript', ['-e', script])).split(/\r?\n/u).map(line => line.trim()).filter(Boolean);
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
return [];
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
async function readLinuxClipboardImage() {
|
|
218
|
+
try {
|
|
219
|
+
const types = await execText('wl-paste', ['--list-types']);
|
|
220
|
+
const mediaType = ['image/png', 'image/jpeg', 'image/webp', 'image/gif']
|
|
221
|
+
.find(type => types.split(/\s+/u).includes(type));
|
|
222
|
+
if (mediaType === undefined)
|
|
223
|
+
return null;
|
|
224
|
+
return { data: await execBytes('wl-paste', ['--no-newline', '--type', mediaType]), mediaType, name: 'clipboard' + extensionFor(mediaType) };
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
for (const mediaType of ['image/png', 'image/jpeg', 'image/webp', 'image/gif']) {
|
|
228
|
+
try {
|
|
229
|
+
const data = await execBytes('xclip', ['-selection', 'clipboard', '-t', mediaType, '-o']);
|
|
230
|
+
if (data.byteLength > 0)
|
|
231
|
+
return { data, mediaType, name: 'clipboard' + extensionFor(mediaType) };
|
|
232
|
+
}
|
|
233
|
+
catch { /* try the next available target */ }
|
|
234
|
+
}
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
function extensionFor(mediaType) {
|
|
239
|
+
if (mediaType === 'image/jpeg')
|
|
240
|
+
return '.jpg';
|
|
241
|
+
return '.' + mediaType.slice('image/'.length);
|
|
242
|
+
}
|
|
243
|
+
async function readWindowsClipboardImage() {
|
|
244
|
+
const script = [
|
|
245
|
+
'Add-Type -AssemblyName System.Windows.Forms',
|
|
246
|
+
'Add-Type -AssemblyName System.Drawing',
|
|
247
|
+
'$image = [System.Windows.Forms.Clipboard]::GetImage()',
|
|
248
|
+
'if ($null -eq $image) { exit 2 }',
|
|
249
|
+
'$stream = New-Object System.IO.MemoryStream',
|
|
250
|
+
'$image.Save($stream, [System.Drawing.Imaging.ImageFormat]::Png)',
|
|
251
|
+
'[Convert]::ToBase64String($stream.ToArray())',
|
|
252
|
+
].join('; ');
|
|
253
|
+
try {
|
|
254
|
+
const encoded = (await execText('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command', script])).trim();
|
|
255
|
+
return encoded === '' ? null : { data: new Uint8Array(Buffer.from(encoded, 'base64')), mediaType: 'image/png', name: 'clipboard.png' };
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
/** Best-effort native clipboard image reader; null lets text paste take over. */
|
|
262
|
+
export async function readImageFromClipboard() {
|
|
263
|
+
if (platform() === 'darwin')
|
|
264
|
+
return readMacClipboardImage();
|
|
265
|
+
if (platform() === 'win32')
|
|
266
|
+
return readWindowsClipboardImage();
|
|
267
|
+
if (platform() === 'linux') {
|
|
268
|
+
if (process.env.WSL_DISTRO_NAME !== undefined || process.env.WSL_INTEROP !== undefined) {
|
|
269
|
+
const windows = await readWindowsClipboardImage();
|
|
270
|
+
if (windows !== null)
|
|
271
|
+
return windows;
|
|
272
|
+
}
|
|
273
|
+
return readLinuxClipboardImage();
|
|
274
|
+
}
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
//# sourceMappingURL=image-paste.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-paste.js","sourceRoot":"","sources":["../src/image-paste.ts"],"names":[],"mappings":"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"}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @agi-fans/dsh-tui — the omdsh TUI capability seam.
|
|
3
|
+
|
|
4
|
+
* Package root is the local terminal provider plugin (apply/Config). Other
|
|
5
|
+
* runtime capabilities live on explicit plugin subpaths; rendering internals
|
|
6
|
+
* remain private implementation modules.
|
|
7
|
+
* @module @agi-fans/dsh-tui
|
|
8
|
+
*/
|
|
9
|
+
export * from './definition.ts';
|
|
10
|
+
export { apply, name, type Config } from './provider-local.ts';
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @agi-fans/dsh-tui — the omdsh TUI capability seam.
|
|
3
|
+
|
|
4
|
+
* Package root is the local terminal provider plugin (apply/Config). Other
|
|
5
|
+
* runtime capabilities live on explicit plugin subpaths; rendering internals
|
|
6
|
+
* remain private implementation modules.
|
|
7
|
+
* @module @agi-fans/dsh-tui
|
|
8
|
+
*/
|
|
9
|
+
export * from "./definition.js";
|
|
10
|
+
export { apply, name } from "./provider-local.js";
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EAAE,KAAK,EAAE,IAAI,EAAe,MAAM,qBAAqB,CAAA"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness human-interaction adapters for the terminal presentation seam.
|
|
3
|
+
*
|
|
4
|
+
* Domain services keep ownership of audit, cancellation, and validation;
|
|
5
|
+
* this module only translates their fixed vocabularies to one Tui prompt.
|
|
6
|
+
* @module @agi-fans/dsh-tui/interaction-adapter
|
|
7
|
+
*/
|
|
8
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
9
|
+
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
10
|
+
import type { AskUserQuestionItem } from '@deepseek-ai/dsh-user-questions';
|
|
11
|
+
import type { TuiService } from './definition.ts';
|
|
12
|
+
/** Resolve a label/number list while preserving unmatched input as custom text. */
|
|
13
|
+
export declare function parsePromptAnswer(input: string, question: Pick<AskUserQuestionItem, 'options' | 'multiSelect'>): {
|
|
14
|
+
selected: string[];
|
|
15
|
+
custom?: string;
|
|
16
|
+
};
|
|
17
|
+
/** Bind the global question provider and route approvals to the active root agent only. */
|
|
18
|
+
export declare function bindHumanInteraction(ctx: Context, tui: TuiService, activeAgent: () => Agent | undefined): () => void;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Harness human-interaction adapters for the terminal presentation seam.
|
|
3
|
+
*
|
|
4
|
+
* Domain services keep ownership of audit, cancellation, and validation;
|
|
5
|
+
* this module only translates their fixed vocabularies to one Tui prompt.
|
|
6
|
+
* @module @agi-fans/dsh-tui/interaction-adapter
|
|
7
|
+
*/
|
|
8
|
+
/** Resolve a label/number list while preserving unmatched input as custom text. */
|
|
9
|
+
export function parsePromptAnswer(input, question) {
|
|
10
|
+
const options = question.options ?? [];
|
|
11
|
+
const tokens = question.multiSelect === true ? input.split(',').map(token => token.trim()) : [input.trim()];
|
|
12
|
+
const selected = [];
|
|
13
|
+
const custom = [];
|
|
14
|
+
for (const token of tokens.filter(Boolean)) {
|
|
15
|
+
const numeric = /^\d+$/u.test(token) ? Number(token) - 1 : -1;
|
|
16
|
+
const match = numeric >= 0
|
|
17
|
+
? options[numeric]
|
|
18
|
+
: options.find(option => option.label.toLowerCase() === token.toLowerCase());
|
|
19
|
+
if (match === undefined)
|
|
20
|
+
custom.push(token);
|
|
21
|
+
else if (!selected.includes(match.label))
|
|
22
|
+
selected.push(match.label);
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
selected,
|
|
26
|
+
...(custom.length === 0 ? {} : { custom: custom.join(question.multiSelect === true ? ', ' : '') }),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
async function askQuestions(tui, request) {
|
|
30
|
+
const answers = [];
|
|
31
|
+
for (const question of request.questions) {
|
|
32
|
+
const raw = await tui.prompt({
|
|
33
|
+
title: question.intent?.kind === 'plan-review' ? 'Plan review' : (question.header ?? 'Question'),
|
|
34
|
+
question: question.question,
|
|
35
|
+
...(question.detail === undefined ? {} : { detail: question.detail }),
|
|
36
|
+
...(question.options === undefined ? {} : { options: question.options }),
|
|
37
|
+
...(question.multiSelect === undefined ? {} : { multiSelect: question.multiSelect }),
|
|
38
|
+
...(question.intent?.kind === 'plan-review'
|
|
39
|
+
? { presentation: 'plan-review', approveValue: question.intent.approve }
|
|
40
|
+
: {}),
|
|
41
|
+
allowCustom: true,
|
|
42
|
+
...(request.signal === undefined ? {} : { signal: request.signal }),
|
|
43
|
+
});
|
|
44
|
+
if (raw === null) {
|
|
45
|
+
answers.push({ id: question.id, selected: [] });
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const parsed = parsePromptAnswer(raw, question);
|
|
49
|
+
answers.push({ id: question.id, ...parsed });
|
|
50
|
+
}
|
|
51
|
+
return { answers };
|
|
52
|
+
}
|
|
53
|
+
async function askApproval(tui, request) {
|
|
54
|
+
const raw = await tui.prompt({
|
|
55
|
+
title: 'Approval required',
|
|
56
|
+
question: `Allow ${request.toolName} once?`,
|
|
57
|
+
...(request.reason === undefined ? {} : { detail: request.reason }),
|
|
58
|
+
options: [
|
|
59
|
+
{ label: 'Allow once', description: 'Run only this requested action.' },
|
|
60
|
+
{ label: 'Reject', description: 'Deny this action.' },
|
|
61
|
+
],
|
|
62
|
+
...(request.signal === undefined ? {} : { signal: request.signal }),
|
|
63
|
+
});
|
|
64
|
+
if (raw === null)
|
|
65
|
+
return 'cancelled';
|
|
66
|
+
const normalized = raw.trim().toLowerCase();
|
|
67
|
+
return normalized === '1' || normalized === 'allow' || normalized === 'allow once'
|
|
68
|
+
|| normalized === 'y' || normalized === 'yes'
|
|
69
|
+
? 'allowed-once'
|
|
70
|
+
: 'rejected';
|
|
71
|
+
}
|
|
72
|
+
/** Bind the global question provider and route approvals to the active root agent only. */
|
|
73
|
+
export function bindHumanInteraction(ctx, tui, activeAgent) {
|
|
74
|
+
const disposers = [];
|
|
75
|
+
const questions = ctx.get('userQuestions');
|
|
76
|
+
if (questions !== undefined) {
|
|
77
|
+
disposers.push(questions.registerProvider({
|
|
78
|
+
ask: request => askQuestions(tui, request),
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
81
|
+
if (ctx.get('approval') !== undefined) {
|
|
82
|
+
disposers.push(ctx.on('approval/request', async (request, next) => {
|
|
83
|
+
if (request.agent !== activeAgent())
|
|
84
|
+
return next();
|
|
85
|
+
return askApproval(tui, request);
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
return () => {
|
|
89
|
+
for (const dispose of disposers.reverse())
|
|
90
|
+
dispose();
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=interaction-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"interaction-adapter.js","sourceRoot":"","sources":["../src/interaction-adapter.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAYH,mFAAmF;AACnF,MAAM,UAAU,iBAAiB,CAC/B,KAAa,EACb,QAA8D;IAE9D,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,IAAI,EAAE,CAAA;IACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;IAC3G,MAAM,QAAQ,GAAa,EAAE,CAAA;IAC7B,MAAM,MAAM,GAAa,EAAE,CAAA;IAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3C,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC7D,MAAM,KAAK,GAAG,OAAO,IAAI,CAAC;YACxB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;YAClB,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;QAC9E,IAAI,KAAK,KAAK,SAAS;YAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;aACtC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IACtE,CAAC;IACD,OAAO;QACL,QAAQ;QACR,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;KACnG,CAAA;AACH,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,GAAe,EAAE,OAA+B;IAC1E,MAAM,OAAO,GAAqC,EAAE,CAAA;IACpD,KAAK,MAAM,QAAQ,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QACzC,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;YAC3B,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,UAAU,CAAC;YAChG,QAAQ,EAAE,QAAQ,CAAC,QAAQ;YAC3B,GAAG,CAAC,QAAQ,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YACrE,GAAG,CAAC,QAAQ,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC;YACxE,GAAG,CAAC,QAAQ,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC;YACpF,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,KAAK,aAAa;gBACzC,CAAC,CAAC,EAAE,YAAY,EAAE,aAAsB,EAAE,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,EAAE;gBACjF,CAAC,CAAC,EAAE,CAAC;YACP,WAAW,EAAE,IAAI;YACjB,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;SACpE,CAAC,CAAA;QACF,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAA;YAC/C,SAAQ;QACV,CAAC;QACD,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;QAC/C,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;IAC9C,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAA;AACpB,CAAC;AAED,KAAK,UAAU,WAAW,CAAC,GAAe,EAAE,OAAwB;IAClE,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,MAAM,CAAC;QAC3B,KAAK,EAAE,mBAAmB;QAC1B,QAAQ,EAAE,SAAS,OAAO,CAAC,QAAQ,QAAQ;QAC3C,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;QACnE,OAAO,EAAE;YACP,EAAE,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,iCAAiC,EAAE;YACvE,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE;SACtD;QACD,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC;KACpE,CAAC,CAAA;IACF,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,WAAW,CAAA;IACpC,MAAM,UAAU,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAA;IAC3C,OAAO,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,YAAY;WAC7E,UAAU,KAAK,GAAG,IAAI,UAAU,KAAK,KAAK;QAC7C,CAAC,CAAC,cAAc;QAChB,CAAC,CAAC,UAAU,CAAA;AAChB,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,oBAAoB,CAClC,GAAY,EACZ,GAAe,EACf,WAAoC;IAEpC,MAAM,SAAS,GAAsB,EAAE,CAAA;IACvC,MAAM,SAAS,GAAG,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;IAC1C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,gBAAgB,CAAC;YACxC,GAAG,EAAE,OAAO,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC;SAC3C,CAAC,CAAC,CAAA;IACL,CAAC;IACD,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,SAAS,EAAE,CAAC;QACtC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,kBAAkB,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;YAChE,IAAI,OAAO,CAAC,KAAK,KAAK,WAAW,EAAE;gBAAE,OAAO,IAAI,EAAE,CAAA;YAClD,OAAO,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QAClC,CAAC,CAAC,CAAC,CAAA;IACL,CAAC;IACD,OAAO,GAAG,EAAE;QACV,KAAK,MAAM,OAAO,IAAI,SAAS,CAAC,OAAO,EAAE;YAAE,OAAO,EAAE,CAAA;IACtD,CAAC,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** User-overridable application keybindings loaded from one JSON document. */
|
|
2
|
+
export type TuiAction = 'external-editor' | 'retry' | 'paste-clipboard' | 'copy-prompt' | 'copy-line';
|
|
3
|
+
export declare const DEFAULT_KEYBINDINGS: Readonly<Record<string, TuiAction>>;
|
|
4
|
+
/** Load `{ "key-id": "action" }`; invalid rows are ignored independently. */
|
|
5
|
+
export declare function loadKeybindings(path: string | undefined): Record<string, TuiAction>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** User-overridable application keybindings loaded from one JSON document. */
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
|
+
export const DEFAULT_KEYBINDINGS = Object.freeze({
|
|
4
|
+
'ctrl+x': 'external-editor',
|
|
5
|
+
'alt+r': 'retry',
|
|
6
|
+
'ctrl+v': 'paste-clipboard',
|
|
7
|
+
'alt+c': 'copy-prompt',
|
|
8
|
+
'ctrl+alt+c': 'copy-line',
|
|
9
|
+
});
|
|
10
|
+
const ACTIONS = ['external-editor', 'retry', 'paste-clipboard', 'copy-prompt', 'copy-line'];
|
|
11
|
+
/** Load `{ "key-id": "action" }`; invalid rows are ignored independently. */
|
|
12
|
+
export function loadKeybindings(path) {
|
|
13
|
+
const result = { ...DEFAULT_KEYBINDINGS };
|
|
14
|
+
if (path === undefined)
|
|
15
|
+
return result;
|
|
16
|
+
try {
|
|
17
|
+
const parsed = JSON.parse(readFileSync(path, 'utf8'));
|
|
18
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
19
|
+
return result;
|
|
20
|
+
for (const [key, action] of Object.entries(parsed)) {
|
|
21
|
+
if (typeof action === 'string' && ACTIONS.includes(action))
|
|
22
|
+
result[key.toLowerCase()] = action;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch { /* missing/malformed user config falls back to shipped bindings */ }
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=keybindings-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keybindings-config.js","sourceRoot":"","sources":["../src/keybindings-config.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAE9E,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AAItC,MAAM,CAAC,MAAM,mBAAmB,GAAwC,MAAM,CAAC,MAAM,CAAC;IACpF,QAAQ,EAAE,iBAAiB;IAC3B,OAAO,EAAE,OAAO;IAChB,QAAQ,EAAE,iBAAiB;IAC3B,OAAO,EAAE,aAAa;IACtB,YAAY,EAAE,WAAW;CAC1B,CAAC,CAAA;AAEF,MAAM,OAAO,GAAyB,CAAC,iBAAiB,EAAE,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,WAAW,CAAC,CAAA;AAEjH,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,IAAwB;IACtD,MAAM,MAAM,GAA8B,EAAE,GAAG,mBAAmB,EAAE,CAAA;IACpE,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,MAAM,CAAA;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;QAC9D,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,MAAM,CAAA;QAChE,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAmB,CAAC;gBAAE,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,GAAG,MAAmB,CAAA;QAC1H,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,kEAAkE,CAAC,CAAC;IAC9E,OAAO,MAAM,CAAA;AACf,CAAC"}
|
package/lib/keys.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal key decoder. Turns raw stdin (legacy CSI, SS3, Kitty CSI-u,
|
|
3
|
+
* modifyOtherKeys) into the same key-id vocabulary oh-my-pi uses:
|
|
4
|
+
* `enter`, `ctrl+a`, `alt+left`, `shift+enter`, …
|
|
5
|
+
* @module @agi-fans/dsh-tui
|
|
6
|
+
*/
|
|
7
|
+
/** One decoded SGR mouse report (`\x1b[<button;col;rowM`). */
|
|
8
|
+
export interface MouseEvent {
|
|
9
|
+
type: 'mouse';
|
|
10
|
+
/** Raw button code (bit 32 = motion, bit 64 = wheel). */
|
|
11
|
+
button: number;
|
|
12
|
+
/** 0-based column. */
|
|
13
|
+
col: number;
|
|
14
|
+
/** 0-based row. */
|
|
15
|
+
row: number;
|
|
16
|
+
/** True for a release report (`m` suffix). */
|
|
17
|
+
release: boolean;
|
|
18
|
+
/** Wheel direction: -1 up, 1 down, null when not a wheel event. */
|
|
19
|
+
wheel: -1 | 1 | null;
|
|
20
|
+
/** Pointer moved (hover or drag). */
|
|
21
|
+
motion: boolean;
|
|
22
|
+
/** Left-button press (not motion, release, or wheel). */
|
|
23
|
+
leftClick: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** One decoded input event. */
|
|
26
|
+
export type KeyEvent = {
|
|
27
|
+
type: 'key';
|
|
28
|
+
id: string;
|
|
29
|
+
} | {
|
|
30
|
+
type: 'text';
|
|
31
|
+
value: string;
|
|
32
|
+
} | {
|
|
33
|
+
type: 'paste-start';
|
|
34
|
+
} | {
|
|
35
|
+
type: 'paste-end';
|
|
36
|
+
} | MouseEvent;
|
|
37
|
+
/** Enable SGR button tracking (wheel + clicks; no motion flood). */
|
|
38
|
+
export declare const MOUSE_TRACKING_ON = "\u001B[?1000h\u001B[?1006h";
|
|
39
|
+
/** Disable the modes enabled by {@link MOUSE_TRACKING_ON}. */
|
|
40
|
+
export declare const MOUSE_TRACKING_OFF = "\u001B[?1006l\u001B[?1000l";
|
|
41
|
+
/** Build `ctrl+shift+alt+name` from a CSI modifier parameter (1 = none). */
|
|
42
|
+
export declare function withMods(name: string, modifier: number): string;
|
|
43
|
+
/**
|
|
44
|
+
* Decode one SGR mouse report. `data` is the full CSI including ESC
|
|
45
|
+
* (`\x1b[<64;10;5M`); returns null when the string is not a complete report.
|
|
46
|
+
*/
|
|
47
|
+
export declare function parseSgrMouse(data: string): MouseEvent | null;
|
|
48
|
+
/**
|
|
49
|
+
* Decode a stdin string into events, leaving an incomplete escape in `rest`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function parseKeys(input: string): {
|
|
52
|
+
events: KeyEvent[];
|
|
53
|
+
rest: string;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Turn a leftover incomplete sequence into events when the ESC timeout fires.
|
|
57
|
+
* A lone ESC becomes `escape`; anything else is dropped.
|
|
58
|
+
*/
|
|
59
|
+
export declare function flushPending(rest: string): KeyEvent[];
|