gencode-ai 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/.env.example +11 -0
- package/CLAUDE.md +70 -0
- package/LICENSE +21 -0
- package/README.md +117 -0
- package/dist/agent/agent.d.ts +84 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +233 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/index.d.ts +6 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +6 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/types.d.ts +47 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/cli/components/App.d.ts +14 -0
- package/dist/cli/components/App.d.ts.map +1 -0
- package/dist/cli/components/App.js +395 -0
- package/dist/cli/components/App.js.map +1 -0
- package/dist/cli/components/CommandSuggestions.d.ts +13 -0
- package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
- package/dist/cli/components/CommandSuggestions.js +32 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -0
- package/dist/cli/components/Header.d.ts +9 -0
- package/dist/cli/components/Header.d.ts.map +1 -0
- package/dist/cli/components/Header.js +13 -0
- package/dist/cli/components/Header.js.map +1 -0
- package/dist/cli/components/Input.d.ts +13 -0
- package/dist/cli/components/Input.d.ts.map +1 -0
- package/dist/cli/components/Input.js +27 -0
- package/dist/cli/components/Input.js.map +1 -0
- package/dist/cli/components/Logo.d.ts +2 -0
- package/dist/cli/components/Logo.d.ts.map +1 -0
- package/dist/cli/components/Logo.js +8 -0
- package/dist/cli/components/Logo.js.map +1 -0
- package/dist/cli/components/Messages.d.ts +37 -0
- package/dist/cli/components/Messages.d.ts.map +1 -0
- package/dist/cli/components/Messages.js +106 -0
- package/dist/cli/components/Messages.js.map +1 -0
- package/dist/cli/components/ModelSelector.d.ts +13 -0
- package/dist/cli/components/ModelSelector.d.ts.map +1 -0
- package/dist/cli/components/ModelSelector.js +72 -0
- package/dist/cli/components/ModelSelector.js.map +1 -0
- package/dist/cli/components/Spinner.d.ts +12 -0
- package/dist/cli/components/Spinner.d.ts.map +1 -0
- package/dist/cli/components/Spinner.js +45 -0
- package/dist/cli/components/Spinner.js.map +1 -0
- package/dist/cli/components/index.d.ts +12 -0
- package/dist/cli/components/index.d.ts.map +1 -0
- package/dist/cli/components/index.js +12 -0
- package/dist/cli/components/index.js.map +1 -0
- package/dist/cli/components/theme.d.ts +31 -0
- package/dist/cli/components/theme.d.ts.map +1 -0
- package/dist/cli/components/theme.js +36 -0
- package/dist/cli/components/theme.js.map +1 -0
- package/dist/cli/index-legacy.d.ts +7 -0
- package/dist/cli/index-legacy.d.ts.map +1 -0
- package/dist/cli/index-legacy.js +431 -0
- package/dist/cli/index-legacy.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +116 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ink-cli.d.ts +7 -0
- package/dist/cli/ink-cli.d.ts.map +1 -0
- package/dist/cli/ink-cli.js +105 -0
- package/dist/cli/ink-cli.js.map +1 -0
- package/dist/cli/session-picker.d.ts +16 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +280 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli/ui.d.ts +61 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +364 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/manager.d.ts +31 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +65 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/types.d.ts +22 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +6 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/index.d.ts +10 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +9 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/init.d.ts +20 -0
- package/dist/memory/init.d.ts.map +1 -0
- package/dist/memory/init.js +332 -0
- package/dist/memory/init.js.map +1 -0
- package/dist/memory/manager.d.ts +85 -0
- package/dist/memory/manager.d.ts.map +1 -0
- package/dist/memory/manager.js +234 -0
- package/dist/memory/manager.js.map +1 -0
- package/dist/memory/types.d.ts +74 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +6 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/permissions/index.d.ts +7 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +6 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/manager.d.ts +32 -0
- package/dist/permissions/manager.d.ts.map +1 -0
- package/dist/permissions/manager.js +79 -0
- package/dist/permissions/manager.js.map +1 -0
- package/dist/permissions/types.d.ts +14 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/providers/anthropic.d.ts +20 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +185 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/gemini.d.ts +21 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +241 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +34 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +72 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai.d.ts +19 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +221 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/types.d.ts +125 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +6 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/session/index.d.ts +6 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +6 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/manager.d.ts +101 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +295 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/types.d.ts +39 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +10 -0
- package/dist/session/types.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +7 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -0
- package/dist/tools/builtin/bash.js +80 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/edit.d.ts +7 -0
- package/dist/tools/builtin/edit.d.ts.map +1 -0
- package/dist/tools/builtin/edit.js +32 -0
- package/dist/tools/builtin/edit.js.map +1 -0
- package/dist/tools/builtin/glob.d.ts +7 -0
- package/dist/tools/builtin/glob.d.ts.map +1 -0
- package/dist/tools/builtin/glob.js +36 -0
- package/dist/tools/builtin/glob.js.map +1 -0
- package/dist/tools/builtin/grep.d.ts +7 -0
- package/dist/tools/builtin/grep.d.ts.map +1 -0
- package/dist/tools/builtin/grep.js +59 -0
- package/dist/tools/builtin/grep.js.map +1 -0
- package/dist/tools/builtin/read.d.ts +7 -0
- package/dist/tools/builtin/read.d.ts.map +1 -0
- package/dist/tools/builtin/read.js +29 -0
- package/dist/tools/builtin/read.js.map +1 -0
- package/dist/tools/builtin/write.d.ts +7 -0
- package/dist/tools/builtin/write.d.ts.map +1 -0
- package/dist/tools/builtin/write.js +24 -0
- package/dist/tools/builtin/write.js.map +1 -0
- package/dist/tools/index.d.ts +38 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +32 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +22 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +71 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +62 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +126 -0
- package/dist/tools/types.js.map +1 -0
- package/docs/README.md +16 -0
- package/docs/proposals/0001-web-fetch-tool.md +293 -0
- package/docs/proposals/0002-web-search-tool.md +306 -0
- package/docs/proposals/0003-task-subagents.md +333 -0
- package/docs/proposals/0004-plan-mode.md +338 -0
- package/docs/proposals/0005-todo-system.md +299 -0
- package/docs/proposals/0006-memory-system.md +539 -0
- package/docs/proposals/0007-context-management.md +429 -0
- package/docs/proposals/0008-checkpointing.md +327 -0
- package/docs/proposals/0009-hooks-system.md +343 -0
- package/docs/proposals/0010-mcp-integration.md +382 -0
- package/docs/proposals/0011-custom-commands.md +374 -0
- package/docs/proposals/0012-ask-user-question.md +317 -0
- package/docs/proposals/0013-multi-edit-tool.md +345 -0
- package/docs/proposals/0014-lsp-tool.md +478 -0
- package/docs/proposals/0015-ls-tool.md +407 -0
- package/docs/proposals/0016-kill-shell-tool.md +455 -0
- package/docs/proposals/0017-background-tasks.md +489 -0
- package/docs/proposals/0018-parallel-tool-execution.md +415 -0
- package/docs/proposals/0019-session-enhancements.md +462 -0
- package/docs/proposals/0020-session-summarization.md +447 -0
- package/docs/proposals/0021-skills-system.md +409 -0
- package/docs/proposals/0022-plugin-system.md +467 -0
- package/docs/proposals/0023-permission-enhancements.md +470 -0
- package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
- package/docs/proposals/0025-cost-tracking.md +447 -0
- package/docs/proposals/0026-git-integration.md +475 -0
- package/docs/proposals/0027-enhanced-read-tool.md +514 -0
- package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
- package/docs/proposals/0029-notebook-edit-tool.md +413 -0
- package/docs/proposals/0030-plugin-marketplace.md +360 -0
- package/docs/proposals/0031-command-suggestions.md +295 -0
- package/docs/proposals/0032-ide-integrations.md +328 -0
- package/docs/proposals/0033-enterprise-deployment.md +221 -0
- package/docs/proposals/0034-sandboxing.md +273 -0
- package/docs/proposals/0035-auto-updater.md +311 -0
- package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
- package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
- package/docs/proposals/0038-interactive-cli-ui.md +373 -0
- package/docs/proposals/0039-streaming-enhancements.md +359 -0
- package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
- package/docs/proposals/README.md +84 -0
- package/docs/proposals/TEMPLATE.md +57 -0
- package/docs/proposals/research/claude-code-research.md +307 -0
- package/examples/agent-demo.ts +115 -0
- package/examples/basic.ts +166 -0
- package/package.json +50 -0
- package/src/agent/agent.ts +276 -0
- package/src/agent/index.ts +6 -0
- package/src/agent/types.ts +62 -0
- package/src/cli/components/App.tsx +565 -0
- package/src/cli/components/CommandSuggestions.tsx +58 -0
- package/src/cli/components/Header.tsx +36 -0
- package/src/cli/components/Input.tsx +60 -0
- package/src/cli/components/Logo.tsx +16 -0
- package/src/cli/components/Messages.tsx +210 -0
- package/src/cli/components/ModelSelector.tsx +135 -0
- package/src/cli/components/Spinner.tsx +72 -0
- package/src/cli/components/index.ts +21 -0
- package/src/cli/components/theme.ts +36 -0
- package/src/cli/index.tsx +136 -0
- package/src/config/index.ts +7 -0
- package/src/config/manager.ts +77 -0
- package/src/config/types.ts +25 -0
- package/src/index.ts +86 -0
- package/src/permissions/index.ts +7 -0
- package/src/permissions/manager.ts +97 -0
- package/src/permissions/types.ts +29 -0
- package/src/providers/anthropic.ts +224 -0
- package/src/providers/gemini.ts +295 -0
- package/src/providers/index.ts +97 -0
- package/src/providers/openai.ts +261 -0
- package/src/providers/types.ts +181 -0
- package/src/session/index.ts +6 -0
- package/src/session/manager.ts +354 -0
- package/src/session/types.ts +49 -0
- package/src/tools/builtin/bash.ts +92 -0
- package/src/tools/builtin/edit.ts +37 -0
- package/src/tools/builtin/glob.ts +42 -0
- package/src/tools/builtin/grep.ts +67 -0
- package/src/tools/builtin/read.ts +34 -0
- package/src/tools/builtin/write.ts +27 -0
- package/src/tools/index.ts +36 -0
- package/src/tools/registry.ts +83 -0
- package/src/tools/types.ts +172 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
# Proposal: Plugin Marketplace
|
|
2
|
+
|
|
3
|
+
- **Proposal ID**: 0030
|
|
4
|
+
- **Author**: mycode team
|
|
5
|
+
- **Status**: Draft
|
|
6
|
+
- **Created**: 2025-01-15
|
|
7
|
+
- **Updated**: 2025-01-15
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Implement a plugin marketplace system for discovering, installing, and updating plugins from multiple sources. This enables community-driven extension of mycode capabilities.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
With the plugin system (0022) in place, users need:
|
|
16
|
+
|
|
17
|
+
1. **Discovery**: Find available plugins
|
|
18
|
+
2. **Easy installation**: One-command install
|
|
19
|
+
3. **Updates**: Keep plugins current
|
|
20
|
+
4. **Trust**: Verify plugin sources
|
|
21
|
+
5. **Community**: Share and contribute
|
|
22
|
+
|
|
23
|
+
A marketplace enables ecosystem growth.
|
|
24
|
+
|
|
25
|
+
## Claude Code Reference
|
|
26
|
+
|
|
27
|
+
Claude Code uses a multi-marketplace architecture:
|
|
28
|
+
|
|
29
|
+
### Known Marketplaces
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"cc-plugins": {
|
|
33
|
+
"type": "local",
|
|
34
|
+
"path": "/path/to/local/plugins"
|
|
35
|
+
},
|
|
36
|
+
"acm-workflows-plugins": {
|
|
37
|
+
"type": "github",
|
|
38
|
+
"source": "stolostron/acm-workflows"
|
|
39
|
+
},
|
|
40
|
+
"claude-plugins-official": {
|
|
41
|
+
"type": "github",
|
|
42
|
+
"source": "anthropics/claude-plugins-official"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Plugin Activation
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"enabledPlugins": {
|
|
51
|
+
"jira-tools@acm-workflows-plugins": true,
|
|
52
|
+
"git@cc-plugins": true
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Detailed Design
|
|
58
|
+
|
|
59
|
+
### API Design
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
// src/marketplace/types.ts
|
|
63
|
+
interface Marketplace {
|
|
64
|
+
id: string;
|
|
65
|
+
name: string;
|
|
66
|
+
type: 'local' | 'github' | 'npm' | 'registry';
|
|
67
|
+
source: string;
|
|
68
|
+
cacheDir?: string;
|
|
69
|
+
priority?: number;
|
|
70
|
+
enabled: boolean;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
interface MarketplacePlugin {
|
|
74
|
+
name: string;
|
|
75
|
+
version: string;
|
|
76
|
+
description: string;
|
|
77
|
+
author: string;
|
|
78
|
+
repository?: string;
|
|
79
|
+
homepage?: string;
|
|
80
|
+
keywords?: string[];
|
|
81
|
+
downloads?: number;
|
|
82
|
+
rating?: number;
|
|
83
|
+
lastUpdated: string;
|
|
84
|
+
marketplace: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface PluginSearchResult {
|
|
88
|
+
plugins: MarketplacePlugin[];
|
|
89
|
+
total: number;
|
|
90
|
+
page: number;
|
|
91
|
+
pageSize: number;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
interface PluginInstallResult {
|
|
95
|
+
success: boolean;
|
|
96
|
+
plugin?: MarketplacePlugin;
|
|
97
|
+
version: string;
|
|
98
|
+
error?: string;
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Marketplace Manager
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// src/marketplace/manager.ts
|
|
106
|
+
class MarketplaceManager {
|
|
107
|
+
private marketplaces: Map<string, Marketplace> = new Map();
|
|
108
|
+
private cache: PluginCache;
|
|
109
|
+
|
|
110
|
+
constructor() {
|
|
111
|
+
this.loadMarketplaces();
|
|
112
|
+
this.cache = new PluginCache();
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async search(
|
|
116
|
+
query: string,
|
|
117
|
+
options?: { marketplace?: string; limit?: number }
|
|
118
|
+
): Promise<PluginSearchResult> {
|
|
119
|
+
const results: MarketplacePlugin[] = [];
|
|
120
|
+
|
|
121
|
+
const markets = options?.marketplace
|
|
122
|
+
? [this.marketplaces.get(options.marketplace)].filter(Boolean)
|
|
123
|
+
: Array.from(this.marketplaces.values());
|
|
124
|
+
|
|
125
|
+
for (const market of markets) {
|
|
126
|
+
if (!market?.enabled) continue;
|
|
127
|
+
|
|
128
|
+
const plugins = await this.searchMarketplace(market, query);
|
|
129
|
+
results.push(...plugins);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Sort by relevance
|
|
133
|
+
results.sort((a, b) => this.scoreRelevance(b, query) - this.scoreRelevance(a, query));
|
|
134
|
+
|
|
135
|
+
const limit = options?.limit || 20;
|
|
136
|
+
return {
|
|
137
|
+
plugins: results.slice(0, limit),
|
|
138
|
+
total: results.length,
|
|
139
|
+
page: 1,
|
|
140
|
+
pageSize: limit
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async install(
|
|
145
|
+
pluginId: string,
|
|
146
|
+
version?: string
|
|
147
|
+
): Promise<PluginInstallResult> {
|
|
148
|
+
const [name, marketplaceId] = this.parsePluginId(pluginId);
|
|
149
|
+
const marketplace = this.marketplaces.get(marketplaceId);
|
|
150
|
+
|
|
151
|
+
if (!marketplace) {
|
|
152
|
+
return { success: false, error: `Marketplace not found: ${marketplaceId}`, version: '' };
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const plugin = await this.fetchPlugin(marketplace, name, version);
|
|
156
|
+
if (!plugin) {
|
|
157
|
+
return { success: false, error: `Plugin not found: ${name}`, version: '' };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
await this.downloadAndCache(marketplace, plugin);
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
success: true,
|
|
164
|
+
plugin,
|
|
165
|
+
version: plugin.version
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async update(pluginId?: string): Promise<UpdateResult[]> {
|
|
170
|
+
const results: UpdateResult[] = [];
|
|
171
|
+
|
|
172
|
+
if (pluginId) {
|
|
173
|
+
// Update specific plugin
|
|
174
|
+
const result = await this.updatePlugin(pluginId);
|
|
175
|
+
results.push(result);
|
|
176
|
+
} else {
|
|
177
|
+
// Update all installed plugins
|
|
178
|
+
const installed = await this.getInstalledPlugins();
|
|
179
|
+
for (const plugin of installed) {
|
|
180
|
+
const result = await this.updatePlugin(`${plugin.name}@${plugin.marketplace}`);
|
|
181
|
+
results.push(result);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return results;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async addMarketplace(marketplace: Marketplace): Promise<void> {
|
|
189
|
+
this.marketplaces.set(marketplace.id, marketplace);
|
|
190
|
+
await this.saveMarketplaces();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async removeMarketplace(id: string): Promise<void> {
|
|
194
|
+
this.marketplaces.delete(id);
|
|
195
|
+
await this.saveMarketplaces();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private async searchMarketplace(
|
|
199
|
+
marketplace: Marketplace,
|
|
200
|
+
query: string
|
|
201
|
+
): Promise<MarketplacePlugin[]> {
|
|
202
|
+
switch (marketplace.type) {
|
|
203
|
+
case 'local':
|
|
204
|
+
return this.searchLocal(marketplace, query);
|
|
205
|
+
case 'github':
|
|
206
|
+
return this.searchGitHub(marketplace, query);
|
|
207
|
+
case 'npm':
|
|
208
|
+
return this.searchNpm(marketplace, query);
|
|
209
|
+
case 'registry':
|
|
210
|
+
return this.searchRegistry(marketplace, query);
|
|
211
|
+
default:
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private async searchGitHub(
|
|
217
|
+
marketplace: Marketplace,
|
|
218
|
+
query: string
|
|
219
|
+
): Promise<MarketplacePlugin[]> {
|
|
220
|
+
const [owner, repo] = marketplace.source.split('/');
|
|
221
|
+
|
|
222
|
+
// Fetch plugin index from repo
|
|
223
|
+
const indexUrl = `https://raw.githubusercontent.com/${owner}/${repo}/main/plugins/index.json`;
|
|
224
|
+
|
|
225
|
+
try {
|
|
226
|
+
const response = await fetch(indexUrl);
|
|
227
|
+
const index = await response.json() as { plugins: MarketplacePlugin[] };
|
|
228
|
+
|
|
229
|
+
return index.plugins.filter(p =>
|
|
230
|
+
p.name.includes(query) ||
|
|
231
|
+
p.description.toLowerCase().includes(query.toLowerCase()) ||
|
|
232
|
+
p.keywords?.some(k => k.includes(query))
|
|
233
|
+
);
|
|
234
|
+
} catch {
|
|
235
|
+
return [];
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### CLI Commands
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
// src/cli/commands/marketplace.ts
|
|
245
|
+
const marketplaceCommands = {
|
|
246
|
+
'/marketplace search <query>': 'Search for plugins',
|
|
247
|
+
'/marketplace install <plugin>': 'Install a plugin',
|
|
248
|
+
'/marketplace update [plugin]': 'Update plugin(s)',
|
|
249
|
+
'/marketplace list': 'List installed plugins',
|
|
250
|
+
'/marketplace info <plugin>': 'Show plugin details',
|
|
251
|
+
'/marketplace add <url>': 'Add marketplace source',
|
|
252
|
+
'/marketplace remove <id>': 'Remove marketplace',
|
|
253
|
+
'/marketplace browse': 'Browse popular plugins'
|
|
254
|
+
};
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### File Changes
|
|
258
|
+
|
|
259
|
+
| File | Action | Description |
|
|
260
|
+
|------|--------|-------------|
|
|
261
|
+
| `src/marketplace/types.ts` | Create | Type definitions |
|
|
262
|
+
| `src/marketplace/manager.ts` | Create | Marketplace management |
|
|
263
|
+
| `src/marketplace/cache.ts` | Create | Plugin caching |
|
|
264
|
+
| `src/marketplace/sources/github.ts` | Create | GitHub source |
|
|
265
|
+
| `src/marketplace/sources/npm.ts` | Create | npm source |
|
|
266
|
+
| `src/marketplace/index.ts` | Create | Module exports |
|
|
267
|
+
| `src/cli/commands/marketplace.ts` | Create | CLI commands |
|
|
268
|
+
|
|
269
|
+
## User Experience
|
|
270
|
+
|
|
271
|
+
### Search Plugins
|
|
272
|
+
```
|
|
273
|
+
User: /marketplace search jira
|
|
274
|
+
|
|
275
|
+
Searching marketplaces...
|
|
276
|
+
|
|
277
|
+
┌─ Plugin Search Results ───────────────────────────────────┐
|
|
278
|
+
│ │
|
|
279
|
+
│ jira-tools@acm-workflows ★ 4.8 ↓ 1.2K│
|
|
280
|
+
│ Comprehensive Jira management for ACM workflows │
|
|
281
|
+
│ v1.2.0 • Updated 2 days ago │
|
|
282
|
+
│ │
|
|
283
|
+
│ jira-sync@community ★ 4.2 ↓ 856 │
|
|
284
|
+
│ Sync Jira issues with local markdown files │
|
|
285
|
+
│ v0.9.0 • Updated 1 week ago │
|
|
286
|
+
│ │
|
|
287
|
+
│ jira-reports@official ★ 4.5 ↓ 2.1K│
|
|
288
|
+
│ Generate beautiful Jira reports │
|
|
289
|
+
│ v2.1.0 • Updated 3 days ago │
|
|
290
|
+
│ │
|
|
291
|
+
└───────────────────────────────────────────────────────────┘
|
|
292
|
+
|
|
293
|
+
Install with: /marketplace install jira-tools@acm-workflows
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Install Plugin
|
|
297
|
+
```
|
|
298
|
+
User: /marketplace install jira-tools@acm-workflows
|
|
299
|
+
|
|
300
|
+
Installing jira-tools from acm-workflows...
|
|
301
|
+
|
|
302
|
+
Fetching plugin metadata...
|
|
303
|
+
Downloading v1.2.0...
|
|
304
|
+
Extracting to ~/.mycode/plugins/cache/...
|
|
305
|
+
|
|
306
|
+
✓ Installed: jira-tools@1.2.0
|
|
307
|
+
|
|
308
|
+
Components:
|
|
309
|
+
Commands: 3 (/jira:my-issues, /jira:sprint-issues, /jira:add-labels)
|
|
310
|
+
Skills: 2 (jira-analyzer, test-plan-generator)
|
|
311
|
+
Agents: 1 (jira-administrator)
|
|
312
|
+
|
|
313
|
+
Enable with: /plugin enable jira-tools@acm-workflows
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Browse Popular
|
|
317
|
+
```
|
|
318
|
+
User: /marketplace browse
|
|
319
|
+
|
|
320
|
+
Popular Plugins:
|
|
321
|
+
┌────────────────────────────────────────────────────────────┐
|
|
322
|
+
│ 🔥 Trending This Week │
|
|
323
|
+
├────────────────────────────────────────────────────────────┤
|
|
324
|
+
│ 1. code-reviewer@official ★ 4.9 ↓ 5.2K │
|
|
325
|
+
│ 2. git-workflows@community ★ 4.7 ↓ 3.8K │
|
|
326
|
+
│ 3. test-generator@official ★ 4.6 ↓ 2.9K │
|
|
327
|
+
│ 4. jira-tools@acm-workflows ★ 4.8 ↓ 1.2K │
|
|
328
|
+
│ 5. docker-helper@community ★ 4.5 ↓ 1.1K │
|
|
329
|
+
└────────────────────────────────────────────────────────────┘
|
|
330
|
+
|
|
331
|
+
Categories: [dev-tools] [testing] [productivity] [devops]
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Security Considerations
|
|
335
|
+
|
|
336
|
+
1. **Source Verification**: Verify marketplace sources
|
|
337
|
+
2. **Checksum Validation**: Verify downloaded content
|
|
338
|
+
3. **Permission Review**: Show required permissions
|
|
339
|
+
4. **Sandboxing**: Option to sandbox plugin execution
|
|
340
|
+
5. **Reporting**: Allow reporting malicious plugins
|
|
341
|
+
|
|
342
|
+
## Testing Strategy
|
|
343
|
+
|
|
344
|
+
1. **Unit Tests**: Search, install, update logic
|
|
345
|
+
2. **Integration Tests**: Full marketplace workflows
|
|
346
|
+
3. **E2E Tests**: Real marketplace interaction
|
|
347
|
+
|
|
348
|
+
## Migration Path
|
|
349
|
+
|
|
350
|
+
1. **Phase 1**: Basic search and install
|
|
351
|
+
2. **Phase 2**: Multiple marketplace support
|
|
352
|
+
3. **Phase 3**: Update mechanism
|
|
353
|
+
4. **Phase 4**: Ratings and reviews
|
|
354
|
+
5. **Phase 5**: Plugin publishing
|
|
355
|
+
|
|
356
|
+
## References
|
|
357
|
+
|
|
358
|
+
- [npm Registry](https://www.npmjs.com/)
|
|
359
|
+
- [VS Code Marketplace](https://marketplace.visualstudio.com/)
|
|
360
|
+
- [Plugin System Proposal (0022)](./0022-plugin-system.md)
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# Proposal: Command Suggestions
|
|
2
|
+
|
|
3
|
+
- **Proposal ID**: 0031
|
|
4
|
+
- **Author**: mycode team
|
|
5
|
+
- **Status**: Draft
|
|
6
|
+
- **Created**: 2025-01-15
|
|
7
|
+
- **Updated**: 2025-01-15
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Implement intelligent command suggestions and autocomplete for the CLI, providing contextual recommendations as users type. This improves discoverability and reduces typing effort.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
Currently, users must know exact command names:
|
|
16
|
+
|
|
17
|
+
1. **No discovery**: Must read docs to find commands
|
|
18
|
+
2. **No autocomplete**: Type full command names
|
|
19
|
+
3. **No context**: Suggestions not context-aware
|
|
20
|
+
4. **Typo friction**: No fuzzy matching
|
|
21
|
+
5. **Slow onboarding**: New users struggle
|
|
22
|
+
|
|
23
|
+
Command suggestions improve productivity and discoverability.
|
|
24
|
+
|
|
25
|
+
## Claude Code Reference
|
|
26
|
+
|
|
27
|
+
Claude Code provides Tab completion and suggestions:
|
|
28
|
+
|
|
29
|
+
### Observed Behavior
|
|
30
|
+
- Tab completes commands
|
|
31
|
+
- Shows available options
|
|
32
|
+
- Fuzzy matching for typos
|
|
33
|
+
|
|
34
|
+
## Detailed Design
|
|
35
|
+
|
|
36
|
+
### API Design
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
// src/cli/suggestions/types.ts
|
|
40
|
+
interface Suggestion {
|
|
41
|
+
text: string;
|
|
42
|
+
displayText?: string;
|
|
43
|
+
description?: string;
|
|
44
|
+
type: 'command' | 'option' | 'path' | 'history' | 'skill';
|
|
45
|
+
score: number;
|
|
46
|
+
source: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface SuggestionContext {
|
|
50
|
+
input: string;
|
|
51
|
+
cursorPosition: number;
|
|
52
|
+
cwd: string;
|
|
53
|
+
history: string[];
|
|
54
|
+
session?: Session;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
interface SuggestionConfig {
|
|
58
|
+
maxSuggestions: number;
|
|
59
|
+
fuzzyMatch: boolean;
|
|
60
|
+
includeHistory: boolean;
|
|
61
|
+
includePaths: boolean;
|
|
62
|
+
includeSkills: boolean;
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Suggestion Engine
|
|
67
|
+
|
|
68
|
+
```typescript
|
|
69
|
+
// src/cli/suggestions/engine.ts
|
|
70
|
+
class SuggestionEngine {
|
|
71
|
+
private config: SuggestionConfig;
|
|
72
|
+
private providers: SuggestionProvider[] = [];
|
|
73
|
+
|
|
74
|
+
constructor(config?: Partial<SuggestionConfig>) {
|
|
75
|
+
this.config = {
|
|
76
|
+
maxSuggestions: 10,
|
|
77
|
+
fuzzyMatch: true,
|
|
78
|
+
includeHistory: true,
|
|
79
|
+
includePaths: true,
|
|
80
|
+
includeSkills: true,
|
|
81
|
+
...config
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
this.registerProviders();
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
private registerProviders(): void {
|
|
88
|
+
this.providers.push(new CommandSuggestionProvider());
|
|
89
|
+
this.providers.push(new HistorySuggestionProvider());
|
|
90
|
+
this.providers.push(new PathSuggestionProvider());
|
|
91
|
+
this.providers.push(new SkillSuggestionProvider());
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async suggest(context: SuggestionContext): Promise<Suggestion[]> {
|
|
95
|
+
const { input } = context;
|
|
96
|
+
|
|
97
|
+
// Gather suggestions from all providers
|
|
98
|
+
const allSuggestions: Suggestion[] = [];
|
|
99
|
+
|
|
100
|
+
for (const provider of this.providers) {
|
|
101
|
+
if (!this.isProviderEnabled(provider)) continue;
|
|
102
|
+
|
|
103
|
+
const suggestions = await provider.suggest(context);
|
|
104
|
+
allSuggestions.push(...suggestions);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Score and sort
|
|
108
|
+
const scored = allSuggestions.map(s => ({
|
|
109
|
+
...s,
|
|
110
|
+
score: this.calculateScore(s, input)
|
|
111
|
+
}));
|
|
112
|
+
|
|
113
|
+
scored.sort((a, b) => b.score - a.score);
|
|
114
|
+
|
|
115
|
+
return scored.slice(0, this.config.maxSuggestions);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private calculateScore(suggestion: Suggestion, input: string): number {
|
|
119
|
+
let score = suggestion.score;
|
|
120
|
+
|
|
121
|
+
// Exact prefix match
|
|
122
|
+
if (suggestion.text.startsWith(input)) {
|
|
123
|
+
score += 100;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Fuzzy match
|
|
127
|
+
if (this.config.fuzzyMatch && this.fuzzyMatch(suggestion.text, input)) {
|
|
128
|
+
score += 50;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Recency for history
|
|
132
|
+
if (suggestion.type === 'history') {
|
|
133
|
+
score += 20;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Command priority
|
|
137
|
+
if (suggestion.type === 'command') {
|
|
138
|
+
score += 30;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return score;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private fuzzyMatch(text: string, pattern: string): boolean {
|
|
145
|
+
let patternIdx = 0;
|
|
146
|
+
for (const char of text.toLowerCase()) {
|
|
147
|
+
if (char === pattern[patternIdx]?.toLowerCase()) {
|
|
148
|
+
patternIdx++;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return patternIdx === pattern.length;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Providers
|
|
156
|
+
class CommandSuggestionProvider implements SuggestionProvider {
|
|
157
|
+
async suggest(context: SuggestionContext): Promise<Suggestion[]> {
|
|
158
|
+
const commands = [
|
|
159
|
+
{ name: '/help', description: 'Show help' },
|
|
160
|
+
{ name: '/sessions', description: 'List sessions' },
|
|
161
|
+
{ name: '/resume', description: 'Resume session' },
|
|
162
|
+
{ name: '/new', description: 'New session' },
|
|
163
|
+
{ name: '/clear', description: 'Clear screen' },
|
|
164
|
+
{ name: '/tasks', description: 'Show background tasks' },
|
|
165
|
+
{ name: '/costs', description: 'Show cost report' },
|
|
166
|
+
{ name: '/plugin', description: 'Manage plugins' },
|
|
167
|
+
// ... more commands
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
return commands
|
|
171
|
+
.filter(c => c.name.startsWith(context.input) || this.fuzzyMatch(c.name, context.input))
|
|
172
|
+
.map(c => ({
|
|
173
|
+
text: c.name,
|
|
174
|
+
description: c.description,
|
|
175
|
+
type: 'command' as const,
|
|
176
|
+
score: 50,
|
|
177
|
+
source: 'commands'
|
|
178
|
+
}));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
class PathSuggestionProvider implements SuggestionProvider {
|
|
183
|
+
async suggest(context: SuggestionContext): Promise<Suggestion[]> {
|
|
184
|
+
// Only suggest paths if input looks like a path
|
|
185
|
+
if (!context.input.includes('/') && !context.input.startsWith('.')) {
|
|
186
|
+
return [];
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const dir = path.dirname(context.input) || '.';
|
|
190
|
+
const prefix = path.basename(context.input);
|
|
191
|
+
|
|
192
|
+
try {
|
|
193
|
+
const entries = await fs.readdir(path.resolve(context.cwd, dir));
|
|
194
|
+
return entries
|
|
195
|
+
.filter(e => e.startsWith(prefix))
|
|
196
|
+
.slice(0, 10)
|
|
197
|
+
.map(e => ({
|
|
198
|
+
text: path.join(dir, e),
|
|
199
|
+
type: 'path' as const,
|
|
200
|
+
score: 30,
|
|
201
|
+
source: 'filesystem'
|
|
202
|
+
}));
|
|
203
|
+
} catch {
|
|
204
|
+
return [];
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### File Changes
|
|
211
|
+
|
|
212
|
+
| File | Action | Description |
|
|
213
|
+
|------|--------|-------------|
|
|
214
|
+
| `src/cli/suggestions/types.ts` | Create | Type definitions |
|
|
215
|
+
| `src/cli/suggestions/engine.ts` | Create | Core engine |
|
|
216
|
+
| `src/cli/suggestions/providers/*.ts` | Create | Suggestion providers |
|
|
217
|
+
| `src/cli/input.ts` | Modify | Integrate suggestions |
|
|
218
|
+
| `src/cli/ui.ts` | Modify | Display suggestions |
|
|
219
|
+
|
|
220
|
+
## User Experience
|
|
221
|
+
|
|
222
|
+
### Tab Completion
|
|
223
|
+
```
|
|
224
|
+
> /ses<Tab>
|
|
225
|
+
|
|
226
|
+
/sessions List sessions
|
|
227
|
+
/session-info Show session details
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### Fuzzy Matching
|
|
231
|
+
```
|
|
232
|
+
> /rsm<Tab>
|
|
233
|
+
|
|
234
|
+
/resume Resume a session (fuzzy match: rsm → resume)
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Path Completion
|
|
238
|
+
```
|
|
239
|
+
> Read src/comp<Tab>
|
|
240
|
+
|
|
241
|
+
src/components/
|
|
242
|
+
src/compiler/
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Inline Suggestions
|
|
246
|
+
```
|
|
247
|
+
> /plug
|
|
248
|
+
↓
|
|
249
|
+
┌─────────────────────────────────┐
|
|
250
|
+
│ /plugin list List plugins │
|
|
251
|
+
│ /plugin install Install plugin │
|
|
252
|
+
│ /plugin enable Enable plugin │
|
|
253
|
+
└─────────────────────────────────┘
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Alternatives Considered
|
|
257
|
+
|
|
258
|
+
### Alternative 1: No Autocomplete
|
|
259
|
+
Rely on documentation.
|
|
260
|
+
|
|
261
|
+
**Pros**: Simpler
|
|
262
|
+
**Cons**: Poor UX
|
|
263
|
+
**Decision**: Rejected
|
|
264
|
+
|
|
265
|
+
### Alternative 2: Full TUI
|
|
266
|
+
Rich terminal UI with menus.
|
|
267
|
+
|
|
268
|
+
**Pros**: More discoverable
|
|
269
|
+
**Cons**: Complex, heavy
|
|
270
|
+
**Decision**: Deferred
|
|
271
|
+
|
|
272
|
+
## Security Considerations
|
|
273
|
+
|
|
274
|
+
1. Path suggestions limited to cwd
|
|
275
|
+
2. No secret exposure in suggestions
|
|
276
|
+
3. History filtering for sensitive commands
|
|
277
|
+
|
|
278
|
+
## Testing Strategy
|
|
279
|
+
|
|
280
|
+
1. Unit tests for matching logic
|
|
281
|
+
2. Integration tests for providers
|
|
282
|
+
3. Manual testing for UX
|
|
283
|
+
|
|
284
|
+
## Migration Path
|
|
285
|
+
|
|
286
|
+
1. **Phase 1**: Command completion
|
|
287
|
+
2. **Phase 2**: Path completion
|
|
288
|
+
3. **Phase 3**: History suggestions
|
|
289
|
+
4. **Phase 4**: Fuzzy matching
|
|
290
|
+
5. **Phase 5**: Inline display
|
|
291
|
+
|
|
292
|
+
## References
|
|
293
|
+
|
|
294
|
+
- [readline - Node.js](https://nodejs.org/api/readline.html)
|
|
295
|
+
- [Fuse.js - Fuzzy Search](https://fusejs.io/)
|