@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
@@ -1,39 +1,39 @@
1
- <frontend_aesthetics>
2
- ## Frontend Design Quality Rules
3
-
4
- When building frontend UI, avoid generic "AI-generated" aesthetics. Make creative, distinctive choices.
5
-
6
- ### Typography
7
- - Avoid default fonts (Inter, Roboto, Arial, system-ui). Choose distinctive fonts.
8
- - Use high contrast: pair display fonts with monospace, serif with geometric sans.
9
- - Use extreme weight differences (200 vs 800) and 3x+ size jumps.
10
- - Load fonts from Google Fonts via <link> or @import.
11
-
12
- ### Color
13
- - Define ALL colors as CSS variables in :root.
14
- - Use a dominant color with 1-2 sharp accents. Avoid evenly-distributed palettes.
15
- - Draw from real palettes: IDE themes (Nord, Catppuccin, Dracula), nature, cultural aesthetics.
16
- - AVOID: purple gradients on white, generic blue buttons, gray-on-gray cards.
17
-
18
- ### Motion
19
- - One high-impact animation per page (staggered reveal on load).
20
- - Micro-interactions: hover lift, focus glow, press feedback.
21
- - Use CSS transitions/animations. Use animation-delay for staggered effects.
22
-
23
- ### Layout
24
- - CSS Grid for page structure, Flexbox for components.
25
- - Generous whitespace. Consistent spacing scale (4/8/12/16/24/32/48/64px).
26
- - Mobile-first responsive design.
27
-
28
- ### Depth & Atmosphere
29
- - Layered gradients, subtle patterns, backdrop-filter for glass effects.
30
- - Elevation hierarchy via box-shadow (not just border).
31
- - Noise/grain textures for premium feel.
32
-
33
- ### What NOT to do
34
- - Cookie-cutter card grids with identical rounded corners
35
- - Generic hero with centered text + gradient
36
- - border-radius: 9999px on everything
37
- - Gray placeholder text that looks like wireframe
38
- - No visual rhythm (identical spacing everywhere)
1
+ <frontend_aesthetics>
2
+ ## Frontend Design Quality Rules
3
+
4
+ When building frontend UI, avoid generic "AI-generated" aesthetics. Make creative, distinctive choices.
5
+
6
+ ### Typography
7
+ - Avoid default fonts (Inter, Roboto, Arial, system-ui). Choose distinctive fonts.
8
+ - Use high contrast: pair display fonts with monospace, serif with geometric sans.
9
+ - Use extreme weight differences (200 vs 800) and 3x+ size jumps.
10
+ - Load fonts from Google Fonts via <link> or @import.
11
+
12
+ ### Color
13
+ - Define ALL colors as CSS variables in :root.
14
+ - Use a dominant color with 1-2 sharp accents. Avoid evenly-distributed palettes.
15
+ - Draw from real palettes: IDE themes (Nord, Catppuccin, Dracula), nature, cultural aesthetics.
16
+ - AVOID: purple gradients on white, generic blue buttons, gray-on-gray cards.
17
+
18
+ ### Motion
19
+ - One high-impact animation per page (staggered reveal on load).
20
+ - Micro-interactions: hover lift, focus glow, press feedback.
21
+ - Use CSS transitions/animations. Use animation-delay for staggered effects.
22
+
23
+ ### Layout
24
+ - CSS Grid for page structure, Flexbox for components.
25
+ - Generous whitespace. Consistent spacing scale (4/8/12/16/24/32/48/64px).
26
+ - Mobile-first responsive design.
27
+
28
+ ### Depth & Atmosphere
29
+ - Layered gradients, subtle patterns, backdrop-filter for glass effects.
30
+ - Elevation hierarchy via box-shadow (not just border).
31
+ - Noise/grain textures for premium feel.
32
+
33
+ ### What NOT to do
34
+ - Cookie-cutter card grids with identical rounded corners
35
+ - Generic hero with centered text + gradient
36
+ - border-radius: 9999px on everything
37
+ - Gray placeholder text that looks like wireframe
38
+ - No visual rhythm (identical spacing everywhere)
39
39
  </frontend_aesthetics>
