@shareai-lab/kode 1.1.13 → 1.1.16

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 (288) hide show
  1. package/dist/entrypoints/cli.js +2 -1
  2. package/dist/entrypoints/cli.js.map +2 -2
  3. package/dist/index.js +5 -26
  4. package/dist/package.json +4 -1
  5. package/package.json +9 -104
  6. package/dist/test/testAdapters.js +0 -88
  7. package/dist/test/testAdapters.js.map +0 -1
  8. package/src/ProjectOnboarding.tsx +0 -198
  9. package/src/Tool.ts +0 -83
  10. package/src/commands/agents.tsx +0 -3416
  11. package/src/commands/approvedTools.ts +0 -53
  12. package/src/commands/bug.tsx +0 -20
  13. package/src/commands/clear.ts +0 -43
  14. package/src/commands/compact.ts +0 -120
  15. package/src/commands/config.tsx +0 -19
  16. package/src/commands/cost.ts +0 -18
  17. package/src/commands/ctx_viz.ts +0 -209
  18. package/src/commands/doctor.ts +0 -24
  19. package/src/commands/help.tsx +0 -19
  20. package/src/commands/init.ts +0 -37
  21. package/src/commands/listen.ts +0 -42
  22. package/src/commands/login.tsx +0 -51
  23. package/src/commands/logout.tsx +0 -40
  24. package/src/commands/mcp.ts +0 -41
  25. package/src/commands/model.tsx +0 -40
  26. package/src/commands/modelstatus.tsx +0 -20
  27. package/src/commands/onboarding.tsx +0 -34
  28. package/src/commands/pr_comments.ts +0 -59
  29. package/src/commands/refreshCommands.ts +0 -54
  30. package/src/commands/release-notes.ts +0 -34
  31. package/src/commands/resume.tsx +0 -31
  32. package/src/commands/review.ts +0 -49
  33. package/src/commands/terminalSetup.ts +0 -221
  34. package/src/commands.ts +0 -139
  35. package/src/components/ApproveApiKey.tsx +0 -93
  36. package/src/components/AsciiLogo.tsx +0 -13
  37. package/src/components/AutoUpdater.tsx +0 -148
  38. package/src/components/Bug.tsx +0 -367
  39. package/src/components/Config.tsx +0 -293
  40. package/src/components/ConsoleOAuthFlow.tsx +0 -327
  41. package/src/components/Cost.tsx +0 -23
  42. package/src/components/CostThresholdDialog.tsx +0 -46
  43. package/src/components/CustomSelect/option-map.ts +0 -42
  44. package/src/components/CustomSelect/select-option.tsx +0 -78
  45. package/src/components/CustomSelect/select.tsx +0 -152
  46. package/src/components/CustomSelect/theme.ts +0 -45
  47. package/src/components/CustomSelect/use-select-state.ts +0 -414
  48. package/src/components/CustomSelect/use-select.ts +0 -35
  49. package/src/components/FallbackToolUseRejectedMessage.tsx +0 -15
  50. package/src/components/FileEditToolUpdatedMessage.tsx +0 -66
  51. package/src/components/Help.tsx +0 -215
  52. package/src/components/HighlightedCode.tsx +0 -33
  53. package/src/components/InvalidConfigDialog.tsx +0 -113
  54. package/src/components/Link.tsx +0 -32
  55. package/src/components/LogSelector.tsx +0 -86
  56. package/src/components/Logo.tsx +0 -170
  57. package/src/components/MCPServerApprovalDialog.tsx +0 -100
  58. package/src/components/MCPServerDialogCopy.tsx +0 -25
  59. package/src/components/MCPServerMultiselectDialog.tsx +0 -109
  60. package/src/components/Message.tsx +0 -221
  61. package/src/components/MessageResponse.tsx +0 -15
  62. package/src/components/MessageSelector.tsx +0 -211
  63. package/src/components/ModeIndicator.tsx +0 -88
  64. package/src/components/ModelConfig.tsx +0 -301
  65. package/src/components/ModelListManager.tsx +0 -227
  66. package/src/components/ModelSelector.tsx +0 -3387
  67. package/src/components/ModelStatusDisplay.tsx +0 -230
  68. package/src/components/Onboarding.tsx +0 -274
  69. package/src/components/PressEnterToContinue.tsx +0 -11
  70. package/src/components/PromptInput.tsx +0 -760
  71. package/src/components/SentryErrorBoundary.ts +0 -39
  72. package/src/components/Spinner.tsx +0 -129
  73. package/src/components/StickerRequestForm.tsx +0 -16
  74. package/src/components/StructuredDiff.tsx +0 -191
  75. package/src/components/TextInput.tsx +0 -259
  76. package/src/components/TodoItem.tsx +0 -47
  77. package/src/components/TokenWarning.tsx +0 -31
  78. package/src/components/ToolUseLoader.tsx +0 -40
  79. package/src/components/TrustDialog.tsx +0 -106
  80. package/src/components/binary-feedback/BinaryFeedback.tsx +0 -63
  81. package/src/components/binary-feedback/BinaryFeedbackOption.tsx +0 -111
  82. package/src/components/binary-feedback/BinaryFeedbackView.tsx +0 -172
  83. package/src/components/binary-feedback/utils.ts +0 -220
  84. package/src/components/messages/AssistantBashOutputMessage.tsx +0 -22
  85. package/src/components/messages/AssistantLocalCommandOutputMessage.tsx +0 -49
  86. package/src/components/messages/AssistantRedactedThinkingMessage.tsx +0 -19
  87. package/src/components/messages/AssistantTextMessage.tsx +0 -144
  88. package/src/components/messages/AssistantThinkingMessage.tsx +0 -40
  89. package/src/components/messages/AssistantToolUseMessage.tsx +0 -132
  90. package/src/components/messages/TaskProgressMessage.tsx +0 -32
  91. package/src/components/messages/TaskToolMessage.tsx +0 -58
  92. package/src/components/messages/UserBashInputMessage.tsx +0 -28
  93. package/src/components/messages/UserCommandMessage.tsx +0 -30
  94. package/src/components/messages/UserKodingInputMessage.tsx +0 -28
  95. package/src/components/messages/UserPromptMessage.tsx +0 -35
  96. package/src/components/messages/UserTextMessage.tsx +0 -39
  97. package/src/components/messages/UserToolResultMessage/UserToolCanceledMessage.tsx +0 -12
  98. package/src/components/messages/UserToolResultMessage/UserToolErrorMessage.tsx +0 -36
  99. package/src/components/messages/UserToolResultMessage/UserToolRejectMessage.tsx +0 -31
  100. package/src/components/messages/UserToolResultMessage/UserToolResultMessage.tsx +0 -57
  101. package/src/components/messages/UserToolResultMessage/UserToolSuccessMessage.tsx +0 -35
  102. package/src/components/messages/UserToolResultMessage/utils.tsx +0 -56
  103. package/src/components/permissions/BashPermissionRequest/BashPermissionRequest.tsx +0 -121
  104. package/src/components/permissions/FallbackPermissionRequest.tsx +0 -153
  105. package/src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx +0 -182
  106. package/src/components/permissions/FileEditPermissionRequest/FileEditToolDiff.tsx +0 -77
  107. package/src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.tsx +0 -164
  108. package/src/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.tsx +0 -83
  109. package/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx +0 -240
  110. package/src/components/permissions/PermissionRequest.tsx +0 -101
  111. package/src/components/permissions/PermissionRequestTitle.tsx +0 -69
  112. package/src/components/permissions/hooks.ts +0 -44
  113. package/src/components/permissions/toolUseOptions.ts +0 -59
  114. package/src/components/permissions/utils.ts +0 -23
  115. package/src/constants/betas.ts +0 -5
  116. package/src/constants/claude-asterisk-ascii-art.tsx +0 -238
  117. package/src/constants/figures.ts +0 -4
  118. package/src/constants/keys.ts +0 -3
  119. package/src/constants/macros.ts +0 -11
  120. package/src/constants/modelCapabilities.ts +0 -179
  121. package/src/constants/models.ts +0 -1025
  122. package/src/constants/oauth.ts +0 -18
  123. package/src/constants/product.ts +0 -17
  124. package/src/constants/prompts.ts +0 -168
  125. package/src/constants/releaseNotes.ts +0 -7
  126. package/src/context/PermissionContext.tsx +0 -149
  127. package/src/context.ts +0 -278
  128. package/src/cost-tracker.ts +0 -84
  129. package/src/entrypoints/cli.tsx +0 -1561
  130. package/src/entrypoints/mcp.ts +0 -175
  131. package/src/history.ts +0 -25
  132. package/src/hooks/useApiKeyVerification.ts +0 -59
  133. package/src/hooks/useArrowKeyHistory.ts +0 -55
  134. package/src/hooks/useCanUseTool.ts +0 -138
  135. package/src/hooks/useCancelRequest.ts +0 -39
  136. package/src/hooks/useDoublePress.ts +0 -41
  137. package/src/hooks/useExitOnCtrlCD.ts +0 -31
  138. package/src/hooks/useInterval.ts +0 -25
  139. package/src/hooks/useLogMessages.ts +0 -16
  140. package/src/hooks/useLogStartupTime.ts +0 -12
  141. package/src/hooks/useNotifyAfterTimeout.ts +0 -65
  142. package/src/hooks/usePermissionRequestLogging.ts +0 -44
  143. package/src/hooks/useTerminalSize.ts +0 -49
  144. package/src/hooks/useTextInput.ts +0 -317
  145. package/src/hooks/useUnifiedCompletion.ts +0 -1405
  146. package/src/index.ts +0 -34
  147. package/src/messages.ts +0 -38
  148. package/src/permissions.ts +0 -268
  149. package/src/query.ts +0 -720
  150. package/src/screens/ConfigureNpmPrefix.tsx +0 -197
  151. package/src/screens/Doctor.tsx +0 -219
  152. package/src/screens/LogList.tsx +0 -68
  153. package/src/screens/REPL.tsx +0 -813
  154. package/src/screens/ResumeConversation.tsx +0 -68
  155. package/src/services/adapters/base.ts +0 -38
  156. package/src/services/adapters/chatCompletions.ts +0 -90
  157. package/src/services/adapters/responsesAPI.ts +0 -170
  158. package/src/services/browserMocks.ts +0 -66
  159. package/src/services/claude.ts +0 -2197
  160. package/src/services/customCommands.ts +0 -704
  161. package/src/services/fileFreshness.ts +0 -377
  162. package/src/services/gpt5ConnectionTest.ts +0 -340
  163. package/src/services/mcpClient.ts +0 -564
  164. package/src/services/mcpServerApproval.tsx +0 -50
  165. package/src/services/mentionProcessor.ts +0 -273
  166. package/src/services/modelAdapterFactory.ts +0 -69
  167. package/src/services/notifier.ts +0 -40
  168. package/src/services/oauth.ts +0 -357
  169. package/src/services/openai.ts +0 -1359
  170. package/src/services/responseStateManager.ts +0 -90
  171. package/src/services/sentry.ts +0 -3
  172. package/src/services/statsig.ts +0 -172
  173. package/src/services/statsigStorage.ts +0 -86
  174. package/src/services/systemReminder.ts +0 -507
  175. package/src/services/vcr.ts +0 -161
  176. package/src/test/testAdapters.ts +0 -96
  177. package/src/tools/ArchitectTool/ArchitectTool.tsx +0 -135
  178. package/src/tools/ArchitectTool/prompt.ts +0 -15
  179. package/src/tools/AskExpertModelTool/AskExpertModelTool.tsx +0 -576
  180. package/src/tools/BashTool/BashTool.tsx +0 -243
  181. package/src/tools/BashTool/BashToolResultMessage.tsx +0 -38
  182. package/src/tools/BashTool/OutputLine.tsx +0 -49
  183. package/src/tools/BashTool/prompt.ts +0 -174
  184. package/src/tools/BashTool/utils.ts +0 -56
  185. package/src/tools/FileEditTool/FileEditTool.tsx +0 -319
  186. package/src/tools/FileEditTool/prompt.ts +0 -51
  187. package/src/tools/FileEditTool/utils.ts +0 -58
  188. package/src/tools/FileReadTool/FileReadTool.tsx +0 -404
  189. package/src/tools/FileReadTool/prompt.ts +0 -7
  190. package/src/tools/FileWriteTool/FileWriteTool.tsx +0 -301
  191. package/src/tools/FileWriteTool/prompt.ts +0 -10
  192. package/src/tools/GlobTool/GlobTool.tsx +0 -119
  193. package/src/tools/GlobTool/prompt.ts +0 -8
  194. package/src/tools/GrepTool/GrepTool.tsx +0 -147
  195. package/src/tools/GrepTool/prompt.ts +0 -11
  196. package/src/tools/MCPTool/MCPTool.tsx +0 -107
  197. package/src/tools/MCPTool/prompt.ts +0 -3
  198. package/src/tools/MemoryReadTool/MemoryReadTool.tsx +0 -127
  199. package/src/tools/MemoryReadTool/prompt.ts +0 -3
  200. package/src/tools/MemoryWriteTool/MemoryWriteTool.tsx +0 -89
  201. package/src/tools/MemoryWriteTool/prompt.ts +0 -3
  202. package/src/tools/MultiEditTool/MultiEditTool.tsx +0 -388
  203. package/src/tools/MultiEditTool/prompt.ts +0 -45
  204. package/src/tools/NotebookEditTool/NotebookEditTool.tsx +0 -298
  205. package/src/tools/NotebookEditTool/prompt.ts +0 -3
  206. package/src/tools/NotebookReadTool/NotebookReadTool.tsx +0 -258
  207. package/src/tools/NotebookReadTool/prompt.ts +0 -3
  208. package/src/tools/StickerRequestTool/StickerRequestTool.tsx +0 -107
  209. package/src/tools/StickerRequestTool/prompt.ts +0 -19
  210. package/src/tools/TaskTool/TaskTool.tsx +0 -438
  211. package/src/tools/TaskTool/constants.ts +0 -1
  212. package/src/tools/TaskTool/prompt.ts +0 -92
  213. package/src/tools/ThinkTool/ThinkTool.tsx +0 -54
  214. package/src/tools/ThinkTool/prompt.ts +0 -12
  215. package/src/tools/TodoWriteTool/TodoWriteTool.tsx +0 -313
  216. package/src/tools/TodoWriteTool/prompt.ts +0 -63
  217. package/src/tools/URLFetcherTool/URLFetcherTool.tsx +0 -178
  218. package/src/tools/URLFetcherTool/cache.ts +0 -55
  219. package/src/tools/URLFetcherTool/htmlToMarkdown.ts +0 -55
  220. package/src/tools/URLFetcherTool/prompt.ts +0 -17
  221. package/src/tools/WebSearchTool/WebSearchTool.tsx +0 -103
  222. package/src/tools/WebSearchTool/prompt.ts +0 -13
  223. package/src/tools/WebSearchTool/searchProviders.ts +0 -66
  224. package/src/tools/lsTool/lsTool.tsx +0 -272
  225. package/src/tools/lsTool/prompt.ts +0 -2
  226. package/src/tools.ts +0 -67
  227. package/src/types/PermissionMode.ts +0 -120
  228. package/src/types/RequestContext.ts +0 -72
  229. package/src/types/common.d.ts +0 -2
  230. package/src/types/conversation.ts +0 -51
  231. package/src/types/logs.ts +0 -58
  232. package/src/types/modelCapabilities.ts +0 -64
  233. package/src/types/notebook.ts +0 -87
  234. package/src/utils/Cursor.ts +0 -436
  235. package/src/utils/PersistentShell.ts +0 -552
  236. package/src/utils/advancedFuzzyMatcher.ts +0 -290
  237. package/src/utils/agentLoader.ts +0 -278
  238. package/src/utils/agentStorage.ts +0 -97
  239. package/src/utils/array.ts +0 -3
  240. package/src/utils/ask.tsx +0 -99
  241. package/src/utils/auth.ts +0 -13
  242. package/src/utils/autoCompactCore.ts +0 -223
  243. package/src/utils/autoUpdater.ts +0 -458
  244. package/src/utils/betas.ts +0 -20
  245. package/src/utils/browser.ts +0 -14
  246. package/src/utils/cleanup.ts +0 -72
  247. package/src/utils/commands.ts +0 -261
  248. package/src/utils/commonUnixCommands.ts +0 -161
  249. package/src/utils/config.ts +0 -945
  250. package/src/utils/conversationRecovery.ts +0 -55
  251. package/src/utils/debugLogger.ts +0 -1235
  252. package/src/utils/diff.ts +0 -42
  253. package/src/utils/env.ts +0 -57
  254. package/src/utils/errors.ts +0 -21
  255. package/src/utils/exampleCommands.ts +0 -109
  256. package/src/utils/execFileNoThrow.ts +0 -51
  257. package/src/utils/expertChatStorage.ts +0 -136
  258. package/src/utils/file.ts +0 -405
  259. package/src/utils/fileRecoveryCore.ts +0 -71
  260. package/src/utils/format.tsx +0 -44
  261. package/src/utils/fuzzyMatcher.ts +0 -328
  262. package/src/utils/generators.ts +0 -62
  263. package/src/utils/git.ts +0 -92
  264. package/src/utils/globalLogger.ts +0 -77
  265. package/src/utils/http.ts +0 -10
  266. package/src/utils/imagePaste.ts +0 -38
  267. package/src/utils/json.ts +0 -13
  268. package/src/utils/log.ts +0 -382
  269. package/src/utils/markdown.ts +0 -213
  270. package/src/utils/messageContextManager.ts +0 -294
  271. package/src/utils/messages.tsx +0 -945
  272. package/src/utils/model.ts +0 -914
  273. package/src/utils/permissions/filesystem.ts +0 -127
  274. package/src/utils/responseState.ts +0 -23
  275. package/src/utils/ripgrep.ts +0 -167
  276. package/src/utils/secureFile.ts +0 -564
  277. package/src/utils/sessionState.ts +0 -49
  278. package/src/utils/state.ts +0 -25
  279. package/src/utils/style.ts +0 -29
  280. package/src/utils/terminal.ts +0 -50
  281. package/src/utils/theme.ts +0 -127
  282. package/src/utils/thinking.ts +0 -144
  283. package/src/utils/todoStorage.ts +0 -431
  284. package/src/utils/tokens.ts +0 -43
  285. package/src/utils/toolExecutionController.ts +0 -163
  286. package/src/utils/unaryLogging.ts +0 -26
  287. package/src/utils/user.ts +0 -37
  288. package/src/utils/validate.ts +0 -165
