@vybestack/llxprt-code 0.3.4-nightly.250918.ed04d656 → 0.3.4-nightly.250921.fdbf3cd7
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 +3 -0
- package/dist/package.json +7 -6
- package/dist/src/commands/extensions/examples/context/LLXPRT.md +8 -0
- package/dist/src/commands/extensions/examples/context/llxprt-extension.json +5 -0
- package/dist/src/commands/extensions/examples/custom-commands/commands/fs/grep-code.toml +6 -0
- package/dist/src/commands/extensions/examples/custom-commands/llxprt-extension.json +4 -0
- package/dist/src/commands/extensions/examples/exclude-tools/llxprt-extension.json +5 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.d.ts +6 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.js +46 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.js.map +1 -0
- package/dist/src/commands/extensions/examples/mcp-server/example.ts +60 -0
- package/dist/src/commands/extensions/examples/mcp-server/llxprt-extension.json +10 -0
- package/dist/src/commands/extensions/install.js +35 -7
- package/dist/src/commands/extensions/install.js.map +1 -1
- package/dist/src/commands/extensions/install.test.js +20 -2
- package/dist/src/commands/extensions/install.test.js.map +1 -1
- package/dist/src/commands/extensions/link.d.ts +12 -0
- package/dist/src/commands/extensions/link.js +37 -0
- package/dist/src/commands/extensions/link.js.map +1 -0
- package/dist/src/commands/extensions/new.d.ts +7 -0
- package/dist/src/commands/extensions/new.js +70 -0
- package/dist/src/commands/extensions/new.js.map +1 -0
- package/dist/src/commands/extensions/new.test.d.ts +6 -0
- package/dist/src/commands/extensions/new.test.js +50 -0
- package/dist/src/commands/extensions/new.test.js.map +1 -0
- package/dist/src/commands/extensions/update.d.ts +2 -1
- package/dist/src/commands/extensions/update.js +40 -13
- package/dist/src/commands/extensions/update.js.map +1 -1
- package/dist/src/commands/extensions.js +4 -0
- package/dist/src/commands/extensions.js.map +1 -1
- package/dist/src/commands/mcp/add.js +1 -1
- package/dist/src/commands/mcp/add.js.map +1 -1
- package/dist/src/commands/mcp/list.js +2 -2
- package/dist/src/commands/mcp/list.js.map +1 -1
- package/dist/src/commands/mcp/remove.js +1 -1
- package/dist/src/commands/mcp/remove.js.map +1 -1
- package/dist/src/config/auth.d.ts +1 -1
- package/dist/src/config/auth.js +6 -13
- package/dist/src/config/auth.js.map +1 -1
- package/dist/src/config/auth.test.js +13 -7
- package/dist/src/config/auth.test.js.map +1 -1
- package/dist/src/config/config.d.ts +4 -1
- package/dist/src/config/config.js +47 -23
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/extension.d.ts +8 -5
- package/dist/src/config/extension.js +76 -24
- package/dist/src/config/extension.js.map +1 -1
- package/dist/src/config/keyBindings.d.ts +1 -0
- package/dist/src/config/keyBindings.js +6 -25
- package/dist/src/config/keyBindings.js.map +1 -1
- package/dist/src/config/settings.d.ts +4 -4
- package/dist/src/config/settings.js +101 -68
- package/dist/src/config/settings.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +252 -3
- package/dist/src/config/settingsSchema.js +248 -3
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/config/trustedFolders.d.ts +14 -3
- package/dist/src/config/trustedFolders.js +63 -37
- package/dist/src/config/trustedFolders.js.map +1 -1
- package/dist/src/config/trustedFolders.test.js +84 -9
- package/dist/src/config/trustedFolders.test.js.map +1 -1
- package/dist/src/gemini.js +74 -18
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.js +7 -23
- package/dist/src/gemini.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +1 -1
- package/dist/src/generated/git-commit.js +1 -1
- package/dist/src/nonInteractiveCli.js +32 -2
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/providers/providerManagerInstance.js +0 -1
- package/dist/src/providers/providerManagerInstance.js.map +1 -1
- package/dist/src/services/FileCommandLoader.d.ts +2 -0
- package/dist/src/services/FileCommandLoader.js +7 -0
- package/dist/src/services/FileCommandLoader.js.map +1 -1
- package/dist/src/ui/App.js +103 -51
- package/dist/src/ui/App.js.map +1 -1
- package/dist/src/ui/commands/directoryCommand.js +1 -1
- package/dist/src/ui/commands/directoryCommand.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.js +1 -1
- package/dist/src/ui/commands/memoryCommand.js.map +1 -1
- package/dist/src/ui/components/AuthDialog.test.js +13 -13
- package/dist/src/ui/components/AuthDialog.test.js.map +1 -1
- package/dist/src/ui/components/FolderTrustDialog.js +5 -3
- package/dist/src/ui/components/FolderTrustDialog.js.map +1 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js +21 -6
- package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/Footer.d.ts +3 -0
- package/dist/src/ui/components/Footer.js +4 -4
- package/dist/src/ui/components/Footer.js.map +1 -1
- package/dist/src/ui/components/GeminiRespondingSpinner.js +5 -3
- package/dist/src/ui/components/GeminiRespondingSpinner.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.d.ts +2 -2
- package/dist/src/ui/components/InputPrompt.js +35 -25
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/MemoryUsageDisplay.js +1 -1
- package/dist/src/ui/components/MemoryUsageDisplay.js.map +1 -1
- package/dist/src/ui/components/ProQuotaDialog.d.ts +13 -0
- package/dist/src/ui/components/ProQuotaDialog.js +22 -0
- package/dist/src/ui/components/ProQuotaDialog.js.map +1 -0
- package/dist/src/ui/components/ProQuotaDialog.test.d.ts +6 -0
- package/dist/src/ui/components/ProQuotaDialog.test.js +57 -0
- package/dist/src/ui/components/ProQuotaDialog.test.js.map +1 -0
- package/dist/src/ui/components/SettingsDialog.test.js +2 -2
- package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
- package/dist/src/ui/components/messages/CompressionMessage.js +1 -1
- package/dist/src/ui/components/messages/CompressionMessage.js.map +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.js +5 -1
- package/dist/src/ui/components/messages/DiffRenderer.js.map +1 -1
- package/dist/src/ui/components/messages/GeminiMessage.js +1 -1
- package/dist/src/ui/components/messages/GeminiMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js +0 -8
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolMessage.js +2 -1
- package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
- package/dist/src/ui/components/messages/UserMessage.js +1 -1
- package/dist/src/ui/components/messages/UserMessage.js.map +1 -1
- package/dist/src/ui/components/shared/MaxSizedBox.js.map +1 -1
- package/dist/src/ui/components/shared/RadioButtonSelect.js +1 -1
- package/dist/src/ui/components/shared/RadioButtonSelect.js.map +1 -1
- package/dist/src/ui/components/shared/RadioButtonSelect.test.js +2 -2
- package/dist/src/ui/components/shared/RadioButtonSelect.test.js.map +1 -1
- package/dist/src/ui/components/shared/text-buffer.js +35 -51
- package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
- package/dist/src/ui/constants.d.ts +8 -2
- package/dist/src/ui/constants.js +9 -2
- package/dist/src/ui/constants.js.map +1 -1
- package/dist/src/ui/containers/SessionController.js +1 -1
- package/dist/src/ui/containers/SessionController.js.map +1 -1
- package/dist/src/ui/containers/SessionController.test.js +1 -0
- package/dist/src/ui/containers/SessionController.test.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.js +255 -42
- package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.test.js +115 -1
- package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.js +3 -1
- package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/useFolderTrust.js +6 -3
- package/dist/src/ui/hooks/useFolderTrust.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.d.ts +2 -1
- package/dist/src/ui/hooks/useGeminiStream.integration.test.js +1 -1
- package/dist/src/ui/hooks/useGeminiStream.integration.test.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.js +170 -35
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useIdeTrustListener.d.ts +15 -0
- package/dist/src/ui/hooks/useIdeTrustListener.js +37 -0
- package/dist/src/ui/hooks/useIdeTrustListener.js.map +1 -0
- package/dist/src/ui/hooks/useInputHistoryStore.d.ts +19 -0
- package/dist/src/ui/hooks/useInputHistoryStore.js +81 -0
- package/dist/src/ui/hooks/useInputHistoryStore.js.map +1 -0
- package/dist/src/ui/hooks/useInputHistoryStore.test.d.ts +6 -0
- package/dist/src/ui/hooks/useInputHistoryStore.test.js +234 -0
- package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -0
- package/dist/src/ui/hooks/useLoadingIndicator.d.ts +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.js +2 -2
- package/dist/src/ui/hooks/useLoadingIndicator.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.test.d.ts +6 -0
- package/dist/src/ui/hooks/useLoadingIndicator.test.js +102 -0
- package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -0
- package/dist/src/ui/hooks/usePhraseCycler.d.ts +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.js +25 -17
- package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
- package/dist/src/ui/hooks/usePrivacySettings.d.ts +1 -1
- package/dist/src/ui/hooks/usePrivacySettings.js +20 -13
- package/dist/src/ui/hooks/usePrivacySettings.js.map +1 -1
- package/dist/src/ui/hooks/usePrivacySettings.test.js +52 -105
- package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js +57 -70
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/keyMatchers.test.js +9 -0
- package/dist/src/ui/keyMatchers.test.js.map +1 -1
- package/dist/src/ui/textConstants.d.ts +9 -0
- package/dist/src/ui/textConstants.js +10 -0
- package/dist/src/ui/textConstants.js.map +1 -0
- package/dist/src/ui/utils/MarkdownDisplay.test.js +2 -2
- package/dist/src/ui/utils/MarkdownDisplay.test.js.map +1 -1
- package/dist/src/ui/utils/highlight.d.ts +10 -0
- package/dist/src/ui/utils/highlight.js +41 -0
- package/dist/src/ui/utils/highlight.js.map +1 -0
- package/dist/src/ui/utils/highlight.test.d.ts +6 -0
- package/dist/src/ui/utils/highlight.test.js +93 -0
- package/dist/src/ui/utils/highlight.test.js.map +1 -0
- package/dist/src/ui/utils/platformConstants.d.ts +24 -1
- package/dist/src/ui/utils/platformConstants.js +26 -1
- package/dist/src/ui/utils/platformConstants.js.map +1 -1
- package/dist/src/utils/envVarResolver.d.ts +39 -0
- package/dist/src/utils/envVarResolver.js +97 -0
- package/dist/src/utils/envVarResolver.js.map +1 -0
- package/dist/src/utils/envVarResolver.test.d.ts +6 -0
- package/dist/src/utils/envVarResolver.test.js +221 -0
- package/dist/src/utils/envVarResolver.test.js.map +1 -0
- package/dist/src/utils/errors.d.ts +9 -0
- package/dist/src/utils/errors.js +18 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/userStartupWarnings.d.ts +1 -1
- package/dist/src/utils/userStartupWarnings.js +1 -1
- package/dist/src/utils/userStartupWarnings.js.map +1 -1
- package/dist/src/zed-integration/schema.d.ts +398 -398
- package/dist/src/zed-integration/zedIntegration.js +11 -7
- package/dist/src/zed-integration/zedIntegration.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -6
package/README.md
CHANGED
@@ -3,6 +3,8 @@
|
|
3
3
|
[](https://github.com/acoliver/llxprt-code/actions/workflows/ci.yml)
|
4
4
|
|
5
5
|
[](https://github.com/Piebald-AI/awesome-gemini-cli)
|
6
|
+
|
7
|
+
[](https://discord.gg/Wc6dZqWWYv)
|
6
8
|
|
7
9
|

|
8
10
|
|
@@ -54,6 +56,7 @@ You have two options to install LLxprt Code.
|
|
54
56
|
```bash
|
55
57
|
llxprt
|
56
58
|
```
|
59
|
+
|
57
60
|
- Pick a beautiful theme
|
58
61
|
- Choose your provider with `/provider` (defaults to Gemini)
|
59
62
|
- Set up authentication as needed
|
package/dist/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@vybestack/llxprt-code",
|
3
|
-
"version": "0.3.4-nightly.
|
3
|
+
"version": "0.3.4-nightly.250921.fdbf3cd7",
|
4
4
|
"description": "LLxprt Code",
|
5
5
|
"repository": {
|
6
6
|
"type": "git",
|
@@ -33,26 +33,28 @@
|
|
33
33
|
"dist"
|
34
34
|
],
|
35
35
|
"config": {
|
36
|
-
"sandboxImageUri": "ghcr.io/acoliver/llxprt-code/sandbox:0.3.4-nightly.
|
36
|
+
"sandboxImageUri": "ghcr.io/acoliver/llxprt-code/sandbox:0.3.4-nightly.250921.fdbf3cd7"
|
37
37
|
},
|
38
38
|
"dependencies": {
|
39
39
|
"@anthropic-ai/sdk": "^0.55.1",
|
40
40
|
"@dqbd/tiktoken": "^1.0.21",
|
41
|
-
"@google/genai": "1.
|
41
|
+
"@google/genai": "1.16.0",
|
42
42
|
"@iarna/toml": "^2.2.5",
|
43
43
|
"@modelcontextprotocol/sdk": "^1.15.1",
|
44
44
|
"@types/update-notifier": "^6.0.8",
|
45
|
-
"@vybestack/llxprt-code-core": "0.3.4-nightly.
|
45
|
+
"@vybestack/llxprt-code-core": "0.3.4-nightly.250921.fdbf3cd7",
|
46
46
|
"chalk": "^5.3.0",
|
47
47
|
"command-exists": "^1.2.9",
|
48
48
|
"diff": "^7.0.0",
|
49
49
|
"dotenv": "^17.1.0",
|
50
|
+
"fzf": "^0.5.2",
|
50
51
|
"glob": "^10.4.1",
|
51
52
|
"highlight.js": "^11.11.1",
|
52
|
-
"ink": "^6.
|
53
|
+
"ink": "^6.3.1",
|
53
54
|
"ink-gradient": "^3.0.0",
|
54
55
|
"ink-select-input": "^6.2.0",
|
55
56
|
"ink-spinner": "^5.0.0",
|
57
|
+
"ink-testing-library": "^4.0.0",
|
56
58
|
"lowlight": "^3.3.0",
|
57
59
|
"mime-types": "^3.0.1",
|
58
60
|
"open": "^10.1.2",
|
@@ -84,7 +86,6 @@
|
|
84
86
|
"@types/yargs": "^17.0.33",
|
85
87
|
"@vybestack/llxprt-code-test-utils": "file:../test-utils",
|
86
88
|
"dom-accessibility-api": "^0.5.16",
|
87
|
-
"ink-testing-library": "^4.0.0",
|
88
89
|
"jsdom": "^26.1.0",
|
89
90
|
"lz-string": "^1.5.0",
|
90
91
|
"pretty-format": "^30.0.2",
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Ink Library Screen Reader Guidance
|
2
|
+
|
3
|
+
When building custom components, it's important to keep accessibility in mind. While Ink provides the building blocks, ensuring your components are accessible will make your CLIs usable by a wider audience.
|
4
|
+
|
5
|
+
## General Principles
|
6
|
+
|
7
|
+
Provide screen reader-friendly output: Use the useIsScreenReaderEnabled hook to detect if a screen reader is active. You can then render a more descriptive output for screen reader users.
|
8
|
+
Leverage ARIA props: For components that have a specific role (e.g., a checkbox or a button), use the aria-role, aria-state, and aria-label props on <Box> and <Text> to provide semantic meaning to screen readers.
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Google LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
7
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
8
|
+
import { z } from 'zod';
|
9
|
+
const server = new McpServer({
|
10
|
+
name: 'prompt-server',
|
11
|
+
version: '1.0.0',
|
12
|
+
});
|
13
|
+
server.registerTool('fetch_posts', {
|
14
|
+
description: 'Fetches a list of posts from a public API.',
|
15
|
+
inputSchema: z.object({}).shape,
|
16
|
+
}, async () => {
|
17
|
+
const apiResponse = await fetch('https://jsonplaceholder.typicode.com/posts');
|
18
|
+
const posts = await apiResponse.json();
|
19
|
+
const response = { posts: posts.slice(0, 5) };
|
20
|
+
return {
|
21
|
+
content: [
|
22
|
+
{
|
23
|
+
type: 'text',
|
24
|
+
text: JSON.stringify(response),
|
25
|
+
},
|
26
|
+
],
|
27
|
+
};
|
28
|
+
});
|
29
|
+
server.registerPrompt('poem-writer', {
|
30
|
+
title: 'Poem Writer',
|
31
|
+
description: 'Write a nice haiku',
|
32
|
+
argsSchema: { title: z.string(), mood: z.string().optional() },
|
33
|
+
}, ({ title, mood }) => ({
|
34
|
+
messages: [
|
35
|
+
{
|
36
|
+
role: 'user',
|
37
|
+
content: {
|
38
|
+
type: 'text',
|
39
|
+
text: `Write a haiku${mood ? ` with the mood ${mood}` : ''} called ${title}. Note that a haiku is 5 syllables followed by 7 syllables followed by 5 syllables `,
|
40
|
+
},
|
41
|
+
},
|
42
|
+
],
|
43
|
+
}));
|
44
|
+
const transport = new StdioServerTransport();
|
45
|
+
await server.connect(transport);
|
46
|
+
//# sourceMappingURL=example.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"example.js","sourceRoot":"","sources":["../../../../../../src/commands/extensions/examples/mcp-server/example.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,MAAM,CAAC,YAAY,CACjB,aAAa,EACb;IACE,WAAW,EAAE,4CAA4C;IACzD,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK;CAChC,EACD,KAAK,IAAI,EAAE;IACT,MAAM,WAAW,GAAG,MAAM,KAAK,CAC7B,4CAA4C,CAC7C,CAAC;IACF,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;IACvC,MAAM,QAAQ,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAC9C,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC;aAC/B;SACF;KACF,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,MAAM,CAAC,cAAc,CACnB,aAAa,EACb;IACE,KAAK,EAAE,aAAa;IACpB,WAAW,EAAE,oBAAoB;IACjC,UAAU,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE;CAC/D,EACD,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;IACpB,QAAQ,EAAE;QACR;YACE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE;gBACP,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,gBAAgB,IAAI,CAAC,CAAC,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,qFAAqF;aAChK;SACF;KACF;CACF,CAAC,CACH,CAAC;AAEF,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Google LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
|
7
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
8
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
9
|
+
import { z } from 'zod';
|
10
|
+
|
11
|
+
const server = new McpServer({
|
12
|
+
name: 'prompt-server',
|
13
|
+
version: '1.0.0',
|
14
|
+
});
|
15
|
+
|
16
|
+
server.registerTool(
|
17
|
+
'fetch_posts',
|
18
|
+
{
|
19
|
+
description: 'Fetches a list of posts from a public API.',
|
20
|
+
inputSchema: z.object({}).shape,
|
21
|
+
},
|
22
|
+
async () => {
|
23
|
+
const apiResponse = await fetch(
|
24
|
+
'https://jsonplaceholder.typicode.com/posts',
|
25
|
+
);
|
26
|
+
const posts = await apiResponse.json();
|
27
|
+
const response = { posts: posts.slice(0, 5) };
|
28
|
+
return {
|
29
|
+
content: [
|
30
|
+
{
|
31
|
+
type: 'text',
|
32
|
+
text: JSON.stringify(response),
|
33
|
+
},
|
34
|
+
],
|
35
|
+
};
|
36
|
+
},
|
37
|
+
);
|
38
|
+
|
39
|
+
server.registerPrompt(
|
40
|
+
'poem-writer',
|
41
|
+
{
|
42
|
+
title: 'Poem Writer',
|
43
|
+
description: 'Write a nice haiku',
|
44
|
+
argsSchema: { title: z.string(), mood: z.string().optional() },
|
45
|
+
},
|
46
|
+
({ title, mood }) => ({
|
47
|
+
messages: [
|
48
|
+
{
|
49
|
+
role: 'user',
|
50
|
+
content: {
|
51
|
+
type: 'text',
|
52
|
+
text: `Write a haiku${mood ? ` with the mood ${mood}` : ''} called ${title}. Note that a haiku is 5 syllables followed by 7 syllables followed by 5 syllables `,
|
53
|
+
},
|
54
|
+
},
|
55
|
+
],
|
56
|
+
}),
|
57
|
+
);
|
58
|
+
|
59
|
+
const transport = new StdioServerTransport();
|
60
|
+
await server.connect(transport);
|
@@ -4,12 +4,40 @@
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
5
5
|
*/
|
6
6
|
import { installExtension, } from '../../config/extension.js';
|
7
|
+
const ORG_REPO_REGEX = /^[a-zA-Z0-9-]+\/[\w.-]+$/;
|
7
8
|
export async function handleInstall(args) {
|
8
9
|
try {
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
let installMetadata;
|
11
|
+
if (args.source) {
|
12
|
+
const { source } = args;
|
13
|
+
if (source.startsWith('http://') ||
|
14
|
+
source.startsWith('https://') ||
|
15
|
+
source.startsWith('git@')) {
|
16
|
+
installMetadata = {
|
17
|
+
source,
|
18
|
+
type: 'git',
|
19
|
+
};
|
20
|
+
}
|
21
|
+
else if (ORG_REPO_REGEX.test(source)) {
|
22
|
+
installMetadata = {
|
23
|
+
source: `https://github.com/${source}.git`,
|
24
|
+
type: 'git',
|
25
|
+
};
|
26
|
+
}
|
27
|
+
else {
|
28
|
+
throw new Error(`The source "${source}" is not a valid URL or "org/repo" format.`);
|
29
|
+
}
|
30
|
+
}
|
31
|
+
else if (args.path) {
|
32
|
+
installMetadata = {
|
33
|
+
source: args.path,
|
34
|
+
type: 'local',
|
35
|
+
};
|
36
|
+
}
|
37
|
+
else {
|
38
|
+
// This should not be reached due to the yargs check.
|
39
|
+
throw new Error('Either --source or --path must be provided.');
|
40
|
+
}
|
13
41
|
const extensionName = await installExtension(installMetadata);
|
14
42
|
console.log(`Extension "${extensionName}" installed successfully and enabled.`);
|
15
43
|
}
|
@@ -20,10 +48,10 @@ export async function handleInstall(args) {
|
|
20
48
|
}
|
21
49
|
export const installCommand = {
|
22
50
|
command: 'install [--source | --path ]',
|
23
|
-
describe: 'Installs an extension from a git repository or a local path.',
|
51
|
+
describe: 'Installs an extension from a git repository (URL or "org/repo") or a local path.',
|
24
52
|
builder: (yargs) => yargs
|
25
53
|
.option('source', {
|
26
|
-
describe: 'The git URL of the extension to install.',
|
54
|
+
describe: 'The git URL or "org/repo" of the extension to install.',
|
27
55
|
type: 'string',
|
28
56
|
})
|
29
57
|
.option('path', {
|
@@ -33,7 +61,7 @@ export const installCommand = {
|
|
33
61
|
.conflicts('source', 'path')
|
34
62
|
.check((argv) => {
|
35
63
|
if (!argv.source && !argv.path) {
|
36
|
-
throw new Error('Either
|
64
|
+
throw new Error('Either --source or --path must be provided.');
|
37
65
|
}
|
38
66
|
return true;
|
39
67
|
}),
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../../src/commands/extensions/install.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,gBAAgB,GAEjB,MAAM,2BAA2B,CAAC;AAOnC,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAiB;IACnD,IAAI,CAAC;QACH,
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../../src/commands/extensions/install.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,gBAAgB,GAEjB,MAAM,2BAA2B,CAAC;AAOnC,MAAM,cAAc,GAAG,0BAA0B,CAAC;AAElD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAiB;IACnD,IAAI,CAAC;QACH,IAAI,eAAyC,CAAC;QAE9C,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;YACxB,IACE,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC;gBAC5B,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC;gBAC7B,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EACzB,CAAC;gBACD,eAAe,GAAG;oBAChB,MAAM;oBACN,IAAI,EAAE,KAAK;iBACZ,CAAC;YACJ,CAAC;iBAAM,IAAI,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBACvC,eAAe,GAAG;oBAChB,MAAM,EAAE,sBAAsB,MAAM,MAAM;oBAC1C,IAAI,EAAE,KAAK;iBACZ,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,KAAK,CACb,eAAe,MAAM,4CAA4C,CAClE,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACrB,eAAe,GAAG;gBAChB,MAAM,EAAE,IAAI,CAAC,IAAI;gBACjB,IAAI,EAAE,OAAO;aACd,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,qDAAqD;YACrD,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,eAAe,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CACT,cAAc,aAAa,uCAAuC,CACnE,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAE,KAAe,CAAC,OAAO,CAAC,CAAC;QACxC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,cAAc,GAAkB;IAC3C,OAAO,EAAE,8BAA8B;IACvC,QAAQ,EACN,kFAAkF;IACpF,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,MAAM,CAAC,QAAQ,EAAE;QAChB,QAAQ,EAAE,wDAAwD;QAClE,IAAI,EAAE,QAAQ;KACf,CAAC;SACD,MAAM,CAAC,MAAM,EAAE;QACd,QAAQ,EAAE,sCAAsC;QAChD,IAAI,EAAE,QAAQ;KACf,CAAC;SACD,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC;SAC3B,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE;QACd,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;IACN,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,MAAM,aAAa,CAAC;YAClB,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAuB;YAC5C,IAAI,EAAE,IAAI,CAAC,MAAM,CAAuB;SACzC,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
@@ -4,16 +4,34 @@
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
5
5
|
*/
|
6
6
|
import { describe, it, expect } from 'vitest';
|
7
|
-
import { installCommand } from './install.js';
|
7
|
+
import { installCommand, handleInstall } from './install.js';
|
8
8
|
import yargs from 'yargs';
|
9
|
+
import * as extension from '../../config/extension.js';
|
10
|
+
vi.mock('../../config/extension.js', () => ({
|
11
|
+
installExtension: vi.fn(),
|
12
|
+
}));
|
9
13
|
describe('extensions install command', () => {
|
10
14
|
it('should fail if no source is provided', () => {
|
11
15
|
const validationParser = yargs([]).command(installCommand).fail(false);
|
12
|
-
expect(() => validationParser.parse('install')).toThrow('Either
|
16
|
+
expect(() => validationParser.parse('install')).toThrow('Either --source or --path must be provided.');
|
13
17
|
});
|
14
18
|
it('should fail if both git source and local path are provided', () => {
|
15
19
|
const validationParser = yargs([]).command(installCommand).fail(false);
|
16
20
|
expect(() => validationParser.parse('install --source some-url --path /some/path')).toThrow('Arguments source and path are mutually exclusive');
|
17
21
|
});
|
18
22
|
});
|
23
|
+
describe('extensions install with org/repo', () => {
|
24
|
+
it('should call installExtension with the correct git URL', async () => {
|
25
|
+
const consoleLogSpy = vi.spyOn(console, 'log').mockImplementation(() => { });
|
26
|
+
const installExtensionSpy = vi
|
27
|
+
.spyOn(extension, 'installExtension')
|
28
|
+
.mockResolvedValue('test-extension');
|
29
|
+
await handleInstall({ source: 'test-org/test-repo' });
|
30
|
+
expect(installExtensionSpy).toHaveBeenCalledWith({
|
31
|
+
source: 'https://github.com/test-org/test-repo.git',
|
32
|
+
type: 'git',
|
33
|
+
});
|
34
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('Extension "test-extension" installed successfully and enabled.');
|
35
|
+
});
|
36
|
+
});
|
19
37
|
//# sourceMappingURL=install.test.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"install.test.js","sourceRoot":"","sources":["../../../../src/commands/extensions/install.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;
|
1
|
+
{"version":3,"file":"install.test.js","sourceRoot":"","sources":["../../../../src/commands/extensions/install.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7D,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,KAAK,SAAS,MAAM,2BAA2B,CAAC;AAEvD,EAAE,CAAC,IAAI,CAAC,2BAA2B,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1C,gBAAgB,EAAE,EAAE,CAAC,EAAE,EAAE;CAC1B,CAAC,CAAC,CAAC;AAEJ,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC9C,MAAM,gBAAgB,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CACrD,6CAA6C,CAC9C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;QACpE,MAAM,gBAAgB,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvE,MAAM,CAAC,GAAG,EAAE,CACV,gBAAgB,CAAC,KAAK,CAAC,6CAA6C,CAAC,CACtE,CAAC,OAAO,CAAC,kDAAkD,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,aAAa,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC5E,MAAM,mBAAmB,GAAG,EAAE;aAC3B,KAAK,CAAC,SAAS,EAAE,kBAAkB,CAAC;aACpC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;QAEvC,MAAM,aAAa,CAAC,EAAE,MAAM,EAAE,oBAAoB,EAAE,CAAC,CAAC;QAEtD,MAAM,CAAC,mBAAmB,CAAC,CAAC,oBAAoB,CAAC;YAC/C,MAAM,EAAE,2CAA2C;YACnD,IAAI,EAAE,KAAK;SACZ,CAAC,CAAC;QACH,MAAM,CAAC,aAAa,CAAC,CAAC,oBAAoB,CACxC,gEAAgE,CACjE,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Google LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
import type { CommandModule } from 'yargs';
|
7
|
+
interface InstallArgs {
|
8
|
+
path: string;
|
9
|
+
}
|
10
|
+
export declare function handleLink(args: InstallArgs): Promise<void>;
|
11
|
+
export declare const linkCommand: CommandModule;
|
12
|
+
export {};
|
@@ -0,0 +1,37 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Google LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
import { installExtension, } from '../../config/extension.js';
|
7
|
+
import { getErrorMessage } from '../../utils/errors.js';
|
8
|
+
export async function handleLink(args) {
|
9
|
+
try {
|
10
|
+
const installMetadata = {
|
11
|
+
source: args.path,
|
12
|
+
type: 'link',
|
13
|
+
};
|
14
|
+
const extensionName = await installExtension(installMetadata);
|
15
|
+
console.log(`Extension "${extensionName}" linked successfully and enabled.`);
|
16
|
+
}
|
17
|
+
catch (error) {
|
18
|
+
console.error(getErrorMessage(error));
|
19
|
+
process.exit(1);
|
20
|
+
}
|
21
|
+
}
|
22
|
+
export const linkCommand = {
|
23
|
+
command: 'link <path>',
|
24
|
+
describe: 'Links an extension from a local path. Updates made to the local path will always be reflected.',
|
25
|
+
builder: (yargs) => yargs
|
26
|
+
.positional('path', {
|
27
|
+
describe: 'The name of the extension to link.',
|
28
|
+
type: 'string',
|
29
|
+
})
|
30
|
+
.check((_) => true),
|
31
|
+
handler: async (argv) => {
|
32
|
+
await handleLink({
|
33
|
+
path: argv['path'],
|
34
|
+
});
|
35
|
+
},
|
36
|
+
};
|
37
|
+
//# sourceMappingURL=link.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"link.js","sourceRoot":"","sources":["../../../../src/commands/extensions/link.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,gBAAgB,GAEjB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAMxD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAiB;IAChD,IAAI,CAAC;QACH,MAAM,eAAe,GAA6B;YAChD,MAAM,EAAE,IAAI,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM;SACb,CAAC;QACF,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC,eAAe,CAAC,CAAC;QAC9D,OAAO,CAAC,GAAG,CACT,cAAc,aAAa,oCAAoC,CAChE,CAAC;IACJ,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;QACtC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,MAAM,WAAW,GAAkB;IACxC,OAAO,EAAE,aAAa;IACtB,QAAQ,EACN,gGAAgG;IAClG,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CACjB,KAAK;SACF,UAAU,CAAC,MAAM,EAAE;QAClB,QAAQ,EAAE,oCAAoC;QAC9C,IAAI,EAAE,QAAQ;KACf,CAAC;SACD,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC;IACvB,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACtB,MAAM,UAAU,CAAC;YACf,IAAI,EAAE,IAAI,CAAC,MAAM,CAAW;SAC7B,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
|
@@ -0,0 +1,70 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Google LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
import { access, cp, mkdir, readdir } from 'node:fs/promises';
|
7
|
+
import { join, dirname } from 'node:path';
|
8
|
+
import { fileURLToPath } from 'node:url';
|
9
|
+
import { getErrorMessage } from '../../utils/errors.js';
|
10
|
+
const __filename = fileURLToPath(import.meta.url);
|
11
|
+
const __dirname = dirname(__filename);
|
12
|
+
const EXAMPLES_PATH = join(__dirname, 'examples');
|
13
|
+
async function pathExists(path) {
|
14
|
+
try {
|
15
|
+
await access(path);
|
16
|
+
return true;
|
17
|
+
}
|
18
|
+
catch (_e) {
|
19
|
+
return false;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
async function copyDirectory(template, path) {
|
23
|
+
if (await pathExists(path)) {
|
24
|
+
throw new Error(`Path already exists: ${path}`);
|
25
|
+
}
|
26
|
+
const examplePath = join(EXAMPLES_PATH, template);
|
27
|
+
await mkdir(path, { recursive: true });
|
28
|
+
await cp(examplePath, path, { recursive: true });
|
29
|
+
}
|
30
|
+
async function handleNew(args) {
|
31
|
+
try {
|
32
|
+
await copyDirectory(args.template, args.path);
|
33
|
+
console.log(`Successfully created new extension from template "${args.template}" at ${args.path}.`);
|
34
|
+
console.log(`You can install this using "llxprt extensions link ${args.path}" to test it out.`);
|
35
|
+
}
|
36
|
+
catch (error) {
|
37
|
+
console.error(getErrorMessage(error));
|
38
|
+
throw error;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
async function getBoilerplateChoices() {
|
42
|
+
const entries = await readdir(EXAMPLES_PATH, { withFileTypes: true });
|
43
|
+
return entries
|
44
|
+
.filter((entry) => entry.isDirectory())
|
45
|
+
.map((entry) => entry.name);
|
46
|
+
}
|
47
|
+
export const newCommand = {
|
48
|
+
command: 'new <path> <template>',
|
49
|
+
describe: 'Create a new extension from a boilerplate example.',
|
50
|
+
builder: async (yargs) => {
|
51
|
+
const choices = await getBoilerplateChoices();
|
52
|
+
return yargs
|
53
|
+
.positional('path', {
|
54
|
+
describe: 'The path to create the extension in.',
|
55
|
+
type: 'string',
|
56
|
+
})
|
57
|
+
.positional('template', {
|
58
|
+
describe: 'The boilerplate template to use.',
|
59
|
+
type: 'string',
|
60
|
+
choices,
|
61
|
+
});
|
62
|
+
},
|
63
|
+
handler: async (args) => {
|
64
|
+
await handleNew({
|
65
|
+
path: args['path'],
|
66
|
+
template: args['template'],
|
67
|
+
});
|
68
|
+
},
|
69
|
+
};
|
70
|
+
//# sourceMappingURL=new.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"new.js","sourceRoot":"","sources":["../../../../src/commands/extensions/new.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Google LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
7
|
+
import { newCommand } from './new.js';
|
8
|
+
import yargs from 'yargs';
|
9
|
+
import * as fsPromises from 'node:fs/promises';
|
10
|
+
vi.mock('node:fs/promises');
|
11
|
+
const mockedFs = vi.mocked(fsPromises);
|
12
|
+
describe('extensions new command', () => {
|
13
|
+
beforeEach(() => {
|
14
|
+
vi.resetAllMocks();
|
15
|
+
const fakeFiles = [
|
16
|
+
{ name: 'context', isDirectory: () => true },
|
17
|
+
{ name: 'custom-commands', isDirectory: () => true },
|
18
|
+
{ name: 'mcp-server', isDirectory: () => true },
|
19
|
+
];
|
20
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
21
|
+
mockedFs.readdir.mockResolvedValue(fakeFiles);
|
22
|
+
});
|
23
|
+
it('should fail if no path is provided', async () => {
|
24
|
+
const parser = yargs([]).command(newCommand).fail(false);
|
25
|
+
await expect(parser.parseAsync('new')).rejects.toThrow('Not enough non-option arguments: got 0, need at least 2');
|
26
|
+
});
|
27
|
+
it('should fail if no template is provided', async () => {
|
28
|
+
const parser = yargs([]).command(newCommand).fail(false);
|
29
|
+
await expect(parser.parseAsync('new /some/path')).rejects.toThrow('Not enough non-option arguments: got 1, need at least 2');
|
30
|
+
});
|
31
|
+
it('should create directory and copy files when path does not exist', async () => {
|
32
|
+
mockedFs.access.mockRejectedValue(new Error('ENOENT'));
|
33
|
+
mockedFs.mkdir.mockResolvedValue(undefined);
|
34
|
+
mockedFs.cp.mockResolvedValue(undefined);
|
35
|
+
const parser = yargs([]).command(newCommand).fail(false);
|
36
|
+
await parser.parseAsync('new /some/path context');
|
37
|
+
expect(mockedFs.mkdir).toHaveBeenCalledWith('/some/path', {
|
38
|
+
recursive: true,
|
39
|
+
});
|
40
|
+
expect(mockedFs.cp).toHaveBeenCalledWith(expect.stringContaining('context'), '/some/path', { recursive: true });
|
41
|
+
});
|
42
|
+
it('should throw an error if the path already exists', async () => {
|
43
|
+
mockedFs.access.mockResolvedValue(undefined);
|
44
|
+
const parser = yargs([]).command(newCommand).fail(false);
|
45
|
+
await expect(parser.parseAsync('new /some/path context')).rejects.toThrow('Path already exists: /some/path');
|
46
|
+
expect(mockedFs.mkdir).not.toHaveBeenCalled();
|
47
|
+
expect(mockedFs.cp).not.toHaveBeenCalled();
|
48
|
+
});
|
49
|
+
});
|
50
|
+
//# sourceMappingURL=new.test.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"new.test.js","sourceRoot":"","sources":["../../../../src/commands/extensions/new.test.ts"],"names":[],"mappings":"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"}
|