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,130 +1,130 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent discovery and configuration
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import * as fs from 'node:fs';
|
|
6
|
-
import * as path from 'node:path';
|
|
7
|
-
import { getAgentDir, parseFrontmatter } from 'shortcutxl';
|
|
8
|
-
|
|
9
|
-
export type AgentScope = 'user' | 'project' | 'both';
|
|
10
|
-
|
|
11
|
-
export interface AgentConfig {
|
|
12
|
-
name: string;
|
|
13
|
-
description: string;
|
|
14
|
-
tools?: string[];
|
|
15
|
-
model?: string;
|
|
16
|
-
systemPrompt: string;
|
|
17
|
-
source: 'user' | 'project';
|
|
18
|
-
filePath: string;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export interface AgentDiscoveryResult {
|
|
22
|
-
agents: AgentConfig[];
|
|
23
|
-
projectAgentsDir: string | null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function loadAgentsFromDir(dir: string, source: 'user' | 'project'): AgentConfig[] {
|
|
27
|
-
const agents: AgentConfig[] = [];
|
|
28
|
-
|
|
29
|
-
if (!fs.existsSync(dir)) {
|
|
30
|
-
return agents;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
let entries: fs.Dirent[];
|
|
34
|
-
try {
|
|
35
|
-
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
36
|
-
} catch {
|
|
37
|
-
return agents;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
for (const entry of entries) {
|
|
41
|
-
if (!entry.name.endsWith('.md')) continue;
|
|
42
|
-
if (!entry.isFile() && !entry.isSymbolicLink()) continue;
|
|
43
|
-
|
|
44
|
-
const filePath = path.join(dir, entry.name);
|
|
45
|
-
let content: string;
|
|
46
|
-
try {
|
|
47
|
-
content = fs.readFileSync(filePath, 'utf-8');
|
|
48
|
-
} catch {
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const { frontmatter, body } = parseFrontmatter<Record<string, string>>(content);
|
|
53
|
-
|
|
54
|
-
if (!frontmatter.name || !frontmatter.description) {
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const tools = frontmatter.tools
|
|
59
|
-
?.split(',')
|
|
60
|
-
.map((t: string) => t.trim())
|
|
61
|
-
.filter(Boolean);
|
|
62
|
-
|
|
63
|
-
agents.push({
|
|
64
|
-
name: frontmatter.name,
|
|
65
|
-
description: frontmatter.description,
|
|
66
|
-
tools: tools && tools.length > 0 ? tools : undefined,
|
|
67
|
-
model: frontmatter.model,
|
|
68
|
-
systemPrompt: body,
|
|
69
|
-
source,
|
|
70
|
-
filePath
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return agents;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function isDirectory(p: string): boolean {
|
|
78
|
-
try {
|
|
79
|
-
return fs.statSync(p).isDirectory();
|
|
80
|
-
} catch {
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function findNearestProjectAgentsDir(cwd: string): string | null {
|
|
86
|
-
let currentDir = cwd;
|
|
87
|
-
while (true) {
|
|
88
|
-
const candidate = path.join(currentDir, '.shortcut', 'agents');
|
|
89
|
-
if (isDirectory(candidate)) return candidate;
|
|
90
|
-
|
|
91
|
-
const parentDir = path.dirname(currentDir);
|
|
92
|
-
if (parentDir === currentDir) return null;
|
|
93
|
-
currentDir = parentDir;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryResult {
|
|
98
|
-
const userDir = path.join(getAgentDir(), 'agents');
|
|
99
|
-
const projectAgentsDir = findNearestProjectAgentsDir(cwd);
|
|
100
|
-
|
|
101
|
-
const userAgents = scope === 'project' ? [] : loadAgentsFromDir(userDir, 'user');
|
|
102
|
-
const projectAgents =
|
|
103
|
-
scope === 'user' || !projectAgentsDir ? [] : loadAgentsFromDir(projectAgentsDir, 'project');
|
|
104
|
-
|
|
105
|
-
const agentMap = new Map<string, AgentConfig>();
|
|
106
|
-
|
|
107
|
-
if (scope === 'both') {
|
|
108
|
-
for (const agent of userAgents) agentMap.set(agent.name, agent);
|
|
109
|
-
for (const agent of projectAgents) agentMap.set(agent.name, agent);
|
|
110
|
-
} else if (scope === 'user') {
|
|
111
|
-
for (const agent of userAgents) agentMap.set(agent.name, agent);
|
|
112
|
-
} else {
|
|
113
|
-
for (const agent of projectAgents) agentMap.set(agent.name, agent);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
return { agents: Array.from(agentMap.values()), projectAgentsDir };
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function formatAgentList(
|
|
120
|
-
agents: AgentConfig[],
|
|
121
|
-
maxItems: number
|
|
122
|
-
): { text: string; remaining: number } {
|
|
123
|
-
if (agents.length === 0) return { text: 'none', remaining: 0 };
|
|
124
|
-
const listed = agents.slice(0, maxItems);
|
|
125
|
-
const remaining = agents.length - listed.length;
|
|
126
|
-
return {
|
|
127
|
-
text: listed.map((a) => `${a.name} (${a.source}): ${a.description}`).join('; '),
|
|
128
|
-
remaining
|
|
129
|
-
};
|
|
130
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Agent discovery and configuration
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import * as fs from 'node:fs';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
import { getAgentDir, parseFrontmatter } from 'shortcutxl';
|
|
8
|
+
|
|
9
|
+
export type AgentScope = 'user' | 'project' | 'both';
|
|
10
|
+
|
|
11
|
+
export interface AgentConfig {
|
|
12
|
+
name: string;
|
|
13
|
+
description: string;
|
|
14
|
+
tools?: string[];
|
|
15
|
+
model?: string;
|
|
16
|
+
systemPrompt: string;
|
|
17
|
+
source: 'user' | 'project';
|
|
18
|
+
filePath: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface AgentDiscoveryResult {
|
|
22
|
+
agents: AgentConfig[];
|
|
23
|
+
projectAgentsDir: string | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function loadAgentsFromDir(dir: string, source: 'user' | 'project'): AgentConfig[] {
|
|
27
|
+
const agents: AgentConfig[] = [];
|
|
28
|
+
|
|
29
|
+
if (!fs.existsSync(dir)) {
|
|
30
|
+
return agents;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let entries: fs.Dirent[];
|
|
34
|
+
try {
|
|
35
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
36
|
+
} catch {
|
|
37
|
+
return agents;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
for (const entry of entries) {
|
|
41
|
+
if (!entry.name.endsWith('.md')) continue;
|
|
42
|
+
if (!entry.isFile() && !entry.isSymbolicLink()) continue;
|
|
43
|
+
|
|
44
|
+
const filePath = path.join(dir, entry.name);
|
|
45
|
+
let content: string;
|
|
46
|
+
try {
|
|
47
|
+
content = fs.readFileSync(filePath, 'utf-8');
|
|
48
|
+
} catch {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const { frontmatter, body } = parseFrontmatter<Record<string, string>>(content);
|
|
53
|
+
|
|
54
|
+
if (!frontmatter.name || !frontmatter.description) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const tools = frontmatter.tools
|
|
59
|
+
?.split(',')
|
|
60
|
+
.map((t: string) => t.trim())
|
|
61
|
+
.filter(Boolean);
|
|
62
|
+
|
|
63
|
+
agents.push({
|
|
64
|
+
name: frontmatter.name,
|
|
65
|
+
description: frontmatter.description,
|
|
66
|
+
tools: tools && tools.length > 0 ? tools : undefined,
|
|
67
|
+
model: frontmatter.model,
|
|
68
|
+
systemPrompt: body,
|
|
69
|
+
source,
|
|
70
|
+
filePath
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return agents;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function isDirectory(p: string): boolean {
|
|
78
|
+
try {
|
|
79
|
+
return fs.statSync(p).isDirectory();
|
|
80
|
+
} catch {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function findNearestProjectAgentsDir(cwd: string): string | null {
|
|
86
|
+
let currentDir = cwd;
|
|
87
|
+
while (true) {
|
|
88
|
+
const candidate = path.join(currentDir, '.shortcut', 'agents');
|
|
89
|
+
if (isDirectory(candidate)) return candidate;
|
|
90
|
+
|
|
91
|
+
const parentDir = path.dirname(currentDir);
|
|
92
|
+
if (parentDir === currentDir) return null;
|
|
93
|
+
currentDir = parentDir;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function discoverAgents(cwd: string, scope: AgentScope): AgentDiscoveryResult {
|
|
98
|
+
const userDir = path.join(getAgentDir(), 'agents');
|
|
99
|
+
const projectAgentsDir = findNearestProjectAgentsDir(cwd);
|
|
100
|
+
|
|
101
|
+
const userAgents = scope === 'project' ? [] : loadAgentsFromDir(userDir, 'user');
|
|
102
|
+
const projectAgents =
|
|
103
|
+
scope === 'user' || !projectAgentsDir ? [] : loadAgentsFromDir(projectAgentsDir, 'project');
|
|
104
|
+
|
|
105
|
+
const agentMap = new Map<string, AgentConfig>();
|
|
106
|
+
|
|
107
|
+
if (scope === 'both') {
|
|
108
|
+
for (const agent of userAgents) agentMap.set(agent.name, agent);
|
|
109
|
+
for (const agent of projectAgents) agentMap.set(agent.name, agent);
|
|
110
|
+
} else if (scope === 'user') {
|
|
111
|
+
for (const agent of userAgents) agentMap.set(agent.name, agent);
|
|
112
|
+
} else {
|
|
113
|
+
for (const agent of projectAgents) agentMap.set(agent.name, agent);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return { agents: Array.from(agentMap.values()), projectAgentsDir };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function formatAgentList(
|
|
120
|
+
agents: AgentConfig[],
|
|
121
|
+
maxItems: number
|
|
122
|
+
): { text: string; remaining: number } {
|
|
123
|
+
if (agents.length === 0) return { text: 'none', remaining: 0 };
|
|
124
|
+
const listed = agents.slice(0, maxItems);
|
|
125
|
+
const remaining = agents.length - listed.length;
|
|
126
|
+
return {
|
|
127
|
+
text: listed.map((a) => `${a.name} (${a.source}): ${a.description}`).join('; '),
|
|
128
|
+
remaining
|
|
129
|
+
};
|
|
130
|
+
}
|