@@ -1,458 +0,0 @@
1
- import { homedir } from 'os'
2
- import { join } from 'path'
3
- import {
4
- existsSync,
5
- mkdirSync,
6
- appendFileSync,
7
- readFileSync,
8
- constants,
9
- writeFileSync,
10
- unlinkSync,
11
- statSync,
12
- } from 'fs'
13
- import { platform } from 'process'
14
- import { execFileNoThrow } from './execFileNoThrow'
15
- import { spawn } from 'child_process'
16
- import { logError } from './log'
17
- import { accessSync } from 'fs'
18
- import { CLAUDE_BASE_DIR } from './env'
19
- import { logEvent, getDynamicConfig } from '../services/statsig'
20
- import { lt, gt } from 'semver'
21
- import { MACRO } from '../constants/macros'
22
- import { PRODUCT_COMMAND, PRODUCT_NAME } from '../constants/product'
23
- import { getGlobalConfig, saveGlobalConfig, isAutoUpdaterDisabled } from './config'
24
- import { env } from './env'
25
- export type InstallStatus =
26
- | 'success'
27
- | 'no_permissions'
28
- | 'install_failed'
29
- | 'in_progress'
30
-
31
- export type AutoUpdaterResult = {
32
- version: string | null
33
- status: InstallStatus
34
- }
35
-
36
- export type VersionConfig = {
37
- minVersion: string
38
- }
39
-
40
- /**
41
- * Checks if the current version meets the minimum required version from Statsig config
42
- * Terminates the process with an error message if the version is too old
43
- */
44
- export async function assertMinVersion(): Promise<void> {
45
- try {
46
- const versionConfig = await getDynamicConfig<VersionConfig>(
47
- 'tengu_version_config',
48
- { minVersion: '0.0.0' },
49
- )
50
-
51
- if (
52
- versionConfig.minVersion &&
53
- lt(MACRO.VERSION, versionConfig.minVersion)
54
- ) {
55
- const suggestions = await getUpdateCommandSuggestions()
56
- const cmdLines = suggestions.map(c => ` ${c}`).join('\n')
57
- console.error(`
58
- 您的 ${PRODUCT_NAME} 版本 (${MACRO.VERSION}) 过低,需要升级到 ${versionConfig.minVersion} 或更高版本。
59
- 请手动执行以下任一命令进行升级:
60
- ${cmdLines}
61
- `)
62
- process.exit(1)
63
- }
64
- } catch (error) {
65
- logError(`Error checking minimum version: ${error}`)
66
- }
67
- }
68
-
69
- // Lock file for auto-updater to prevent concurrent updates
70
- export const LOCK_FILE_PATH = join(CLAUDE_BASE_DIR, '.update.lock')
71
- const LOCK_TIMEOUT_MS = 5 * 60 * 1000 // 5 minute timeout for locks
72
-
73
- /**
74
- * Attempts to acquire a lock for auto-updater
75
- * @returns {boolean} true if lock was acquired, false if another process holds the lock
76
- */
77
- function acquireLock(): boolean {
78
- try {
79
- // Ensure the base directory exists
80
- if (!existsSync(CLAUDE_BASE_DIR)) {
81
- mkdirSync(CLAUDE_BASE_DIR, { recursive: true })
82
- }
83
-
84
- // Check if lock file exists and is not stale
85
- if (existsSync(LOCK_FILE_PATH)) {
86
- const stats = statSync(LOCK_FILE_PATH)
87
- const age = Date.now() - stats.mtimeMs
88
-
89
- // If lock file is older than timeout, consider it stale
90
- if (age < LOCK_TIMEOUT_MS) {
91
- return false
92
- }
93
-
94
- // Lock is stale, we can take over
95
- try {
96
- unlinkSync(LOCK_FILE_PATH)
97
- } catch (err) {
98
- logError(`Failed to remove stale lock file: ${err}`)
99
- return false
100
- }
101
- }
102
-
103
- // Create lock file with current pid
104
- writeFileSync(LOCK_FILE_PATH, `${process.pid}`, 'utf8')
105
- return true
106
- } catch (err) {
107
- logError(`Failed to acquire lock: ${err}`)
108
- return false
109
- }
110
- }
111
-
112
- /**
113
- * Releases the update lock if it's held by this process
114
- */
115
- function releaseLock(): void {
116
- try {
117
- if (existsSync(LOCK_FILE_PATH)) {
118
- const lockData = readFileSync(LOCK_FILE_PATH, 'utf8')
119
- if (lockData === `${process.pid}`) {
120
- unlinkSync(LOCK_FILE_PATH)
121
- }
122
- }
123
- } catch (err) {
124
- logError(`Failed to release lock: ${err}`)
125
- }
126
- }
127
-
128
- export async function checkNpmPermissions(): Promise<{
129
- hasPermissions: boolean
130
- npmPrefix: string | null
131
- }> {
132
- try {
133
- const prefixResult = await execFileNoThrow('npm', [
134
- '-g',
135
- 'config',
136
- 'get',
137
- 'prefix',
138
- ])
139
- if (prefixResult.code !== 0) {
140
- logError('Failed to check npm permissions')
141
- return { hasPermissions: false, npmPrefix: null }
142
- }
143
-
144
- const prefix = prefixResult.stdout.trim()
145
-
146
- let testWriteResult = false
147
- try {
148
- accessSync(prefix, constants.W_OK)
149
- testWriteResult = true
150
- } catch {
151
- testWriteResult = false
152
- }
153
-
154
- if (testWriteResult) {
155
- return { hasPermissions: true, npmPrefix: prefix }
156
- }
157
-
158
- logError('Insufficient permissions for global npm install.')
159
- return { hasPermissions: false, npmPrefix: prefix }
160
- } catch (error) {
161
- logError(`Failed to verify npm global install permissions: ${error}`)
162
- return { hasPermissions: false, npmPrefix: null }
163
- }
164
- }
165
-
166
- export async function setupNewPrefix(prefix: string): Promise<void> {
167
- if (!acquireLock()) {
168
- // Log the lock contention to statsig
169
- logEvent('tengu_auto_updater_prefix_lock_contention', {
170
- pid: String(process.pid),
171
- currentVersion: MACRO.VERSION,
172
- prefix,
173
- })
174
- throw new Error('Another process is currently setting up npm prefix')
175
- }
176
-
177
- try {
178
- // Create directory if it doesn't exist
179
- if (!existsSync(prefix)) {
180
- mkdirSync(prefix, { recursive: true })
181
- }
182
-
183
- // Set npm prefix
184
- const setPrefix = await execFileNoThrow('npm', [
185
- '-g',
186
- 'config',
187
- 'set',
188
- 'prefix',
189
- prefix,
190
- ])
191
-
192
- if (setPrefix.code !== 0) {
193
- throw new Error(`Failed to set npm prefix: ${setPrefix.stderr}`)
194
- }
195
-
196
- // Update shell config files
197
- const pathUpdate = `\n# npm global path\nexport PATH="${prefix}/bin:$PATH"\n`
198
-
199
- if (platform === 'win32') {
200
- // On Windows, update user PATH environment variable
201
- const setxResult = await execFileNoThrow('setx', [
202
- 'PATH',
203
- `${process.env.PATH};${prefix}`,
204
- ])
205
- if (setxResult.code !== 0) {
206
- throw new Error(
207
- `Failed to update PATH on Windows: ${setxResult.stderr}`,
208
- )
209
- }
210
- } else {
211
- // Unix-like systems
212
- const shellConfigs = [
213
- // Bash
214
- join(homedir(), '.bashrc'),
215
- join(homedir(), '.bash_profile'),
216
- // Zsh
217
- join(homedir(), '.zshrc'),
218
- // Fish
219
- join(homedir(), '.config', 'fish', 'config.fish'),
220
- ]
221
-
222
- for (const config of shellConfigs) {
223
- if (existsSync(config)) {
224
- try {
225
- const content = readFileSync(config, 'utf8')
226
- if (!content.includes(prefix)) {
227
- if (config.includes('fish')) {
228
- // Fish shell has different syntax
229
- const fishPath = `\n# npm global path\nset -gx PATH ${prefix}/bin $PATH\n`
230
- appendFileSync(config, fishPath)
231
- } else {
232
- appendFileSync(config, pathUpdate)
233
- }
234
-
235
- logEvent('npm_prefix_path_updated', {
236
- configPath: config,
237
- })
238
- }
239
- } catch (err) {
240
- // Log but don't throw - continue with other configs
241
- logEvent('npm_prefix_path_update_failed', {
242
- configPath: config,
243
- error:
244
- err instanceof Error
245
- ? err.message.slice(0, 200)
246
- : String(err).slice(0, 200),
247
- })
248
- logError(`Failed to update shell config ${config}: ${err}`)
249
- }
250
- }
251
- }
252
- }
253
- } finally {
254
- releaseLock()
255
- }
256
- }
257
-
258
- export function getDefaultNpmPrefix(): string {
259
- return join(homedir(), '.npm-global')
260
- }
261
-
262
- export function getPermissionsCommand(npmPrefix: string): string {
263
- const windowsCommand = `icacls "${npmPrefix}" /grant "%USERNAME%:(OI)(CI)F"`
264
- const prefixPath = npmPrefix || '$(npm -g config get prefix)'
265
- const unixCommand = `sudo chown -R $USER:$(id -gn) ${prefixPath} && sudo chmod -R u+w ${prefixPath}`
266
-
267
- return platform === 'win32' ? windowsCommand : unixCommand
268
- }
269
-
270
- export async function getLatestVersion(): Promise<string | null> {
271
- // 1) Try npm CLI (fast when available)
272
- try {
273
- const abortController = new AbortController()
274
- setTimeout(() => abortController.abort(), 5000)
275
- const result = await execFileNoThrow(
276
- 'npm',
277
- ['view', MACRO.PACKAGE_URL, 'version'],
278
- abortController.signal,
279
- )
280
- if (result.code === 0) {
281
- const v = result.stdout.trim()
282
- if (v) return v
283
- }
284
- } catch {}
285
-
286
- // 2) Fallback: fetch npm registry (works in Bun/Node without npm)
287
- try {
288
- const controller = new AbortController()
289
- const timer = setTimeout(() => controller.abort(), 5000)
290
- const res = await fetch(
291
- `https://registry.npmjs.org/${encodeURIComponent(MACRO.PACKAGE_URL)}`,
292
- {
293
- method: 'GET',
294
- headers: {
295
- Accept: 'application/vnd.npm.install-v1+json',
296
- 'User-Agent': `${PRODUCT_NAME}/${MACRO.VERSION}`,
297
- },
298
- signal: controller.signal,
299
- },
300
- )
301
- clearTimeout(timer)
302
- if (!res.ok) return null
303
- const json: any = await res.json().catch(() => null)
304
- const latest = json && json['dist-tags'] && json['dist-tags'].latest
305
- return typeof latest === 'string' ? latest : null
306
- } catch {
307
- return null
308
- }
309
- }
310
-
311
- export async function installGlobalPackage(): Promise<InstallStatus> {
312
- // Detect preferred package manager and install accordingly
313
- if (!acquireLock()) {
314
- logError('Another process is currently installing an update')
315
- // Log the lock contention to statsig
316
- logEvent('tengu_auto_updater_lock_contention', {
317
- pid: String(process.pid),
318
- currentVersion: MACRO.VERSION,
319
- })
320
- return 'in_progress'
321
- }
322
-
323
- try {
324
- const manager = await detectPackageManager()
325
- if (manager === 'npm') {
326
- const { hasPermissions } = await checkNpmPermissions()
327
- if (!hasPermissions) {
328
- return 'no_permissions'
329
- }
330
- // Stream实时输出,减少用户等待感
331
- const code = await runStreaming('npm', ['install', '-g', MACRO.PACKAGE_URL])
332
- if (code !== 0) {
333
- logError(`Failed to install new version via npm (exit ${code})`)
334
- return 'install_failed'
335
- }
336
- return 'success'
337
- }
338
-
339
- if (manager === 'bun') {
340
- const code = await runStreaming('bun', ['add', '-g', `${MACRO.PACKAGE_URL}@latest`])
341
- if (code !== 0) {
342
- logError(`Failed to install new version via bun (exit ${code})`)
343
- return 'install_failed'
344
- }
345
- return 'success'
346
- }
347
-
348
- // Fallback to npm if unknown
349
- const { hasPermissions } = await checkNpmPermissions()
350
- if (!hasPermissions) return 'no_permissions'
351
- const code = await runStreaming('npm', ['install', '-g', MACRO.PACKAGE_URL])
352
- if (code !== 0) return 'install_failed'
353
- return 'success'
354
- } finally {
355
- // Ensure we always release the lock
356
- releaseLock()
357
- }
358
- }
359
-
360
- export type PackageManager = 'npm' | 'bun'
361
-
362
- export async function detectPackageManager(): Promise<PackageManager> {
363
- // Respect explicit override if provided later via config/env (future-proof)
364
- try {
365
- // Heuristic 1: npm available and global root resolvable
366
- const npmRoot = await execFileNoThrow('npm', ['-g', 'root'])
367
- if (npmRoot.code === 0 && npmRoot.stdout.trim()) {
368
- return 'npm'
369
- }
370
- } catch {}
371
-
372
- try {
373
- // Heuristic 2: running on a system with bun and installed path hints bun
374
- const bunVer = await execFileNoThrow('bun', ['--version'])
375
- if (bunVer.code === 0) {
376
- // BUN_INSTALL defaults to ~/.bun; if our package lives under that tree, prefer bun
377
- // If npm not detected but bun is available, choose bun
378
- return 'bun'
379
- }
380
- } catch {}
381
-
382
- // Default to npm when uncertain
383
- return 'npm'
384
- }
385
-
386
- function runStreaming(cmd: string, args: string[]): Promise<number> {
387
- return new Promise(resolve => {
388
- // 打印正在使用的包管理器与命令,增强透明度
389
- try {
390
- // eslint-disable-next-line no-console
391
- console.log(`> ${cmd} ${args.join(' ')}`)
392
- } catch {}
393
-
394
- const child = spawn(cmd, args, {
395
- stdio: 'inherit',
396
- env: process.env,
397
- })
398
- child.on('close', code => resolve(code ?? 0))
399
- child.on('error', () => resolve(1))
400
- })
401
- }
402
-
403
- /**
404
- * Generate human-friendly update commands for the detected package manager.
405
- * Also includes an alternative manager command as fallback for users.
406
- */
407
- export async function getUpdateCommandSuggestions(): Promise<string[]> {
408
- // Prefer Bun first, then npm (consistent, simple UX). Include @latest.
409
- return [
410
- `bun add -g ${MACRO.PACKAGE_URL}@latest`,
411
- `npm install -g ${MACRO.PACKAGE_URL}@latest`,
412
- ]
413
- }
414
-
415
- /**
416
- * Non-blocking update notifier (daily)
417
- * - Respects CI and disabled auto-updater
418
- * - Uses env.hasInternetAccess() to quickly skip offline cases
419
- * - Stores last check timestamp + last suggested version in global config
420
- */
421
- export async function checkAndNotifyUpdate(): Promise<void> {
422
- try {
423
- if (process.env.NODE_ENV === 'test') return
424
- if (await isAutoUpdaterDisabled()) return
425
- if (await env.getIsDocker()) return
426
- if (!(await env.hasInternetAccess())) return
427
-
428
- const config: any = getGlobalConfig()
429
- const now = Date.now()
430
- const DAY_MS = 24 * 60 * 60 * 1000
431
- const lastCheck = Number(config.lastUpdateCheckAt || 0)
432
- if (lastCheck && now - lastCheck < DAY_MS) return
433
-
434
- const latest = await getLatestVersion()
435
- if (!latest) {
436
- // Still record the check to avoid spamming
437
- saveGlobalConfig({ ...config, lastUpdateCheckAt: now })
438
- return
439
- }
440
-
441
- if (gt(latest, MACRO.VERSION)) {
442
- // Update stored state and print a low-noise hint
443
- saveGlobalConfig({
444
- ...config,
445
- lastUpdateCheckAt: now,
446
- lastSuggestedVersion: latest,
447
- })
448
- const suggestions = await getUpdateCommandSuggestions()
449
- const first = suggestions[0]
450
- console.log(`New version available: ${latest}. Recommended: ${first}`)
451
- } else {
452
- saveGlobalConfig({ ...config, lastUpdateCheckAt: now })
453
- }
454
- } catch (error) {
455
- // Never block or throw; just log and move on
456
- logError(`update-notify: ${error}`)
457
- }
458
- }
@@ -1,20 +0,0 @@
1
- import { memoize } from 'lodash-es'
2
- import { checkGate } from '../services/statsig'
3
- import {
4
- GATE_TOKEN_EFFICIENT_TOOLS,
5
- BETA_HEADER_TOKEN_EFFICIENT_TOOLS,
6
- CLAUDE_CODE_20250219_BETA_HEADER,
7
- } from '../constants/betas.js'
8
-
9
- export const getBetas = memoize(async (): Promise<string[]> => {
10
- const betaHeaders = [CLAUDE_CODE_20250219_BETA_HEADER]
11
-
12
- if (process.env.USER_TYPE === 'ant' || process.env.SWE_BENCH) {
13
- const useTokenEfficientTools = await checkGate(GATE_TOKEN_EFFICIENT_TOOLS)
14
- if (useTokenEfficientTools) {
15
- betaHeaders.push(BETA_HEADER_TOKEN_EFFICIENT_TOOLS)
16
- }
17
- }
18
-
19
- return betaHeaders
20
- })
@@ -1,14 +0,0 @@
1
- import { execFileNoThrow } from './execFileNoThrow'
2
-
3
- export async function openBrowser(url: string): Promise<boolean> {
4
- const platform = process.platform
5
- const command =
6
- platform === 'win32' ? 'start' : platform === 'darwin' ? 'open' : 'xdg-open'
7
-
8
- try {
9
- const { code } = await execFileNoThrow(command, [url])
10
- return code === 0
11
- } catch (_) {
12
- return false
13
- }
14
- }
@@ -1,72 +0,0 @@
1
- import { promises as fs } from 'fs'
2
- import { join } from 'path'
3
- import { logError } from './log'
4
- import { CACHE_PATHS } from './log'
5
-
6
- const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000
7
-
8
- export type CleanupResult = {
9
- messages: number
10
- errors: number
11
- }
12
-
13
- export function convertFileNameToDate(filename: string): Date {
14
- const isoStr = filename
15
- .split('.')[0]!
16
- .replace(/T(\d{2})-(\d{2})-(\d{2})-(\d{3})Z/, 'T$1:$2:$3.$4Z')
17
- return new Date(isoStr)
18
- }
19
-
20
- export async function cleanupOldMessageFiles(): Promise<CleanupResult> {
21
- const messagePath = CACHE_PATHS.messages()
22
- const errorPath = CACHE_PATHS.errors()
23
- const thirtyDaysAgo = new Date(Date.now() - THIRTY_DAYS_MS)
24
- const deletedCounts: CleanupResult = { messages: 0, errors: 0 }
25
-
26
- for (const path of [messagePath, errorPath]) {
27
- try {
28
- const files = await fs.readdir(path)
29
-
30
- for (const file of files) {
31
- try {
32
- // Convert filename format where all ':.' were replaced with '-'
33
- const timestamp = convertFileNameToDate(file)
34
- if (timestamp < thirtyDaysAgo) {
35
- await fs.unlink(join(path, file))
36
- // Increment the appropriate counter
37
- if (path === messagePath) {
38
- deletedCounts.messages++
39
- } else {
40
- deletedCounts.errors++
41
- }
42
- }
43
- } catch (error: unknown) {
44
- // Log but continue processing other files
45
- logError(
46
- `Failed to process file ${file}: ${error instanceof Error ? error.message : String(error)}`,
47
- )
48
- }
49
- }
50
- } catch (error: unknown) {
51
- // Ignore if directory doesn't exist
52
- if (
53
- error instanceof Error &&
54
- 'code' in error &&
55
- error.code !== 'ENOENT'
56
- ) {
57
- logError(
58
- `Failed to cleanup directory ${path}: ${error instanceof Error ? error.message : String(error)}`,
59
- )
60
- }
61
- }
62
- }
63
-
64
- return deletedCounts
65
- }
66
-
67
- export function cleanupOldMessageFilesInBackground(): void {
68
- const immediate = setImmediate(cleanupOldMessageFiles)
69
-
70
- // Prevent the setImmediate from keeping the process alive
71
- immediate.unref()
72
- }