@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.
Files changed (163) hide show
  1. package/LICENSE +674 -674
  2. package/README.md +452 -387
  3. package/package.json +50 -46
  4. package/src/agent/agent.mjs +228 -220
  5. package/src/agent/custom-agent-loader.mjs +6 -3
  6. package/src/agent/generator.mjs +2 -2
  7. package/src/agent/prompt/assistant.txt +12 -0
  8. package/src/agent/prompt/bug-hunter.txt +89 -89
  9. package/src/agent/prompt/frontend-designer.txt +58 -58
  10. package/src/agent/prompt/guide.txt +1 -1
  11. package/src/agent/prompt/longagent-blueprint-agent.txt +83 -83
  12. package/src/agent/prompt/longagent-coding-agent.txt +37 -37
  13. package/src/agent/prompt/longagent-debugging-agent.txt +46 -46
  14. package/src/agent/prompt/longagent-preview-agent.txt +63 -63
  15. package/src/command/custom-commands.mjs +2 -2
  16. package/src/commands/agent.mjs +1 -1
  17. package/src/commands/background.mjs +145 -4
  18. package/src/commands/chat.mjs +117 -76
  19. package/src/commands/config.mjs +148 -1
  20. package/src/commands/doctor.mjs +30 -6
  21. package/src/commands/init.mjs +32 -6
  22. package/src/commands/longagent.mjs +117 -0
  23. package/src/commands/mcp.mjs +275 -43
  24. package/src/commands/permission.mjs +1 -1
  25. package/src/commands/session.mjs +195 -140
  26. package/src/commands/skill.mjs +63 -0
  27. package/src/commands/theme.mjs +1 -1
  28. package/src/config/defaults.mjs +280 -260
  29. package/src/config/import-config.mjs +1 -1
  30. package/src/config/load-config.mjs +61 -4
  31. package/src/config/schema.mjs +591 -574
  32. package/src/context.mjs +4 -1
  33. package/src/core/constants.mjs +97 -91
  34. package/src/core/types.mjs +1 -1
  35. package/src/github/api.mjs +78 -78
  36. package/src/github/auth.mjs +294 -286
  37. package/src/github/flow.mjs +298 -298
  38. package/src/github/workspace.mjs +225 -212
  39. package/src/index.mjs +84 -82
  40. package/src/knowledge/frontend-aesthetics.txt +38 -38
  41. package/src/mcp/client-http.mjs +139 -141
  42. package/src/mcp/client-sse.mjs +297 -288
  43. package/src/mcp/client-stdio.mjs +534 -533
  44. package/src/mcp/constants.mjs +2 -2
  45. package/src/mcp/registry.mjs +498 -479
  46. package/src/mcp/stdio-framing.mjs +135 -133
  47. package/src/mcp/tool-result.mjs +24 -24
  48. package/src/observability/edit-diagnostics.mjs +449 -0
  49. package/src/observability/index.mjs +42 -42
  50. package/src/observability/metrics.mjs +165 -137
  51. package/src/observability/tracer.mjs +137 -137
  52. package/src/onboarding.mjs +209 -0
  53. package/src/orchestration/background-manager.mjs +567 -372
  54. package/src/orchestration/background-worker.mjs +419 -305
  55. package/src/orchestration/interruption-reason.mjs +21 -0
  56. package/src/orchestration/longagent-manager.mjs +197 -171
  57. package/src/orchestration/stage-scheduler.mjs +733 -728
  58. package/src/orchestration/subagent-router.mjs +7 -1
  59. package/src/orchestration/task-scheduler.mjs +219 -7
  60. package/src/permission/engine.mjs +1 -1
  61. package/src/permission/exec-policy.mjs +370 -370
  62. package/src/permission/file-edit-policy.mjs +108 -0
  63. package/src/permission/prompt.mjs +1 -1
  64. package/src/permission/rules.mjs +116 -7
  65. package/src/plugin/builtin-hooks/post-edit-format.mjs +2 -1
  66. package/src/plugin/builtin-hooks/post-edit-typecheck.mjs +104 -40
  67. package/src/plugin/hook-bus.mjs +19 -5
  68. package/src/plugin/manifest-loader.mjs +222 -0
  69. package/src/provider/anthropic.mjs +396 -390
  70. package/src/provider/ollama.mjs +7 -1
  71. package/src/provider/openai.mjs +382 -340
  72. package/src/provider/retry-policy.mjs +74 -68
  73. package/src/provider/router.mjs +242 -241
  74. package/src/provider/sse.mjs +104 -104
  75. package/src/provider/wizard.mjs +556 -0
  76. package/src/repl/capability-facade.mjs +30 -0
  77. package/src/repl/command-surface.mjs +23 -0
  78. package/src/repl/controller-entry.mjs +40 -0
  79. package/src/repl/core-shell.mjs +208 -0
  80. package/src/repl/dialog-router.mjs +87 -0
  81. package/src/repl/input-engine.mjs +76 -0
  82. package/src/repl/keymap.mjs +7 -0
  83. package/src/repl/operator-surface.mjs +15 -0
  84. package/src/repl/permission-flow.mjs +49 -0
  85. package/src/repl/runtime-facade.mjs +36 -0
  86. package/src/repl/slash-router.mjs +62 -0
  87. package/src/repl/state-store.mjs +29 -0
  88. package/src/repl/turn-controller.mjs +58 -0
  89. package/src/repl/verification.mjs +23 -0
  90. package/src/repl.mjs +3368 -2981
  91. package/src/rules/load-rules.mjs +3 -3
  92. package/src/runtime.mjs +1 -1
  93. package/src/session/agent-transaction.mjs +86 -0
  94. package/src/session/checkpoint.mjs +302 -302
  95. package/src/session/compaction.mjs +298 -298
  96. package/src/session/engine.mjs +417 -232
  97. package/src/session/longagent-4stage.mjs +467 -460
  98. package/src/session/longagent-hybrid.mjs +1344 -1097
  99. package/src/session/longagent-plan.mjs +376 -365
  100. package/src/session/longagent-project-memory.mjs +53 -53
  101. package/src/session/longagent-scaffold.mjs +291 -291
  102. package/src/session/longagent-task-bus.mjs +138 -54
  103. package/src/session/longagent-utils.mjs +828 -472
  104. package/src/session/longagent.mjs +911 -900
  105. package/src/session/loop.mjs +1005 -930
  106. package/src/session/prompt/agent.txt +25 -25
  107. package/src/session/prompt/anthropic.txt +150 -150
  108. package/src/session/prompt/beast.txt +1 -1
  109. package/src/session/prompt/plan.txt +31 -31
  110. package/src/session/prompt/qwen.txt +46 -46
  111. package/src/session/recovery.mjs +21 -0
  112. package/src/session/rollback.mjs +196 -195
  113. package/src/session/routing-observability.mjs +72 -0
  114. package/src/session/runtime-state.mjs +47 -0
  115. package/src/session/store.mjs +523 -519
  116. package/src/session/system-prompt.mjs +308 -273
  117. package/src/session/task-validator.mjs +267 -267
  118. package/src/session/usability-gates.mjs +2 -2
  119. package/src/skill/builtin/commit.mjs +64 -64
  120. package/src/skill/builtin/design.mjs +76 -76
  121. package/src/skill/generator.mjs +18 -2
  122. package/src/skill/registry.mjs +642 -390
  123. package/src/storage/audit-store.mjs +18 -11
  124. package/src/storage/event-log.mjs +7 -1
  125. package/src/storage/ghost-commit-store.mjs +243 -245
  126. package/src/storage/paths.mjs +13 -0
  127. package/src/theme/default-theme.mjs +1 -1
  128. package/src/theme/markdown.mjs +4 -0
  129. package/src/theme/schema.mjs +1 -1
  130. package/src/theme/status-bar.mjs +162 -158
  131. package/src/tool/audit-wrapper.mjs +18 -2
  132. package/src/tool/edit-transaction.mjs +23 -0
  133. package/src/tool/executor.mjs +26 -1
  134. package/src/tool/file-read-state.mjs +65 -0
  135. package/src/tool/git-auto.mjs +526 -526
  136. package/src/tool/git-full-auto.mjs +487 -478
  137. package/src/tool/mutation-guard.mjs +54 -0
  138. package/src/tool/prompt/edit.txt +3 -3
  139. package/src/tool/prompt/multiedit.txt +1 -0
  140. package/src/tool/prompt/notebookedit.txt +2 -1
  141. package/src/tool/prompt/patch.txt +25 -24
  142. package/src/tool/prompt/read.txt +3 -3
  143. package/src/tool/prompt/sysinfo.txt +29 -0
  144. package/src/tool/prompt/task.txt +66 -4
  145. package/src/tool/prompt/write.txt +2 -2
  146. package/src/tool/question-prompt.mjs +99 -93
  147. package/src/tool/registry.mjs +1701 -1343
  148. package/src/tool/task-tool.mjs +14 -6
  149. package/src/ui/activity-renderer.mjs +667 -664
  150. package/src/ui/repl-background-panel.mjs +7 -0
  151. package/src/ui/repl-capability-panel.mjs +9 -0
  152. package/src/ui/repl-dashboard.mjs +54 -4
  153. package/src/ui/repl-help.mjs +110 -0
  154. package/src/ui/repl-operator-panel.mjs +12 -0
  155. package/src/ui/repl-route-feedback.mjs +35 -0
  156. package/src/ui/repl-status-view.mjs +76 -0
  157. package/src/ui/repl-task-panel.mjs +5 -0
  158. package/src/ui/repl-transcript-panel.mjs +56 -0
  159. package/src/ui/repl-turn-summary.mjs +135 -0
  160. package/src/usage/pricing.mjs +122 -121
  161. package/src/usage/usage-meter.mjs +1 -0
  162. package/src/util/git.mjs +562 -519
  163. package/src/util/template.mjs +6 -1
