@kkelly-offical/kkcode 0.1.7 → 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 +228 -220
- 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 +89 -89
- 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 -2981
- 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 +298 -298
- package/src/session/engine.mjs +417 -232
- package/src/session/longagent-4stage.mjs +467 -460
- package/src/session/longagent-hybrid.mjs +1344 -1097
- 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 -900
- package/src/session/loop.mjs +1005 -930
- package/src/session/prompt/agent.txt +25 -25
- package/src/session/prompt/anthropic.txt +150 -150
- package/src/session/prompt/beast.txt +1 -1
- package/src/session/prompt/plan.txt +31 -31
- package/src/session/prompt/qwen.txt +46 -46
- package/src/session/recovery.mjs +21 -0
- package/src/session/rollback.mjs +196 -195
- package/src/session/routing-observability.mjs +72 -0
- package/src/session/runtime-state.mjs +47 -0
- package/src/session/store.mjs +523 -519
- package/src/session/system-prompt.mjs +308 -273
- 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 +99 -93
- 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/package.json
CHANGED
|
@@ -1,46 +1,50 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@kkelly-offical/kkcode",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "
|
|
5
|
-
"type": "module",
|
|
6
|
-
"packageManager": "pnpm@10.5.2",
|
|
7
|
-
"license": "GPL-3.0",
|
|
8
|
-
"author": "kkelly-offical",
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "https://github.com/kkelly-offical/kkcode.git"
|
|
12
|
-
},
|
|
13
|
-
"homepage": "https://github.com/kkelly-offical/kkcode",
|
|
14
|
-
"bugs": {
|
|
15
|
-
"url": "https://github.com/kkelly-offical/kkcode/issues"
|
|
16
|
-
},
|
|
17
|
-
"keywords": [
|
|
18
|
-
"ai",
|
|
19
|
-
"coding-agent",
|
|
20
|
-
"cli",
|
|
21
|
-
"terminal",
|
|
22
|
-
"github",
|
|
23
|
-
"longagent",
|
|
24
|
-
"code-review",
|
|
25
|
-
"mcp"
|
|
26
|
-
],
|
|
27
|
-
"bin": {
|
|
28
|
-
"kkcode": "./src/index.mjs"
|
|
29
|
-
},
|
|
30
|
-
"files": [
|
|
31
|
-
"src/",
|
|
32
|
-
"LICENSE"
|
|
33
|
-
],
|
|
34
|
-
"engines": {
|
|
35
|
-
"node": ">=22"
|
|
36
|
-
},
|
|
37
|
-
"scripts": {
|
|
38
|
-
"start": "node ./src/index.mjs",
|
|
39
|
-
"
|
|
40
|
-
"test
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
}
|
|
46
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@kkelly-offical/kkcode",
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "CLI-first personal assistant with dedicated coding and LongAgent modes for governed terminal workflows, MCP integrations, and extensible automation.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"packageManager": "pnpm@10.5.2",
|
|
7
|
+
"license": "GPL-3.0",
|
|
8
|
+
"author": "kkelly-offical",
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/kkelly-offical/kkcode.git"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/kkelly-offical/kkcode",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/kkelly-offical/kkcode/issues"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"ai",
|
|
19
|
+
"coding-agent",
|
|
20
|
+
"cli",
|
|
21
|
+
"terminal",
|
|
22
|
+
"github",
|
|
23
|
+
"longagent",
|
|
24
|
+
"code-review",
|
|
25
|
+
"mcp"
|
|
26
|
+
],
|
|
27
|
+
"bin": {
|
|
28
|
+
"kkcode": "./src/index.mjs"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"src/",
|
|
32
|
+
"LICENSE"
|
|
33
|
+
],
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=22"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"start": "node ./src/index.mjs",
|
|
39
|
+
"lint": "node ./scripts/check-node-syntax.mjs",
|
|
40
|
+
"test": "node ./scripts/run-node-tests.mjs",
|
|
41
|
+
"test:e2e": "node --test test/e2e/*.mjs",
|
|
42
|
+
"typecheck": "node ./scripts/check-types.mjs",
|
|
43
|
+
"coverage": "node ./scripts/run-node-tests.mjs --coverage",
|
|
44
|
+
"release:verify": "node ./scripts/release-verify.mjs"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"commander": "^13.1.0",
|
|
48
|
+
"yaml": "^2.8.2"
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/agent/agent.mjs
CHANGED
|
@@ -1,220 +1,228 @@
|
|
|
1
|
-
import { readFile } from "node:fs/promises"
|
|
2
|
-
import path from "node:path"
|
|
3
|
-
import { fileURLToPath } from "node:url"
|
|
4
|
-
|
|
5
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
6
|
-
|
|
7
|
-
const registry = new Map()
|
|
8
|
-
|
|
9
|
-
function promptPath(name) {
|
|
10
|
-
return path.join(__dirname, "prompt", `${name}.txt`)
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async function loadPrompt(name) {
|
|
14
|
-
try {
|
|
15
|
-
return (await readFile(promptPath(name), "utf8")).trim()
|
|
16
|
-
} catch {
|
|
17
|
-
return ""
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export function defineAgent(spec) {
|
|
22
|
-
const agent = {
|
|
23
|
-
name: spec.name,
|
|
24
|
-
description: spec.description || "",
|
|
25
|
-
mode: spec.mode || "primary",
|
|
26
|
-
permission: spec.permission || "default",
|
|
27
|
-
tools: spec.tools || null,
|
|
28
|
-
model: spec.model || null,
|
|
29
|
-
temperature: spec.temperature ?? null,
|
|
30
|
-
maxTurns: spec.maxTurns || null,
|
|
31
|
-
hidden: spec.hidden || false,
|
|
32
|
-
promptFile: spec.promptFile || spec.name,
|
|
33
|
-
_promptCache: spec._promptCache ?? null,
|
|
34
|
-
_customAgent: spec._customAgent || false,
|
|
35
|
-
_scope: spec._scope || null,
|
|
36
|
-
_source: spec._source || null
|
|
37
|
-
}
|
|
38
|
-
registry.set(agent.name, agent)
|
|
39
|
-
return agent
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export async function getAgentPrompt(name) {
|
|
43
|
-
const agent = registry.get(name)
|
|
44
|
-
if (!agent) return ""
|
|
45
|
-
if (agent._promptCache !== null) return agent._promptCache
|
|
46
|
-
agent._promptCache = await loadPrompt(agent.promptFile)
|
|
47
|
-
return agent._promptCache
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function getAgent(name) {
|
|
51
|
-
return registry.get(name) || null
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function listAgents({ includeHidden = false } = {}) {
|
|
55
|
-
const agents = [...registry.values()]
|
|
56
|
-
return includeHidden ? agents : agents.filter((a) => !a.hidden)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function resolveAgentForMode(mode) {
|
|
60
|
-
if (registry.has(mode)) return registry.get(mode)
|
|
61
|
-
const modeMap = {
|
|
62
|
-
const mapped = modeMap[mode]
|
|
63
|
-
return mapped ? registry.get(mapped) || null : null
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
defineAgent({
|
|
67
|
-
name: "
|
|
68
|
-
description: "Default
|
|
69
|
-
mode: "primary",
|
|
70
|
-
permission: "full",
|
|
71
|
-
tools: null
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
defineAgent({
|
|
75
|
-
name: "
|
|
76
|
-
description: "
|
|
77
|
-
mode: "primary",
|
|
78
|
-
permission: "
|
|
79
|
-
tools:
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
defineAgent({
|
|
83
|
-
name: "
|
|
84
|
-
description: "
|
|
85
|
-
mode: "
|
|
86
|
-
permission: "readonly",
|
|
87
|
-
tools: ["read", "glob", "grep", "list", "
|
|
88
|
-
})
|
|
89
|
-
|
|
90
|
-
defineAgent({
|
|
91
|
-
name: "
|
|
92
|
-
description: "
|
|
93
|
-
mode: "
|
|
94
|
-
permission: "
|
|
95
|
-
tools:
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
defineAgent({
|
|
99
|
-
name: "
|
|
100
|
-
description: "
|
|
101
|
-
mode: "
|
|
102
|
-
permission: "
|
|
103
|
-
tools:
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
defineAgent({
|
|
107
|
-
name: "
|
|
108
|
-
description: "
|
|
109
|
-
mode: "subagent",
|
|
110
|
-
permission: "readonly",
|
|
111
|
-
tools: ["read", "glob", "grep", "list", "bash"
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
defineAgent({
|
|
115
|
-
name: "
|
|
116
|
-
description: "
|
|
117
|
-
mode: "subagent",
|
|
118
|
-
permission: "readonly",
|
|
119
|
-
tools: ["read", "glob", "grep", "list", "bash"]
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
defineAgent({
|
|
123
|
-
name: "
|
|
124
|
-
description: "
|
|
125
|
-
mode: "subagent",
|
|
126
|
-
permission: "readonly",
|
|
127
|
-
tools: ["read", "glob", "grep", "list", "
|
|
128
|
-
})
|
|
129
|
-
|
|
130
|
-
defineAgent({
|
|
131
|
-
name: "
|
|
132
|
-
description: "
|
|
133
|
-
mode: "subagent",
|
|
134
|
-
permission: "readonly",
|
|
135
|
-
tools: ["read", "glob", "grep", "list", "
|
|
136
|
-
})
|
|
137
|
-
|
|
138
|
-
defineAgent({
|
|
139
|
-
name: "
|
|
140
|
-
description: "
|
|
141
|
-
mode: "subagent",
|
|
142
|
-
permission: "
|
|
143
|
-
tools: ["read", "
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
defineAgent({
|
|
147
|
-
name: "
|
|
148
|
-
description: "
|
|
149
|
-
mode: "subagent",
|
|
150
|
-
permission: "full",
|
|
151
|
-
tools: ["read", "write", "edit", "bash", "glob", "grep", "list"]
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
defineAgent({
|
|
155
|
-
name: "
|
|
156
|
-
description: "
|
|
157
|
-
mode: "subagent",
|
|
158
|
-
permission: "full",
|
|
159
|
-
tools: ["read", "write", "edit", "bash", "glob", "grep", "list"]
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
defineAgent({
|
|
163
|
-
name: "
|
|
164
|
-
description: "
|
|
165
|
-
mode: "subagent",
|
|
166
|
-
permission: "
|
|
167
|
-
tools: []
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
defineAgent({
|
|
190
|
-
name: "
|
|
191
|
-
description: "4-Stage LongAgent: Stage
|
|
192
|
-
mode: "subagent",
|
|
193
|
-
permission: "readonly",
|
|
194
|
-
tools: ["read", "glob", "grep", "list", "bash", "question", "todowrite"]
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
defineAgent({
|
|
198
|
-
name: "
|
|
199
|
-
description: "4-Stage LongAgent: Stage
|
|
200
|
-
mode: "subagent",
|
|
201
|
-
permission: "
|
|
202
|
-
tools:
|
|
203
|
-
})
|
|
204
|
-
|
|
205
|
-
defineAgent({
|
|
206
|
-
name: "
|
|
207
|
-
description: "4-Stage LongAgent: Stage
|
|
208
|
-
mode: "subagent",
|
|
209
|
-
permission: "full",
|
|
210
|
-
tools: null
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
defineAgent({
|
|
214
|
-
name: "
|
|
215
|
-
description: "
|
|
216
|
-
mode: "subagent",
|
|
217
|
-
permission: "full",
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
1
|
+
import { readFile } from "node:fs/promises"
|
|
2
|
+
import path from "node:path"
|
|
3
|
+
import { fileURLToPath } from "node:url"
|
|
4
|
+
|
|
5
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
6
|
+
|
|
7
|
+
const registry = new Map()
|
|
8
|
+
|
|
9
|
+
function promptPath(name) {
|
|
10
|
+
return path.join(__dirname, "prompt", `${name}.txt`)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function loadPrompt(name) {
|
|
14
|
+
try {
|
|
15
|
+
return (await readFile(promptPath(name), "utf8")).trim()
|
|
16
|
+
} catch {
|
|
17
|
+
return ""
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function defineAgent(spec) {
|
|
22
|
+
const agent = {
|
|
23
|
+
name: spec.name,
|
|
24
|
+
description: spec.description || "",
|
|
25
|
+
mode: spec.mode || "primary",
|
|
26
|
+
permission: spec.permission || "default",
|
|
27
|
+
tools: spec.tools || null,
|
|
28
|
+
model: spec.model || null,
|
|
29
|
+
temperature: spec.temperature ?? null,
|
|
30
|
+
maxTurns: spec.maxTurns || null,
|
|
31
|
+
hidden: spec.hidden || false,
|
|
32
|
+
promptFile: spec.promptFile || spec.name,
|
|
33
|
+
_promptCache: spec._promptCache ?? null,
|
|
34
|
+
_customAgent: spec._customAgent || false,
|
|
35
|
+
_scope: spec._scope || null,
|
|
36
|
+
_source: spec._source || null
|
|
37
|
+
}
|
|
38
|
+
registry.set(agent.name, agent)
|
|
39
|
+
return agent
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export async function getAgentPrompt(name) {
|
|
43
|
+
const agent = registry.get(name)
|
|
44
|
+
if (!agent) return ""
|
|
45
|
+
if (agent._promptCache !== null) return agent._promptCache
|
|
46
|
+
agent._promptCache = await loadPrompt(agent.promptFile)
|
|
47
|
+
return agent._promptCache
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function getAgent(name) {
|
|
51
|
+
return registry.get(name) || null
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function listAgents({ includeHidden = false } = {}) {
|
|
55
|
+
const agents = [...registry.values()]
|
|
56
|
+
return includeHidden ? agents : agents.filter((a) => !a.hidden)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function resolveAgentForMode(mode) {
|
|
60
|
+
if (registry.has(mode)) return registry.get(mode)
|
|
61
|
+
const modeMap = { assistant: "assistant", plan: "plan", agent: "build", longagent: "longagent" }
|
|
62
|
+
const mapped = modeMap[mode]
|
|
63
|
+
return mapped ? registry.get(mapped) || null : null
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
defineAgent({
|
|
67
|
+
name: "assistant",
|
|
68
|
+
description: "Default CLI personal assistant for terminal-native personal work, local tasks, research, and lightweight automation",
|
|
69
|
+
mode: "primary",
|
|
70
|
+
permission: "full",
|
|
71
|
+
tools: null
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
defineAgent({
|
|
75
|
+
name: "build",
|
|
76
|
+
description: "Default agent with full tool access for code development",
|
|
77
|
+
mode: "primary",
|
|
78
|
+
permission: "full",
|
|
79
|
+
tools: null
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
defineAgent({
|
|
83
|
+
name: "plan",
|
|
84
|
+
description: "Read-only analysis agent, no file editing allowed",
|
|
85
|
+
mode: "primary",
|
|
86
|
+
permission: "readonly",
|
|
87
|
+
tools: ["read", "glob", "grep", "list", "webfetch", "websearch", "question", "enter_plan", "exit_plan"]
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
defineAgent({
|
|
91
|
+
name: "explore",
|
|
92
|
+
description: "Fast file search subagent for codebase exploration",
|
|
93
|
+
mode: "subagent",
|
|
94
|
+
permission: "readonly",
|
|
95
|
+
tools: ["read", "glob", "grep", "list", "bash"]
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
defineAgent({
|
|
99
|
+
name: "longagent",
|
|
100
|
+
description: "Persistent iterative execution agent for complex multi-step tasks",
|
|
101
|
+
mode: "primary",
|
|
102
|
+
permission: "full",
|
|
103
|
+
tools: null
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
defineAgent({
|
|
107
|
+
name: "reviewer",
|
|
108
|
+
description: "Code review specialist for analyzing code quality, bugs, and security issues",
|
|
109
|
+
mode: "subagent",
|
|
110
|
+
permission: "readonly",
|
|
111
|
+
tools: ["read", "glob", "grep", "list", "bash"]
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
defineAgent({
|
|
115
|
+
name: "researcher",
|
|
116
|
+
description: "Deep codebase research and web-augmented exploration agent",
|
|
117
|
+
mode: "subagent",
|
|
118
|
+
permission: "readonly",
|
|
119
|
+
tools: ["read", "glob", "grep", "list", "bash", "websearch", "codesearch", "webfetch"]
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
defineAgent({
|
|
123
|
+
name: "architect",
|
|
124
|
+
description: "Feature architecture designer. Analyzes codebase patterns, designs implementation blueprints with specific files, component designs, data flows.",
|
|
125
|
+
mode: "subagent",
|
|
126
|
+
permission: "readonly",
|
|
127
|
+
tools: ["read", "glob", "grep", "list", "bash"]
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
defineAgent({
|
|
131
|
+
name: "guide",
|
|
132
|
+
description: "kkcode self-help guide. Answers questions about kkcode features, tools, configuration, modes, skills, hooks, MCP servers, and usage patterns by searching the kkcode source code.",
|
|
133
|
+
mode: "subagent",
|
|
134
|
+
permission: "readonly",
|
|
135
|
+
tools: ["read", "glob", "grep", "list", "webfetch", "websearch"]
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
defineAgent({
|
|
139
|
+
name: "security-reviewer",
|
|
140
|
+
description: "Security audit specialist. Performs OWASP Top 10 checks, hardcoded secret scans, dependency audits, and authentication/authorization reviews.",
|
|
141
|
+
mode: "subagent",
|
|
142
|
+
permission: "readonly",
|
|
143
|
+
tools: ["read", "glob", "grep", "list", "bash"]
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
defineAgent({
|
|
147
|
+
name: "tdd-guide",
|
|
148
|
+
description: "TDD specialist. Guides and executes test-driven development: scaffold interfaces, write failing tests (RED), implement minimum code (GREEN), refactor (IMPROVE). Targets 80%+ coverage.",
|
|
149
|
+
mode: "subagent",
|
|
150
|
+
permission: "full",
|
|
151
|
+
tools: ["read", "write", "edit", "bash", "glob", "grep", "list"]
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
defineAgent({
|
|
155
|
+
name: "build-fixer",
|
|
156
|
+
description: "Build error diagnosis and repair. Analyzes build failures, identifies root causes, applies fixes, and verifies the build succeeds. Supports TypeScript, Python, Go, Rust, Java.",
|
|
157
|
+
mode: "subagent",
|
|
158
|
+
permission: "full",
|
|
159
|
+
tools: ["read", "write", "edit", "bash", "glob", "grep", "list"]
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
defineAgent({
|
|
163
|
+
name: "frontend-designer",
|
|
164
|
+
description: "Frontend design specialist. Creates polished, distinctive UIs with strong aesthetics — typography, color, motion, layout. Avoids generic AI-style designs. Reads project design system (Tailwind, CSS vars, component libraries) and produces production-grade frontend code.",
|
|
165
|
+
mode: "subagent",
|
|
166
|
+
permission: "full",
|
|
167
|
+
tools: ["read", "write", "edit", "bash", "glob", "grep", "list"]
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
defineAgent({
|
|
171
|
+
name: "compaction",
|
|
172
|
+
description: "Conversation summarizer for context compression",
|
|
173
|
+
mode: "subagent",
|
|
174
|
+
permission: "none",
|
|
175
|
+
tools: [],
|
|
176
|
+
hidden: true
|
|
177
|
+
})
|
|
178
|
+
|
|
179
|
+
defineAgent({
|
|
180
|
+
name: "title",
|
|
181
|
+
description: "Session title generator",
|
|
182
|
+
mode: "subagent",
|
|
183
|
+
permission: "none",
|
|
184
|
+
tools: [],
|
|
185
|
+
hidden: true
|
|
186
|
+
})
|
|
187
|
+
|
|
188
|
+
// 4-Stage LongAgent agents
|
|
189
|
+
defineAgent({
|
|
190
|
+
name: "preview-agent",
|
|
191
|
+
description: "4-Stage LongAgent: Stage 1 - Previewing Agent. Explores codebase, extracts requirements, no editing allowed.",
|
|
192
|
+
mode: "subagent",
|
|
193
|
+
permission: "readonly",
|
|
194
|
+
tools: ["read", "glob", "grep", "list", "bash", "question", "todowrite"]
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
defineAgent({
|
|
198
|
+
name: "blueprint-agent",
|
|
199
|
+
description: "4-Stage LongAgent: Stage 2 - Blueprint Agent. Creates detailed implementation plan, function designs, architecture.",
|
|
200
|
+
mode: "subagent",
|
|
201
|
+
permission: "readonly",
|
|
202
|
+
tools: ["read", "glob", "grep", "list", "bash", "question", "todowrite"]
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
defineAgent({
|
|
206
|
+
name: "coding-agent",
|
|
207
|
+
description: "4-Stage LongAgent: Stage 3 - Coding Agent. Implements code strictly according to blueprint.",
|
|
208
|
+
mode: "subagent",
|
|
209
|
+
permission: "full",
|
|
210
|
+
tools: null
|
|
211
|
+
})
|
|
212
|
+
|
|
213
|
+
defineAgent({
|
|
214
|
+
name: "debugging-agent",
|
|
215
|
+
description: "4-Stage LongAgent: Stage 4 - Debugging Agent. Verifies implementation, runs tests, finds and fixes bugs.",
|
|
216
|
+
mode: "subagent",
|
|
217
|
+
permission: "full",
|
|
218
|
+
tools: null
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
defineAgent({
|
|
222
|
+
name: "bug-hunter",
|
|
223
|
+
description: "Deep bug detection specialist. Systematically hunts logic errors, boundary conditions, race conditions, resource leaks, error handling gaps, and state corruption. Reports only HIGH/MEDIUM confidence bugs with concrete trigger paths.",
|
|
224
|
+
mode: "subagent",
|
|
225
|
+
permission: "full",
|
|
226
|
+
maxTurns: 30,
|
|
227
|
+
tools: ["read", "glob", "grep", "list", "bash"]
|
|
228
|
+
})
|
|
@@ -3,6 +3,7 @@ import { access, readdir, readFile } from "node:fs/promises"
|
|
|
3
3
|
import { pathToFileURL } from "node:url"
|
|
4
4
|
import { parseYaml } from "../util/yaml.mjs"
|
|
5
5
|
import { defineAgent, getAgent } from "./agent.mjs"
|
|
6
|
+
import { userRootDir } from "../storage/paths.mjs"
|
|
6
7
|
|
|
7
8
|
const state = {
|
|
8
9
|
agents: new Map(),
|
|
@@ -82,12 +83,15 @@ async function loadMdAgent(filePath, scope) {
|
|
|
82
83
|
|
|
83
84
|
async function loadAgentsFromDir(dir, scope) {
|
|
84
85
|
if (!(await exists(dir))) return []
|
|
86
|
+
const resolvedDir = path.resolve(dir)
|
|
85
87
|
const entries = await readdir(dir, { withFileTypes: true })
|
|
86
88
|
const agents = []
|
|
87
89
|
for (const entry of entries) {
|
|
88
90
|
if (!entry.isFile()) continue
|
|
89
91
|
const ext = path.extname(entry.name).toLowerCase()
|
|
90
|
-
const full = path.
|
|
92
|
+
const full = path.resolve(dir, entry.name)
|
|
93
|
+
// Path boundary check: ensure resolved path is within expected directory
|
|
94
|
+
if (!full.startsWith(resolvedDir + path.sep) && full !== resolvedDir) continue
|
|
91
95
|
try {
|
|
92
96
|
if (ext === ".yaml" || ext === ".yml") {
|
|
93
97
|
const agent = await loadYamlAgent(full, scope)
|
|
@@ -107,8 +111,7 @@ async function loadAgentsFromDir(dir, scope) {
|
|
|
107
111
|
export const CustomAgentRegistry = {
|
|
108
112
|
async initialize(cwd = process.cwd()) {
|
|
109
113
|
state.agents.clear()
|
|
110
|
-
const
|
|
111
|
-
const globalDir = path.join(userRoot, ".kkcode", "agents")
|
|
114
|
+
const globalDir = path.join(userRootDir(), "agents")
|
|
112
115
|
const projectDir = path.join(cwd, ".kkcode", "agents")
|
|
113
116
|
|
|
114
117
|
const [globalAgents, projectAgents] = await Promise.all([
|
package/src/agent/generator.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { writeFile, mkdir } from "node:fs/promises"
|
|
2
2
|
import { join } from "node:path"
|
|
3
|
-
import { homedir } from "node:os"
|
|
4
3
|
import { requestProvider } from "../provider/router.mjs"
|
|
4
|
+
import { userRootDir } from "../storage/paths.mjs"
|
|
5
5
|
|
|
6
6
|
const AGENT_GEN_SYSTEM = `You are an agent definition generator for kkcode, a terminal AI coding agent.
|
|
7
7
|
Your task is to generate an agent definition file in YAML format based on the user's description.
|
|
@@ -96,7 +96,7 @@ export async function generateAgent({ description, configState, providerType, mo
|
|
|
96
96
|
* Save an agent definition to the global agents directory.
|
|
97
97
|
*/
|
|
98
98
|
export async function saveAgentGlobal(filename, content) {
|
|
99
|
-
const dir = join(
|
|
99
|
+
const dir = join(userRootDir(), "agents")
|
|
100
100
|
await mkdir(dir, { recursive: true })
|
|
101
101
|
const filePath = join(dir, filename)
|
|
102
102
|
await writeFile(filePath, content, "utf-8")
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
You are kkcode in ASSISTANT mode: a CLI-first personal assistant for terminal-native work. You can help with local files, directories, logs, system/runtime checks, web lookup/fetch, Git/GitHub assistance, notes, task organization, and bounded automation through the available tools.
|
|
2
|
+
|
|
3
|
+
# Operating Contract
|
|
4
|
+
- Prefer the lightest terminal-native path that fully answers or completes the user request.
|
|
5
|
+
- Use existing permission, budget, audit, and tool boundaries; never bypass approvals.
|
|
6
|
+
- Treat ordinary local inspection, summarization, command checks, repo hygiene, and research as first-class assistant work.
|
|
7
|
+
- When the request is clearly code mutation, debugging, refactoring, or test repair, use the dedicated coding lane semantics from `agent` / `code` / `coding`.
|
|
8
|
+
- When the request is broad, cross-module, staged, or needs ownership gates, recommend or use LongAgent rather than improvising.
|
|
9
|
+
- Do not imply unsupported surfaces such as GUI desktop automation, IDE integration, remote platform control, or marketplace install flows.
|
|
10
|
+
|
|
11
|
+
# Response Style
|
|
12
|
+
Be concise, outcome-first, and practical. State what you checked, what changed or did not change, and the next useful action only when it matters.
|