@shareai-lab/kode 1.1.14 → 1.1.16-dev.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 (289) hide show
  1. package/cli.js +77 -82
  2. package/dist/entrypoints/cli.js +59 -38
  3. package/dist/entrypoints/cli.js.map +3 -3
  4. package/dist/index.js +5 -26
  5. package/dist/package.json +4 -1
  6. package/package.json +11 -104
  7. package/dist/test/testAdapters.js +0 -88
  8. package/dist/test/testAdapters.js.map +0 -1
  9. package/src/ProjectOnboarding.tsx +0 -198
  10. package/src/Tool.ts +0 -83
  11. package/src/commands/agents.tsx +0 -3416
  12. package/src/commands/approvedTools.ts +0 -53
  13. package/src/commands/bug.tsx +0 -20
  14. package/src/commands/clear.ts +0 -43
  15. package/src/commands/compact.ts +0 -120
  16. package/src/commands/config.tsx +0 -19
  17. package/src/commands/cost.ts +0 -18
  18. package/src/commands/ctx_viz.ts +0 -209
  19. package/src/commands/doctor.ts +0 -24
  20. package/src/commands/help.tsx +0 -19
  21. package/src/commands/init.ts +0 -37
  22. package/src/commands/listen.ts +0 -42
  23. package/src/commands/login.tsx +0 -51
  24. package/src/commands/logout.tsx +0 -40
  25. package/src/commands/mcp.ts +0 -41
  26. package/src/commands/model.tsx +0 -40
  27. package/src/commands/modelstatus.tsx +0 -20
  28. package/src/commands/onboarding.tsx +0 -34
  29. package/src/commands/pr_comments.ts +0 -59
  30. package/src/commands/refreshCommands.ts +0 -54
  31. package/src/commands/release-notes.ts +0 -34
  32. package/src/commands/resume.tsx +0 -31
  33. package/src/commands/review.ts +0 -49
  34. package/src/commands/terminalSetup.ts +0 -221
  35. package/src/commands.ts +0 -139
  36. package/src/components/ApproveApiKey.tsx +0 -93
  37. package/src/components/AsciiLogo.tsx +0 -13
  38. package/src/components/AutoUpdater.tsx +0 -148
  39. package/src/components/Bug.tsx +0 -367
  40. package/src/components/Config.tsx +0 -293
  41. package/src/components/ConsoleOAuthFlow.tsx +0 -327
  42. package/src/components/Cost.tsx +0 -23
  43. package/src/components/CostThresholdDialog.tsx +0 -46
  44. package/src/components/CustomSelect/option-map.ts +0 -42
  45. package/src/components/CustomSelect/select-option.tsx +0 -78
  46. package/src/components/CustomSelect/select.tsx +0 -152
  47. package/src/components/CustomSelect/theme.ts +0 -45
  48. package/src/components/CustomSelect/use-select-state.ts +0 -414
  49. package/src/components/CustomSelect/use-select.ts +0 -35
  50. package/src/components/FallbackToolUseRejectedMessage.tsx +0 -15
  51. package/src/components/FileEditToolUpdatedMessage.tsx +0 -66
  52. package/src/components/Help.tsx +0 -215
  53. package/src/components/HighlightedCode.tsx +0 -33
  54. package/src/components/InvalidConfigDialog.tsx +0 -113
  55. package/src/components/Link.tsx +0 -32
  56. package/src/components/LogSelector.tsx +0 -86
  57. package/src/components/Logo.tsx +0 -170
  58. package/src/components/MCPServerApprovalDialog.tsx +0 -100
  59. package/src/components/MCPServerDialogCopy.tsx +0 -25
  60. package/src/components/MCPServerMultiselectDialog.tsx +0 -109
  61. package/src/components/Message.tsx +0 -221
  62. package/src/components/MessageResponse.tsx +0 -15
  63. package/src/components/MessageSelector.tsx +0 -211
  64. package/src/components/ModeIndicator.tsx +0 -88
  65. package/src/components/ModelConfig.tsx +0 -301
  66. package/src/components/ModelListManager.tsx +0 -227
  67. package/src/components/ModelSelector.tsx +0 -3387
  68. package/src/components/ModelStatusDisplay.tsx +0 -230
  69. package/src/components/Onboarding.tsx +0 -274
  70. package/src/components/PressEnterToContinue.tsx +0 -11
  71. package/src/components/PromptInput.tsx +0 -760
  72. package/src/components/SentryErrorBoundary.ts +0 -39
  73. package/src/components/Spinner.tsx +0 -129
  74. package/src/components/StickerRequestForm.tsx +0 -16
  75. package/src/components/StructuredDiff.tsx +0 -191
  76. package/src/components/TextInput.tsx +0 -259
  77. package/src/components/TodoItem.tsx +0 -47
  78. package/src/components/TokenWarning.tsx +0 -31
  79. package/src/components/ToolUseLoader.tsx +0 -40
  80. package/src/components/TrustDialog.tsx +0 -106
  81. package/src/components/binary-feedback/BinaryFeedback.tsx +0 -63
  82. package/src/components/binary-feedback/BinaryFeedbackOption.tsx +0 -111
  83. package/src/components/binary-feedback/BinaryFeedbackView.tsx +0 -172
  84. package/src/components/binary-feedback/utils.ts +0 -220
  85. package/src/components/messages/AssistantBashOutputMessage.tsx +0 -22
  86. package/src/components/messages/AssistantLocalCommandOutputMessage.tsx +0 -49
  87. package/src/components/messages/AssistantRedactedThinkingMessage.tsx +0 -19
  88. package/src/components/messages/AssistantTextMessage.tsx +0 -144
  89. package/src/components/messages/AssistantThinkingMessage.tsx +0 -40
  90. package/src/components/messages/AssistantToolUseMessage.tsx +0 -132
  91. package/src/components/messages/TaskProgressMessage.tsx +0 -32
  92. package/src/components/messages/TaskToolMessage.tsx +0 -58
  93. package/src/components/messages/UserBashInputMessage.tsx +0 -28
  94. package/src/components/messages/UserCommandMessage.tsx +0 -30
  95. package/src/components/messages/UserKodingInputMessage.tsx +0 -28
  96. package/src/components/messages/UserPromptMessage.tsx +0 -35
  97. package/src/components/messages/UserTextMessage.tsx +0 -39
  98. package/src/components/messages/UserToolResultMessage/UserToolCanceledMessage.tsx +0 -12
  99. package/src/components/messages/UserToolResultMessage/UserToolErrorMessage.tsx +0 -36
  100. package/src/components/messages/UserToolResultMessage/UserToolRejectMessage.tsx +0 -31
  101. package/src/components/messages/UserToolResultMessage/UserToolResultMessage.tsx +0 -57
  102. package/src/components/messages/UserToolResultMessage/UserToolSuccessMessage.tsx +0 -35
  103. package/src/components/messages/UserToolResultMessage/utils.tsx +0 -56
  104. package/src/components/permissions/BashPermissionRequest/BashPermissionRequest.tsx +0 -121
  105. package/src/components/permissions/FallbackPermissionRequest.tsx +0 -153
  106. package/src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx +0 -182
  107. package/src/components/permissions/FileEditPermissionRequest/FileEditToolDiff.tsx +0 -77
  108. package/src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.tsx +0 -164
  109. package/src/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.tsx +0 -83
  110. package/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx +0 -240
  111. package/src/components/permissions/PermissionRequest.tsx +0 -101
  112. package/src/components/permissions/PermissionRequestTitle.tsx +0 -69
  113. package/src/components/permissions/hooks.ts +0 -44
  114. package/src/components/permissions/toolUseOptions.ts +0 -59
  115. package/src/components/permissions/utils.ts +0 -23
  116. package/src/constants/betas.ts +0 -5
  117. package/src/constants/claude-asterisk-ascii-art.tsx +0 -238
  118. package/src/constants/figures.ts +0 -4
  119. package/src/constants/keys.ts +0 -3
  120. package/src/constants/macros.ts +0 -11
  121. package/src/constants/modelCapabilities.ts +0 -179
  122. package/src/constants/models.ts +0 -1025
  123. package/src/constants/oauth.ts +0 -18
  124. package/src/constants/product.ts +0 -17
  125. package/src/constants/prompts.ts +0 -168
  126. package/src/constants/releaseNotes.ts +0 -7
  127. package/src/context/PermissionContext.tsx +0 -149
  128. package/src/context.ts +0 -278
  129. package/src/cost-tracker.ts +0 -84
  130. package/src/entrypoints/cli.tsx +0 -1561
  131. package/src/entrypoints/mcp.ts +0 -175
  132. package/src/history.ts +0 -25
  133. package/src/hooks/useApiKeyVerification.ts +0 -59
  134. package/src/hooks/useArrowKeyHistory.ts +0 -55
  135. package/src/hooks/useCanUseTool.ts +0 -138
  136. package/src/hooks/useCancelRequest.ts +0 -39
  137. package/src/hooks/useDoublePress.ts +0 -41
  138. package/src/hooks/useExitOnCtrlCD.ts +0 -31
  139. package/src/hooks/useInterval.ts +0 -25
  140. package/src/hooks/useLogMessages.ts +0 -16
  141. package/src/hooks/useLogStartupTime.ts +0 -12
  142. package/src/hooks/useNotifyAfterTimeout.ts +0 -65
  143. package/src/hooks/usePermissionRequestLogging.ts +0 -44
  144. package/src/hooks/useTerminalSize.ts +0 -49
  145. package/src/hooks/useTextInput.ts +0 -317
  146. package/src/hooks/useUnifiedCompletion.ts +0 -1405
  147. package/src/index.ts +0 -34
  148. package/src/messages.ts +0 -38
  149. package/src/permissions.ts +0 -268
  150. package/src/query.ts +0 -720
  151. package/src/screens/ConfigureNpmPrefix.tsx +0 -197
  152. package/src/screens/Doctor.tsx +0 -219
  153. package/src/screens/LogList.tsx +0 -68
  154. package/src/screens/REPL.tsx +0 -813
  155. package/src/screens/ResumeConversation.tsx +0 -68
  156. package/src/services/adapters/base.ts +0 -38
  157. package/src/services/adapters/chatCompletions.ts +0 -90
  158. package/src/services/adapters/responsesAPI.ts +0 -170
  159. package/src/services/browserMocks.ts +0 -66
  160. package/src/services/claude.ts +0 -2197
  161. package/src/services/customCommands.ts +0 -704
  162. package/src/services/fileFreshness.ts +0 -377
  163. package/src/services/gpt5ConnectionTest.ts +0 -340
  164. package/src/services/mcpClient.ts +0 -564
  165. package/src/services/mcpServerApproval.tsx +0 -50
  166. package/src/services/mentionProcessor.ts +0 -273
  167. package/src/services/modelAdapterFactory.ts +0 -69
  168. package/src/services/notifier.ts +0 -40
  169. package/src/services/oauth.ts +0 -357
  170. package/src/services/openai.ts +0 -1359
  171. package/src/services/responseStateManager.ts +0 -90
  172. package/src/services/sentry.ts +0 -3
  173. package/src/services/statsig.ts +0 -172
  174. package/src/services/statsigStorage.ts +0 -86
  175. package/src/services/systemReminder.ts +0 -507
  176. package/src/services/vcr.ts +0 -161
  177. package/src/test/testAdapters.ts +0 -96
  178. package/src/tools/ArchitectTool/ArchitectTool.tsx +0 -135
  179. package/src/tools/ArchitectTool/prompt.ts +0 -15
  180. package/src/tools/AskExpertModelTool/AskExpertModelTool.tsx +0 -576
  181. package/src/tools/BashTool/BashTool.tsx +0 -243
  182. package/src/tools/BashTool/BashToolResultMessage.tsx +0 -38
  183. package/src/tools/BashTool/OutputLine.tsx +0 -49
  184. package/src/tools/BashTool/prompt.ts +0 -174
  185. package/src/tools/BashTool/utils.ts +0 -56
  186. package/src/tools/FileEditTool/FileEditTool.tsx +0 -319
  187. package/src/tools/FileEditTool/prompt.ts +0 -51
  188. package/src/tools/FileEditTool/utils.ts +0 -58
  189. package/src/tools/FileReadTool/FileReadTool.tsx +0 -404
  190. package/src/tools/FileReadTool/prompt.ts +0 -7
  191. package/src/tools/FileWriteTool/FileWriteTool.tsx +0 -301
  192. package/src/tools/FileWriteTool/prompt.ts +0 -10
  193. package/src/tools/GlobTool/GlobTool.tsx +0 -119
  194. package/src/tools/GlobTool/prompt.ts +0 -8
  195. package/src/tools/GrepTool/GrepTool.tsx +0 -147
  196. package/src/tools/GrepTool/prompt.ts +0 -11
  197. package/src/tools/MCPTool/MCPTool.tsx +0 -107
  198. package/src/tools/MCPTool/prompt.ts +0 -3
  199. package/src/tools/MemoryReadTool/MemoryReadTool.tsx +0 -127
  200. package/src/tools/MemoryReadTool/prompt.ts +0 -3
  201. package/src/tools/MemoryWriteTool/MemoryWriteTool.tsx +0 -89
  202. package/src/tools/MemoryWriteTool/prompt.ts +0 -3
  203. package/src/tools/MultiEditTool/MultiEditTool.tsx +0 -388
  204. package/src/tools/MultiEditTool/prompt.ts +0 -45
  205. package/src/tools/NotebookEditTool/NotebookEditTool.tsx +0 -298
  206. package/src/tools/NotebookEditTool/prompt.ts +0 -3
  207. package/src/tools/NotebookReadTool/NotebookReadTool.tsx +0 -258
  208. package/src/tools/NotebookReadTool/prompt.ts +0 -3
  209. package/src/tools/StickerRequestTool/StickerRequestTool.tsx +0 -107
  210. package/src/tools/StickerRequestTool/prompt.ts +0 -19
  211. package/src/tools/TaskTool/TaskTool.tsx +0 -438
  212. package/src/tools/TaskTool/constants.ts +0 -1
  213. package/src/tools/TaskTool/prompt.ts +0 -92
  214. package/src/tools/ThinkTool/ThinkTool.tsx +0 -54
  215. package/src/tools/ThinkTool/prompt.ts +0 -12
  216. package/src/tools/TodoWriteTool/TodoWriteTool.tsx +0 -313
  217. package/src/tools/TodoWriteTool/prompt.ts +0 -63
  218. package/src/tools/URLFetcherTool/URLFetcherTool.tsx +0 -178
  219. package/src/tools/URLFetcherTool/cache.ts +0 -55
  220. package/src/tools/URLFetcherTool/htmlToMarkdown.ts +0 -55
  221. package/src/tools/URLFetcherTool/prompt.ts +0 -17
  222. package/src/tools/WebSearchTool/WebSearchTool.tsx +0 -103
  223. package/src/tools/WebSearchTool/prompt.ts +0 -13
  224. package/src/tools/WebSearchTool/searchProviders.ts +0 -66
  225. package/src/tools/lsTool/lsTool.tsx +0 -272
  226. package/src/tools/lsTool/prompt.ts +0 -2
  227. package/src/tools.ts +0 -67
  228. package/src/types/PermissionMode.ts +0 -120
  229. package/src/types/RequestContext.ts +0 -72
  230. package/src/types/common.d.ts +0 -2
  231. package/src/types/conversation.ts +0 -51
  232. package/src/types/logs.ts +0 -58
  233. package/src/types/modelCapabilities.ts +0 -64
  234. package/src/types/notebook.ts +0 -87
  235. package/src/utils/Cursor.ts +0 -436
  236. package/src/utils/PersistentShell.ts +0 -552
  237. package/src/utils/advancedFuzzyMatcher.ts +0 -290
  238. package/src/utils/agentLoader.ts +0 -278
  239. package/src/utils/agentStorage.ts +0 -97
  240. package/src/utils/array.ts +0 -3
  241. package/src/utils/ask.tsx +0 -99
  242. package/src/utils/auth.ts +0 -13
  243. package/src/utils/autoCompactCore.ts +0 -223
  244. package/src/utils/autoUpdater.ts +0 -458
  245. package/src/utils/betas.ts +0 -20
  246. package/src/utils/browser.ts +0 -14
  247. package/src/utils/cleanup.ts +0 -72
  248. package/src/utils/commands.ts +0 -261
  249. package/src/utils/commonUnixCommands.ts +0 -161
  250. package/src/utils/config.ts +0 -945
  251. package/src/utils/conversationRecovery.ts +0 -55
  252. package/src/utils/debugLogger.ts +0 -1235
  253. package/src/utils/diff.ts +0 -42
  254. package/src/utils/env.ts +0 -57
  255. package/src/utils/errors.ts +0 -21
  256. package/src/utils/exampleCommands.ts +0 -109
  257. package/src/utils/execFileNoThrow.ts +0 -51
  258. package/src/utils/expertChatStorage.ts +0 -136
  259. package/src/utils/file.ts +0 -405
  260. package/src/utils/fileRecoveryCore.ts +0 -71
  261. package/src/utils/format.tsx +0 -44
  262. package/src/utils/fuzzyMatcher.ts +0 -328
  263. package/src/utils/generators.ts +0 -62
  264. package/src/utils/git.ts +0 -92
  265. package/src/utils/globalLogger.ts +0 -77
  266. package/src/utils/http.ts +0 -10
  267. package/src/utils/imagePaste.ts +0 -38
  268. package/src/utils/json.ts +0 -13
  269. package/src/utils/log.ts +0 -382
  270. package/src/utils/markdown.ts +0 -213
  271. package/src/utils/messageContextManager.ts +0 -294
  272. package/src/utils/messages.tsx +0 -945
  273. package/src/utils/model.ts +0 -914
  274. package/src/utils/permissions/filesystem.ts +0 -127
  275. package/src/utils/responseState.ts +0 -23
  276. package/src/utils/ripgrep.ts +0 -167
  277. package/src/utils/secureFile.ts +0 -564
  278. package/src/utils/sessionState.ts +0 -49
  279. package/src/utils/state.ts +0 -25
  280. package/src/utils/style.ts +0 -29
  281. package/src/utils/terminal.ts +0 -50
  282. package/src/utils/theme.ts +0 -127
  283. package/src/utils/thinking.ts +0 -144
  284. package/src/utils/todoStorage.ts +0 -431
  285. package/src/utils/tokens.ts +0 -43
  286. package/src/utils/toolExecutionController.ts +0 -163
  287. package/src/utils/unaryLogging.ts +0 -26
  288. package/src/utils/user.ts +0 -37
  289. package/src/utils/validate.ts +0 -165