@@ -1,141 +1,139 @@
1
- import { McpError } from "../core/errors.mjs"
2
- import { EventBus } from "../core/events.mjs"
3
- import { EVENT_TYPES } from "../core/constants.mjs"
4
- import { normalizeToolResult } from "./tool-result.mjs"
5
-
6
- function timeoutSignal(ms, parentSignal = null) {
7
- const own = AbortSignal.timeout(ms)
8
- if (!parentSignal) return own
9
- return AbortSignal.any([parentSignal, own])
10
- }
11
-
12
- function classifyHttpError(error, status = null) {
13
- const msg = String(error?.message || error || "")
14
- if (msg.includes("AbortError") || msg.includes("timeout") || msg.includes("abort")) return "timeout"
15
- if (msg.includes("ECONNREFUSED") || msg.includes("fetch failed")) return "connection_refused"
16
- if (status && status >= 500) return "server_crash"
17
- if (status && status >= 400) return "bad_response"
18
- return "unknown"
19
- }
20
-
21
- async function requestJson({ serverName, method, url, body = null, timeoutMs = 10000, headers = {}, signal = null }) {
22
- const action = method === "GET" ? url.split("/").pop() : body?.args ? "call_tool" : "request"
23
- const startedAt = Date.now()
24
- let status = null
25
-
26
- try {
27
- const res = await fetch(url, {
28
- method,
29
- headers: {
30
- "content-type": "application/json",
31
- ...headers
32
- },
33
- body: body ? JSON.stringify(body) : undefined,
34
- signal: timeoutSignal(timeoutMs, signal)
35
- })
36
-
37
- status = res.status
38
- const elapsed = Date.now() - startedAt
39
-
40
- EventBus.emit({
41
- type: EVENT_TYPES.MCP_REQUEST,
42
- payload: { server: serverName, action, method, elapsed, status }
43
- }).catch(() => {})
44
-
45
- if (!res.ok) {
46
- const text = await res.text().catch(() => "")
47
- const reason = classifyHttpError(null, status)
48
- throw new McpError(
49
- `mcp server "${serverName}" HTTP ${status} on ${method} ${url}: ${text.slice(0, 500)}`,
50
- { reason, server: serverName, action, phase: "request", statusCode: status }
51
- )
52
- }
53
- return res.json().catch((parseErr) => {
54
- const action = body?.args ? "call_tool" : "request"
55
- EventBus.emit({
56
- type: EVENT_TYPES.MCP_REQUEST,
57
- payload: { server: serverName, action, warning: "malformed_json_response", detail: parseErr.message }
58
- }).catch(() => {})
59
- return {}
60
- })
61
- } catch (error) {
62
- if (error instanceof McpError) throw error
63
- const reason = classifyHttpError(error, status)
64
- throw new McpError(
65
- `mcp server "${serverName}" ${reason} on ${method} ${url}: ${error.message}`,
66
- { reason, server: serverName, action, phase: "request", statusCode: status }
67
- )
68
- }
69
- }
70
-
71
- export function createHttpMcpClient(serverName, config) {
72
- const baseUrl = String(config.url || "").replace(/\/$/, "")
73
- const timeoutMs = Number(config.timeout_ms || 10000)
74
- const headers = config.headers || {}
75
-
76
- return {
77
- serverName,
78
- transport: "http",
79
- async health() {
80
- try {
81
- await requestJson({ serverName, method: "GET", url: `${baseUrl}/health`, timeoutMs, headers })
82
- return { ok: true }
83
- } catch (error) {
84
- return { ok: false, error: error.message, reason: error.reason || "unknown" }
85
- }
86
- },
87
- async listTools() {
88
- const out = await requestJson({ serverName, method: "GET", url: `${baseUrl}/tools`, timeoutMs, headers })
89
- return Array.isArray(out?.tools) ? out.tools : []
90
- },
91
- async listPrompts() {
92
- try {
93
- const out = await requestJson({ serverName, method: "GET", url: `${baseUrl}/prompts`, timeoutMs, headers })
94
- return Array.isArray(out?.prompts) ? out.prompts : []
95
- } catch {
96
- return []
97
- }
98
- },
99
- async getPrompt(name, args = {}) {
100
- return requestJson({
101
- serverName,
102
- method: "POST",
103
- url: `${baseUrl}/prompts/${encodeURIComponent(name)}`,
104
- body: { arguments: args },
105
- timeoutMs,
106
- headers
107
- })
108
- },
109
- async listResources() {
110
- try {
111
- const out = await requestJson({ serverName, method: "GET", url: `${baseUrl}/resources`, timeoutMs, headers })
112
- return Array.isArray(out?.resources) ? out.resources : []
113
- } catch {
114
- return []
115
- }
116
- },
117
- async listTemplates() {
118
- try {
119
- const out = await requestJson({ serverName, method: "GET", url: `${baseUrl}/templates`, timeoutMs, headers })
120
- return Array.isArray(out?.templates) ? out.templates : []
121
- } catch {
122
- return []
123
- }
124
- },
125
- async callTool(name, args = {}, signal = null) {
126
- const result = await requestJson({
127
- serverName,
128
- method: "POST",
129
- url: `${baseUrl}/tools/${encodeURIComponent(name)}`,
130
- body: { args },
131
- timeoutMs,
132
- headers,
133
- signal
134
- })
135
- return normalizeToolResult(result, serverName, name)
136
- },
137
- shutdown() {
138
- // HTTP client is stateless — no persistent connections to clean up
139
- }
140
- }
141
- }
1
+ import { McpError } from "../core/errors.mjs"
2
+ import { EventBus } from "../core/events.mjs"
3
+ import { EVENT_TYPES } from "../core/constants.mjs"
4
+ import { normalizeToolResult } from "./tool-result.mjs"
5
+
6
+ function timeoutSignal(ms, parentSignal = null) {
7
+ const own = AbortSignal.timeout(ms)
8
+ if (!parentSignal) return own
9
+ return AbortSignal.any([parentSignal, own])
10
+ }
11
+
12
+ function classifyHttpError(error, status = null) {
13
+ const msg = String(error?.message || error || "")
14
+ if (msg.includes("AbortError") || msg.includes("timeout") || msg.includes("abort")) return "timeout"
15
+ if (msg.includes("ECONNREFUSED") || msg.includes("fetch failed")) return "connection_refused"
16
+ if (status && status >= 500) return "server_crash"
17
+ if (status && status >= 400) return "bad_response"
18
+ return "unknown"
19
+ }
20
+
21
+ async function requestJson({ serverName, method, url, body = null, timeoutMs = 10000, headers = {}, signal = null }) {
22
+ const action = method === "GET" ? url.split("/").pop() : body?.args ? "call_tool" : "request"
23
+ const startedAt = Date.now()
24
+ let status = null
25
+
26
+ try {
27
+ const res = await fetch(url, {
28
+ method,
29
+ headers: {
30
+ "content-type": "application/json",
31
+ ...headers
32
+ },
33
+ body: body ? JSON.stringify(body) : undefined,
34
+ signal: timeoutSignal(timeoutMs, signal)
35
+ })
36
+
37
+ status = res.status
38
+ const elapsed = Date.now() - startedAt
39
+
40
+ EventBus.emit({
41
+ type: EVENT_TYPES.MCP_REQUEST,
42
+ payload: { server: serverName, action, method, elapsed, status }
43
+ }).catch(() => {})
44
+
45
+ if (!res.ok) {
46
+ const text = await res.text().catch(() => "")
47
+ const reason = classifyHttpError(null, status)
48
+ throw new McpError(
49
+ `mcp server "${serverName}" HTTP ${status} on ${method} ${url}: ${text.slice(0, 500)}`,
50
+ { reason, server: serverName, action, phase: "request", statusCode: status }
51
+ )
52
+ }
53
+ return res.json().catch((parseErr) => {
54
+ throw new McpError(
55
+ `mcp server "${serverName}" malformed JSON response: ${parseErr.message}`,
56
+ { reason: "bad_response", server: serverName, action: body?.method || "request", phase: "request" }
57
+ )
58
+ })
59
+ } catch (error) {
60
+ if (error instanceof McpError) throw error
61
+ const reason = classifyHttpError(error, status)
62
+ throw new McpError(
63
+ `mcp server "${serverName}" ${reason} on ${method} ${url}: ${error.message}`,
64
+ { reason, server: serverName, action, phase: "request", statusCode: status }
65
+ )
66
+ }
67
+ }
68
+
69
+ export function createHttpMcpClient(serverName, config) {
70
+ const baseUrl = String(config.url || "").replace(/\/$/, "")
71
+ const timeoutMs = Number(config.timeout_ms || 10000)
72
+ const headers = config.headers || {}
73
+
74
+ return {
75
+ serverName,
76
+ transport: "http",
77
+ async health() {
78
+ try {
79
+ await requestJson({ serverName, method: "GET", url: `${baseUrl}/health`, timeoutMs, headers })
80
+ return { ok: true }
81
+ } catch (error) {
82
+ return { ok: false, error: error.message, reason: error.reason || "unknown" }
83
+ }
84
+ },
85
+ async listTools() {
86
+ const out = await requestJson({ serverName, method: "GET", url: `${baseUrl}/tools`, timeoutMs, headers })
87
+ return Array.isArray(out?.tools) ? out.tools : []
88
+ },
89
+ async listPrompts() {
90
+ try {
91
+ const out = await requestJson({ serverName, method: "GET", url: `${baseUrl}/prompts`, timeoutMs, headers })
92
+ return Array.isArray(out?.prompts) ? out.prompts : []
93
+ } catch {
94
+ return []
95
+ }
96
+ },
97
+ async getPrompt(name, args = {}) {
98
+ return requestJson({
99
+ serverName,
100
+ method: "POST",
101
+ url: `${baseUrl}/prompts/${encodeURIComponent(name)}`,
102
+ body: { arguments: args },
103
+ timeoutMs,
104
+ headers
105
+ })
106
+ },
107
+ async listResources() {
108
+ try {
109
+ const out = await requestJson({ serverName, method: "GET", url: `${baseUrl}/resources`, timeoutMs, headers })
110
+ return Array.isArray(out?.resources) ? out.resources : []
111
+ } catch {
112
+ return []
113
+ }
114
+ },
115
+ async listTemplates() {
116
+ try {
117
+ const out = await requestJson({ serverName, method: "GET", url: `${baseUrl}/templates`, timeoutMs, headers })
118
+ return Array.isArray(out?.templates) ? out.templates : []
119
+ } catch {
120
+ return []
121
+ }
122
+ },
123
+ async callTool(name, args = {}, signal = null) {
124
+ const result = await requestJson({
125
+ serverName,
126
+ method: "POST",
127
+ url: `${baseUrl}/tools/${encodeURIComponent(name)}`,
128
+ body: { arguments: args },
129
+ timeoutMs,
130
+ headers,
131
+ signal
132
+ })
133
+ return normalizeToolResult(result, serverName, name)
134
+ },
135
+ shutdown() {
136
+ // HTTP client is stateless — no persistent connections to clean up
137
+ }
138
+ }
139
+ }