@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/src/provider/sse.mjs
CHANGED
|
@@ -1,104 +1,104 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 将 fetch response.body (ReadableStream) 解析为 SSE 事件的 AsyncIterator。
|
|
3
|
-
* 同时支持 OpenAI(纯 data: 行)和 Anthropic(event: + data: 对)格式。
|
|
4
|
-
*
|
|
5
|
-
* @param {ReadableStream} body
|
|
6
|
-
* @param {AbortSignal} [signal]
|
|
7
|
-
* @param {object} [options]
|
|
8
|
-
* @param {number} [options.idleTimeoutMs] - per-chunk idle timeout (resets on each chunk)
|
|
9
|
-
* @yields {{ event: string|null, data: string }}
|
|
10
|
-
*/
|
|
11
|
-
export async function* parseSSE(body, signal, options = {}) {
|
|
12
|
-
const reader = body.getReader()
|
|
13
|
-
const decoder = new TextDecoder()
|
|
14
|
-
let buffer = ""
|
|
15
|
-
const idleMs = options.idleTimeoutMs || 0
|
|
16
|
-
let currentTimeout = null
|
|
17
|
-
|
|
18
|
-
try {
|
|
19
|
-
while (true) {
|
|
20
|
-
if (signal?.aborted) break
|
|
21
|
-
|
|
22
|
-
let readResult
|
|
23
|
-
if (idleMs > 0) {
|
|
24
|
-
if (currentTimeout) currentTimeout.cancel()
|
|
25
|
-
currentTimeout = idleTimeout(idleMs, signal)
|
|
26
|
-
readResult = await Promise.race([
|
|
27
|
-
reader.read(),
|
|
28
|
-
currentTimeout.promise
|
|
29
|
-
])
|
|
30
|
-
} else {
|
|
31
|
-
readResult = await reader.read()
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const { done, value } = readResult
|
|
35
|
-
if (done) break
|
|
36
|
-
buffer += decoder.decode(value, { stream: true })
|
|
37
|
-
|
|
38
|
-
const parts = buffer.split("\n\n")
|
|
39
|
-
buffer = parts.pop()
|
|
40
|
-
|
|
41
|
-
for (const part of parts) {
|
|
42
|
-
const result = parsePart(part)
|
|
43
|
-
if (result === null) return // [DONE]
|
|
44
|
-
if (result) yield result
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
// flush remaining buffer
|
|
48
|
-
if (buffer.trim()) {
|
|
49
|
-
const result = parsePart(buffer)
|
|
50
|
-
if (result && result !== null) yield result
|
|
51
|
-
}
|
|
52
|
-
} finally {
|
|
53
|
-
if (currentTimeout) currentTimeout.cancel()
|
|
54
|
-
try { reader.releaseLock() } catch { /* reader may have pending read if generator was force-closed */ }
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function idleTimeout(ms, signal) {
|
|
59
|
-
let timer = null
|
|
60
|
-
let onAbort = null
|
|
61
|
-
const promise = new Promise((resolve, reject) => {
|
|
62
|
-
timer = setTimeout(() => {
|
|
63
|
-
const err = new Error(`stream idle timeout: no data received for ${ms}ms`)
|
|
64
|
-
err.code = "STREAM_IDLE_TIMEOUT"
|
|
65
|
-
reject(err)
|
|
66
|
-
}, ms)
|
|
67
|
-
if (signal) {
|
|
68
|
-
onAbort = () => {
|
|
69
|
-
clearTimeout(timer)
|
|
70
|
-
const err = new Error("aborted")
|
|
71
|
-
err.code = "ABORT_ERR"
|
|
72
|
-
reject(err)
|
|
73
|
-
}
|
|
74
|
-
if (signal.aborted) { clearTimeout(timer); onAbort(); return }
|
|
75
|
-
signal.addEventListener("abort", onAbort, { once: true })
|
|
76
|
-
}
|
|
77
|
-
})
|
|
78
|
-
function cancel() {
|
|
79
|
-
if (timer !== null) { clearTimeout(timer); timer = null }
|
|
80
|
-
if (onAbort && signal) {
|
|
81
|
-
signal.removeEventListener("abort", onAbort)
|
|
82
|
-
onAbort = null
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return { promise, cancel }
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function parsePart(part) {
|
|
89
|
-
const trimmed = part.trim()
|
|
90
|
-
if (!trimmed) return undefined
|
|
91
|
-
let event = null
|
|
92
|
-
let data = ""
|
|
93
|
-
for (const line of trimmed.split("\n")) {
|
|
94
|
-
if (line.startsWith("event:")) {
|
|
95
|
-
event = line.slice(6).trim()
|
|
96
|
-
} else if (line.startsWith("data:")) {
|
|
97
|
-
const payload = line.slice(5).trim()
|
|
98
|
-
if (payload === "[DONE]") return null
|
|
99
|
-
data = payload
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
if (!data) return undefined
|
|
103
|
-
return { event, data }
|
|
104
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 将 fetch response.body (ReadableStream) 解析为 SSE 事件的 AsyncIterator。
|
|
3
|
+
* 同时支持 OpenAI(纯 data: 行)和 Anthropic(event: + data: 对)格式。
|
|
4
|
+
*
|
|
5
|
+
* @param {ReadableStream} body
|
|
6
|
+
* @param {AbortSignal} [signal]
|
|
7
|
+
* @param {object} [options]
|
|
8
|
+
* @param {number} [options.idleTimeoutMs] - per-chunk idle timeout (resets on each chunk)
|
|
9
|
+
* @yields {{ event: string|null, data: string }}
|
|
10
|
+
*/
|
|
11
|
+
export async function* parseSSE(body, signal, options = {}) {
|
|
12
|
+
const reader = body.getReader()
|
|
13
|
+
const decoder = new TextDecoder()
|
|
14
|
+
let buffer = ""
|
|
15
|
+
const idleMs = options.idleTimeoutMs || 0
|
|
16
|
+
let currentTimeout = null
|
|
17
|
+
|
|
18
|
+
try {
|
|
19
|
+
while (true) {
|
|
20
|
+
if (signal?.aborted) break
|
|
21
|
+
|
|
22
|
+
let readResult
|
|
23
|
+
if (idleMs > 0) {
|
|
24
|
+
if (currentTimeout) currentTimeout.cancel()
|
|
25
|
+
currentTimeout = idleTimeout(idleMs, signal)
|
|
26
|
+
readResult = await Promise.race([
|
|
27
|
+
reader.read(),
|
|
28
|
+
currentTimeout.promise
|
|
29
|
+
])
|
|
30
|
+
} else {
|
|
31
|
+
readResult = await reader.read()
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const { done, value } = readResult
|
|
35
|
+
if (done) break
|
|
36
|
+
buffer += decoder.decode(value, { stream: true })
|
|
37
|
+
|
|
38
|
+
const parts = buffer.split("\n\n")
|
|
39
|
+
buffer = parts.pop()
|
|
40
|
+
|
|
41
|
+
for (const part of parts) {
|
|
42
|
+
const result = parsePart(part)
|
|
43
|
+
if (result === null) return // [DONE]
|
|
44
|
+
if (result) yield result
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
// flush remaining buffer
|
|
48
|
+
if (buffer.trim()) {
|
|
49
|
+
const result = parsePart(buffer)
|
|
50
|
+
if (result && result !== null) yield result
|
|
51
|
+
}
|
|
52
|
+
} finally {
|
|
53
|
+
if (currentTimeout) currentTimeout.cancel()
|
|
54
|
+
try { reader.releaseLock() } catch { /* reader may have pending read if generator was force-closed */ }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function idleTimeout(ms, signal) {
|
|
59
|
+
let timer = null
|
|
60
|
+
let onAbort = null
|
|
61
|
+
const promise = new Promise((resolve, reject) => {
|
|
62
|
+
timer = setTimeout(() => {
|
|
63
|
+
const err = new Error(`stream idle timeout: no data received for ${ms}ms`)
|
|
64
|
+
err.code = "STREAM_IDLE_TIMEOUT"
|
|
65
|
+
reject(err)
|
|
66
|
+
}, ms)
|
|
67
|
+
if (signal) {
|
|
68
|
+
onAbort = () => {
|
|
69
|
+
clearTimeout(timer)
|
|
70
|
+
const err = new Error("aborted")
|
|
71
|
+
err.code = "ABORT_ERR"
|
|
72
|
+
reject(err)
|
|
73
|
+
}
|
|
74
|
+
if (signal.aborted) { clearTimeout(timer); onAbort(); return }
|
|
75
|
+
signal.addEventListener("abort", onAbort, { once: true })
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
function cancel() {
|
|
79
|
+
if (timer !== null) { clearTimeout(timer); timer = null }
|
|
80
|
+
if (onAbort && signal) {
|
|
81
|
+
signal.removeEventListener("abort", onAbort)
|
|
82
|
+
onAbort = null
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return { promise, cancel }
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function parsePart(part) {
|
|
89
|
+
const trimmed = part.trim()
|
|
90
|
+
if (!trimmed) return undefined
|
|
91
|
+
let event = null
|
|
92
|
+
let data = ""
|
|
93
|
+
for (const line of trimmed.split("\n")) {
|
|
94
|
+
if (line.startsWith("event:")) {
|
|
95
|
+
event = line.slice(6).trim()
|
|
96
|
+
} else if (line.startsWith("data:")) {
|
|
97
|
+
const payload = line.slice(5).trim()
|
|
98
|
+
if (payload === "[DONE]") return null
|
|
99
|
+
data = data ? data + "\n" + payload : payload
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (!data) return undefined
|
|
103
|
+
return { event, data }
|
|
104
|
+
}
|