@@ -1,290 +0,0 @@
1
- /**
2
- * Advanced Fuzzy Matching Algorithm
3
- *
4
- * Inspired by:
5
- * - Chinese Pinyin input methods (Sogou, Baidu)
6
- * - IDE intelligent completion (VSCode, IntelliJ)
7
- * - Terminal fuzzy finders (fzf, peco)
8
- *
9
- * Key features:
10
- * - Hyphen-aware matching (dao → dao-qi-harmony)
11
- * - Numeric suffix matching (py3 → python3)
12
- * - Abbreviation matching (dq → dao-qi)
13
- * - Subsequence matching
14
- * - Word boundary bonus
15
- */
16
-
17
- export interface MatchResult {
18
- score: number
19
- matched: boolean
20
- algorithm: string
21
- }
22
-
23
- export class AdvancedFuzzyMatcher {
24
- /**
25
- * Main matching function - combines multiple algorithms
26
- */
27
- match(candidate: string, query: string): MatchResult {
28
- // Normalize inputs
29
- const text = candidate.toLowerCase()
30
- const pattern = query.toLowerCase()
31
-
32
- // Quick exact match - give HUGE score for exact matches
33
- if (text === pattern) {
34
- return { score: 10000, matched: true, algorithm: 'exact' }
35
- }
36
-
37
- // Try all algorithms and combine scores
38
- const algorithms = [
39
- this.exactPrefixMatch(text, pattern),
40
- this.hyphenAwareMatch(text, pattern),
41
- this.wordBoundaryMatch(text, pattern),
42
- this.abbreviationMatch(text, pattern),
43
- this.numericSuffixMatch(text, pattern),
44
- this.subsequenceMatch(text, pattern),
45
- this.fuzzySegmentMatch(text, pattern),
46
- ]
47
-
48
- // Get best score
49
- let bestScore = 0
50
- let bestAlgorithm = 'none'
51
-
52
- for (const result of algorithms) {
53
- if (result.score > bestScore) {
54
- bestScore = result.score
55
- bestAlgorithm = result.algorithm
56
- }
57
- }
58
-
59
- return {
60
- score: bestScore,
61
- matched: bestScore > 10,
62
- algorithm: bestAlgorithm
63
- }
64
- }
65
-
66
- /**
67
- * Exact prefix matching
68
- */
69
- private exactPrefixMatch(text: string, pattern: string): { score: number; algorithm: string } {
70
- if (text.startsWith(pattern)) {
71
- const coverage = pattern.length / text.length
72
- // Higher base score for prefix matches to prioritize them
73
- return { score: 1000 + coverage * 500, algorithm: 'prefix' }
74
- }
75
- return { score: 0, algorithm: 'prefix' }
76
- }
77
-
78
- /**
79
- * Hyphen-aware matching (dao → dao-qi-harmony-designer)
80
- * Treats hyphens as optional word boundaries
81
- */
82
- private hyphenAwareMatch(text: string, pattern: string): { score: number; algorithm: string } {
83
- // Split by hyphens and try to match
84
- const words = text.split('-')
85
-
86
- // Check if pattern matches the beginning of hyphenated words
87
- if (words[0].startsWith(pattern)) {
88
- const coverage = pattern.length / words[0].length
89
- return { score: 300 + coverage * 100, algorithm: 'hyphen-prefix' }
90
- }
91
-
92
- // Check if pattern matches concatenated words (ignoring hyphens)
93
- const concatenated = words.join('')
94
- if (concatenated.startsWith(pattern)) {
95
- const coverage = pattern.length / concatenated.length
96
- return { score: 250 + coverage * 100, algorithm: 'hyphen-concat' }
97
- }
98
-
99
- // Check if pattern matches any word start
100
- for (let i = 0; i < words.length; i++) {
101
- if (words[i].startsWith(pattern)) {
102
- return { score: 200 - i * 10, algorithm: 'hyphen-word' }
103
- }
104
- }
105
-
106
- return { score: 0, algorithm: 'hyphen' }
107
- }
108
-
109
- /**
110
- * Word boundary matching (dq → dao-qi)
111
- * Matches characters at word boundaries
112
- */
113
- private wordBoundaryMatch(text: string, pattern: string): { score: number; algorithm: string } {
114
- const words = text.split(/[-_\s]+/)
115
- let patternIdx = 0
116
- let score = 0
117
- let matched = false
118
-
119
- for (const word of words) {
120
- if (patternIdx >= pattern.length) break
121
-
122
- if (word[0] === pattern[patternIdx]) {
123
- score += 50 // Bonus for word boundary match
124
- patternIdx++
125
- matched = true
126
-
127
- // Try to match more characters in this word
128
- for (let i = 1; i < word.length && patternIdx < pattern.length; i++) {
129
- if (word[i] === pattern[patternIdx]) {
130
- score += 20
131
- patternIdx++
132
- }
133
- }
134
- }
135
- }
136
-
137
- if (matched && patternIdx === pattern.length) {
138
- return { score, algorithm: 'word-boundary' }
139
- }
140
-
141
- return { score: 0, algorithm: 'word-boundary' }
142
- }
143
-
144
- /**
145
- * Abbreviation matching (nde → node, daoqi → dao-qi)
146
- */
147
- private abbreviationMatch(text: string, pattern: string): { score: number; algorithm: string } {
148
- let textIdx = 0
149
- let patternIdx = 0
150
- let score = 0
151
- let lastMatchIdx = -1
152
-
153
- while (patternIdx < pattern.length && textIdx < text.length) {
154
- if (text[textIdx] === pattern[patternIdx]) {
155
- // Calculate position score
156
- const gap = lastMatchIdx === -1 ? 0 : textIdx - lastMatchIdx - 1
157
-
158
- if (textIdx === 0) {
159
- score += 50 // First character match
160
- } else if (lastMatchIdx >= 0 && gap === 0) {
161
- score += 30 // Consecutive match
162
- } else if (text[textIdx - 1] === '-' || text[textIdx - 1] === '_') {
163
- score += 40 // Word boundary match
164
- } else {
165
- score += Math.max(5, 20 - gap * 2) // Distance penalty
166
- }
167
-
168
- lastMatchIdx = textIdx
169
- patternIdx++
170
- }
171
- textIdx++
172
- }
173
-
174
- if (patternIdx === pattern.length) {
175
- // Bonus for compact matches
176
- const spread = lastMatchIdx / pattern.length
177
- if (spread <= 3) score += 50
178
- else if (spread <= 5) score += 30
179
-
180
- return { score, algorithm: 'abbreviation' }
181
- }
182
-
183
- return { score: 0, algorithm: 'abbreviation' }
184
- }
185
-
186
- /**
187
- * Numeric suffix matching (py3 → python3, np18 → node18)
188
- */
189
- private numericSuffixMatch(text: string, pattern: string): { score: number; algorithm: string } {
190
- // Check if pattern has numeric suffix
191
- const patternMatch = pattern.match(/^(.+?)(\d+)$/)
192
- if (!patternMatch) return { score: 0, algorithm: 'numeric' }
193
-
194
- const [, prefix, suffix] = patternMatch
195
-
196
- // Check if text ends with same number
197
- if (!text.endsWith(suffix)) return { score: 0, algorithm: 'numeric' }
198
-
199
- // Check if prefix matches start of text
200
- const textWithoutSuffix = text.slice(0, -suffix.length)
201
- if (textWithoutSuffix.startsWith(prefix)) {
202
- const coverage = prefix.length / textWithoutSuffix.length
203
- return { score: 200 + coverage * 100, algorithm: 'numeric-suffix' }
204
- }
205
-
206
- // Check abbreviation match for prefix
207
- const abbrevResult = this.abbreviationMatch(textWithoutSuffix, prefix)
208
- if (abbrevResult.score > 0) {
209
- return { score: abbrevResult.score + 50, algorithm: 'numeric-abbrev' }
210
- }
211
-
212
- return { score: 0, algorithm: 'numeric' }
213
- }
214
-
215
- /**
216
- * Subsequence matching - characters appear in order
217
- */
218
- private subsequenceMatch(text: string, pattern: string): { score: number; algorithm: string } {
219
- let textIdx = 0
220
- let patternIdx = 0
221
- let score = 0
222
-
223
- while (patternIdx < pattern.length && textIdx < text.length) {
224
- if (text[textIdx] === pattern[patternIdx]) {
225
- score += 10
226
- patternIdx++
227
- }
228
- textIdx++
229
- }
230
-
231
- if (patternIdx === pattern.length) {
232
- // Penalty for spread
233
- const spread = textIdx / pattern.length
234
- score = Math.max(10, score - spread * 5)
235
- return { score, algorithm: 'subsequence' }
236
- }
237
-
238
- return { score: 0, algorithm: 'subsequence' }
239
- }
240
-
241
- /**
242
- * Fuzzy segment matching (dao → dao-qi-harmony)
243
- * Matches segments flexibly
244
- */
245
- private fuzzySegmentMatch(text: string, pattern: string): { score: number; algorithm: string } {
246
- // Remove hyphens and underscores for matching
247
- const cleanText = text.replace(/[-_]/g, '')
248
- const cleanPattern = pattern.replace(/[-_]/g, '')
249
-
250
- // Check if clean pattern is a prefix of clean text
251
- if (cleanText.startsWith(cleanPattern)) {
252
- const coverage = cleanPattern.length / cleanText.length
253
- return { score: 150 + coverage * 100, algorithm: 'fuzzy-segment' }
254
- }
255
-
256
- // Check if pattern appears anywhere in clean text
257
- const index = cleanText.indexOf(cleanPattern)
258
- if (index !== -1) {
259
- const positionPenalty = index * 5
260
- return { score: Math.max(50, 100 - positionPenalty), algorithm: 'fuzzy-contains' }
261
- }
262
-
263
- return { score: 0, algorithm: 'fuzzy-segment' }
264
- }
265
- }
266
-
267
- // Export singleton instance and helper functions
268
- export const advancedMatcher = new AdvancedFuzzyMatcher()
269
-
270
- export function matchAdvanced(candidate: string, query: string): MatchResult {
271
- return advancedMatcher.match(candidate, query)
272
- }
273
-
274
- export function matchManyAdvanced(
275
- candidates: string[],
276
- query: string,
277
- minScore: number = 10
278
- ): Array<{ candidate: string; score: number; algorithm: string }> {
279
- return candidates
280
- .map(candidate => {
281
- const result = advancedMatcher.match(candidate, query)
282
- return {
283
- candidate,
284
- score: result.score,
285
- algorithm: result.algorithm
286
- }
287
- })
288
- .filter(item => item.score >= minScore)
289
- .sort((a, b) => b.score - a.score)
290
- }
@@ -1,278 +0,0 @@
1
- /**
2
- * Agent configuration loader
3
- * Loads agent configurations from markdown files with YAML frontmatter
4
- * Following Claude Code's agent system architecture
5
- */
6
-
7
- import { existsSync, readFileSync, readdirSync, statSync, watch, FSWatcher } from 'fs'
8
- import { join, resolve } from 'path'
9
- import { homedir } from 'os'
10
- import matter from 'gray-matter'
11
- import { getCwd } from './state'
12
- import { memoize } from 'lodash-es'
13
-
14
- // Track warned agents to avoid spam
15
- const warnedAgents = new Set<string>()
16
-
17
- export interface AgentConfig {
18
- agentType: string // Agent identifier (matches subagent_type)
19
- whenToUse: string // Description of when to use this agent
20
- tools: string[] | '*' // Tool permissions
21
- systemPrompt: string // System prompt content
22
- location: 'built-in' | 'user' | 'project'
23
- color?: string // Optional UI color
24
- model_name?: string // Optional model override
25
- }
26
-
27
- // Built-in general-purpose agent as fallback
28
- const BUILTIN_GENERAL_PURPOSE: AgentConfig = {
29
- agentType: 'general-purpose',
30
- whenToUse: 'General-purpose agent for researching complex questions, searching for code, and executing multi-step tasks',
31
- tools: '*',
32
- systemPrompt: `You are a general-purpose agent. Given the user's task, use the tools available to complete it efficiently and thoroughly.
33
-
34
- When to use your capabilities:
35
- - Searching for code, configurations, and patterns across large codebases
36
- - Analyzing multiple files to understand system architecture
37
- - Investigating complex questions that require exploring many files
38
- - Performing multi-step research tasks
39
-
40
- Guidelines:
41
- - For file searches: Use Grep or Glob when you need to search broadly. Use FileRead when you know the specific file path.
42
- - For analysis: Start broad and narrow down. Use multiple search strategies if the first doesn't yield results.
43
- - Be thorough: Check multiple locations, consider different naming conventions, look for related files.
44
- - Complete tasks directly using your capabilities.`,
45
- location: 'built-in'
46
- }
47
-
48
- /**
49
- * Parse tools field from frontmatter
50
- */
51
- function parseTools(tools: any): string[] | '*' {
52
- if (!tools) return '*'
53
- if (tools === '*') return '*'
54
- if (Array.isArray(tools)) {
55
- // Ensure all items are strings and filter out non-strings
56
- const filteredTools = tools.filter((t): t is string => typeof t === 'string')
57
- return filteredTools.length > 0 ? filteredTools : '*'
58
- }
59
- if (typeof tools === 'string') {
60
- return [tools]
61
- }
62
- return '*'
63
- }
64
-
65
- /**
66
- * Scan a directory for agent configuration files
67
- */
68
- async function scanAgentDirectory(dirPath: string, location: 'user' | 'project'): Promise<AgentConfig[]> {
69
- if (!existsSync(dirPath)) {
70
- return []
71
- }
72
-
73
- const agents: AgentConfig[] = []
74
-
75
- try {
76
- const files = readdirSync(dirPath)
77
-
78
- for (const file of files) {
79
- if (!file.endsWith('.md')) continue
80
-
81
- const filePath = join(dirPath, file)
82
- const stat = statSync(filePath)
83
-
84
- if (!stat.isFile()) continue
85
-
86
- try {
87
- const content = readFileSync(filePath, 'utf-8')
88
- const { data: frontmatter, content: body } = matter(content)
89
-
90
- // Validate required fields
91
- if (!frontmatter.name || !frontmatter.description) {
92
- console.warn(`Skipping ${filePath}: missing required fields (name, description)`)
93
- continue
94
- }
95
-
96
- // Silently ignore deprecated 'model' field - no warnings by default
97
- // Only warn if KODE_DEBUG_AGENTS environment variable is set
98
- if (frontmatter.model && !frontmatter.model_name && !warnedAgents.has(frontmatter.name) && process.env.KODE_DEBUG_AGENTS) {
99
- console.warn(`⚠️ Agent ${frontmatter.name}: 'model' field is deprecated and ignored. Use 'model_name' instead, or omit to use default 'task' model.`)
100
- warnedAgents.add(frontmatter.name)
101
- }
102
-
103
- // Build agent config
104
- const agent: AgentConfig = {
105
- agentType: frontmatter.name,
106
- whenToUse: frontmatter.description.replace(/\\n/g, '\n'),
107
- tools: parseTools(frontmatter.tools),
108
- systemPrompt: body.trim(),
109
- location,
110
- ...(frontmatter.color && { color: frontmatter.color }),
111
- // Only use model_name field, ignore deprecated 'model' field
112
- ...(frontmatter.model_name && { model_name: frontmatter.model_name })
113
- }
114
-
115
- agents.push(agent)
116
- } catch (error) {
117
- console.warn(`Failed to parse agent file ${filePath}:`, error)
118
- }
119
- }
120
- } catch (error) {
121
- console.warn(`Failed to scan directory ${dirPath}:`, error)
122
- }
123
-
124
- return agents
125
- }
126
-
127
- /**
128
- * Load all agent configurations
129
- */
130
- async function loadAllAgents(): Promise<{
131
- activeAgents: AgentConfig[]
132
- allAgents: AgentConfig[]
133
- }> {
134
- try {
135
- // Scan both .claude and .kode directories in parallel
136
- // Claude Code compatibility: support both ~/.claude/agents and ~/.kode/agents
137
- const userClaudeDir = join(homedir(), '.claude', 'agents')
138
- const userKodeDir = join(homedir(), '.kode', 'agents')
139
- const projectClaudeDir = join(getCwd(), '.claude', 'agents')
140
- const projectKodeDir = join(getCwd(), '.kode', 'agents')
141
-
142
- const [userClaudeAgents, userKodeAgents, projectClaudeAgents, projectKodeAgents] = await Promise.all([
143
- scanAgentDirectory(userClaudeDir, 'user'),
144
- scanAgentDirectory(userKodeDir, 'user'),
145
- scanAgentDirectory(projectClaudeDir, 'project'),
146
- scanAgentDirectory(projectKodeDir, 'project')
147
- ])
148
-
149
- // Built-in agents (currently just general-purpose)
150
- const builtinAgents = [BUILTIN_GENERAL_PURPOSE]
151
-
152
- // Apply priority override: built-in < .claude (user) < .kode (user) < .claude (project) < .kode (project)
153
- const agentMap = new Map<string, AgentConfig>()
154
-
155
- // Add in priority order (later entries override earlier ones)
156
- for (const agent of builtinAgents) {
157
- agentMap.set(agent.agentType, agent)
158
- }
159
- for (const agent of userClaudeAgents) {
160
- agentMap.set(agent.agentType, agent)
161
- }
162
- for (const agent of userKodeAgents) {
163
- agentMap.set(agent.agentType, agent)
164
- }
165
- for (const agent of projectClaudeAgents) {
166
- agentMap.set(agent.agentType, agent)
167
- }
168
- for (const agent of projectKodeAgents) {
169
- agentMap.set(agent.agentType, agent)
170
- }
171
-
172
- const activeAgents = Array.from(agentMap.values())
173
- const allAgents = [...builtinAgents, ...userClaudeAgents, ...userKodeAgents, ...projectClaudeAgents, ...projectKodeAgents]
174
-
175
- return { activeAgents, allAgents }
176
- } catch (error) {
177
- console.error('Failed to load agents, falling back to built-in:', error)
178
- return {
179
- activeAgents: [BUILTIN_GENERAL_PURPOSE],
180
- allAgents: [BUILTIN_GENERAL_PURPOSE]
181
- }
182
- }
183
- }
184
-
185
- // Memoized version for performance
186
- export const getActiveAgents = memoize(
187
- async (): Promise<AgentConfig[]> => {
188
- const { activeAgents } = await loadAllAgents()
189
- return activeAgents
190
- }
191
- )
192
-
193
- // Get all agents (both active and overridden)
194
- export const getAllAgents = memoize(
195
- async (): Promise<AgentConfig[]> => {
196
- const { allAgents } = await loadAllAgents()
197
- return allAgents
198
- }
199
- )
200
-
201
- // Clear cache when needed
202
- export function clearAgentCache() {
203
- getActiveAgents.cache?.clear?.()
204
- getAllAgents.cache?.clear?.()
205
- getAgentByType.cache?.clear?.()
206
- getAvailableAgentTypes.cache?.clear?.()
207
- }
208
-
209
- // Get a specific agent by type
210
- export const getAgentByType = memoize(
211
- async (agentType: string): Promise<AgentConfig | undefined> => {
212
- const agents = await getActiveAgents()
213
- return agents.find(agent => agent.agentType === agentType)
214
- }
215
- )
216
-
217
- // Get all available agent types for validation
218
- export const getAvailableAgentTypes = memoize(
219
- async (): Promise<string[]> => {
220
- const agents = await getActiveAgents()
221
- return agents.map(agent => agent.agentType)
222
- }
223
- )
224
-
225
- // File watcher for hot reload
226
- let watchers: FSWatcher[] = []
227
-
228
- /**
229
- * Start watching agent configuration directories for changes
230
- */
231
- export async function startAgentWatcher(onChange?: () => void): Promise<void> {
232
- await stopAgentWatcher() // Clean up any existing watchers
233
-
234
- // Watch both .claude and .kode directories
235
- const userClaudeDir = join(homedir(), '.claude', 'agents')
236
- const userKodeDir = join(homedir(), '.kode', 'agents')
237
- const projectClaudeDir = join(getCwd(), '.claude', 'agents')
238
- const projectKodeDir = join(getCwd(), '.kode', 'agents')
239
-
240
- const watchDirectory = (dirPath: string, label: string) => {
241
- if (existsSync(dirPath)) {
242
- const watcher = watch(dirPath, { recursive: false }, async (eventType, filename) => {
243
- if (filename && filename.endsWith('.md')) {
244
- console.log(`🔄 Agent configuration changed in ${label}: ${filename}`)
245
- clearAgentCache()
246
- // Also clear any other related caches
247
- getAllAgents.cache?.clear?.()
248
- onChange?.()
249
- }
250
- })
251
- watchers.push(watcher)
252
- }
253
- }
254
-
255
- // Watch all directories
256
- watchDirectory(userClaudeDir, 'user/.claude')
257
- watchDirectory(userKodeDir, 'user/.kode')
258
- watchDirectory(projectClaudeDir, 'project/.claude')
259
- watchDirectory(projectKodeDir, 'project/.kode')
260
- }
261
-
262
- /**
263
- * Stop watching agent configuration directories
264
- */
265
- export async function stopAgentWatcher(): Promise<void> {
266
- // FSWatcher.close() is synchronous and does not accept a callback on Node 18/20
267
- try {
268
- for (const watcher of watchers) {
269
- try {
270
- watcher.close()
271
- } catch (err) {
272
- console.error('Failed to close file watcher:', err)
273
- }
274
- }
275
- } finally {
276
- watchers = []
277
- }
278
- }
@@ -1,97 +0,0 @@
1
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs'
2
- import { join } from 'path'
3
- import { homedir } from 'os'
4
- import { randomUUID } from 'crypto'
5
-
6
- /**
7
- * Agent Storage Utilities
8
- * Provides file-based state isolation for different agents
9
- * Based on Kode's Agent ID architecture
10
- */
11
-
12
- /**
13
- * Get the kode config directory
14
- */
15
- function getConfigDirectory(): string {
16
- return process.env.KODE_CONFIG_DIR ?? process.env.ANYKODE_CONFIG_DIR ?? join(homedir(), '.kode')
17
- }
18
-
19
- /**
20
- * Get the current session ID
21
- */
22
- function getSessionId(): string {
23
- // This should be set when the session starts
24
- return process.env.ANYKODE_SESSION_ID ?? 'default-session'
25
- }
26
-
27
- /**
28
- * Generate agent-specific file path
29
- * Pattern: ${sessionId}-agent-${agentId}.json
30
- * Stored in ~/.kode/ directory
31
- */
32
- export function getAgentFilePath(agentId: string): string {
33
- const sessionId = getSessionId()
34
- const filename = `${sessionId}-agent-${agentId}.json`
35
- const configDir = getConfigDirectory()
36
-
37
- // Ensure kode config directory exists
38
- if (!existsSync(configDir)) {
39
- mkdirSync(configDir, { recursive: true })
40
- }
41
-
42
- return join(configDir, filename)
43
- }
44
-
45
- /**
46
- * Read agent-specific data from storage
47
- */
48
- export function readAgentData<T = any>(agentId: string): T | null {
49
- const filePath = getAgentFilePath(agentId)
50
-
51
- if (!existsSync(filePath)) {
52
- return null
53
- }
54
-
55
- try {
56
- const content = readFileSync(filePath, 'utf-8')
57
- return JSON.parse(content) as T
58
- } catch (error) {
59
- console.error(`Failed to read agent data for ${agentId}:`, error)
60
- return null
61
- }
62
- }
63
-
64
- /**
65
- * Write agent-specific data to storage
66
- */
67
- export function writeAgentData<T = any>(agentId: string, data: T): void {
68
- const filePath = getAgentFilePath(agentId)
69
-
70
- try {
71
- writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8')
72
- } catch (error) {
73
- console.error(`Failed to write agent data for ${agentId}:`, error)
74
- throw error
75
- }
76
- }
77
-
78
- /**
79
- * Get default agent ID if none is provided
80
- */
81
- export function getDefaultAgentId(): string {
82
- return 'default'
83
- }
84
-
85
- /**
86
- * Resolve agent ID from context
87
- */
88
- export function resolveAgentId(agentId?: string): string {
89
- return agentId || getDefaultAgentId()
90
- }
91
-
92
- /**
93
- * Generate a new unique Agent ID
94
- */
95
- export function generateAgentId(): string {
96
- return randomUUID()
97
- }
@@ -1,3 +0,0 @@
1
- export function intersperse<A>(as: A[], separator: (index: number) => A): A[] {
2
- return as.flatMap((a, i) => (i ? [separator(i), a] : [a]))
3
- }