@shareai-lab/kode 1.0.70 → 1.0.73

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 (278) hide show
  1. package/README.md +342 -75
  2. package/README.zh-CN.md +292 -0
  3. package/cli.js +62 -0
  4. package/package.json +49 -25
  5. package/scripts/postinstall.js +56 -0
  6. package/src/ProjectOnboarding.tsx +198 -0
  7. package/src/Tool.ts +82 -0
  8. package/src/commands/agents.tsx +3401 -0
  9. package/src/commands/approvedTools.ts +53 -0
  10. package/src/commands/bug.tsx +20 -0
  11. package/src/commands/clear.ts +43 -0
  12. package/src/commands/compact.ts +120 -0
  13. package/src/commands/config.tsx +19 -0
  14. package/src/commands/cost.ts +18 -0
  15. package/src/commands/ctx_viz.ts +209 -0
  16. package/src/commands/doctor.ts +24 -0
  17. package/src/commands/help.tsx +19 -0
  18. package/src/commands/init.ts +37 -0
  19. package/src/commands/listen.ts +42 -0
  20. package/src/commands/login.tsx +51 -0
  21. package/src/commands/logout.tsx +40 -0
  22. package/src/commands/mcp.ts +41 -0
  23. package/src/commands/model.tsx +40 -0
  24. package/src/commands/modelstatus.tsx +20 -0
  25. package/src/commands/onboarding.tsx +34 -0
  26. package/src/commands/pr_comments.ts +59 -0
  27. package/src/commands/refreshCommands.ts +54 -0
  28. package/src/commands/release-notes.ts +34 -0
  29. package/src/commands/resume.tsx +31 -0
  30. package/src/commands/review.ts +49 -0
  31. package/src/commands/terminalSetup.ts +221 -0
  32. package/src/commands.ts +139 -0
  33. package/src/components/ApproveApiKey.tsx +93 -0
  34. package/src/components/AsciiLogo.tsx +13 -0
  35. package/src/components/AutoUpdater.tsx +148 -0
  36. package/src/components/Bug.tsx +367 -0
  37. package/src/components/Config.tsx +293 -0
  38. package/src/components/ConsoleOAuthFlow.tsx +327 -0
  39. package/src/components/Cost.tsx +23 -0
  40. package/src/components/CostThresholdDialog.tsx +46 -0
  41. package/src/components/CustomSelect/option-map.ts +42 -0
  42. package/src/components/CustomSelect/select-option.tsx +78 -0
  43. package/src/components/CustomSelect/select.tsx +152 -0
  44. package/src/components/CustomSelect/theme.ts +45 -0
  45. package/src/components/CustomSelect/use-select-state.ts +414 -0
  46. package/src/components/CustomSelect/use-select.ts +35 -0
  47. package/src/components/FallbackToolUseRejectedMessage.tsx +15 -0
  48. package/src/components/FileEditToolUpdatedMessage.tsx +66 -0
  49. package/src/components/Help.tsx +215 -0
  50. package/src/components/HighlightedCode.tsx +33 -0
  51. package/src/components/InvalidConfigDialog.tsx +113 -0
  52. package/src/components/Link.tsx +32 -0
  53. package/src/components/LogSelector.tsx +86 -0
  54. package/src/components/Logo.tsx +145 -0
  55. package/src/components/MCPServerApprovalDialog.tsx +100 -0
  56. package/src/components/MCPServerDialogCopy.tsx +25 -0
  57. package/src/components/MCPServerMultiselectDialog.tsx +109 -0
  58. package/src/components/Message.tsx +221 -0
  59. package/src/components/MessageResponse.tsx +15 -0
  60. package/src/components/MessageSelector.tsx +211 -0
  61. package/src/components/ModeIndicator.tsx +88 -0
  62. package/src/components/ModelConfig.tsx +301 -0
  63. package/src/components/ModelListManager.tsx +227 -0
  64. package/src/components/ModelSelector.tsx +3386 -0
  65. package/src/components/ModelStatusDisplay.tsx +230 -0
  66. package/src/components/Onboarding.tsx +274 -0
  67. package/src/components/PressEnterToContinue.tsx +11 -0
  68. package/src/components/PromptInput.tsx +740 -0
  69. package/src/components/SentryErrorBoundary.ts +33 -0
  70. package/src/components/Spinner.tsx +129 -0
  71. package/src/components/StickerRequestForm.tsx +16 -0
  72. package/src/components/StructuredDiff.tsx +191 -0
  73. package/src/components/TextInput.tsx +259 -0
  74. package/src/components/TodoItem.tsx +11 -0
  75. package/src/components/TokenWarning.tsx +31 -0
  76. package/src/components/ToolUseLoader.tsx +40 -0
  77. package/src/components/TrustDialog.tsx +106 -0
  78. package/src/components/binary-feedback/BinaryFeedback.tsx +63 -0
  79. package/src/components/binary-feedback/BinaryFeedbackOption.tsx +111 -0
  80. package/src/components/binary-feedback/BinaryFeedbackView.tsx +172 -0
  81. package/src/components/binary-feedback/utils.ts +220 -0
  82. package/src/components/messages/AssistantBashOutputMessage.tsx +22 -0
  83. package/src/components/messages/AssistantLocalCommandOutputMessage.tsx +49 -0
  84. package/src/components/messages/AssistantRedactedThinkingMessage.tsx +19 -0
  85. package/src/components/messages/AssistantTextMessage.tsx +144 -0
  86. package/src/components/messages/AssistantThinkingMessage.tsx +40 -0
  87. package/src/components/messages/AssistantToolUseMessage.tsx +133 -0
  88. package/src/components/messages/TaskProgressMessage.tsx +32 -0
  89. package/src/components/messages/TaskToolMessage.tsx +58 -0
  90. package/src/components/messages/UserBashInputMessage.tsx +28 -0
  91. package/src/components/messages/UserCommandMessage.tsx +30 -0
  92. package/src/components/messages/UserKodingInputMessage.tsx +28 -0
  93. package/src/components/messages/UserPromptMessage.tsx +35 -0
  94. package/src/components/messages/UserTextMessage.tsx +39 -0
  95. package/src/components/messages/UserToolResultMessage/UserToolCanceledMessage.tsx +12 -0
  96. package/src/components/messages/UserToolResultMessage/UserToolErrorMessage.tsx +36 -0
  97. package/src/components/messages/UserToolResultMessage/UserToolRejectMessage.tsx +31 -0
  98. package/src/components/messages/UserToolResultMessage/UserToolResultMessage.tsx +57 -0
  99. package/src/components/messages/UserToolResultMessage/UserToolSuccessMessage.tsx +35 -0
  100. package/src/components/messages/UserToolResultMessage/utils.tsx +56 -0
  101. package/src/components/permissions/BashPermissionRequest/BashPermissionRequest.tsx +121 -0
  102. package/src/components/permissions/FallbackPermissionRequest.tsx +153 -0
  103. package/src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx +182 -0
  104. package/src/components/permissions/FileEditPermissionRequest/FileEditToolDiff.tsx +77 -0
  105. package/src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.tsx +164 -0
  106. package/src/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.tsx +83 -0
  107. package/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx +240 -0
  108. package/src/components/permissions/PermissionRequest.tsx +101 -0
  109. package/src/components/permissions/PermissionRequestTitle.tsx +69 -0
  110. package/src/components/permissions/hooks.ts +44 -0
  111. package/src/components/permissions/toolUseOptions.ts +59 -0
  112. package/src/components/permissions/utils.ts +23 -0
  113. package/src/constants/betas.ts +5 -0
  114. package/src/constants/claude-asterisk-ascii-art.tsx +238 -0
  115. package/src/constants/figures.ts +4 -0
  116. package/src/constants/keys.ts +3 -0
  117. package/src/constants/macros.ts +8 -0
  118. package/src/constants/modelCapabilities.ts +179 -0
  119. package/src/constants/models.ts +1025 -0
  120. package/src/constants/oauth.ts +18 -0
  121. package/src/constants/product.ts +17 -0
  122. package/src/constants/prompts.ts +177 -0
  123. package/src/constants/releaseNotes.ts +7 -0
  124. package/src/context/PermissionContext.tsx +149 -0
  125. package/src/context.ts +278 -0
  126. package/src/cost-tracker.ts +84 -0
  127. package/src/entrypoints/cli.tsx +1518 -0
  128. package/src/entrypoints/mcp.ts +176 -0
  129. package/src/history.ts +25 -0
  130. package/src/hooks/useApiKeyVerification.ts +59 -0
  131. package/src/hooks/useArrowKeyHistory.ts +55 -0
  132. package/src/hooks/useCanUseTool.ts +138 -0
  133. package/src/hooks/useCancelRequest.ts +39 -0
  134. package/src/hooks/useDoublePress.ts +42 -0
  135. package/src/hooks/useExitOnCtrlCD.ts +31 -0
  136. package/src/hooks/useInterval.ts +25 -0
  137. package/src/hooks/useLogMessages.ts +16 -0
  138. package/src/hooks/useLogStartupTime.ts +12 -0
  139. package/src/hooks/useNotifyAfterTimeout.ts +65 -0
  140. package/src/hooks/usePermissionRequestLogging.ts +44 -0
  141. package/src/hooks/useTerminalSize.ts +49 -0
  142. package/src/hooks/useTextInput.ts +318 -0
  143. package/src/hooks/useUnifiedCompletion.ts +1404 -0
  144. package/src/messages.ts +38 -0
  145. package/src/permissions.ts +268 -0
  146. package/src/query.ts +707 -0
  147. package/src/screens/ConfigureNpmPrefix.tsx +197 -0
  148. package/src/screens/Doctor.tsx +219 -0
  149. package/src/screens/LogList.tsx +68 -0
  150. package/src/screens/REPL.tsx +798 -0
  151. package/src/screens/ResumeConversation.tsx +68 -0
  152. package/src/services/adapters/base.ts +38 -0
  153. package/src/services/adapters/chatCompletions.ts +90 -0
  154. package/src/services/adapters/responsesAPI.ts +170 -0
  155. package/src/services/browserMocks.ts +66 -0
  156. package/src/services/claude.ts +2083 -0
  157. package/src/services/customCommands.ts +704 -0
  158. package/src/services/fileFreshness.ts +377 -0
  159. package/src/services/gpt5ConnectionTest.ts +340 -0
  160. package/src/services/mcpClient.ts +564 -0
  161. package/src/services/mcpServerApproval.tsx +50 -0
  162. package/src/services/mentionProcessor.ts +273 -0
  163. package/src/services/modelAdapterFactory.ts +69 -0
  164. package/src/services/notifier.ts +40 -0
  165. package/src/services/oauth.ts +357 -0
  166. package/src/services/openai.ts +1305 -0
  167. package/src/services/responseStateManager.ts +90 -0
  168. package/src/services/sentry.ts +3 -0
  169. package/src/services/statsig.ts +171 -0
  170. package/src/services/statsigStorage.ts +86 -0
  171. package/src/services/systemReminder.ts +507 -0
  172. package/src/services/vcr.ts +161 -0
  173. package/src/test/testAdapters.ts +96 -0
  174. package/src/tools/ArchitectTool/ArchitectTool.tsx +122 -0
  175. package/src/tools/ArchitectTool/prompt.ts +15 -0
  176. package/src/tools/AskExpertModelTool/AskExpertModelTool.tsx +569 -0
  177. package/src/tools/BashTool/BashTool.tsx +243 -0
  178. package/src/tools/BashTool/BashToolResultMessage.tsx +38 -0
  179. package/src/tools/BashTool/OutputLine.tsx +49 -0
  180. package/src/tools/BashTool/prompt.ts +174 -0
  181. package/src/tools/BashTool/utils.ts +56 -0
  182. package/src/tools/FileEditTool/FileEditTool.tsx +315 -0
  183. package/src/tools/FileEditTool/prompt.ts +51 -0
  184. package/src/tools/FileEditTool/utils.ts +58 -0
  185. package/src/tools/FileReadTool/FileReadTool.tsx +404 -0
  186. package/src/tools/FileReadTool/prompt.ts +7 -0
  187. package/src/tools/FileWriteTool/FileWriteTool.tsx +297 -0
  188. package/src/tools/FileWriteTool/prompt.ts +10 -0
  189. package/src/tools/GlobTool/GlobTool.tsx +119 -0
  190. package/src/tools/GlobTool/prompt.ts +8 -0
  191. package/src/tools/GrepTool/GrepTool.tsx +147 -0
  192. package/src/tools/GrepTool/prompt.ts +11 -0
  193. package/src/tools/MCPTool/MCPTool.tsx +107 -0
  194. package/src/tools/MCPTool/prompt.ts +3 -0
  195. package/src/tools/MemoryReadTool/MemoryReadTool.tsx +127 -0
  196. package/src/tools/MemoryReadTool/prompt.ts +3 -0
  197. package/src/tools/MemoryWriteTool/MemoryWriteTool.tsx +89 -0
  198. package/src/tools/MemoryWriteTool/prompt.ts +3 -0
  199. package/src/tools/MultiEditTool/MultiEditTool.tsx +366 -0
  200. package/src/tools/MultiEditTool/prompt.ts +45 -0
  201. package/src/tools/NotebookEditTool/NotebookEditTool.tsx +298 -0
  202. package/src/tools/NotebookEditTool/prompt.ts +3 -0
  203. package/src/tools/NotebookReadTool/NotebookReadTool.tsx +258 -0
  204. package/src/tools/NotebookReadTool/prompt.ts +3 -0
  205. package/src/tools/StickerRequestTool/StickerRequestTool.tsx +93 -0
  206. package/src/tools/StickerRequestTool/prompt.ts +19 -0
  207. package/src/tools/TaskTool/TaskTool.tsx +466 -0
  208. package/src/tools/TaskTool/constants.ts +1 -0
  209. package/src/tools/TaskTool/prompt.ts +92 -0
  210. package/src/tools/ThinkTool/ThinkTool.tsx +54 -0
  211. package/src/tools/ThinkTool/prompt.ts +12 -0
  212. package/src/tools/TodoWriteTool/TodoWriteTool.tsx +290 -0
  213. package/src/tools/TodoWriteTool/prompt.ts +63 -0
  214. package/src/tools/lsTool/lsTool.tsx +272 -0
  215. package/src/tools/lsTool/prompt.ts +2 -0
  216. package/src/tools.ts +63 -0
  217. package/src/types/PermissionMode.ts +120 -0
  218. package/src/types/RequestContext.ts +72 -0
  219. package/src/types/conversation.ts +51 -0
  220. package/src/types/logs.ts +58 -0
  221. package/src/types/modelCapabilities.ts +64 -0
  222. package/src/types/notebook.ts +87 -0
  223. package/src/utils/Cursor.ts +436 -0
  224. package/src/utils/PersistentShell.ts +373 -0
  225. package/src/utils/advancedFuzzyMatcher.ts +290 -0
  226. package/src/utils/agentLoader.ts +284 -0
  227. package/src/utils/agentStorage.ts +97 -0
  228. package/src/utils/array.ts +3 -0
  229. package/src/utils/ask.tsx +99 -0
  230. package/src/utils/auth.ts +13 -0
  231. package/src/utils/autoCompactCore.ts +223 -0
  232. package/src/utils/autoUpdater.ts +318 -0
  233. package/src/utils/betas.ts +20 -0
  234. package/src/utils/browser.ts +14 -0
  235. package/src/utils/cleanup.ts +72 -0
  236. package/src/utils/commands.ts +261 -0
  237. package/src/utils/commonUnixCommands.ts +161 -0
  238. package/src/utils/config.ts +942 -0
  239. package/src/utils/conversationRecovery.ts +55 -0
  240. package/src/utils/debugLogger.ts +1123 -0
  241. package/src/utils/diff.ts +42 -0
  242. package/src/utils/env.ts +57 -0
  243. package/src/utils/errors.ts +21 -0
  244. package/src/utils/exampleCommands.ts +109 -0
  245. package/src/utils/execFileNoThrow.ts +51 -0
  246. package/src/utils/expertChatStorage.ts +136 -0
  247. package/src/utils/file.ts +402 -0
  248. package/src/utils/fileRecoveryCore.ts +71 -0
  249. package/src/utils/format.tsx +44 -0
  250. package/src/utils/fuzzyMatcher.ts +328 -0
  251. package/src/utils/generators.ts +62 -0
  252. package/src/utils/git.ts +92 -0
  253. package/src/utils/globalLogger.ts +77 -0
  254. package/src/utils/http.ts +10 -0
  255. package/src/utils/imagePaste.ts +38 -0
  256. package/src/utils/json.ts +13 -0
  257. package/src/utils/log.ts +382 -0
  258. package/src/utils/markdown.ts +213 -0
  259. package/src/utils/messageContextManager.ts +289 -0
  260. package/src/utils/messages.tsx +939 -0
  261. package/src/utils/model.ts +836 -0
  262. package/src/utils/permissions/filesystem.ts +118 -0
  263. package/src/utils/responseState.ts +23 -0
  264. package/src/utils/ripgrep.ts +167 -0
  265. package/src/utils/secureFile.ts +559 -0
  266. package/src/utils/sessionState.ts +49 -0
  267. package/src/utils/state.ts +25 -0
  268. package/src/utils/style.ts +29 -0
  269. package/src/utils/terminal.ts +50 -0
  270. package/src/utils/theme.ts +133 -0
  271. package/src/utils/thinking.ts +144 -0
  272. package/src/utils/todoStorage.ts +431 -0
  273. package/src/utils/tokens.ts +43 -0
  274. package/src/utils/toolExecutionController.ts +163 -0
  275. package/src/utils/unaryLogging.ts +26 -0
  276. package/src/utils/user.ts +37 -0
  277. package/src/utils/validate.ts +165 -0
  278. package/cli.mjs +0 -1803
