@kkelly-offical/kkcode 0.1.6 → 0.2.1
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/LICENSE +674 -674
- package/README.md +452 -387
- package/package.json +50 -46
- package/src/agent/agent.mjs +19 -2
- package/src/agent/custom-agent-loader.mjs +6 -3
- package/src/agent/generator.mjs +2 -2
- package/src/agent/prompt/assistant.txt +12 -0
- package/src/agent/prompt/bug-hunter.txt +90 -0
- package/src/agent/prompt/frontend-designer.txt +58 -58
- package/src/agent/prompt/guide.txt +1 -1
- package/src/agent/prompt/longagent-blueprint-agent.txt +83 -83
- package/src/agent/prompt/longagent-coding-agent.txt +37 -37
- package/src/agent/prompt/longagent-debugging-agent.txt +46 -46
- package/src/agent/prompt/longagent-preview-agent.txt +63 -63
- package/src/command/custom-commands.mjs +2 -2
- package/src/commands/agent.mjs +1 -1
- package/src/commands/background.mjs +145 -4
- package/src/commands/chat.mjs +117 -76
- package/src/commands/config.mjs +148 -1
- package/src/commands/doctor.mjs +30 -6
- package/src/commands/init.mjs +32 -6
- package/src/commands/longagent.mjs +117 -0
- package/src/commands/mcp.mjs +275 -43
- package/src/commands/permission.mjs +1 -1
- package/src/commands/session.mjs +195 -140
- package/src/commands/skill.mjs +63 -0
- package/src/commands/theme.mjs +1 -1
- package/src/config/defaults.mjs +280 -260
- package/src/config/import-config.mjs +1 -1
- package/src/config/load-config.mjs +61 -4
- package/src/config/schema.mjs +591 -574
- package/src/context.mjs +4 -1
- package/src/core/constants.mjs +97 -91
- package/src/core/types.mjs +1 -1
- package/src/github/api.mjs +78 -78
- package/src/github/auth.mjs +294 -286
- package/src/github/flow.mjs +298 -298
- package/src/github/workspace.mjs +225 -212
- package/src/index.mjs +84 -82
- package/src/knowledge/frontend-aesthetics.txt +38 -38
- package/src/mcp/client-http.mjs +139 -141
- package/src/mcp/client-sse.mjs +297 -288
- package/src/mcp/client-stdio.mjs +534 -533
- package/src/mcp/constants.mjs +2 -2
- package/src/mcp/registry.mjs +498 -479
- package/src/mcp/stdio-framing.mjs +135 -133
- package/src/mcp/tool-result.mjs +24 -24
- package/src/observability/edit-diagnostics.mjs +449 -0
- package/src/observability/index.mjs +42 -42
- package/src/observability/metrics.mjs +165 -137
- package/src/observability/tracer.mjs +137 -137
- package/src/onboarding.mjs +209 -0
- package/src/orchestration/background-manager.mjs +567 -372
- package/src/orchestration/background-worker.mjs +419 -305
- package/src/orchestration/interruption-reason.mjs +21 -0
- package/src/orchestration/longagent-manager.mjs +197 -171
- package/src/orchestration/stage-scheduler.mjs +733 -728
- package/src/orchestration/subagent-router.mjs +7 -1
- package/src/orchestration/task-scheduler.mjs +219 -7
- package/src/permission/engine.mjs +1 -1
- package/src/permission/exec-policy.mjs +370 -370
- package/src/permission/file-edit-policy.mjs +108 -0
- package/src/permission/prompt.mjs +1 -1
- package/src/permission/rules.mjs +116 -7
- package/src/plugin/builtin-hooks/post-edit-format.mjs +2 -1
- package/src/plugin/builtin-hooks/post-edit-typecheck.mjs +104 -40
- package/src/plugin/hook-bus.mjs +19 -5
- package/src/plugin/manifest-loader.mjs +222 -0
- package/src/provider/anthropic.mjs +396 -390
- package/src/provider/ollama.mjs +7 -1
- package/src/provider/openai.mjs +382 -340
- package/src/provider/retry-policy.mjs +74 -68
- package/src/provider/router.mjs +242 -241
- package/src/provider/sse.mjs +104 -104
- package/src/provider/wizard.mjs +556 -0
- package/src/repl/capability-facade.mjs +30 -0
- package/src/repl/command-surface.mjs +23 -0
- package/src/repl/controller-entry.mjs +40 -0
- package/src/repl/core-shell.mjs +208 -0
- package/src/repl/dialog-router.mjs +87 -0
- package/src/repl/input-engine.mjs +76 -0
- package/src/repl/keymap.mjs +7 -0
- package/src/repl/operator-surface.mjs +15 -0
- package/src/repl/permission-flow.mjs +49 -0
- package/src/repl/runtime-facade.mjs +36 -0
- package/src/repl/slash-router.mjs +62 -0
- package/src/repl/state-store.mjs +29 -0
- package/src/repl/turn-controller.mjs +58 -0
- package/src/repl/verification.mjs +23 -0
- package/src/repl.mjs +3368 -2929
- package/src/rules/load-rules.mjs +3 -3
- package/src/runtime.mjs +1 -1
- package/src/session/agent-transaction.mjs +86 -0
- package/src/session/checkpoint.mjs +302 -302
- package/src/session/compaction.mjs +36 -14
- package/src/session/engine.mjs +417 -227
- package/src/session/longagent-4stage.mjs +467 -460
- package/src/session/longagent-hybrid.mjs +1344 -1081
- package/src/session/longagent-plan.mjs +376 -365
- package/src/session/longagent-project-memory.mjs +53 -53
- package/src/session/longagent-scaffold.mjs +291 -291
- package/src/session/longagent-task-bus.mjs +138 -54
- package/src/session/longagent-utils.mjs +828 -472
- package/src/session/longagent.mjs +911 -884
- package/src/session/loop.mjs +1005 -905
- package/src/session/prompt/agent.txt +25 -0
- package/src/session/prompt/anthropic.txt +150 -150
- package/src/session/prompt/beast.txt +1 -1
- package/src/session/prompt/plan.txt +28 -6
- package/src/session/prompt/qwen.txt +46 -46
- package/src/session/recovery.mjs +21 -0
- package/src/session/rollback.mjs +197 -0
- package/src/session/routing-observability.mjs +72 -0
- package/src/session/runtime-state.mjs +47 -0
- package/src/session/store.mjs +523 -510
- package/src/session/system-prompt.mjs +56 -8
- package/src/session/task-validator.mjs +267 -267
- package/src/session/usability-gates.mjs +2 -2
- package/src/skill/builtin/commit.mjs +64 -64
- package/src/skill/builtin/design.mjs +76 -76
- package/src/skill/generator.mjs +18 -2
- package/src/skill/registry.mjs +642 -390
- package/src/storage/audit-store.mjs +18 -11
- package/src/storage/event-log.mjs +7 -1
- package/src/storage/ghost-commit-store.mjs +243 -245
- package/src/storage/paths.mjs +13 -0
- package/src/theme/default-theme.mjs +1 -1
- package/src/theme/markdown.mjs +4 -0
- package/src/theme/schema.mjs +1 -1
- package/src/theme/status-bar.mjs +162 -158
- package/src/tool/audit-wrapper.mjs +18 -2
- package/src/tool/edit-transaction.mjs +23 -0
- package/src/tool/executor.mjs +26 -1
- package/src/tool/file-read-state.mjs +65 -0
- package/src/tool/git-auto.mjs +526 -526
- package/src/tool/git-full-auto.mjs +487 -478
- package/src/tool/mutation-guard.mjs +54 -0
- package/src/tool/prompt/edit.txt +3 -3
- package/src/tool/prompt/multiedit.txt +1 -0
- package/src/tool/prompt/notebookedit.txt +2 -1
- package/src/tool/prompt/patch.txt +25 -24
- package/src/tool/prompt/read.txt +3 -3
- package/src/tool/prompt/sysinfo.txt +29 -0
- package/src/tool/prompt/task.txt +66 -4
- package/src/tool/prompt/write.txt +2 -2
- package/src/tool/question-prompt.mjs +17 -4
- package/src/tool/registry.mjs +1701 -1343
- package/src/tool/task-tool.mjs +14 -6
- package/src/ui/activity-renderer.mjs +667 -664
- package/src/ui/repl-background-panel.mjs +7 -0
- package/src/ui/repl-capability-panel.mjs +9 -0
- package/src/ui/repl-dashboard.mjs +54 -4
- package/src/ui/repl-help.mjs +110 -0
- package/src/ui/repl-operator-panel.mjs +12 -0
- package/src/ui/repl-route-feedback.mjs +35 -0
- package/src/ui/repl-status-view.mjs +76 -0
- package/src/ui/repl-task-panel.mjs +5 -0
- package/src/ui/repl-transcript-panel.mjs +56 -0
- package/src/ui/repl-turn-summary.mjs +135 -0
- package/src/usage/pricing.mjs +122 -121
- package/src/usage/usage-meter.mjs +1 -0
- package/src/util/git.mjs +562 -519
- package/src/util/template.mjs +6 -1
package/src/commands/mcp.mjs
CHANGED
|
@@ -1,6 +1,122 @@
|
|
|
1
1
|
import { Command } from "commander"
|
|
2
|
+
import { access, mkdir, readFile, writeFile } from "node:fs/promises"
|
|
3
|
+
import { dirname, join, resolve } from "node:path"
|
|
2
4
|
import { buildContext, printContextWarnings } from "../context.mjs"
|
|
3
5
|
import { McpRegistry } from "../mcp/registry.mjs"
|
|
6
|
+
import { ensureDefaultSkillPack } from "../skill/registry.mjs"
|
|
7
|
+
import { userRootDir } from "../storage/paths.mjs"
|
|
8
|
+
|
|
9
|
+
const DEFAULT_MCP_INIT_CONFIG = {
|
|
10
|
+
servers: {
|
|
11
|
+
context7: {
|
|
12
|
+
enabled: false,
|
|
13
|
+
command: "npx",
|
|
14
|
+
args: ["--yes", "@upstash/context7-mcp"],
|
|
15
|
+
startup_timeout_ms: 60000
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function withInitializedMcp(run) {
|
|
21
|
+
const ctx = await buildContext()
|
|
22
|
+
printContextWarnings(ctx)
|
|
23
|
+
try {
|
|
24
|
+
await McpRegistry.initialize(ctx.configState.config)
|
|
25
|
+
return await run(ctx)
|
|
26
|
+
} finally {
|
|
27
|
+
McpRegistry.shutdown()
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function exists(target) {
|
|
32
|
+
try {
|
|
33
|
+
await access(target)
|
|
34
|
+
return true
|
|
35
|
+
} catch {
|
|
36
|
+
return false
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function projectMcpPath(cwd = process.cwd()) {
|
|
41
|
+
return join(cwd, ".kkcode", "mcp.json")
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function globalMcpPath() {
|
|
45
|
+
return join(userRootDir(), "mcp.json")
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function renderPathLabel(filePath) {
|
|
49
|
+
const home = process.env.HOME || process.env.USERPROFILE
|
|
50
|
+
if (!home) return filePath
|
|
51
|
+
const homeNorm = resolve(home).replace(/\\/g, "/")
|
|
52
|
+
const fileNorm = resolve(filePath).replace(/\\/g, "/")
|
|
53
|
+
if (fileNorm === homeNorm) return "~"
|
|
54
|
+
if (fileNorm.startsWith(`${homeNorm}/`)) {
|
|
55
|
+
return `~${fileNorm.slice(homeNorm.length)}`
|
|
56
|
+
}
|
|
57
|
+
return filePath
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function globalScopeLabel() {
|
|
61
|
+
const home = process.env.HOME || process.env.USERPROFILE
|
|
62
|
+
const userRoot = globalMcpPath()
|
|
63
|
+
if (!home) return userRoot
|
|
64
|
+
const homeNorm = resolve(home).replace(/\\/g, "/")
|
|
65
|
+
const rootNorm = resolve(userRoot).replace(/\\/g, "/")
|
|
66
|
+
if (rootNorm === homeNorm) return "~"
|
|
67
|
+
if (rootNorm.startsWith(`${homeNorm}/`)) {
|
|
68
|
+
return `~${rootNorm.slice(homeNorm.length)}`
|
|
69
|
+
}
|
|
70
|
+
return userRoot
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function legacyMcpPaths(cwd = process.cwd()) {
|
|
74
|
+
return [
|
|
75
|
+
{ kind: "local", path: join(cwd, ".mcp.json"), label: ".mcp.json" },
|
|
76
|
+
{ kind: "local", path: join(cwd, ".mcp", "config.json"), label: ".mcp/config.json" },
|
|
77
|
+
{ kind: "project", path: join(cwd, ".kkcode", "mcp.json"), label: ".kkcode/mcp.json" },
|
|
78
|
+
{ kind: "global", path: globalMcpPath(), label: renderPathLabel(globalMcpPath()) }
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function stringifyMcpConfig(config) {
|
|
83
|
+
return JSON.stringify(config, null, 2) + "\n"
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function collectServers(fileConfig) {
|
|
87
|
+
if (!fileConfig || typeof fileConfig !== "object") return []
|
|
88
|
+
const servers = fileConfig.servers || fileConfig.mcpServers || {}
|
|
89
|
+
if (!servers || typeof servers !== "object") return []
|
|
90
|
+
return Object.entries(servers)
|
|
91
|
+
.filter((entry) => {
|
|
92
|
+
const name = entry[0]
|
|
93
|
+
const cfg = entry[1]
|
|
94
|
+
return !!name && cfg !== null && cfg !== undefined
|
|
95
|
+
})
|
|
96
|
+
.map((entry) => entry[0])
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function parseMcpConfig(text) {
|
|
100
|
+
if (!text || !text.trim()) return { raw: {}, error: "empty" }
|
|
101
|
+
const normalizedText = text.replace(/^\uFEFF/, "").trim()
|
|
102
|
+
const first = normalizedText[0]
|
|
103
|
+
if (first !== "{" && first !== "[") {
|
|
104
|
+
return { raw: null, error: "unsupported format (expected JSON)" }
|
|
105
|
+
}
|
|
106
|
+
try {
|
|
107
|
+
return { raw: JSON.parse(normalizedText), error: null }
|
|
108
|
+
} catch (error) {
|
|
109
|
+
const cleaned = normalizedText
|
|
110
|
+
.replace(/\/\*[\s\S]*?\*\//g, "")
|
|
111
|
+
.replace(/(^|[^:])\/\/.*$/gm, "$1")
|
|
112
|
+
.replace(/,\s*([}\]])/g, "$1")
|
|
113
|
+
try {
|
|
114
|
+
return { raw: JSON.parse(cleaned), error: null }
|
|
115
|
+
} catch (fallbackError) {
|
|
116
|
+
return { raw: null, error: error.message || "invalid JSON", fallbackError: fallbackError?.message || "invalid JSON" }
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
4
120
|
|
|
5
121
|
export function createMcpCommand() {
|
|
6
122
|
const cmd = new Command("mcp").description("manage MCP servers and tools")
|
|
@@ -9,20 +125,18 @@ export function createMcpCommand() {
|
|
|
9
125
|
.command("list")
|
|
10
126
|
.description("list configured and healthy MCP servers")
|
|
11
127
|
.action(async () => {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
console.log(JSON.stringify(McpRegistry.listServers(), null, 2))
|
|
128
|
+
await withInitializedMcp(async () => {
|
|
129
|
+
console.log(JSON.stringify(McpRegistry.listServers(), null, 2))
|
|
130
|
+
})
|
|
16
131
|
})
|
|
17
132
|
|
|
18
133
|
cmd
|
|
19
134
|
.command("tools")
|
|
20
|
-
.description("list MCP
|
|
135
|
+
.description("list tools for all MCP servers")
|
|
21
136
|
.action(async () => {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
console.log(JSON.stringify(McpRegistry.listTools(), null, 2))
|
|
137
|
+
await withInitializedMcp(async () => {
|
|
138
|
+
console.log(JSON.stringify(McpRegistry.listTools(), null, 2))
|
|
139
|
+
})
|
|
26
140
|
})
|
|
27
141
|
|
|
28
142
|
cmd
|
|
@@ -30,11 +144,10 @@ export function createMcpCommand() {
|
|
|
30
144
|
.description("list resources for MCP server")
|
|
31
145
|
.requiredOption("--server <name>", "server name")
|
|
32
146
|
.action(async (options) => {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
console.log(JSON.stringify(list, null, 2))
|
|
147
|
+
await withInitializedMcp(async () => {
|
|
148
|
+
const list = await McpRegistry.listResources(options.server)
|
|
149
|
+
console.log(JSON.stringify(list, null, 2))
|
|
150
|
+
})
|
|
38
151
|
})
|
|
39
152
|
|
|
40
153
|
cmd
|
|
@@ -42,11 +155,10 @@ export function createMcpCommand() {
|
|
|
42
155
|
.description("list templates for MCP server")
|
|
43
156
|
.requiredOption("--server <name>", "server name")
|
|
44
157
|
.action(async (options) => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
console.log(JSON.stringify(list, null, 2))
|
|
158
|
+
await withInitializedMcp(async () => {
|
|
159
|
+
const list = await McpRegistry.listTemplates(options.server)
|
|
160
|
+
console.log(JSON.stringify(list, null, 2))
|
|
161
|
+
})
|
|
50
162
|
})
|
|
51
163
|
|
|
52
164
|
cmd
|
|
@@ -54,36 +166,156 @@ export function createMcpCommand() {
|
|
|
54
166
|
.description("test MCP health and tool discovery")
|
|
55
167
|
.option("--json", "print JSON output", false)
|
|
56
168
|
.action(async (options) => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
169
|
+
await withInitializedMcp(async () => {
|
|
170
|
+
const snapshot = McpRegistry.healthSnapshot()
|
|
171
|
+
const tools = McpRegistry.listTools()
|
|
172
|
+
const healthy = snapshot.filter((item) => item.ok).length
|
|
173
|
+
const unhealthy = snapshot.length - healthy
|
|
174
|
+
|
|
175
|
+
if (options.json) {
|
|
176
|
+
console.log(JSON.stringify({
|
|
177
|
+
configured: snapshot.length,
|
|
178
|
+
healthy,
|
|
179
|
+
unhealthy,
|
|
180
|
+
tools: tools.length,
|
|
181
|
+
servers: snapshot
|
|
182
|
+
}, null, 2))
|
|
183
|
+
return
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
console.log(`configured: ${snapshot.length}`)
|
|
187
|
+
console.log(`healthy: ${healthy}`)
|
|
188
|
+
console.log(`unhealthy: ${unhealthy}`)
|
|
189
|
+
console.log(`tools: ${tools.length}`)
|
|
190
|
+
for (const item of snapshot) {
|
|
191
|
+
const status = item.ok ? "ok" : "fail"
|
|
192
|
+
const reason = item.reason || "-"
|
|
193
|
+
const error = item.error ? ` | ${item.error}` : ""
|
|
194
|
+
console.log(`- ${item.name} [${item.transport}] ${status} (${reason})${error}`)
|
|
195
|
+
}
|
|
196
|
+
})
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
cmd
|
|
200
|
+
.command("discover")
|
|
201
|
+
.description("discover MCP config files in current workspace")
|
|
202
|
+
.option("--json", "print JSON output", false)
|
|
203
|
+
.action(async (options) => {
|
|
204
|
+
const cwd = process.cwd()
|
|
205
|
+
const candidates = legacyMcpPaths(cwd)
|
|
206
|
+
const results = []
|
|
207
|
+
|
|
208
|
+
for (const item of candidates) {
|
|
209
|
+
const existsNow = await exists(item.path)
|
|
210
|
+
if (!existsNow) {
|
|
211
|
+
results.push({ ...item, exists: false })
|
|
212
|
+
continue
|
|
213
|
+
}
|
|
64
214
|
|
|
215
|
+
const text = await readFile(item.path, "utf8")
|
|
216
|
+
const { raw, error, fallbackError } = parseMcpConfig(text)
|
|
217
|
+
const servers = collectServers(raw)
|
|
218
|
+
results.push({
|
|
219
|
+
...item,
|
|
220
|
+
exists: true,
|
|
221
|
+
parsed: error === null,
|
|
222
|
+
parseError: error,
|
|
223
|
+
parseFallbackError: fallbackError || null,
|
|
224
|
+
servers,
|
|
225
|
+
serverCount: servers.length
|
|
226
|
+
})
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const foundCount = results.filter((entry) => entry.exists).length
|
|
65
230
|
if (options.json) {
|
|
66
|
-
console.log(JSON.stringify({
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
231
|
+
console.log(JSON.stringify({ total: candidates.length, found: foundCount, configs: results }, null, 2))
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (!foundCount) {
|
|
236
|
+
console.log("no MCP config file found")
|
|
237
|
+
console.log("run: kkcode mcp init --project")
|
|
73
238
|
return
|
|
74
239
|
}
|
|
75
240
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
241
|
+
for (const item of results) {
|
|
242
|
+
if (!item.exists) continue
|
|
243
|
+
if (!item.parsed) {
|
|
244
|
+
const pathHint = item.parseFallbackError ? ` fallback=${item.parseFallbackError}` : ""
|
|
245
|
+
console.log(`- ${item.label}: parse error (${item.parseError})${pathHint}`)
|
|
246
|
+
if (item.parseError?.includes("unsupported format")) {
|
|
247
|
+
console.log(" tip: check file is JSON and contains { servers: ... } or { mcpServers: ... }")
|
|
248
|
+
}
|
|
249
|
+
} else {
|
|
250
|
+
console.log(`- ${item.label}: ${item.serverCount} server(s)`)
|
|
251
|
+
for (const serverName of item.servers) {
|
|
252
|
+
console.log(` - ${serverName}`)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
cmd
|
|
259
|
+
.command("init")
|
|
260
|
+
.description("initialize MCP config for quick one-click import")
|
|
261
|
+
.option("--global", `write to ${globalScopeLabel()}`)
|
|
262
|
+
.option("--project", "write to .kkcode/mcp.json")
|
|
263
|
+
.option("--all", "write both global and project config")
|
|
264
|
+
.option("--force", "overwrite existing files")
|
|
265
|
+
.option("--with-skills", "also initialize built-in skill packs")
|
|
266
|
+
.action(async (options) => {
|
|
267
|
+
const includeProject = options.all || options.project || (!options.global && !options.project)
|
|
268
|
+
const includeGlobal = options.all || options.global || (!options.global && !options.project)
|
|
269
|
+
const targets = []
|
|
270
|
+
|
|
271
|
+
if (includeProject) targets.push(projectMcpPath(process.cwd()))
|
|
272
|
+
if (includeGlobal) targets.push(globalMcpPath())
|
|
273
|
+
|
|
274
|
+
if (!targets.length) {
|
|
275
|
+
console.log("no target selected for MCP init")
|
|
276
|
+
return
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const rendered = stringifyMcpConfig(DEFAULT_MCP_INIT_CONFIG)
|
|
280
|
+
for (const target of targets) {
|
|
281
|
+
await mkdir(dirname(target), { recursive: true })
|
|
282
|
+
if (await exists(target) && !options.force) {
|
|
283
|
+
console.log(`skip: exists ${target}`)
|
|
284
|
+
continue
|
|
285
|
+
}
|
|
286
|
+
await writeFile(target, rendered, "utf8")
|
|
287
|
+
console.log(`created: ${target}`)
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
if (options.withSkills) {
|
|
291
|
+
const seedResults = await ensureDefaultSkillPack({
|
|
292
|
+
cwd: process.cwd(),
|
|
293
|
+
force: options.force || false,
|
|
294
|
+
includeProject,
|
|
295
|
+
includeGlobal
|
|
296
|
+
})
|
|
297
|
+
if (seedResults.length) {
|
|
298
|
+
console.log("skill init summary:")
|
|
299
|
+
for (const item of seedResults) {
|
|
300
|
+
const created = item.created.join(", ")
|
|
301
|
+
const skipped = item.skipped.join(", ")
|
|
302
|
+
if (created.length) {
|
|
303
|
+
console.log(`- [${item.scope}] created: ${created}`)
|
|
304
|
+
}
|
|
305
|
+
if (skipped.length) {
|
|
306
|
+
console.log(`- [${item.scope}] already exists: ${skipped}`)
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
console.log("tip: set enabled: true for desired servers after editing")
|
|
313
|
+
if (options.withSkills) {
|
|
314
|
+
console.log("tip: run kkcode skill init to re-seed or adjust scopes")
|
|
85
315
|
}
|
|
316
|
+
console.log("kkcode mcp discover # verify config is readable")
|
|
317
|
+
console.log("kkcode mcp test # verify health")
|
|
86
318
|
})
|
|
87
319
|
|
|
88
320
|
return cmd
|
|
89
|
-
}
|
|
321
|
+
}
|