ccjk 9.6.1 → 9.8.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/dist/chunks/boost.mjs +246 -7
- package/dist/chunks/ccjk-mcp.mjs +1 -1
- package/dist/chunks/ccr.mjs +25 -28
- package/dist/chunks/check-updates.mjs +4 -3
- package/dist/chunks/claude-code-config-manager.mjs +1 -1
- package/dist/chunks/claude-code-incremental-manager.mjs +1 -1
- package/dist/chunks/claude-config.mjs +1 -1
- package/dist/chunks/codex-config-switch.mjs +3 -4
- package/dist/chunks/codex-provider-manager.mjs +1 -2
- package/dist/chunks/codex.mjs +204 -3
- package/dist/chunks/config-switch.mjs +2 -3
- package/dist/chunks/config.mjs +1 -1
- package/dist/chunks/doctor.mjs +1 -1
- package/dist/chunks/features.mjs +24 -15
- package/dist/chunks/hook-installer.mjs +44 -0
- package/dist/chunks/index3.mjs +32 -32
- package/dist/chunks/init.mjs +129 -87
- package/dist/chunks/installer2.mjs +1 -1
- package/dist/chunks/interview.mjs +1 -1
- package/dist/chunks/mcp.mjs +1058 -17
- package/dist/chunks/menu.mjs +140 -56
- package/dist/chunks/package.mjs +2 -210
- package/dist/chunks/platform.mjs +1 -1
- package/dist/chunks/quick-setup.mjs +35 -18
- package/dist/chunks/simple-config.mjs +1 -1
- package/dist/{shared/ccjk.q1koQxEE.mjs → chunks/smart-defaults.mjs} +77 -79
- package/dist/chunks/status.mjs +208 -101
- package/dist/chunks/thinking.mjs +1 -1
- package/dist/chunks/uninstall.mjs +6 -4
- package/dist/chunks/update.mjs +4 -7
- package/dist/chunks/version-checker.mjs +1 -1
- package/dist/cli.mjs +4 -80
- package/dist/index.d.mts +17 -1482
- package/dist/index.d.ts +17 -1482
- package/dist/index.mjs +12 -4191
- package/dist/shared/{ccjk.CSkyCZIM.mjs → ccjk.Bndhan7G.mjs} +4 -242
- package/dist/shared/ccjk.CeE8RLG2.mjs +62 -0
- package/dist/shared/ccjk.DKojSRzw.mjs +266 -0
- package/dist/shared/{ccjk.CItD1fpl.mjs → ccjk.DvIrK0wz.mjs} +1 -1
- package/dist/shared/ccjk.LsPZ2PYo.mjs +1048 -0
- package/package.json +1 -1
- package/dist/chunks/api-adapter.mjs +0 -180
- package/dist/chunks/cli.mjs +0 -2227
- package/dist/chunks/context-menu.mjs +0 -913
- package/dist/chunks/hooks-sync.mjs +0 -1627
- package/dist/chunks/mcp-market.mjs +0 -1077
- package/dist/chunks/mcp-server.mjs +0 -776
- package/dist/chunks/project-detector.mjs +0 -131
- package/dist/chunks/provider-registry.mjs +0 -92
- package/dist/chunks/setup-wizard.mjs +0 -362
- package/dist/chunks/tools.mjs +0 -143
- package/dist/chunks/workflows2.mjs +0 -232
- package/dist/shared/ccjk.C0pb50xH.mjs +0 -347
- package/dist/shared/ccjk.ChMkBmdL.mjs +0 -490
- package/dist/shared/ccjk.CtSfXUSh.mjs +0 -209
- package/dist/shared/ccjk.xfAjmbJp.mjs +0 -75
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { basename, join } from 'pathe';
|
|
3
|
-
|
|
4
|
-
async function detectProjectInfo(cwd = process.cwd()) {
|
|
5
|
-
const projectName = basename(cwd);
|
|
6
|
-
let projectType;
|
|
7
|
-
let language;
|
|
8
|
-
let skillsCount = 0;
|
|
9
|
-
let mcpCount = 0;
|
|
10
|
-
let agentsCount = 0;
|
|
11
|
-
const detectionResult = await detectProjectType(cwd);
|
|
12
|
-
projectType = detectionResult.type;
|
|
13
|
-
language = detectionResult.language;
|
|
14
|
-
const ccjkConfig = await detectCcjkConfig(cwd);
|
|
15
|
-
skillsCount = ccjkConfig.skillsCount;
|
|
16
|
-
mcpCount = ccjkConfig.mcpCount;
|
|
17
|
-
agentsCount = ccjkConfig.agentsCount;
|
|
18
|
-
return {
|
|
19
|
-
name: projectName,
|
|
20
|
-
type: projectType,
|
|
21
|
-
language,
|
|
22
|
-
skillsCount,
|
|
23
|
-
mcpCount,
|
|
24
|
-
agentsCount
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
async function detectProjectType(cwd) {
|
|
28
|
-
const packageJsonPath = join(cwd, "package.json");
|
|
29
|
-
if (existsSync(packageJsonPath)) {
|
|
30
|
-
try {
|
|
31
|
-
const content = readFileSync(packageJsonPath, "utf-8");
|
|
32
|
-
const pkg = JSON.parse(content);
|
|
33
|
-
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
34
|
-
if (deps.next)
|
|
35
|
-
return { type: "Next.js", language: "TypeScript" };
|
|
36
|
-
if (deps.nuxt)
|
|
37
|
-
return { type: "Nuxt", language: "TypeScript" };
|
|
38
|
-
if (deps.vue)
|
|
39
|
-
return { type: "Vue", language: "TypeScript" };
|
|
40
|
-
if (deps.react)
|
|
41
|
-
return { type: "React", language: "TypeScript" };
|
|
42
|
-
if (deps["@angular/core"])
|
|
43
|
-
return { type: "Angular", language: "TypeScript" };
|
|
44
|
-
if (deps.svelte)
|
|
45
|
-
return { type: "Svelte", language: "TypeScript" };
|
|
46
|
-
if (deps.express)
|
|
47
|
-
return { type: "Express", language: "JavaScript" };
|
|
48
|
-
if (deps.fastify)
|
|
49
|
-
return { type: "Fastify", language: "TypeScript" };
|
|
50
|
-
if (deps.nest)
|
|
51
|
-
return { type: "NestJS", language: "TypeScript" };
|
|
52
|
-
if (deps.electron)
|
|
53
|
-
return { type: "Electron", language: "TypeScript" };
|
|
54
|
-
if (deps.tauri)
|
|
55
|
-
return { type: "Tauri", language: "TypeScript" };
|
|
56
|
-
const hasTypeScript = existsSync(join(cwd, "tsconfig.json")) || deps.typescript;
|
|
57
|
-
return {
|
|
58
|
-
type: "Node.js",
|
|
59
|
-
language: hasTypeScript ? "TypeScript" : "JavaScript"
|
|
60
|
-
};
|
|
61
|
-
} catch {
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
if (existsSync(join(cwd, "Cargo.toml"))) {
|
|
65
|
-
return { type: "Rust", language: "Rust" };
|
|
66
|
-
}
|
|
67
|
-
if (existsSync(join(cwd, "go.mod"))) {
|
|
68
|
-
return { type: "Go", language: "Go" };
|
|
69
|
-
}
|
|
70
|
-
if (existsSync(join(cwd, "pyproject.toml")) || existsSync(join(cwd, "setup.py"))) {
|
|
71
|
-
return { type: "Python", language: "Python" };
|
|
72
|
-
}
|
|
73
|
-
if (existsSync(join(cwd, "pom.xml"))) {
|
|
74
|
-
return { type: "Maven", language: "Java" };
|
|
75
|
-
}
|
|
76
|
-
if (existsSync(join(cwd, "build.gradle")) || existsSync(join(cwd, "build.gradle.kts"))) {
|
|
77
|
-
return { type: "Gradle", language: "Java" };
|
|
78
|
-
}
|
|
79
|
-
if (existsSync(join(cwd, "Gemfile"))) {
|
|
80
|
-
return { type: "Ruby", language: "Ruby" };
|
|
81
|
-
}
|
|
82
|
-
if (existsSync(join(cwd, "composer.json"))) {
|
|
83
|
-
return { type: "PHP", language: "PHP" };
|
|
84
|
-
}
|
|
85
|
-
const csprojFiles = await findFiles(cwd, "*.csproj");
|
|
86
|
-
if (csprojFiles.length > 0) {
|
|
87
|
-
return { type: ".NET", language: "C#" };
|
|
88
|
-
}
|
|
89
|
-
return { type: void 0, language: void 0 };
|
|
90
|
-
}
|
|
91
|
-
async function detectCcjkConfig(cwd) {
|
|
92
|
-
let skillsCount = 0;
|
|
93
|
-
let mcpCount = 0;
|
|
94
|
-
let agentsCount = 0;
|
|
95
|
-
const ccjkDir = join(cwd, ".ccjk");
|
|
96
|
-
if (existsSync(ccjkDir)) {
|
|
97
|
-
const skillsDir = join(ccjkDir, "skills");
|
|
98
|
-
if (existsSync(skillsDir)) {
|
|
99
|
-
const skillFiles = await findFiles(skillsDir, "*.md");
|
|
100
|
-
skillsCount = skillFiles.length;
|
|
101
|
-
}
|
|
102
|
-
const agentsDir = join(ccjkDir, "agents");
|
|
103
|
-
if (existsSync(agentsDir)) {
|
|
104
|
-
const agentFiles = await findFiles(agentsDir, "*.md");
|
|
105
|
-
agentsCount = agentFiles.length;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
const claudeDir = join(cwd, ".claude");
|
|
109
|
-
if (existsSync(claudeDir)) {
|
|
110
|
-
const mcpConfigPath = join(claudeDir, "mcp.json");
|
|
111
|
-
if (existsSync(mcpConfigPath)) {
|
|
112
|
-
try {
|
|
113
|
-
const content = readFileSync(mcpConfigPath, "utf-8");
|
|
114
|
-
const config = JSON.parse(content);
|
|
115
|
-
mcpCount = Object.keys(config.mcpServers || {}).length;
|
|
116
|
-
} catch {
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
return { skillsCount, mcpCount, agentsCount };
|
|
121
|
-
}
|
|
122
|
-
async function findFiles(dir, pattern) {
|
|
123
|
-
try {
|
|
124
|
-
const { glob } = await import('glob');
|
|
125
|
-
return await glob(pattern, { cwd: dir, absolute: true });
|
|
126
|
-
} catch {
|
|
127
|
-
return [];
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
export { detectProjectInfo };
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
class ProviderRegistry {
|
|
2
|
-
static instance;
|
|
3
|
-
providers = /* @__PURE__ */ new Map();
|
|
4
|
-
metadata = /* @__PURE__ */ new Map();
|
|
5
|
-
constructor() {
|
|
6
|
-
}
|
|
7
|
-
static getInstance() {
|
|
8
|
-
if (!ProviderRegistry.instance) {
|
|
9
|
-
ProviderRegistry.instance = new ProviderRegistry();
|
|
10
|
-
}
|
|
11
|
-
return ProviderRegistry.instance;
|
|
12
|
-
}
|
|
13
|
-
/**
|
|
14
|
-
* Register a provider
|
|
15
|
-
*/
|
|
16
|
-
register(provider, metadata) {
|
|
17
|
-
const config = provider.getConfig();
|
|
18
|
-
this.providers.set(config.id, provider);
|
|
19
|
-
const fullMetadata = {
|
|
20
|
-
id: config.id,
|
|
21
|
-
name: config.name,
|
|
22
|
-
description: config.description,
|
|
23
|
-
icon: config.icon,
|
|
24
|
-
popular: metadata?.popular ?? false,
|
|
25
|
-
setupTime: metadata?.setupTime ?? "1 minute",
|
|
26
|
-
difficulty: metadata?.difficulty ?? "easy"
|
|
27
|
-
};
|
|
28
|
-
this.metadata.set(config.id, fullMetadata);
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Get a provider by ID
|
|
32
|
-
*/
|
|
33
|
-
getProvider(id) {
|
|
34
|
-
return this.providers.get(id);
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Get all registered providers
|
|
38
|
-
*/
|
|
39
|
-
getAllProviders() {
|
|
40
|
-
return Array.from(this.providers.values());
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Get provider metadata
|
|
44
|
-
*/
|
|
45
|
-
getMetadata(id) {
|
|
46
|
-
return this.metadata.get(id);
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Get all provider metadata
|
|
50
|
-
*/
|
|
51
|
-
getAllMetadata() {
|
|
52
|
-
return Array.from(this.metadata.values());
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Get popular providers
|
|
56
|
-
*/
|
|
57
|
-
getPopularProviders() {
|
|
58
|
-
return this.getAllMetadata().filter((m) => m.popular).sort((a, b) => a.name.localeCompare(b.name));
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Search providers by name or description
|
|
62
|
-
*/
|
|
63
|
-
searchProviders(query) {
|
|
64
|
-
const lowerQuery = query.toLowerCase();
|
|
65
|
-
return this.getAllMetadata().filter(
|
|
66
|
-
(m) => m.name.toLowerCase().includes(lowerQuery) || m.description.toLowerCase().includes(lowerQuery)
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Check if provider exists
|
|
71
|
-
*/
|
|
72
|
-
hasProvider(id) {
|
|
73
|
-
return this.providers.has(id);
|
|
74
|
-
}
|
|
75
|
-
/**
|
|
76
|
-
* Unregister a provider (for testing)
|
|
77
|
-
*/
|
|
78
|
-
unregister(id) {
|
|
79
|
-
this.providers.delete(id);
|
|
80
|
-
this.metadata.delete(id);
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* Clear all providers (for testing)
|
|
84
|
-
*/
|
|
85
|
-
clear() {
|
|
86
|
-
this.providers.clear();
|
|
87
|
-
this.metadata.clear();
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
const providerRegistry = ProviderRegistry.getInstance();
|
|
91
|
-
|
|
92
|
-
export { ProviderRegistry, providerRegistry };
|
|
@@ -1,362 +0,0 @@
|
|
|
1
|
-
import { providerRegistry } from './provider-registry.mjs';
|
|
2
|
-
|
|
3
|
-
class ProviderFactory {
|
|
4
|
-
/**
|
|
5
|
-
* Create a provider setup from minimal input
|
|
6
|
-
*/
|
|
7
|
-
static async createSetup(providerId, apiKey, customFields) {
|
|
8
|
-
const provider = providerRegistry.getProvider(providerId);
|
|
9
|
-
if (!provider) {
|
|
10
|
-
throw new Error(`Provider not found: ${providerId}`);
|
|
11
|
-
}
|
|
12
|
-
const config = provider.getConfig();
|
|
13
|
-
const credentials = {
|
|
14
|
-
apiKey,
|
|
15
|
-
customFields
|
|
16
|
-
};
|
|
17
|
-
let autoFilled = {};
|
|
18
|
-
if (provider.autoFillFromApiKey) {
|
|
19
|
-
autoFilled = provider.autoFillFromApiKey(apiKey);
|
|
20
|
-
}
|
|
21
|
-
return {
|
|
22
|
-
provider: config,
|
|
23
|
-
credentials,
|
|
24
|
-
model: autoFilled.model || config.defaultModel
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
/**
|
|
28
|
-
* Validate a provider setup
|
|
29
|
-
*/
|
|
30
|
-
static async validateSetup(setup) {
|
|
31
|
-
const provider = providerRegistry.getProvider(setup.provider.id);
|
|
32
|
-
if (!provider) {
|
|
33
|
-
return {
|
|
34
|
-
valid: false,
|
|
35
|
-
errors: [`Provider not found: ${setup.provider.id}`],
|
|
36
|
-
warnings: []
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
const result = await provider.validateCredentials(setup.credentials);
|
|
40
|
-
return {
|
|
41
|
-
valid: result.valid,
|
|
42
|
-
errors: result.errors || [],
|
|
43
|
-
warnings: result.warnings || []
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Test provider connection
|
|
48
|
-
*/
|
|
49
|
-
static async testConnection(providerId, credentials) {
|
|
50
|
-
const provider = providerRegistry.getProvider(providerId);
|
|
51
|
-
if (!provider) {
|
|
52
|
-
return {
|
|
53
|
-
success: false,
|
|
54
|
-
message: `Provider not found: ${providerId}`
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
try {
|
|
58
|
-
const result = await provider.testConnection(credentials);
|
|
59
|
-
return {
|
|
60
|
-
success: result.valid,
|
|
61
|
-
message: result.valid ? "Connection successful!" : result.errors?.join(", ") || "Connection failed",
|
|
62
|
-
suggestions: result.suggestions
|
|
63
|
-
};
|
|
64
|
-
} catch (error) {
|
|
65
|
-
const errorHelp = provider.getErrorHelp(error);
|
|
66
|
-
return {
|
|
67
|
-
success: false,
|
|
68
|
-
message: error.message,
|
|
69
|
-
suggestions: [errorHelp]
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Get quick setup template for a provider
|
|
75
|
-
*/
|
|
76
|
-
static getQuickSetupTemplate(providerId) {
|
|
77
|
-
const provider = providerRegistry.getProvider(providerId);
|
|
78
|
-
if (!provider) {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
const config = provider.getConfig();
|
|
82
|
-
const fields = [];
|
|
83
|
-
if (config.requiresApiKey) {
|
|
84
|
-
fields.push({
|
|
85
|
-
name: "apiKey",
|
|
86
|
-
label: "API Key",
|
|
87
|
-
type: "password",
|
|
88
|
-
required: true
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
if (config.customFields) {
|
|
92
|
-
config.customFields.forEach((field) => {
|
|
93
|
-
fields.push({
|
|
94
|
-
name: field.key,
|
|
95
|
-
label: field.label,
|
|
96
|
-
type: field.type,
|
|
97
|
-
required: field.required
|
|
98
|
-
});
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
return {
|
|
102
|
-
provider: config.name,
|
|
103
|
-
steps: provider.getSetupInstructions(),
|
|
104
|
-
fields
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
/**
|
|
108
|
-
* Clone setup with different credentials
|
|
109
|
-
*/
|
|
110
|
-
static cloneSetup(original, newCredentials) {
|
|
111
|
-
return {
|
|
112
|
-
...original,
|
|
113
|
-
credentials: {
|
|
114
|
-
...original.credentials,
|
|
115
|
-
...newCredentials
|
|
116
|
-
}
|
|
117
|
-
};
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Export setup to JSON
|
|
121
|
-
*/
|
|
122
|
-
static exportSetup(setup, includeCredentials = false) {
|
|
123
|
-
const exportData = {
|
|
124
|
-
providerId: setup.provider.id,
|
|
125
|
-
providerName: setup.provider.name,
|
|
126
|
-
model: setup.model,
|
|
127
|
-
...includeCredentials && { credentials: setup.credentials }
|
|
128
|
-
};
|
|
129
|
-
return JSON.stringify(exportData, null, 2);
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Import setup from JSON
|
|
133
|
-
*/
|
|
134
|
-
static async importSetup(json) {
|
|
135
|
-
const data = JSON.parse(json);
|
|
136
|
-
const provider = providerRegistry.getProvider(data.providerId);
|
|
137
|
-
if (!provider) {
|
|
138
|
-
throw new Error(`Provider not found: ${data.providerId}`);
|
|
139
|
-
}
|
|
140
|
-
return {
|
|
141
|
-
provider: provider.getConfig(),
|
|
142
|
-
credentials: data.credentials || {},
|
|
143
|
-
model: data.model
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
class SetupWizard {
|
|
149
|
-
state = {
|
|
150
|
-
currentStep: 1,
|
|
151
|
-
credentials: {},
|
|
152
|
-
errors: [],
|
|
153
|
-
warnings: []
|
|
154
|
-
};
|
|
155
|
-
/**
|
|
156
|
-
* Get Step 1: Provider Selection
|
|
157
|
-
*/
|
|
158
|
-
getStep1() {
|
|
159
|
-
const providers = providerRegistry.getAllMetadata();
|
|
160
|
-
const popularProviders = providers.filter((p) => p.popular);
|
|
161
|
-
const otherProviders = providers.filter((p) => !p.popular);
|
|
162
|
-
const options = [
|
|
163
|
-
...popularProviders.map((p) => ({
|
|
164
|
-
value: p.id,
|
|
165
|
-
label: `${p.icon || ""} ${p.name}`,
|
|
166
|
-
description: `${p.description} (Setup: ${p.setupTime})`
|
|
167
|
-
})),
|
|
168
|
-
{ value: "---", label: "--- Other Providers ---", description: "" },
|
|
169
|
-
...otherProviders.map((p) => ({
|
|
170
|
-
value: p.id,
|
|
171
|
-
label: `${p.icon || ""} ${p.name}`,
|
|
172
|
-
description: `${p.description} (Setup: ${p.setupTime})`
|
|
173
|
-
}))
|
|
174
|
-
];
|
|
175
|
-
return {
|
|
176
|
-
step: 1,
|
|
177
|
-
title: "Choose Your AI Provider",
|
|
178
|
-
description: "Select the AI service you want to use. Popular providers are listed first.",
|
|
179
|
-
fields: [
|
|
180
|
-
{
|
|
181
|
-
name: "provider",
|
|
182
|
-
label: "AI Provider",
|
|
183
|
-
type: "select",
|
|
184
|
-
required: true,
|
|
185
|
-
options,
|
|
186
|
-
helpText: "Choose based on your preference and region. All providers support Claude-like models."
|
|
187
|
-
}
|
|
188
|
-
]
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Get Step 2: API Configuration
|
|
193
|
-
*/
|
|
194
|
-
getStep2(providerId) {
|
|
195
|
-
const provider = providerRegistry.getProvider(providerId);
|
|
196
|
-
if (!provider) {
|
|
197
|
-
throw new Error(`Provider not found: ${providerId}`);
|
|
198
|
-
}
|
|
199
|
-
const config = provider.getConfig();
|
|
200
|
-
const fields = [];
|
|
201
|
-
if (config.requiresApiKey) {
|
|
202
|
-
fields.push({
|
|
203
|
-
name: "apiKey",
|
|
204
|
-
label: "API Key",
|
|
205
|
-
type: "password",
|
|
206
|
-
required: true,
|
|
207
|
-
placeholder: "Paste your API key here",
|
|
208
|
-
helpText: provider.getSetupInstructions().join(" \u2192 ")
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
if (config.customFields) {
|
|
212
|
-
config.customFields.forEach((field) => {
|
|
213
|
-
const wizardField = {
|
|
214
|
-
name: field.key,
|
|
215
|
-
label: field.label,
|
|
216
|
-
type: field.type,
|
|
217
|
-
required: field.required,
|
|
218
|
-
placeholder: field.placeholder,
|
|
219
|
-
helpText: field.helpText,
|
|
220
|
-
defaultValue: field.defaultValue
|
|
221
|
-
};
|
|
222
|
-
if (field.type === "select" && field.options) {
|
|
223
|
-
wizardField.options = field.options.map((opt) => ({
|
|
224
|
-
value: opt,
|
|
225
|
-
label: opt
|
|
226
|
-
}));
|
|
227
|
-
}
|
|
228
|
-
fields.push(wizardField);
|
|
229
|
-
});
|
|
230
|
-
}
|
|
231
|
-
if (config.availableModels.length > 0) {
|
|
232
|
-
fields.push({
|
|
233
|
-
name: "model",
|
|
234
|
-
label: "Model (Optional)",
|
|
235
|
-
type: "select",
|
|
236
|
-
required: false,
|
|
237
|
-
options: config.availableModels.map((model) => ({
|
|
238
|
-
value: model,
|
|
239
|
-
label: model
|
|
240
|
-
})),
|
|
241
|
-
defaultValue: config.defaultModel,
|
|
242
|
-
helpText: `Default: ${config.defaultModel}. You can change this later.`
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
return {
|
|
246
|
-
step: 2,
|
|
247
|
-
title: "Enter Your API Key",
|
|
248
|
-
description: `Just paste your ${config.name} API key and you're done!`,
|
|
249
|
-
fields
|
|
250
|
-
};
|
|
251
|
-
}
|
|
252
|
-
/**
|
|
253
|
-
* Set provider selection (Step 1)
|
|
254
|
-
*/
|
|
255
|
-
setProvider(providerId) {
|
|
256
|
-
if (!providerRegistry.hasProvider(providerId)) {
|
|
257
|
-
this.state.errors.push(`Provider not found: ${providerId}`);
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
this.state.providerId = providerId;
|
|
261
|
-
this.state.currentStep = 2;
|
|
262
|
-
this.state.errors = [];
|
|
263
|
-
this.state.warnings = [];
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* Set credentials (Step 2)
|
|
267
|
-
*/
|
|
268
|
-
async setCredentials(data) {
|
|
269
|
-
if (!this.state.providerId) {
|
|
270
|
-
this.state.errors.push("Please select a provider first");
|
|
271
|
-
return;
|
|
272
|
-
}
|
|
273
|
-
const provider = providerRegistry.getProvider(this.state.providerId);
|
|
274
|
-
if (!provider) {
|
|
275
|
-
this.state.errors.push("Provider not found");
|
|
276
|
-
return;
|
|
277
|
-
}
|
|
278
|
-
const { apiKey, model, ...customFields } = data;
|
|
279
|
-
this.state.credentials = {
|
|
280
|
-
apiKey,
|
|
281
|
-
customFields: Object.keys(customFields).length > 0 ? customFields : void 0
|
|
282
|
-
};
|
|
283
|
-
if (model) {
|
|
284
|
-
this.state.model = model;
|
|
285
|
-
}
|
|
286
|
-
const validation = await provider.validateCredentials(this.state.credentials);
|
|
287
|
-
this.state.errors = validation.errors || [];
|
|
288
|
-
this.state.warnings = validation.warnings || [];
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
|
-
* Complete setup and return configuration
|
|
292
|
-
*/
|
|
293
|
-
async complete() {
|
|
294
|
-
if (!this.state.providerId) {
|
|
295
|
-
throw new Error("Provider not selected");
|
|
296
|
-
}
|
|
297
|
-
if (this.state.errors.length > 0) {
|
|
298
|
-
throw new Error(`Configuration errors: ${this.state.errors.join(", ")}`);
|
|
299
|
-
}
|
|
300
|
-
const setup = await ProviderFactory.createSetup(
|
|
301
|
-
this.state.providerId,
|
|
302
|
-
this.state.credentials.apiKey,
|
|
303
|
-
this.state.credentials.customFields
|
|
304
|
-
);
|
|
305
|
-
if (this.state.model) {
|
|
306
|
-
setup.model = this.state.model;
|
|
307
|
-
}
|
|
308
|
-
return setup;
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Test connection before completing
|
|
312
|
-
*/
|
|
313
|
-
async testConnection() {
|
|
314
|
-
if (!this.state.providerId) {
|
|
315
|
-
return {
|
|
316
|
-
success: false,
|
|
317
|
-
message: "Provider not selected"
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
return ProviderFactory.testConnection(this.state.providerId, this.state.credentials);
|
|
321
|
-
}
|
|
322
|
-
/**
|
|
323
|
-
* Get current state
|
|
324
|
-
*/
|
|
325
|
-
getState() {
|
|
326
|
-
return { ...this.state };
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Reset wizard
|
|
330
|
-
*/
|
|
331
|
-
reset() {
|
|
332
|
-
this.state = {
|
|
333
|
-
currentStep: 1,
|
|
334
|
-
credentials: {},
|
|
335
|
-
errors: [],
|
|
336
|
-
warnings: []
|
|
337
|
-
};
|
|
338
|
-
}
|
|
339
|
-
/**
|
|
340
|
-
* Get progress percentage
|
|
341
|
-
*/
|
|
342
|
-
getProgress() {
|
|
343
|
-
return this.state.currentStep / 2 * 100;
|
|
344
|
-
}
|
|
345
|
-
/**
|
|
346
|
-
* Quick setup with provider ID and API key only
|
|
347
|
-
*/
|
|
348
|
-
async quickSetup(providerId, apiKey) {
|
|
349
|
-
this.reset();
|
|
350
|
-
this.setProvider(providerId);
|
|
351
|
-
await this.setCredentials({ apiKey });
|
|
352
|
-
if (this.state.errors.length > 0) {
|
|
353
|
-
throw new Error(this.state.errors.join(", "));
|
|
354
|
-
}
|
|
355
|
-
return this.complete();
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
function createWizard() {
|
|
359
|
-
return new SetupWizard();
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
export { SetupWizard, createWizard };
|