@shareai-lab/kode 1.1.14 → 1.1.16-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli.js +77 -82
- package/dist/entrypoints/cli.js +59 -38
- package/dist/entrypoints/cli.js.map +3 -3
- package/dist/index.js +5 -26
- package/dist/package.json +4 -1
- package/package.json +11 -104
- package/dist/test/testAdapters.js +0 -88
- package/dist/test/testAdapters.js.map +0 -1
- package/src/ProjectOnboarding.tsx +0 -198
- package/src/Tool.ts +0 -83
- package/src/commands/agents.tsx +0 -3416
- package/src/commands/approvedTools.ts +0 -53
- package/src/commands/bug.tsx +0 -20
- package/src/commands/clear.ts +0 -43
- package/src/commands/compact.ts +0 -120
- package/src/commands/config.tsx +0 -19
- package/src/commands/cost.ts +0 -18
- package/src/commands/ctx_viz.ts +0 -209
- package/src/commands/doctor.ts +0 -24
- package/src/commands/help.tsx +0 -19
- package/src/commands/init.ts +0 -37
- package/src/commands/listen.ts +0 -42
- package/src/commands/login.tsx +0 -51
- package/src/commands/logout.tsx +0 -40
- package/src/commands/mcp.ts +0 -41
- package/src/commands/model.tsx +0 -40
- package/src/commands/modelstatus.tsx +0 -20
- package/src/commands/onboarding.tsx +0 -34
- package/src/commands/pr_comments.ts +0 -59
- package/src/commands/refreshCommands.ts +0 -54
- package/src/commands/release-notes.ts +0 -34
- package/src/commands/resume.tsx +0 -31
- package/src/commands/review.ts +0 -49
- package/src/commands/terminalSetup.ts +0 -221
- package/src/commands.ts +0 -139
- package/src/components/ApproveApiKey.tsx +0 -93
- package/src/components/AsciiLogo.tsx +0 -13
- package/src/components/AutoUpdater.tsx +0 -148
- package/src/components/Bug.tsx +0 -367
- package/src/components/Config.tsx +0 -293
- package/src/components/ConsoleOAuthFlow.tsx +0 -327
- package/src/components/Cost.tsx +0 -23
- package/src/components/CostThresholdDialog.tsx +0 -46
- package/src/components/CustomSelect/option-map.ts +0 -42
- package/src/components/CustomSelect/select-option.tsx +0 -78
- package/src/components/CustomSelect/select.tsx +0 -152
- package/src/components/CustomSelect/theme.ts +0 -45
- package/src/components/CustomSelect/use-select-state.ts +0 -414
- package/src/components/CustomSelect/use-select.ts +0 -35
- package/src/components/FallbackToolUseRejectedMessage.tsx +0 -15
- package/src/components/FileEditToolUpdatedMessage.tsx +0 -66
- package/src/components/Help.tsx +0 -215
- package/src/components/HighlightedCode.tsx +0 -33
- package/src/components/InvalidConfigDialog.tsx +0 -113
- package/src/components/Link.tsx +0 -32
- package/src/components/LogSelector.tsx +0 -86
- package/src/components/Logo.tsx +0 -170
- package/src/components/MCPServerApprovalDialog.tsx +0 -100
- package/src/components/MCPServerDialogCopy.tsx +0 -25
- package/src/components/MCPServerMultiselectDialog.tsx +0 -109
- package/src/components/Message.tsx +0 -221
- package/src/components/MessageResponse.tsx +0 -15
- package/src/components/MessageSelector.tsx +0 -211
- package/src/components/ModeIndicator.tsx +0 -88
- package/src/components/ModelConfig.tsx +0 -301
- package/src/components/ModelListManager.tsx +0 -227
- package/src/components/ModelSelector.tsx +0 -3387
- package/src/components/ModelStatusDisplay.tsx +0 -230
- package/src/components/Onboarding.tsx +0 -274
- package/src/components/PressEnterToContinue.tsx +0 -11
- package/src/components/PromptInput.tsx +0 -760
- package/src/components/SentryErrorBoundary.ts +0 -39
- package/src/components/Spinner.tsx +0 -129
- package/src/components/StickerRequestForm.tsx +0 -16
- package/src/components/StructuredDiff.tsx +0 -191
- package/src/components/TextInput.tsx +0 -259
- package/src/components/TodoItem.tsx +0 -47
- package/src/components/TokenWarning.tsx +0 -31
- package/src/components/ToolUseLoader.tsx +0 -40
- package/src/components/TrustDialog.tsx +0 -106
- package/src/components/binary-feedback/BinaryFeedback.tsx +0 -63
- package/src/components/binary-feedback/BinaryFeedbackOption.tsx +0 -111
- package/src/components/binary-feedback/BinaryFeedbackView.tsx +0 -172
- package/src/components/binary-feedback/utils.ts +0 -220
- package/src/components/messages/AssistantBashOutputMessage.tsx +0 -22
- package/src/components/messages/AssistantLocalCommandOutputMessage.tsx +0 -49
- package/src/components/messages/AssistantRedactedThinkingMessage.tsx +0 -19
- package/src/components/messages/AssistantTextMessage.tsx +0 -144
- package/src/components/messages/AssistantThinkingMessage.tsx +0 -40
- package/src/components/messages/AssistantToolUseMessage.tsx +0 -132
- package/src/components/messages/TaskProgressMessage.tsx +0 -32
- package/src/components/messages/TaskToolMessage.tsx +0 -58
- package/src/components/messages/UserBashInputMessage.tsx +0 -28
- package/src/components/messages/UserCommandMessage.tsx +0 -30
- package/src/components/messages/UserKodingInputMessage.tsx +0 -28
- package/src/components/messages/UserPromptMessage.tsx +0 -35
- package/src/components/messages/UserTextMessage.tsx +0 -39
- package/src/components/messages/UserToolResultMessage/UserToolCanceledMessage.tsx +0 -12
- package/src/components/messages/UserToolResultMessage/UserToolErrorMessage.tsx +0 -36
- package/src/components/messages/UserToolResultMessage/UserToolRejectMessage.tsx +0 -31
- package/src/components/messages/UserToolResultMessage/UserToolResultMessage.tsx +0 -57
- package/src/components/messages/UserToolResultMessage/UserToolSuccessMessage.tsx +0 -35
- package/src/components/messages/UserToolResultMessage/utils.tsx +0 -56
- package/src/components/permissions/BashPermissionRequest/BashPermissionRequest.tsx +0 -121
- package/src/components/permissions/FallbackPermissionRequest.tsx +0 -153
- package/src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx +0 -182
- package/src/components/permissions/FileEditPermissionRequest/FileEditToolDiff.tsx +0 -77
- package/src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.tsx +0 -164
- package/src/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.tsx +0 -83
- package/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx +0 -240
- package/src/components/permissions/PermissionRequest.tsx +0 -101
- package/src/components/permissions/PermissionRequestTitle.tsx +0 -69
- package/src/components/permissions/hooks.ts +0 -44
- package/src/components/permissions/toolUseOptions.ts +0 -59
- package/src/components/permissions/utils.ts +0 -23
- package/src/constants/betas.ts +0 -5
- package/src/constants/claude-asterisk-ascii-art.tsx +0 -238
- package/src/constants/figures.ts +0 -4
- package/src/constants/keys.ts +0 -3
- package/src/constants/macros.ts +0 -11
- package/src/constants/modelCapabilities.ts +0 -179
- package/src/constants/models.ts +0 -1025
- package/src/constants/oauth.ts +0 -18
- package/src/constants/product.ts +0 -17
- package/src/constants/prompts.ts +0 -168
- package/src/constants/releaseNotes.ts +0 -7
- package/src/context/PermissionContext.tsx +0 -149
- package/src/context.ts +0 -278
- package/src/cost-tracker.ts +0 -84
- package/src/entrypoints/cli.tsx +0 -1561
- package/src/entrypoints/mcp.ts +0 -175
- package/src/history.ts +0 -25
- package/src/hooks/useApiKeyVerification.ts +0 -59
- package/src/hooks/useArrowKeyHistory.ts +0 -55
- package/src/hooks/useCanUseTool.ts +0 -138
- package/src/hooks/useCancelRequest.ts +0 -39
- package/src/hooks/useDoublePress.ts +0 -41
- package/src/hooks/useExitOnCtrlCD.ts +0 -31
- package/src/hooks/useInterval.ts +0 -25
- package/src/hooks/useLogMessages.ts +0 -16
- package/src/hooks/useLogStartupTime.ts +0 -12
- package/src/hooks/useNotifyAfterTimeout.ts +0 -65
- package/src/hooks/usePermissionRequestLogging.ts +0 -44
- package/src/hooks/useTerminalSize.ts +0 -49
- package/src/hooks/useTextInput.ts +0 -317
- package/src/hooks/useUnifiedCompletion.ts +0 -1405
- package/src/index.ts +0 -34
- package/src/messages.ts +0 -38
- package/src/permissions.ts +0 -268
- package/src/query.ts +0 -720
- package/src/screens/ConfigureNpmPrefix.tsx +0 -197
- package/src/screens/Doctor.tsx +0 -219
- package/src/screens/LogList.tsx +0 -68
- package/src/screens/REPL.tsx +0 -813
- package/src/screens/ResumeConversation.tsx +0 -68
- package/src/services/adapters/base.ts +0 -38
- package/src/services/adapters/chatCompletions.ts +0 -90
- package/src/services/adapters/responsesAPI.ts +0 -170
- package/src/services/browserMocks.ts +0 -66
- package/src/services/claude.ts +0 -2197
- package/src/services/customCommands.ts +0 -704
- package/src/services/fileFreshness.ts +0 -377
- package/src/services/gpt5ConnectionTest.ts +0 -340
- package/src/services/mcpClient.ts +0 -564
- package/src/services/mcpServerApproval.tsx +0 -50
- package/src/services/mentionProcessor.ts +0 -273
- package/src/services/modelAdapterFactory.ts +0 -69
- package/src/services/notifier.ts +0 -40
- package/src/services/oauth.ts +0 -357
- package/src/services/openai.ts +0 -1359
- package/src/services/responseStateManager.ts +0 -90
- package/src/services/sentry.ts +0 -3
- package/src/services/statsig.ts +0 -172
- package/src/services/statsigStorage.ts +0 -86
- package/src/services/systemReminder.ts +0 -507
- package/src/services/vcr.ts +0 -161
- package/src/test/testAdapters.ts +0 -96
- package/src/tools/ArchitectTool/ArchitectTool.tsx +0 -135
- package/src/tools/ArchitectTool/prompt.ts +0 -15
- package/src/tools/AskExpertModelTool/AskExpertModelTool.tsx +0 -576
- package/src/tools/BashTool/BashTool.tsx +0 -243
- package/src/tools/BashTool/BashToolResultMessage.tsx +0 -38
- package/src/tools/BashTool/OutputLine.tsx +0 -49
- package/src/tools/BashTool/prompt.ts +0 -174
- package/src/tools/BashTool/utils.ts +0 -56
- package/src/tools/FileEditTool/FileEditTool.tsx +0 -319
- package/src/tools/FileEditTool/prompt.ts +0 -51
- package/src/tools/FileEditTool/utils.ts +0 -58
- package/src/tools/FileReadTool/FileReadTool.tsx +0 -404
- package/src/tools/FileReadTool/prompt.ts +0 -7
- package/src/tools/FileWriteTool/FileWriteTool.tsx +0 -301
- package/src/tools/FileWriteTool/prompt.ts +0 -10
- package/src/tools/GlobTool/GlobTool.tsx +0 -119
- package/src/tools/GlobTool/prompt.ts +0 -8
- package/src/tools/GrepTool/GrepTool.tsx +0 -147
- package/src/tools/GrepTool/prompt.ts +0 -11
- package/src/tools/MCPTool/MCPTool.tsx +0 -107
- package/src/tools/MCPTool/prompt.ts +0 -3
- package/src/tools/MemoryReadTool/MemoryReadTool.tsx +0 -127
- package/src/tools/MemoryReadTool/prompt.ts +0 -3
- package/src/tools/MemoryWriteTool/MemoryWriteTool.tsx +0 -89
- package/src/tools/MemoryWriteTool/prompt.ts +0 -3
- package/src/tools/MultiEditTool/MultiEditTool.tsx +0 -388
- package/src/tools/MultiEditTool/prompt.ts +0 -45
- package/src/tools/NotebookEditTool/NotebookEditTool.tsx +0 -298
- package/src/tools/NotebookEditTool/prompt.ts +0 -3
- package/src/tools/NotebookReadTool/NotebookReadTool.tsx +0 -258
- package/src/tools/NotebookReadTool/prompt.ts +0 -3
- package/src/tools/StickerRequestTool/StickerRequestTool.tsx +0 -107
- package/src/tools/StickerRequestTool/prompt.ts +0 -19
- package/src/tools/TaskTool/TaskTool.tsx +0 -438
- package/src/tools/TaskTool/constants.ts +0 -1
- package/src/tools/TaskTool/prompt.ts +0 -92
- package/src/tools/ThinkTool/ThinkTool.tsx +0 -54
- package/src/tools/ThinkTool/prompt.ts +0 -12
- package/src/tools/TodoWriteTool/TodoWriteTool.tsx +0 -313
- package/src/tools/TodoWriteTool/prompt.ts +0 -63
- package/src/tools/URLFetcherTool/URLFetcherTool.tsx +0 -178
- package/src/tools/URLFetcherTool/cache.ts +0 -55
- package/src/tools/URLFetcherTool/htmlToMarkdown.ts +0 -55
- package/src/tools/URLFetcherTool/prompt.ts +0 -17
- package/src/tools/WebSearchTool/WebSearchTool.tsx +0 -103
- package/src/tools/WebSearchTool/prompt.ts +0 -13
- package/src/tools/WebSearchTool/searchProviders.ts +0 -66
- package/src/tools/lsTool/lsTool.tsx +0 -272
- package/src/tools/lsTool/prompt.ts +0 -2
- package/src/tools.ts +0 -67
- package/src/types/PermissionMode.ts +0 -120
- package/src/types/RequestContext.ts +0 -72
- package/src/types/common.d.ts +0 -2
- package/src/types/conversation.ts +0 -51
- package/src/types/logs.ts +0 -58
- package/src/types/modelCapabilities.ts +0 -64
- package/src/types/notebook.ts +0 -87
- package/src/utils/Cursor.ts +0 -436
- package/src/utils/PersistentShell.ts +0 -552
- package/src/utils/advancedFuzzyMatcher.ts +0 -290
- package/src/utils/agentLoader.ts +0 -278
- package/src/utils/agentStorage.ts +0 -97
- package/src/utils/array.ts +0 -3
- package/src/utils/ask.tsx +0 -99
- package/src/utils/auth.ts +0 -13
- package/src/utils/autoCompactCore.ts +0 -223
- package/src/utils/autoUpdater.ts +0 -458
- package/src/utils/betas.ts +0 -20
- package/src/utils/browser.ts +0 -14
- package/src/utils/cleanup.ts +0 -72
- package/src/utils/commands.ts +0 -261
- package/src/utils/commonUnixCommands.ts +0 -161
- package/src/utils/config.ts +0 -945
- package/src/utils/conversationRecovery.ts +0 -55
- package/src/utils/debugLogger.ts +0 -1235
- package/src/utils/diff.ts +0 -42
- package/src/utils/env.ts +0 -57
- package/src/utils/errors.ts +0 -21
- package/src/utils/exampleCommands.ts +0 -109
- package/src/utils/execFileNoThrow.ts +0 -51
- package/src/utils/expertChatStorage.ts +0 -136
- package/src/utils/file.ts +0 -405
- package/src/utils/fileRecoveryCore.ts +0 -71
- package/src/utils/format.tsx +0 -44
- package/src/utils/fuzzyMatcher.ts +0 -328
- package/src/utils/generators.ts +0 -62
- package/src/utils/git.ts +0 -92
- package/src/utils/globalLogger.ts +0 -77
- package/src/utils/http.ts +0 -10
- package/src/utils/imagePaste.ts +0 -38
- package/src/utils/json.ts +0 -13
- package/src/utils/log.ts +0 -382
- package/src/utils/markdown.ts +0 -213
- package/src/utils/messageContextManager.ts +0 -294
- package/src/utils/messages.tsx +0 -945
- package/src/utils/model.ts +0 -914
- package/src/utils/permissions/filesystem.ts +0 -127
- package/src/utils/responseState.ts +0 -23
- package/src/utils/ripgrep.ts +0 -167
- package/src/utils/secureFile.ts +0 -564
- package/src/utils/sessionState.ts +0 -49
- package/src/utils/state.ts +0 -25
- package/src/utils/style.ts +0 -29
- package/src/utils/terminal.ts +0 -50
- package/src/utils/theme.ts +0 -127
- package/src/utils/thinking.ts +0 -144
- package/src/utils/todoStorage.ts +0 -431
- package/src/utils/tokens.ts +0 -43
- package/src/utils/toolExecutionController.ts +0 -163
- package/src/utils/unaryLogging.ts +0 -26
- package/src/utils/user.ts +0 -37
- package/src/utils/validate.ts +0 -165
package/src/utils/autoUpdater.ts
DELETED
|
@@ -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
|
-
}
|
package/src/utils/betas.ts
DELETED
|
@@ -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
|
-
})
|
package/src/utils/browser.ts
DELETED
|
@@ -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
|
-
}
|
package/src/utils/cleanup.ts
DELETED
|
@@ -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
|
-
}
|