@kkelly-offical/kkcode 0.1.7 → 0.2.3-preview.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 (166) hide show
  1. package/LICENSE +674 -674
  2. package/README.md +474 -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/commands/update.mjs +32 -0
  29. package/src/config/defaults.mjs +289 -260
  30. package/src/config/import-config.mjs +1 -1
  31. package/src/config/load-config.mjs +61 -4
  32. package/src/config/schema.mjs +604 -574
  33. package/src/context.mjs +4 -1
  34. package/src/core/constants.mjs +97 -91
  35. package/src/core/types.mjs +1 -1
  36. package/src/github/api.mjs +78 -78
  37. package/src/github/auth.mjs +294 -286
  38. package/src/github/flow.mjs +298 -298
  39. package/src/github/workspace.mjs +225 -212
  40. package/src/index.mjs +87 -82
  41. package/src/knowledge/frontend-aesthetics.txt +38 -38
  42. package/src/mcp/client-http.mjs +139 -141
  43. package/src/mcp/client-sse.mjs +297 -288
  44. package/src/mcp/client-stdio.mjs +534 -533
  45. package/src/mcp/constants.mjs +4 -2
  46. package/src/mcp/registry.mjs +498 -479
  47. package/src/mcp/stdio-framing.mjs +135 -133
  48. package/src/mcp/tool-result.mjs +24 -24
  49. package/src/observability/edit-diagnostics.mjs +449 -0
  50. package/src/observability/index.mjs +42 -42
  51. package/src/observability/metrics.mjs +165 -137
  52. package/src/observability/tracer.mjs +137 -137
  53. package/src/onboarding.mjs +209 -0
  54. package/src/orchestration/background-manager.mjs +567 -372
  55. package/src/orchestration/background-worker.mjs +419 -305
  56. package/src/orchestration/interruption-reason.mjs +21 -0
  57. package/src/orchestration/longagent-manager.mjs +197 -171
  58. package/src/orchestration/stage-scheduler.mjs +733 -728
  59. package/src/orchestration/subagent-router.mjs +7 -1
  60. package/src/orchestration/task-scheduler.mjs +219 -7
  61. package/src/permission/engine.mjs +1 -1
  62. package/src/permission/exec-policy.mjs +370 -370
  63. package/src/permission/file-edit-policy.mjs +108 -0
  64. package/src/permission/prompt.mjs +1 -1
  65. package/src/permission/rules.mjs +116 -7
  66. package/src/plugin/builtin-hooks/post-edit-format.mjs +2 -1
  67. package/src/plugin/builtin-hooks/post-edit-typecheck.mjs +104 -40
  68. package/src/plugin/hook-bus.mjs +19 -5
  69. package/src/plugin/manifest-loader.mjs +222 -0
  70. package/src/provider/anthropic.mjs +396 -390
  71. package/src/provider/ollama.mjs +7 -1
  72. package/src/provider/openai.mjs +382 -340
  73. package/src/provider/retry-policy.mjs +74 -68
  74. package/src/provider/router.mjs +242 -241
  75. package/src/provider/sse.mjs +104 -104
  76. package/src/provider/wizard.mjs +556 -0
  77. package/src/repl/capability-facade.mjs +30 -0
  78. package/src/repl/command-surface.mjs +23 -0
  79. package/src/repl/controller-entry.mjs +40 -0
  80. package/src/repl/core-shell.mjs +208 -0
  81. package/src/repl/dialog-router.mjs +87 -0
  82. package/src/repl/input-engine.mjs +76 -0
  83. package/src/repl/keymap.mjs +7 -0
  84. package/src/repl/operator-surface.mjs +15 -0
  85. package/src/repl/permission-flow.mjs +49 -0
  86. package/src/repl/runtime-facade.mjs +36 -0
  87. package/src/repl/slash-router.mjs +62 -0
  88. package/src/repl/state-store.mjs +29 -0
  89. package/src/repl/turn-controller.mjs +58 -0
  90. package/src/repl/verification.mjs +23 -0
  91. package/src/repl.mjs +3371 -2981
  92. package/src/rules/load-rules.mjs +3 -3
  93. package/src/runtime.mjs +1 -1
  94. package/src/session/agent-transaction.mjs +86 -0
  95. package/src/session/checkpoint.mjs +302 -302
  96. package/src/session/compaction.mjs +298 -298
  97. package/src/session/engine.mjs +417 -232
  98. package/src/session/longagent-4stage.mjs +467 -460
  99. package/src/session/longagent-hybrid.mjs +1344 -1097
  100. package/src/session/longagent-plan.mjs +376 -365
  101. package/src/session/longagent-project-memory.mjs +53 -53
  102. package/src/session/longagent-scaffold.mjs +291 -291
  103. package/src/session/longagent-task-bus.mjs +138 -54
  104. package/src/session/longagent-utils.mjs +828 -472
  105. package/src/session/longagent.mjs +911 -900
  106. package/src/session/loop.mjs +1005 -930
  107. package/src/session/prompt/agent.txt +25 -25
  108. package/src/session/prompt/anthropic.txt +150 -150
  109. package/src/session/prompt/beast.txt +1 -1
  110. package/src/session/prompt/plan.txt +31 -31
  111. package/src/session/prompt/qwen.txt +46 -46
  112. package/src/session/recovery.mjs +21 -0
  113. package/src/session/rollback.mjs +196 -195
  114. package/src/session/routing-observability.mjs +72 -0
  115. package/src/session/runtime-state.mjs +47 -0
  116. package/src/session/store.mjs +523 -519
  117. package/src/session/system-prompt.mjs +308 -273
  118. package/src/session/task-validator.mjs +267 -267
  119. package/src/session/usability-gates.mjs +2 -2
  120. package/src/skill/builtin/commit.mjs +64 -64
  121. package/src/skill/builtin/design.mjs +76 -76
  122. package/src/skill/generator.mjs +18 -2
  123. package/src/skill/registry.mjs +642 -390
  124. package/src/storage/audit-store.mjs +18 -11
  125. package/src/storage/event-log.mjs +7 -1
  126. package/src/storage/ghost-commit-store.mjs +243 -245
  127. package/src/storage/paths.mjs +17 -0
  128. package/src/theme/default-theme.mjs +1 -1
  129. package/src/theme/markdown.mjs +4 -0
  130. package/src/theme/schema.mjs +1 -1
  131. package/src/theme/status-bar.mjs +162 -158
  132. package/src/tool/audit-wrapper.mjs +18 -2
  133. package/src/tool/edit-transaction.mjs +23 -0
  134. package/src/tool/executor.mjs +26 -1
  135. package/src/tool/file-read-state.mjs +65 -0
  136. package/src/tool/git-auto.mjs +526 -526
  137. package/src/tool/git-full-auto.mjs +487 -478
  138. package/src/tool/mutation-guard.mjs +54 -0
  139. package/src/tool/prompt/edit.txt +3 -3
  140. package/src/tool/prompt/multiedit.txt +1 -0
  141. package/src/tool/prompt/notebookedit.txt +2 -1
  142. package/src/tool/prompt/patch.txt +25 -24
  143. package/src/tool/prompt/read.txt +3 -3
  144. package/src/tool/prompt/sysinfo.txt +29 -0
  145. package/src/tool/prompt/task.txt +66 -4
  146. package/src/tool/prompt/write.txt +2 -2
  147. package/src/tool/question-prompt.mjs +99 -93
  148. package/src/tool/registry.mjs +1701 -1343
  149. package/src/tool/task-tool.mjs +14 -6
  150. package/src/ui/activity-renderer.mjs +667 -664
  151. package/src/ui/repl-background-panel.mjs +7 -0
  152. package/src/ui/repl-capability-panel.mjs +9 -0
  153. package/src/ui/repl-dashboard.mjs +54 -4
  154. package/src/ui/repl-help.mjs +110 -0
  155. package/src/ui/repl-operator-panel.mjs +12 -0
  156. package/src/ui/repl-route-feedback.mjs +35 -0
  157. package/src/ui/repl-status-view.mjs +76 -0
  158. package/src/ui/repl-task-panel.mjs +5 -0
  159. package/src/ui/repl-transcript-panel.mjs +56 -0
  160. package/src/ui/repl-turn-summary.mjs +135 -0
  161. package/src/update/checker.mjs +184 -0
  162. package/src/usage/pricing.mjs +122 -121
  163. package/src/usage/usage-meter.mjs +1 -0
  164. package/src/util/git.mjs +562 -519
  165. package/src/util/template.mjs +6 -1
  166. package/src/version.mjs +3 -0
@@ -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
+ }