@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
@@ -1,54 +1,138 @@
1
- /**
2
- * Task Bus — 并行 task 间的轻量通信机制
3
- * task 可以发布消息(接口变更、共享数据),其他 task 通过 priorContext 读取
4
- */
5
-
6
- export class TaskBus {
7
- constructor({ maxMessages = 500 } = {}) {
8
- this._messages = []
9
- this._shared = {}
10
- this._maxMessages = maxMessages
11
- }
12
-
13
- publish(taskId, key, value) {
14
- this._messages.push({ taskId, key, value, ts: Date.now() })
15
- // Evict oldest messages when exceeding capacity
16
- if (this._messages.length > this._maxMessages) {
17
- this._messages = this._messages.slice(-Math.round(this._maxMessages * 0.8))
18
- }
19
- this._shared[key] = { value, from: taskId, ts: Date.now() }
20
- }
21
-
22
- get(key) {
23
- return this._shared[key]?.value ?? null
24
- }
25
-
26
- snapshot() {
27
- return { ...this._shared }
28
- }
29
-
30
- toContextString(maxLen = 2000) {
31
- const entries = Object.entries(this._shared)
32
- if (!entries.length) return ""
33
- const lines = ["### Task Bus (shared context)"]
34
- for (const [key, { value, from }] of entries) {
35
- const val = typeof value === "string" ? value : JSON.stringify(value)
36
- lines.push(`- [${from}] ${key}: ${val.slice(0, 200)}`)
37
- }
38
- const result = lines.join("\n")
39
- return result.length > maxLen ? result.slice(0, maxLen) + "\n..." : result
40
- }
41
-
42
- parseTaskOutput(taskId, text) {
43
- const pattern = /\[TASK_BROADCAST:\s*(\w+)\s*=\s*(.*?)\]/g
44
- let match
45
- while ((match = pattern.exec(text)) !== null) {
46
- this.publish(taskId, match[1], match[2].trim())
47
- }
48
- }
49
-
50
- clear() {
51
- this._messages = []
52
- this._shared = {}
53
- }
54
- }
1
+ /**
2
+ * Task Bus — 并行 task 间的轻量通信机制
3
+ * task 可以发布消息(接口变更、共享数据),其他 task 通过 priorContext 读取
4
+ *
5
+ * Phase 3 增强:
6
+ * - 索引替代时间戳,修复 toDeltaString 竞态
7
+ * - topic 分类支持,按类别查询
8
+ * - parseTaskOutput 支持结构化 JSON 值
9
+ */
10
+
11
+ export class TaskBus {
12
+ constructor({ maxMessages = 500 } = {}) {
13
+ this._messages = []
14
+ this._shared = {}
15
+ this._maxMessages = maxMessages
16
+ this._lastFlushedIdx = 0
17
+ }
18
+
19
+ publish(taskId, key, value, topic = null) {
20
+ this._messages.push({ taskId, key, value, topic, ts: Date.now() })
21
+ // Evict oldest messages when exceeding capacity
22
+ if (this._messages.length > this._maxMessages) {
23
+ const keep = Math.round(this._maxMessages * 0.8)
24
+ const removed = this._messages.length - keep
25
+ this._messages = this._messages.slice(-keep)
26
+ // 调整索引偏移,防止 delta 丢失
27
+ this._lastFlushedIdx = Math.max(0, this._lastFlushedIdx - removed)
28
+ }
29
+ this._shared[key] = { value, from: taskId, topic, ts: Date.now() }
30
+ }
31
+
32
+ get(key) {
33
+ return this._shared[key]?.value ?? null
34
+ }
35
+
36
+ getByTopic(topic) {
37
+ const result = {}
38
+ for (const [key, entry] of Object.entries(this._shared)) {
39
+ if (entry.topic === topic) result[key] = entry.value
40
+ }
41
+ return result
42
+ }
43
+
44
+ snapshot() {
45
+ return { ...this._shared }
46
+ }
47
+
48
+ hasPendingMessages() {
49
+ return this._lastFlushedIdx < this._messages.length
50
+ }
51
+
52
+ toContextString(maxLen = 2000) {
53
+ const entries = Object.entries(this._shared)
54
+ if (!entries.length) return ""
55
+ const lines = ["### Task Bus (shared context)"]
56
+ for (const [key, { value, from }] of entries) {
57
+ const val = typeof value === "string" ? value : JSON.stringify(value)
58
+ lines.push(`- [${from}] ${key}: ${val.slice(0, 200)}`)
59
+ }
60
+ const result = lines.join("\n")
61
+ return result.length > maxLen ? result.slice(0, maxLen) + "\n..." : result
62
+ }
63
+
64
+ toDeltaString(maxLen = 2000) {
65
+ // 用索引替代时间戳,避免竞态丢消息
66
+ const startIdx = this._lastFlushedIdx
67
+ this._lastFlushedIdx = this._messages.length
68
+ if (startIdx >= this._messages.length) return ""
69
+ const newMessages = this._messages.slice(startIdx)
70
+ if (!newMessages.length) return ""
71
+ const lines = ["### Task Bus (new since last stage)"]
72
+ for (const { taskId, key, value } of newMessages) {
73
+ const val = typeof value === "string" ? value : JSON.stringify(value)
74
+ lines.push(`- [${taskId}] ${key}: ${val.slice(0, 200)}`)
75
+ }
76
+ const result = lines.join("\n")
77
+ return result.length > maxLen ? result.slice(0, maxLen) + "\n..." : result
78
+ }
79
+
80
+ parseTaskOutput(taskId, text) {
81
+ const marker = "[TASK_BROADCAST:"
82
+ let pos = 0
83
+ while ((pos = text.indexOf(marker, pos)) !== -1) {
84
+ const start = pos + marker.length
85
+ // 提取 key(支持 key@topic 语法)
86
+ const eqIdx = text.indexOf("=", start)
87
+ if (eqIdx === -1) { pos = start; continue }
88
+ const rawKey = text.slice(start, eqIdx).trim()
89
+ if (!rawKey) { pos = start; continue }
90
+
91
+ // 提取 value — 处理嵌套括号
92
+ let valStart = eqIdx + 1
93
+ while (valStart < text.length && text[valStart] === " ") valStart++
94
+ let valEnd = -1
95
+ const ch = text[valStart]
96
+ if (ch === "{" || ch === "[") {
97
+ // 平衡括号扫描
98
+ let depth = 0
99
+ for (let i = valStart; i < text.length; i++) {
100
+ if (text[i] === "{" || text[i] === "[") depth++
101
+ else if (text[i] === "}" || text[i] === "]") {
102
+ depth--
103
+ if (depth === 0) { valEnd = i + 1; break }
104
+ }
105
+ }
106
+ if (valEnd === -1) { pos = start; continue }
107
+ } else {
108
+ // 简单值 — 找到下一个 ]
109
+ valEnd = text.indexOf("]", valStart)
110
+ if (valEnd === -1) { pos = start; continue }
111
+ }
112
+
113
+ const raw = text.slice(valStart, valEnd).trim()
114
+ // 跳过闭合的 ]
115
+ pos = valEnd + 1
116
+
117
+ // 解析值
118
+ let value = raw
119
+ if (raw.startsWith("{") || raw.startsWith("[")) {
120
+ try { value = JSON.parse(raw) } catch { /* 保持字符串 */ }
121
+ }
122
+
123
+ // 解析 key@topic
124
+ const topicMatch = rawKey.match(/^(\w+)@(\w+)$/)
125
+ if (topicMatch) {
126
+ this.publish(taskId, topicMatch[1], value, topicMatch[2])
127
+ } else {
128
+ this.publish(taskId, rawKey, value)
129
+ }
130
+ }
131
+ }
132
+
133
+ clear() {
134
+ this._messages = []
135
+ this._shared = {}
136
+ this._lastFlushedIdx = 0
137
+ }
138
+ }