@@ -0,0 +1,43 @@
1
+ import { Message } from '../query'
2
+ import { SYNTHETIC_ASSISTANT_MESSAGES } from './messages'
3
+
4
+ export function countTokens(messages: Message[]): number {
5
+ let i = messages.length - 1
6
+ while (i >= 0) {
7
+ const message = messages[i]
8
+ if (
9
+ message?.type === 'assistant' &&
10
+ 'usage' in message.message &&
11
+ !(
12
+ message.message.content[0]?.type === 'text' &&
13
+ SYNTHETIC_ASSISTANT_MESSAGES.has(message.message.content[0].text)
14
+ )
15
+ ) {
16
+ const { usage } = message.message
17
+ return (
18
+ usage.input_tokens +
19
+ (usage.cache_creation_input_tokens ?? 0) +
20
+ (usage.cache_read_input_tokens ?? 0) +
21
+ usage.output_tokens
22
+ )
23
+ }
24
+ i--
25
+ }
26
+ return 0
27
+ }
28
+
29
+ export function countCachedTokens(messages: Message[]): number {
30
+ let i = messages.length - 1
31
+ while (i >= 0) {
32
+ const message = messages[i]
33
+ if (message?.type === 'assistant' && 'usage' in message.message) {
34
+ const { usage } = message.message
35
+ return (
36
+ (usage.cache_creation_input_tokens ?? 0) +
37
+ (usage.cache_read_input_tokens ?? 0)
38
+ )
39
+ }
40
+ i--
41
+ }
42
+ return 0
43
+ }
@@ -0,0 +1,163 @@
1
+ import { ToolUseBlock } from '@anthropic-ai/sdk/resources/index.mjs'
2
+ import type { Tool } from '../Tool'
3
+
4
+ export interface ToolExecutionGroup {
5
+ concurrent: ToolUseBlock[]
6
+ sequential: ToolUseBlock[]
7
+ }
8
+
9
+ /**
10
+ * Tool Execution Controller
11
+ * Manages tool execution based on concurrency safety and dependencies
12
+ */
13
+ export class ToolExecutionController {
14
+ private tools: Tool[]
15
+
16
+ constructor(tools: Tool[]) {
17
+ this.tools = tools
18
+ }
19
+
20
+ /**
21
+ * Group tools into concurrent and sequential execution groups
22
+ */
23
+ groupToolsForExecution(
24
+ toolUseMessages: ToolUseBlock[],
25
+ ): ToolExecutionGroup[] {
26
+ const groups: ToolExecutionGroup[] = []
27
+ let currentGroup: ToolExecutionGroup = { concurrent: [], sequential: [] }
28
+
29
+ for (const toolUse of toolUseMessages) {
30
+ const tool = this.findTool(toolUse.name)
31
+
32
+ if (!tool) {
33
+ // Unknown tool, execute sequentially for safety
34
+ this.flushCurrentGroup(groups, currentGroup)
35
+ currentGroup = { concurrent: [], sequential: [toolUse] }
36
+ continue
37
+ }
38
+
39
+ if (tool.isConcurrencySafe()) {
40
+ // Safe for concurrent execution
41
+ currentGroup.concurrent.push(toolUse)
42
+ } else {
43
+ // Must be executed sequentially
44
+ this.flushCurrentGroup(groups, currentGroup)
45
+ currentGroup = { concurrent: [], sequential: [toolUse] }
46
+ }
47
+ }
48
+
49
+ // Flush the last group
50
+ this.flushCurrentGroup(groups, currentGroup)
51
+
52
+ return groups.filter(
53
+ group => group.concurrent.length > 0 || group.sequential.length > 0,
54
+ )
55
+ }
56
+
57
+ /**
58
+ * Check if all tools in a list can be executed concurrently
59
+ */
60
+ canExecuteConcurrently(toolUseMessages: ToolUseBlock[]): boolean {
61
+ return toolUseMessages.every(msg => {
62
+ const tool = this.findTool(msg.name)
63
+ return tool?.isConcurrencySafe() ?? false
64
+ })
65
+ }
66
+
67
+ /**
68
+ * Get tool concurrency safety status
69
+ */
70
+ getToolConcurrencyInfo(toolName: string): {
71
+ found: boolean
72
+ isConcurrencySafe: boolean
73
+ isReadOnly: boolean
74
+ } {
75
+ const tool = this.findTool(toolName)
76
+
77
+ if (!tool) {
78
+ return { found: false, isConcurrencySafe: false, isReadOnly: false }
79
+ }
80
+
81
+ return {
82
+ found: true,
83
+ isConcurrencySafe: tool.isConcurrencySafe(),
84
+ isReadOnly: tool.isReadOnly(),
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Analyze tool execution plan and provide recommendations
90
+ */
91
+ analyzeExecutionPlan(toolUseMessages: ToolUseBlock[]): {
92
+ canOptimize: boolean
93
+ concurrentCount: number
94
+ sequentialCount: number
95
+ groups: ToolExecutionGroup[]
96
+ recommendations: string[]
97
+ } {
98
+ const groups = this.groupToolsForExecution(toolUseMessages)
99
+ const concurrentCount = groups.reduce(
100
+ (sum, g) => sum + g.concurrent.length,
101
+ 0,
102
+ )
103
+ const sequentialCount = groups.reduce(
104
+ (sum, g) => sum + g.sequential.length,
105
+ 0,
106
+ )
107
+
108
+ const recommendations: string[] = []
109
+
110
+ if (concurrentCount > 1) {
111
+ recommendations.push(
112
+ `${concurrentCount} tools can run concurrently for better performance`,
113
+ )
114
+ }
115
+
116
+ if (sequentialCount > 1) {
117
+ recommendations.push(
118
+ `${sequentialCount} tools must run sequentially for safety`,
119
+ )
120
+ }
121
+
122
+ if (groups.length > 1) {
123
+ recommendations.push(
124
+ `Execution will be divided into ${groups.length} groups`,
125
+ )
126
+ }
127
+
128
+ return {
129
+ canOptimize: concurrentCount > 1,
130
+ concurrentCount,
131
+ sequentialCount,
132
+ groups,
133
+ recommendations,
134
+ }
135
+ }
136
+
137
+ private findTool(name: string): Tool | undefined {
138
+ return this.tools.find(t => t.name === name)
139
+ }
140
+
141
+ private flushCurrentGroup(
142
+ groups: ToolExecutionGroup[],
143
+ currentGroup: ToolExecutionGroup,
144
+ ): void {
145
+ if (
146
+ currentGroup.concurrent.length > 0 ||
147
+ currentGroup.sequential.length > 0
148
+ ) {
149
+ groups.push({ ...currentGroup })
150
+ currentGroup.concurrent = []
151
+ currentGroup.sequential = []
152
+ }
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Create a tool execution controller for the given tools
158
+ */
159
+ export function createToolExecutionController(
160
+ tools: Tool[],
161
+ ): ToolExecutionController {
162
+ return new ToolExecutionController(tools)
163
+ }
@@ -0,0 +1,26 @@
1
+ import { logEvent } from '../services/statsig'
2
+
3
+ export type CompletionType =
4
+ | 'str_replace_single'
5
+ | 'write_file_single'
6
+ | 'tool_use_single'
7
+
8
+ type LogEvent = {
9
+ completion_type: CompletionType
10
+ event: 'accept' | 'reject' | 'response'
11
+ metadata: {
12
+ language_name: string
13
+ message_id: string
14
+ platform: string
15
+ }
16
+ }
17
+
18
+ export function logUnaryEvent(event: LogEvent): void {
19
+ logEvent('tengu_unary_event', {
20
+ event: event.event,
21
+ completion_type: event.completion_type,
22
+ language_name: event.metadata.language_name,
23
+ message_id: event.metadata.message_id,
24
+ platform: event.metadata.platform,
25
+ })
26
+ }
@@ -0,0 +1,37 @@
1
+ import { getGlobalConfig, getOrCreateUserID } from './config'
2
+ import { memoize } from 'lodash-es'
3
+ import { env } from './env'
4
+ import { type StatsigUser } from '@statsig/js-client'
5
+ import { execFileNoThrow } from './execFileNoThrow'
6
+ import { logError, SESSION_ID } from './log'
7
+ import { MACRO } from '../constants/macros'
8
+ export const getGitEmail = memoize(async (): Promise<string | undefined> => {
9
+ const result = await execFileNoThrow('git', ['config', 'user.email'])
10
+ if (result.code !== 0) {
11
+ logError(`Failed to get git email: ${result.stdout} ${result.stderr}`)
12
+ return undefined
13
+ }
14
+ return result.stdout.trim() || undefined
15
+ })
16
+
17
+ export const getUser = memoize(async (): Promise<StatsigUser> => {
18
+ const userID = getOrCreateUserID()
19
+ const config = getGlobalConfig()
20
+ const email = undefined
21
+ return {
22
+ customIDs: {
23
+ // for session level tests
24
+ sessionId: SESSION_ID,
25
+ },
26
+ userID,
27
+ appVersion: MACRO.VERSION,
28
+ userAgent: env.platform,
29
+ email,
30
+ custom: {
31
+ nodeVersion: env.nodeVersion,
32
+ userType: process.env.USER_TYPE,
33
+ organizationUuid: config.oauthAccount?.organizationUuid,
34
+ accountUuid: config.oauthAccount?.accountUuid,
35
+ },
36
+ }
37
+ })
@@ -0,0 +1,165 @@
1
+ export type FormData = {
2
+ name: string
3
+ email: string
4
+ address1: string
5
+ address2: string
6
+ city: string
7
+ state: string
8
+ zip: string
9
+ phone: string
10
+ usLocation: boolean
11
+ }
12
+
13
+ export type ValidationError = {
14
+ message: string
15
+ }
16
+
17
+ export function validateField(
18
+ field: keyof FormData,
19
+ value: string,
20
+ ): ValidationError | null {
21
+ // Trim whitespace for validation
22
+ const trimmed = value.trim()
23
+
24
+ if (!trimmed && field === 'address2') {
25
+ return null // address2 is optional
26
+ }
27
+
28
+ // Basic required field check
29
+ if (!trimmed) {
30
+ return { message: 'This field is required' }
31
+ }
32
+
33
+ switch (field) {
34
+ case 'email': {
35
+ const emailRegex =
36
+ /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
37
+ if (!emailRegex.test(trimmed)) {
38
+ return { message: 'Please enter a valid email address' }
39
+ }
40
+ break
41
+ }
42
+
43
+ case 'name':
44
+ if (trimmed.length < 2) {
45
+ return { message: 'Name must be at least 2 characters long' }
46
+ }
47
+ break
48
+
49
+ case 'address1': {
50
+ if (trimmed.length < 3) {
51
+ return { message: 'Please enter a valid address' }
52
+ }
53
+ // Accept PO Box format or regular street address
54
+ const isPOBox = /^P\.?O\.?\s*Box\s+\d+$/i.test(trimmed)
55
+ const hasNumber = /\d+/.test(trimmed)
56
+ if (!isPOBox && !hasNumber) {
57
+ return { message: 'Please include a number in the street address' }
58
+ }
59
+ break
60
+ }
61
+ case 'address2':
62
+ break
63
+
64
+ case 'city':
65
+ if (trimmed.length < 2) {
66
+ return { message: 'City name must be at least 2 characters long' }
67
+ }
68
+ if (!/^[a-zA-Z\s.-]+$/.test(trimmed)) {
69
+ return {
70
+ message:
71
+ 'City can only contain letters, spaces, periods, and hyphens',
72
+ }
73
+ }
74
+ break
75
+
76
+ case 'state': {
77
+ const states = new Set([
78
+ 'AL',
79
+ 'AK',
80
+ 'AZ',
81
+ 'AR',
82
+ 'CA',
83
+ 'CO',
84
+ 'CT',
85
+ 'DE',
86
+ 'FL',
87
+ 'GA',
88
+ 'HI',
89
+ 'ID',
90
+ 'IL',
91
+ 'IN',
92
+ 'IA',
93
+ 'KS',
94
+ 'KY',
95
+ 'LA',
96
+ 'ME',
97
+ 'MD',
98
+ 'MA',
99
+ 'MI',
100
+ 'MN',
101
+ 'MS',
102
+ 'MO',
103
+ 'MT',
104
+ 'NE',
105
+ 'NV',
106
+ 'NH',
107
+ 'NJ',
108
+ 'NM',
109
+ 'NY',
110
+ 'NC',
111
+ 'ND',
112
+ 'OH',
113
+ 'OK',
114
+ 'OR',
115
+ 'PA',
116
+ 'RI',
117
+ 'SC',
118
+ 'SD',
119
+ 'TN',
120
+ 'TX',
121
+ 'UT',
122
+ 'VT',
123
+ 'VA',
124
+ 'WA',
125
+ 'WV',
126
+ 'WI',
127
+ 'WY',
128
+ 'DC',
129
+ ])
130
+ const stateCode = trimmed.toUpperCase()
131
+ if (!states.has(stateCode)) {
132
+ return { message: 'Please enter a valid US state code (e.g. CA)' }
133
+ }
134
+ break
135
+ }
136
+
137
+ case 'usLocation': {
138
+ const normalized = trimmed.toLowerCase()
139
+ if (!['y', 'yes', 'n', 'no'].includes(normalized)) {
140
+ return { message: 'Please enter y/yes or n/no' }
141
+ }
142
+ break
143
+ }
144
+
145
+ case 'zip':
146
+ // ZIP code validation for US
147
+ if (!/^\d{5}(-\d{4})?$/.test(trimmed)) {
148
+ return {
149
+ message: 'Please enter a valid ZIP code (e.g. 12345 or 12345-6789)',
150
+ }
151
+ }
152
+ break
153
+
154
+ case 'phone':
155
+ // Phone validation for US (allow various formats)
156
+ if (!/^(\+1\s?)?(\d{3}[-.\s]??)?\d{3}[-.\s]??\d{4}$/.test(trimmed)) {
157
+ return {
158
+ message: 'Please enter a valid US phone number',
159
+ }
160
+ }
161
+ break
162
+ }
163
+
164
+ return null
165
+ }