@@ -0,0 +1,209 @@
1
+ import { createInterface } from "node:readline/promises"
2
+ import { stdin as input, stdout as output } from "node:process"
3
+ import { writeFile, readFile, mkdir } from "node:fs/promises"
4
+ import { dirname } from "node:path"
5
+ import YAML from "yaml"
6
+ import { paint } from "./theme/color.mjs"
7
+ import { profilePath } from "./storage/paths.mjs"
8
+
9
+ function ln(text = "", color, opts) {
10
+ console.log(color ? paint(text, color, opts) : text)
11
+ }
12
+
13
+ function termWidth() {
14
+ return Math.max(60, Math.min(process.stdout.columns || 100, 120))
15
+ }
16
+
17
+ function hr(char = "─", color = "#444") {
18
+ ln(paint(char.repeat(termWidth()), color))
19
+ }
20
+
21
+ function header() {
22
+ ln()
23
+ ln(paint(" ██╗ ██╗██╗ ██╗ ██████╗ ██████╗ ██████╗ ███████╗", "#4af5f0", { bold: true }))
24
+ ln(paint(" ██║ ██╔╝██║ ██╔╝██╔════╝██╔═══██╗██╔══██╗██╔════╝", "#38c8ff", { bold: true }))
25
+ ln(paint(" █████╔╝ █████╔╝ ██║ ██║ ██║██║ ██║█████╗ ", "#58a0ff", { bold: true }))
26
+ ln(paint(" ██╔═██╗ ██╔═██╗ ██║ ██║ ██║██║ ██║██╔══╝ ", "#8876ff", { bold: true }))
27
+ ln(paint(" ██║ ██╗██║ ██╗╚██████╗╚██████╔╝██████╔╝███████╗", "#d037ff", { bold: true }))
28
+ ln(paint(" ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝", "#e828f0", { bold: true }))
29
+ ln()
30
+ ln(paint(" Welcome to kkcode — AI Coding Agent", "#ffffff", { bold: true }))
31
+ ln(paint(" Let's set up your profile so kkcode knows how to work with you.", "#aaaaaa"))
32
+ ln()
33
+ hr()
34
+ }
35
+
36
+ // Single-choice menu: returns selected index (0-based)
37
+ async function menu(rl, prompt, choices) {
38
+ ln()
39
+ ln(paint(` ${prompt}`, "#ffffff", { bold: true }))
40
+ for (let i = 0; i < choices.length; i++) {
41
+ ln(paint(` ${i + 1}) `, "#888") + paint(choices[i], "#dddddd"))
42
+ }
43
+ ln()
44
+ while (true) {
45
+ const raw = await rl.question(paint(" Enter number: ", "#4af5f0"))
46
+ const n = parseInt(raw.trim(), 10)
47
+ if (n >= 1 && n <= choices.length) return n - 1
48
+ ln(paint(" Please enter a valid number.", "#ff6b6b"))
49
+ }
50
+ }
51
+
52
+ // Multi-choice menu: returns array of selected indices
53
+ async function multiMenu(rl, prompt, choices, hint = "comma-separated, e.g. 1,3") {
54
+ ln()
55
+ ln(paint(` ${prompt}`, "#ffffff", { bold: true }))
56
+ for (let i = 0; i < choices.length; i++) {
57
+ ln(paint(` ${i + 1}) `, "#888") + paint(choices[i], "#dddddd"))
58
+ }
59
+ ln(paint(` (${hint}, or press Enter to skip)`, "#888"))
60
+ ln()
61
+ const raw = await rl.question(paint(" Your choice: ", "#4af5f0"))
62
+ if (!raw.trim()) return []
63
+ return raw.split(",")
64
+ .map((s) => parseInt(s.trim(), 10) - 1)
65
+ .filter((n) => n >= 0 && n < choices.length)
66
+ }
67
+
68
+ // Free-text input
69
+ async function ask(rl, prompt, placeholder = "") {
70
+ ln()
71
+ if (placeholder) ln(paint(` e.g. ${placeholder}`, "#666"))
72
+ const raw = await rl.question(paint(` ${prompt}: `, "#4af5f0"))
73
+ return raw.trim()
74
+ }
75
+
76
+ // ─── Section renderers ────────────────────────────────────────────────────────
77
+
78
+ function sectionTitle(title) {
79
+ ln()
80
+ hr("─", "#333")
81
+ ln(paint(` ${title}`, "#2ac26f", { bold: true }))
82
+ hr("─", "#333")
83
+ }
84
+
85
+ // ─── Default profile ──────────────────────────────────────────────────────────
86
+
87
+ export function defaultProfile() {
88
+ return {
89
+ beginner: true,
90
+ tech_stack: [],
91
+ languages: [],
92
+ design_style: "clean and minimal",
93
+ extra_notes: "",
94
+ created_at: new Date().toISOString()
95
+ }
96
+ }
97
+
98
+ // ─── Save / load ──────────────────────────────────────────────────────────────
99
+
100
+ export async function saveProfile(profile) {
101
+ const p = profilePath()
102
+ await mkdir(dirname(p), { recursive: true })
103
+ await writeFile(p, YAML.stringify(profile), "utf8")
104
+ }
105
+
106
+ export async function loadProfile() {
107
+ try {
108
+ const raw = await readFile(profilePath(), "utf8")
109
+ return YAML.parse(raw) || null
110
+ } catch {
111
+ return null
112
+ }
113
+ }
114
+
115
+ export function isFirstRun() {
116
+ // Resolved lazily — call loadProfile() to check
117
+ return loadProfile().then((p) => p === null)
118
+ }
119
+
120
+ // ─── Main onboarding flow ─────────────────────────────────────────────────────
121
+
122
+ export async function runOnboarding() {
123
+ if (!process.stdin.isTTY || !process.stdout.isTTY) {
124
+ // Non-interactive: write default profile silently
125
+ await saveProfile(defaultProfile())
126
+ return defaultProfile()
127
+ }
128
+
129
+ const rl = createInterface({ input, output, terminal: true })
130
+
131
+ try {
132
+ header()
133
+
134
+ ln(paint(" Quick start options:", "#ffffff", { bold: true }))
135
+ ln()
136
+ ln(paint(" 1) ", "#888") + paint("I'm new — use kkcode defaults (recommended for beginners)", "#dddddd"))
137
+ ln(paint(" 2) ", "#888") + paint("Set up my profile now", "#dddddd"))
138
+ ln()
139
+
140
+ const modeRaw = await rl.question(paint(" Enter number [1]: ", "#4af5f0"))
141
+ const mode = modeRaw.trim() === "2" ? "custom" : "default"
142
+
143
+ if (mode === "default") {
144
+ const profile = defaultProfile()
145
+ await saveProfile(profile)
146
+ ln()
147
+ ln(paint(" ✓ Default profile saved. You can update it anytime with /profile.", "#2ac26f", { bold: true }))
148
+ ln()
149
+ return profile
150
+ }
151
+
152
+ // ── Custom setup ──────────────────────────────────────────────────────────
153
+ const profile = { beginner: false, created_at: new Date().toISOString() }
154
+
155
+ // 1. Programming languages
156
+ sectionTitle("1 / 4 Programming Languages")
157
+ const langChoices = ["JavaScript / TypeScript", "Python", "Rust", "Go", "Java / Kotlin", "C / C++", "Ruby", "PHP", "Swift", "Other"]
158
+ const langIdxs = await multiMenu(rl, "Which languages do you mainly use?", langChoices)
159
+ profile.languages = langIdxs.map((i) => langChoices[i])
160
+ if (langIdxs.includes(langChoices.length - 1) || profile.languages.length === 0) {
161
+ const extra = await ask(rl, "Specify languages (optional)", "Elixir, Dart, ...")
162
+ if (extra) profile.languages = [...profile.languages.filter((l) => l !== "Other"), extra]
163
+ }
164
+
165
+ // 2. Tech stack / frameworks
166
+ sectionTitle("2 / 4 Tech Stack & Frameworks")
167
+ const stackChoices = ["React", "Vue", "Next.js", "Node.js / Express", "FastAPI / Django", "Spring Boot", "Docker / Kubernetes", "AWS / GCP / Azure", "PostgreSQL / MySQL", "MongoDB", "Other"]
168
+ const stackIdxs = await multiMenu(rl, "Which frameworks / tools do you use?", stackChoices)
169
+ profile.tech_stack = stackIdxs.map((i) => stackChoices[i])
170
+ if (stackIdxs.includes(stackChoices.length - 1) || profile.tech_stack.length === 0) {
171
+ const extra = await ask(rl, "Specify stack (optional)", "Svelte, Prisma, Redis, ...")
172
+ if (extra) profile.tech_stack = [...profile.tech_stack.filter((s) => s !== "Other"), extra]
173
+ }
174
+
175
+ // 3. Design / code style
176
+ sectionTitle("3 / 4 Design & Code Style")
177
+ const styleChoices = [
178
+ "Clean and minimal — less is more",
179
+ "Functional — prefer pure functions, immutability",
180
+ "Object-oriented — classes and patterns",
181
+ "Performance-first — optimize aggressively",
182
+ "Pragmatic — whatever works best for the task"
183
+ ]
184
+ const styleIdx = await menu(rl, "What's your preferred coding style?", styleChoices)
185
+ profile.design_style = styleChoices[styleIdx]
186
+
187
+ // 4. Extra notes
188
+ sectionTitle("4 / 4 Anything Else?")
189
+ ln(paint(" Tell kkcode anything else it should remember about you.", "#aaaaaa"))
190
+ ln(paint(" e.g. \"Always write tests\", \"I prefer concise code\", \"Use Chinese for comments\"", "#666"))
191
+ const notes = await ask(rl, "Extra notes (optional, press Enter to skip)")
192
+ profile.extra_notes = notes
193
+
194
+ // ── Save ──────────────────────────────────────────────────────────────────
195
+ await saveProfile(profile)
196
+
197
+ ln()
198
+ hr()
199
+ ln()
200
+ ln(paint(" ✓ Profile saved!", "#2ac26f", { bold: true }))
201
+ ln(paint(" kkcode will use this context in every conversation.", "#aaaaaa"))
202
+ ln(paint(" You can update it anytime with /profile.", "#aaaaaa"))
203
+ ln()
204
+
205
+ return profile
206
+ } finally {
207
+ rl.close()
208
+ }
209
+ }