shortcutxl 0.2.12 → 0.2.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -26
- package/agent-docs/README.md +397 -397
- package/agent-docs/docs/compaction.md +390 -390
- package/agent-docs/docs/custom-provider.md +580 -580
- package/agent-docs/docs/extensions.md +1971 -1971
- package/agent-docs/docs/packages.md +209 -209
- package/agent-docs/docs/rpc.md +1317 -1317
- package/agent-docs/docs/sdk.md +962 -962
- package/agent-docs/docs/session.md +412 -412
- package/agent-docs/docs/termux.md +127 -127
- package/agent-docs/docs/tui.md +887 -887
- package/agent-docs/examples/README.md +25 -25
- package/agent-docs/examples/extensions/README.md +205 -205
- package/agent-docs/examples/extensions/antigravity-image-gen.ts +447 -447
- package/agent-docs/examples/extensions/auto-commit-on-exit.ts +49 -49
- package/agent-docs/examples/extensions/bash-spawn-hook.ts +30 -30
- package/agent-docs/examples/extensions/bookmark.ts +50 -50
- package/agent-docs/examples/extensions/built-in-tool-renderer.ts +256 -256
- package/agent-docs/examples/extensions/claude-rules.ts +86 -86
- package/agent-docs/examples/extensions/commands.ts +75 -75
- package/agent-docs/examples/extensions/confirm-destructive.ts +59 -59
- package/agent-docs/examples/extensions/custom-compaction.ts +126 -126
- package/agent-docs/examples/extensions/custom-footer.ts +63 -63
- package/agent-docs/examples/extensions/custom-header.ts +73 -73
- package/agent-docs/examples/extensions/custom-provider-anthropic/index.ts +660 -660
- package/agent-docs/examples/extensions/custom-provider-gitlab-duo/index.ts +362 -362
- package/agent-docs/examples/extensions/custom-provider-gitlab-duo/test.ts +88 -88
- package/agent-docs/examples/extensions/custom-provider-qwen-cli/index.ts +349 -349
- package/agent-docs/examples/extensions/dirty-repo-guard.ts +56 -56
- package/agent-docs/examples/extensions/doom-overlay/doom-component.ts +133 -133
- package/agent-docs/examples/extensions/doom-overlay/doom-keys.ts +108 -108
- package/agent-docs/examples/extensions/doom-overlay/index.ts +74 -74
- package/agent-docs/examples/extensions/dynamic-resources/index.ts +15 -15
- package/agent-docs/examples/extensions/dynamic-tools.ts +77 -77
- package/agent-docs/examples/extensions/event-bus.ts +43 -43
- package/agent-docs/examples/extensions/file-trigger.ts +41 -41
- package/agent-docs/examples/extensions/git-checkpoint.ts +53 -53
- package/agent-docs/examples/extensions/handoff.ts +155 -155
- package/agent-docs/examples/extensions/hello.ts +25 -25
- package/agent-docs/examples/extensions/inline-bash.ts +94 -94
- package/agent-docs/examples/extensions/input-transform.ts +43 -43
- package/agent-docs/examples/extensions/interactive-shell.ts +209 -209
- package/agent-docs/examples/extensions/mac-system-theme.ts +47 -47
- package/agent-docs/examples/extensions/message-renderer.ts +59 -59
- package/agent-docs/examples/extensions/minimal-mode.ts +430 -430
- package/agent-docs/examples/extensions/modal-editor.ts +90 -90
- package/agent-docs/examples/extensions/model-status.ts +31 -31
- package/agent-docs/examples/extensions/notify.ts +55 -55
- package/agent-docs/examples/extensions/overlay-qa-tests.ts +936 -936
- package/agent-docs/examples/extensions/overlay-test.ts +159 -159
- package/agent-docs/examples/extensions/permission-gate.ts +37 -37
- package/agent-docs/examples/extensions/pirate.ts +47 -47
- package/agent-docs/examples/extensions/plan-mode/index.ts +363 -363
- package/agent-docs/examples/extensions/preset.ts +418 -418
- package/agent-docs/examples/extensions/protected-paths.ts +30 -30
- package/agent-docs/examples/extensions/qna.ts +122 -122
- package/agent-docs/examples/extensions/question.ts +278 -278
- package/agent-docs/examples/extensions/questionnaire.ts +440 -440
- package/agent-docs/examples/extensions/rainbow-editor.ts +90 -90
- package/agent-docs/examples/extensions/reload-runtime.ts +37 -37
- package/agent-docs/examples/extensions/rpc-demo.ts +124 -124
- package/agent-docs/examples/extensions/sandbox/index.ts +324 -324
- package/agent-docs/examples/extensions/send-user-message.ts +97 -97
- package/agent-docs/examples/extensions/session-name.ts +27 -27
- package/agent-docs/examples/extensions/shutdown-command.ts +69 -69
- package/agent-docs/examples/extensions/snake.ts +343 -343
- package/agent-docs/examples/extensions/space-invaders.ts +566 -566
- package/agent-docs/examples/extensions/ssh.ts +233 -233
- package/agent-docs/examples/extensions/status-line.ts +40 -40
- package/agent-docs/examples/extensions/subagent/agents.ts +130 -130
- package/agent-docs/examples/extensions/subagent/index.ts +1068 -1068
- package/agent-docs/examples/extensions/summarize.ts +206 -206
- package/agent-docs/examples/extensions/system-prompt-header.ts +17 -17
- package/agent-docs/examples/extensions/timed-confirm.ts +72 -72
- package/agent-docs/examples/extensions/titlebar-spinner.ts +58 -58
- package/agent-docs/examples/extensions/todo.ts +314 -314
- package/agent-docs/examples/extensions/tool-override.ts +146 -146
- package/agent-docs/examples/extensions/tools.ts +145 -145
- package/agent-docs/examples/extensions/trigger-compact.ts +40 -40
- package/agent-docs/examples/extensions/truncated-tool.ts +194 -194
- package/agent-docs/examples/extensions/widget-placement.ts +17 -17
- package/agent-docs/examples/extensions/with-deps/index.ts +37 -37
- package/agent-docs/examples/rpc-extension-ui.ts +654 -654
- package/agent-docs/examples/sdk/01-minimal.ts +22 -22
- package/agent-docs/examples/sdk/02-custom-model.ts +48 -48
- package/agent-docs/examples/sdk/03-custom-prompt.ts +55 -55
- package/agent-docs/examples/sdk/04-skills.ts +53 -53
- package/agent-docs/examples/sdk/05-tools.ts +56 -56
- package/agent-docs/examples/sdk/06-extensions.ts +88 -88
- package/agent-docs/examples/sdk/07-context-files.ts +40 -40
- package/agent-docs/examples/sdk/08-prompt-templates.ts +47 -47
- package/agent-docs/examples/sdk/09-api-keys-and-oauth.ts +48 -48
- package/agent-docs/examples/sdk/10-settings.ts +54 -54
- package/agent-docs/examples/sdk/11-sessions.ts +48 -48
- package/agent-docs/examples/sdk/12-full-control.ts +82 -82
- package/agent-docs/examples/sdk/README.md +144 -144
- package/agent-docs/xll-spec.md +110 -110
- package/dist/core/auth-storage.js +21 -2
- package/package.json +1 -1
- package/xll/ShortcutXL.xll +0 -0
- package/xll/modules/debug_render.py +272 -272
- package/xll/modules/gameboy.py +241 -241
- package/xll/modules/pong.py +188 -188
- package/xll/modules/shortcut_xl/_diff_highlight.py +176 -0
- package/xll/modules/shortcut_xl/_log.py +12 -12
- package/xll/modules/shortcut_xl/_registry.py +44 -44
- package/xll/modules/stocks.py +100 -100
- /package/skills/{com-advanced-api → COM-advanced-api}/SKILL.md +0 -0
- /package/skills/{com-advanced-api → COM-advanced-api}/excel-type-library.py +0 -0
- /package/skills/{com-advanced-api → COM-advanced-api}/office-type-library.py +0 -0
|
@@ -1,90 +1,90 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Modal Editor - vim-like modal editing example
|
|
3
|
-
*
|
|
4
|
-
* Usage: shortcut --extension ./examples/extensions/modal-editor.ts
|
|
5
|
-
*
|
|
6
|
-
* - Escape: insert → normal mode (in normal mode, aborts agent)
|
|
7
|
-
* - i: normal → insert mode
|
|
8
|
-
* - hjkl: navigation in normal mode
|
|
9
|
-
* - ctrl+c, ctrl+d, etc. work in both modes
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
CustomEditor,
|
|
14
|
-
matchesKey,
|
|
15
|
-
truncateToWidth,
|
|
16
|
-
visibleWidth,
|
|
17
|
-
type ExtensionAPI
|
|
18
|
-
} from 'shortcutxl';
|
|
19
|
-
|
|
20
|
-
// Normal mode key mappings: key -> escape sequence (or null for mode switch)
|
|
21
|
-
const NORMAL_KEYS: Record<string, string | null> = {
|
|
22
|
-
h: '\x1b[D', // left
|
|
23
|
-
j: '\x1b[B', // down
|
|
24
|
-
k: '\x1b[A', // up
|
|
25
|
-
l: '\x1b[C', // right
|
|
26
|
-
'0': '\x01', // line start
|
|
27
|
-
$: '\x05', // line end
|
|
28
|
-
x: '\x1b[3~', // delete char
|
|
29
|
-
i: null, // insert mode
|
|
30
|
-
a: null // append (insert + right)
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
class ModalEditor extends CustomEditor {
|
|
34
|
-
private mode: 'normal' | 'insert' = 'insert';
|
|
35
|
-
|
|
36
|
-
handleInput(data: string): void {
|
|
37
|
-
// Escape toggles to normal mode, or passes through for app handling
|
|
38
|
-
if (matchesKey(data, 'escape')) {
|
|
39
|
-
if (this.mode === 'insert') {
|
|
40
|
-
this.mode = 'normal';
|
|
41
|
-
} else {
|
|
42
|
-
super.handleInput(data); // abort agent, etc.
|
|
43
|
-
}
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Insert mode: pass everything through
|
|
48
|
-
if (this.mode === 'insert') {
|
|
49
|
-
super.handleInput(data);
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Normal mode: check mapped keys
|
|
54
|
-
if (data in NORMAL_KEYS) {
|
|
55
|
-
const seq = NORMAL_KEYS[data];
|
|
56
|
-
if (data === 'i') {
|
|
57
|
-
this.mode = 'insert';
|
|
58
|
-
} else if (data === 'a') {
|
|
59
|
-
this.mode = 'insert';
|
|
60
|
-
super.handleInput('\x1b[C'); // move right first
|
|
61
|
-
} else if (seq) {
|
|
62
|
-
super.handleInput(seq);
|
|
63
|
-
}
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Pass control sequences (ctrl+c, etc.) to super, ignore printable chars
|
|
68
|
-
if (data.length === 1 && data.charCodeAt(0) >= 32) return;
|
|
69
|
-
super.handleInput(data);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
render(width: number): string[] {
|
|
73
|
-
const lines = super.render(width);
|
|
74
|
-
if (lines.length === 0) return lines;
|
|
75
|
-
|
|
76
|
-
// Add mode indicator to bottom border
|
|
77
|
-
const label = this.mode === 'normal' ? ' NORMAL ' : ' INSERT ';
|
|
78
|
-
const last = lines.length - 1;
|
|
79
|
-
if (visibleWidth(lines[last]!) >= label.length) {
|
|
80
|
-
lines[last] = truncateToWidth(lines[last]!, width - label.length, '') + label;
|
|
81
|
-
}
|
|
82
|
-
return lines;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
export default function (shortcut: ExtensionAPI) {
|
|
87
|
-
shortcut.on('session_start', (_event, ctx) => {
|
|
88
|
-
ctx.ui.setEditorComponent((tui, theme, kb) => new ModalEditor(tui, theme, kb));
|
|
89
|
-
});
|
|
90
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Modal Editor - vim-like modal editing example
|
|
3
|
+
*
|
|
4
|
+
* Usage: shortcut --extension ./examples/extensions/modal-editor.ts
|
|
5
|
+
*
|
|
6
|
+
* - Escape: insert → normal mode (in normal mode, aborts agent)
|
|
7
|
+
* - i: normal → insert mode
|
|
8
|
+
* - hjkl: navigation in normal mode
|
|
9
|
+
* - ctrl+c, ctrl+d, etc. work in both modes
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
CustomEditor,
|
|
14
|
+
matchesKey,
|
|
15
|
+
truncateToWidth,
|
|
16
|
+
visibleWidth,
|
|
17
|
+
type ExtensionAPI
|
|
18
|
+
} from 'shortcutxl';
|
|
19
|
+
|
|
20
|
+
// Normal mode key mappings: key -> escape sequence (or null for mode switch)
|
|
21
|
+
const NORMAL_KEYS: Record<string, string | null> = {
|
|
22
|
+
h: '\x1b[D', // left
|
|
23
|
+
j: '\x1b[B', // down
|
|
24
|
+
k: '\x1b[A', // up
|
|
25
|
+
l: '\x1b[C', // right
|
|
26
|
+
'0': '\x01', // line start
|
|
27
|
+
$: '\x05', // line end
|
|
28
|
+
x: '\x1b[3~', // delete char
|
|
29
|
+
i: null, // insert mode
|
|
30
|
+
a: null // append (insert + right)
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
class ModalEditor extends CustomEditor {
|
|
34
|
+
private mode: 'normal' | 'insert' = 'insert';
|
|
35
|
+
|
|
36
|
+
handleInput(data: string): void {
|
|
37
|
+
// Escape toggles to normal mode, or passes through for app handling
|
|
38
|
+
if (matchesKey(data, 'escape')) {
|
|
39
|
+
if (this.mode === 'insert') {
|
|
40
|
+
this.mode = 'normal';
|
|
41
|
+
} else {
|
|
42
|
+
super.handleInput(data); // abort agent, etc.
|
|
43
|
+
}
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Insert mode: pass everything through
|
|
48
|
+
if (this.mode === 'insert') {
|
|
49
|
+
super.handleInput(data);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Normal mode: check mapped keys
|
|
54
|
+
if (data in NORMAL_KEYS) {
|
|
55
|
+
const seq = NORMAL_KEYS[data];
|
|
56
|
+
if (data === 'i') {
|
|
57
|
+
this.mode = 'insert';
|
|
58
|
+
} else if (data === 'a') {
|
|
59
|
+
this.mode = 'insert';
|
|
60
|
+
super.handleInput('\x1b[C'); // move right first
|
|
61
|
+
} else if (seq) {
|
|
62
|
+
super.handleInput(seq);
|
|
63
|
+
}
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Pass control sequences (ctrl+c, etc.) to super, ignore printable chars
|
|
68
|
+
if (data.length === 1 && data.charCodeAt(0) >= 32) return;
|
|
69
|
+
super.handleInput(data);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
render(width: number): string[] {
|
|
73
|
+
const lines = super.render(width);
|
|
74
|
+
if (lines.length === 0) return lines;
|
|
75
|
+
|
|
76
|
+
// Add mode indicator to bottom border
|
|
77
|
+
const label = this.mode === 'normal' ? ' NORMAL ' : ' INSERT ';
|
|
78
|
+
const last = lines.length - 1;
|
|
79
|
+
if (visibleWidth(lines[last]!) >= label.length) {
|
|
80
|
+
lines[last] = truncateToWidth(lines[last]!, width - label.length, '') + label;
|
|
81
|
+
}
|
|
82
|
+
return lines;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default function (shortcut: ExtensionAPI) {
|
|
87
|
+
shortcut.on('session_start', (_event, ctx) => {
|
|
88
|
+
ctx.ui.setEditorComponent((tui, theme, kb) => new ModalEditor(tui, theme, kb));
|
|
89
|
+
});
|
|
90
|
+
}
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Model status extension - shows model changes in the status bar.
|
|
3
|
-
*
|
|
4
|
-
* Demonstrates the `model_select` hook which fires when the model changes
|
|
5
|
-
* via /model command, Ctrl+P cycling, or session restore.
|
|
6
|
-
*
|
|
7
|
-
* Usage: shortcut -e ./model-status.ts
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import type { ExtensionAPI } from 'shortcutxl';
|
|
11
|
-
|
|
12
|
-
export default function (shortcut: ExtensionAPI) {
|
|
13
|
-
shortcut.on('model_select', async (event, ctx) => {
|
|
14
|
-
const { model, previousModel, source } = event;
|
|
15
|
-
|
|
16
|
-
// Format model identifiers
|
|
17
|
-
const next = `${model.provider}/${model.id}`;
|
|
18
|
-
const prev = previousModel ? `${previousModel.provider}/${previousModel.id}` : 'none';
|
|
19
|
-
|
|
20
|
-
// Show notification on change
|
|
21
|
-
if (source !== 'restore') {
|
|
22
|
-
ctx.ui.notify(`Model: ${next}`, 'info');
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
// Update status bar with current model
|
|
26
|
-
ctx.ui.setStatus('model', `🤖 ${model.id}`);
|
|
27
|
-
|
|
28
|
-
// Log change details (visible in debug output)
|
|
29
|
-
console.log(`[model_select] ${prev} → ${next} (${source})`);
|
|
30
|
-
});
|
|
31
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Model status extension - shows model changes in the status bar.
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates the `model_select` hook which fires when the model changes
|
|
5
|
+
* via /model command, Ctrl+P cycling, or session restore.
|
|
6
|
+
*
|
|
7
|
+
* Usage: shortcut -e ./model-status.ts
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { ExtensionAPI } from 'shortcutxl';
|
|
11
|
+
|
|
12
|
+
export default function (shortcut: ExtensionAPI) {
|
|
13
|
+
shortcut.on('model_select', async (event, ctx) => {
|
|
14
|
+
const { model, previousModel, source } = event;
|
|
15
|
+
|
|
16
|
+
// Format model identifiers
|
|
17
|
+
const next = `${model.provider}/${model.id}`;
|
|
18
|
+
const prev = previousModel ? `${previousModel.provider}/${previousModel.id}` : 'none';
|
|
19
|
+
|
|
20
|
+
// Show notification on change
|
|
21
|
+
if (source !== 'restore') {
|
|
22
|
+
ctx.ui.notify(`Model: ${next}`, 'info');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Update status bar with current model
|
|
26
|
+
ctx.ui.setStatus('model', `🤖 ${model.id}`);
|
|
27
|
+
|
|
28
|
+
// Log change details (visible in debug output)
|
|
29
|
+
console.log(`[model_select] ${prev} → ${next} (${source})`);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pi Notify Extension
|
|
3
|
-
*
|
|
4
|
-
* Sends a native terminal notification when Pi agent is done and waiting for input.
|
|
5
|
-
* Supports multiple terminal protocols:
|
|
6
|
-
* - OSC 777: Ghostty, iTerm2, WezTerm, rxvt-unicode
|
|
7
|
-
* - OSC 99: Kitty
|
|
8
|
-
* - Windows toast: Windows Terminal (WSL)
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { ExtensionAPI } from 'shortcutxl';
|
|
12
|
-
|
|
13
|
-
function windowsToastScript(title: string, body: string): string {
|
|
14
|
-
const type = 'Windows.UI.Notifications';
|
|
15
|
-
const mgr = `[${type}.ToastNotificationManager, ${type}, ContentType = WindowsRuntime]`;
|
|
16
|
-
const template = `[${type}.ToastTemplateType]::ToastText01`;
|
|
17
|
-
const toast = `[${type}.ToastNotification]::new($xml)`;
|
|
18
|
-
return [
|
|
19
|
-
`${mgr} > $null`,
|
|
20
|
-
`$xml = [${type}.ToastNotificationManager]::GetTemplateContent(${template})`,
|
|
21
|
-
`$xml.GetElementsByTagName('text')[0].AppendChild($xml.CreateTextNode('${body}')) > $null`,
|
|
22
|
-
`[${type}.ToastNotificationManager]::CreateToastNotifier('${title}').Show(${toast})`
|
|
23
|
-
].join('; ');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function notifyOSC777(title: string, body: string): void {
|
|
27
|
-
process.stdout.write(`\x1b]777;notify;${title};${body}\x07`);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function notifyOSC99(title: string, body: string): void {
|
|
31
|
-
// Kitty OSC 99: i=notification id, d=0 means not done yet, p=body for second part
|
|
32
|
-
process.stdout.write(`\x1b]99;i=1:d=0;${title}\x1b\\`);
|
|
33
|
-
process.stdout.write(`\x1b]99;i=1:p=body;${body}\x1b\\`);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function notifyWindows(title: string, body: string): void {
|
|
37
|
-
const { execFile } = require('child_process');
|
|
38
|
-
execFile('powershell.exe', ['-NoProfile', '-Command', windowsToastScript(title, body)]);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function notify(title: string, body: string): void {
|
|
42
|
-
if (process.env.WT_SESSION) {
|
|
43
|
-
notifyWindows(title, body);
|
|
44
|
-
} else if (process.env.KITTY_WINDOW_ID) {
|
|
45
|
-
notifyOSC99(title, body);
|
|
46
|
-
} else {
|
|
47
|
-
notifyOSC777(title, body);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export default function (shortcut: ExtensionAPI) {
|
|
52
|
-
shortcut.on('agent_end', async () => {
|
|
53
|
-
notify('Pi', 'Ready for input');
|
|
54
|
-
});
|
|
55
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Pi Notify Extension
|
|
3
|
+
*
|
|
4
|
+
* Sends a native terminal notification when Pi agent is done and waiting for input.
|
|
5
|
+
* Supports multiple terminal protocols:
|
|
6
|
+
* - OSC 777: Ghostty, iTerm2, WezTerm, rxvt-unicode
|
|
7
|
+
* - OSC 99: Kitty
|
|
8
|
+
* - Windows toast: Windows Terminal (WSL)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import type { ExtensionAPI } from 'shortcutxl';
|
|
12
|
+
|
|
13
|
+
function windowsToastScript(title: string, body: string): string {
|
|
14
|
+
const type = 'Windows.UI.Notifications';
|
|
15
|
+
const mgr = `[${type}.ToastNotificationManager, ${type}, ContentType = WindowsRuntime]`;
|
|
16
|
+
const template = `[${type}.ToastTemplateType]::ToastText01`;
|
|
17
|
+
const toast = `[${type}.ToastNotification]::new($xml)`;
|
|
18
|
+
return [
|
|
19
|
+
`${mgr} > $null`,
|
|
20
|
+
`$xml = [${type}.ToastNotificationManager]::GetTemplateContent(${template})`,
|
|
21
|
+
`$xml.GetElementsByTagName('text')[0].AppendChild($xml.CreateTextNode('${body}')) > $null`,
|
|
22
|
+
`[${type}.ToastNotificationManager]::CreateToastNotifier('${title}').Show(${toast})`
|
|
23
|
+
].join('; ');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function notifyOSC777(title: string, body: string): void {
|
|
27
|
+
process.stdout.write(`\x1b]777;notify;${title};${body}\x07`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function notifyOSC99(title: string, body: string): void {
|
|
31
|
+
// Kitty OSC 99: i=notification id, d=0 means not done yet, p=body for second part
|
|
32
|
+
process.stdout.write(`\x1b]99;i=1:d=0;${title}\x1b\\`);
|
|
33
|
+
process.stdout.write(`\x1b]99;i=1:p=body;${body}\x1b\\`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function notifyWindows(title: string, body: string): void {
|
|
37
|
+
const { execFile } = require('child_process');
|
|
38
|
+
execFile('powershell.exe', ['-NoProfile', '-Command', windowsToastScript(title, body)]);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function notify(title: string, body: string): void {
|
|
42
|
+
if (process.env.WT_SESSION) {
|
|
43
|
+
notifyWindows(title, body);
|
|
44
|
+
} else if (process.env.KITTY_WINDOW_ID) {
|
|
45
|
+
notifyOSC99(title, body);
|
|
46
|
+
} else {
|
|
47
|
+
notifyOSC777(title, body);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default function (shortcut: ExtensionAPI) {
|
|
52
|
+
shortcut.on('agent_end', async () => {
|
|
53
|
+
notify('Pi', 'Ready for input');
|
|
54
|
+
});
|
|
55
|
+
}
|