@kkelly-offical/kkcode 0.1.3 → 0.1.7
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/README.md +110 -172
- package/package.json +46 -46
- package/src/agent/agent.mjs +220 -170
- package/src/agent/prompt/bug-hunter.txt +90 -0
- package/src/agent/prompt/frontend-designer.txt +58 -0
- package/src/agent/prompt/longagent-blueprint-agent.txt +83 -0
- package/src/agent/prompt/longagent-coding-agent.txt +37 -0
- package/src/agent/prompt/longagent-debugging-agent.txt +46 -0
- package/src/agent/prompt/longagent-preview-agent.txt +63 -0
- package/src/config/defaults.mjs +260 -195
- package/src/config/schema.mjs +71 -6
- package/src/core/constants.mjs +91 -46
- package/src/index.mjs +1 -1
- package/src/knowledge/frontend-aesthetics.txt +39 -0
- package/src/knowledge/loader.mjs +2 -1
- package/src/knowledge/tailwind.txt +12 -3
- package/src/mcp/client-http.mjs +141 -157
- package/src/mcp/client-sse.mjs +288 -286
- package/src/mcp/client-stdio.mjs +533 -451
- package/src/mcp/constants.mjs +2 -0
- package/src/mcp/registry.mjs +479 -394
- package/src/mcp/stdio-framing.mjs +133 -127
- package/src/mcp/tool-result.mjs +24 -0
- package/src/observability/index.mjs +42 -0
- package/src/observability/metrics.mjs +137 -0
- package/src/observability/tracer.mjs +137 -0
- package/src/orchestration/background-manager.mjs +372 -358
- package/src/orchestration/background-worker.mjs +305 -245
- package/src/orchestration/longagent-manager.mjs +171 -116
- package/src/orchestration/stage-scheduler.mjs +728 -489
- package/src/permission/exec-policy.mjs +9 -11
- package/src/provider/anthropic.mjs +1 -0
- package/src/provider/openai.mjs +340 -339
- package/src/provider/retry-policy.mjs +68 -68
- package/src/provider/router.mjs +241 -228
- package/src/provider/sse.mjs +104 -91
- package/src/repl.mjs +59 -7
- package/src/session/checkpoint.mjs +66 -3
- package/src/session/compaction.mjs +298 -276
- package/src/session/engine.mjs +232 -225
- package/src/session/longagent-4stage.mjs +460 -0
- package/src/session/longagent-hybrid.mjs +1097 -0
- package/src/session/longagent-plan.mjs +365 -329
- package/src/session/longagent-project-memory.mjs +53 -0
- package/src/session/longagent-scaffold.mjs +291 -100
- package/src/session/longagent-task-bus.mjs +54 -0
- package/src/session/longagent-utils.mjs +472 -0
- package/src/session/longagent.mjs +900 -1462
- package/src/session/loop.mjs +65 -40
- package/src/session/project-context.mjs +30 -0
- package/src/session/prompt/agent.txt +25 -0
- package/src/session/prompt/plan.txt +31 -9
- package/src/session/rollback.mjs +196 -0
- package/src/session/store.mjs +519 -503
- package/src/session/system-prompt.mjs +273 -260
- package/src/session/task-validator.mjs +4 -3
- package/src/skill/builtin/design.mjs +76 -0
- package/src/skill/builtin/frontend.mjs +8 -0
- package/src/skill/registry.mjs +390 -336
- package/src/storage/ghost-commit-store.mjs +18 -8
- package/src/tool/executor.mjs +11 -0
- package/src/tool/git-auto.mjs +0 -19
- package/src/tool/question-prompt.mjs +93 -86
- package/src/tool/registry.mjs +71 -37
- package/src/ui/activity-renderer.mjs +664 -410
- package/src/util/git.mjs +23 -0
package/src/mcp/client-http.mjs
CHANGED
|
@@ -1,157 +1,141 @@
|
|
|
1
|
-
import { McpError } from "../core/errors.mjs"
|
|
2
|
-
import { EventBus } from "../core/events.mjs"
|
|
3
|
-
import { EVENT_TYPES } from "../core/constants.mjs"
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
if (msg.includes("
|
|
15
|
-
if (
|
|
16
|
-
if (status && status >=
|
|
17
|
-
return "
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const result = await requestJson({
|
|
143
|
-
serverName,
|
|
144
|
-
method: "POST",
|
|
145
|
-
url: `${baseUrl}/tools/${encodeURIComponent(name)}`,
|
|
146
|
-
body: { args },
|
|
147
|
-
timeoutMs,
|
|
148
|
-
headers,
|
|
149
|
-
signal
|
|
150
|
-
})
|
|
151
|
-
return normalizeToolResult(result, serverName, name)
|
|
152
|
-
},
|
|
153
|
-
shutdown() {
|
|
154
|
-
// HTTP client is stateless — no persistent connections to clean up
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
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
|
+
}
|