@shareai-lab/kode 1.1.13 → 1.1.16-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/commands/logout.tsx
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import type { Command } from '../commands'
|
|
3
|
-
import { getGlobalConfig, saveGlobalConfig } from '../utils/config'
|
|
4
|
-
import { clearTerminal } from '../utils/terminal'
|
|
5
|
-
import { Text } from 'ink'
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
type: 'local-jsx',
|
|
9
|
-
name: 'logout',
|
|
10
|
-
description: 'Sign out from your Anthropic account',
|
|
11
|
-
isEnabled: true,
|
|
12
|
-
isHidden: false,
|
|
13
|
-
async call() {
|
|
14
|
-
await clearTerminal()
|
|
15
|
-
|
|
16
|
-
const config = getGlobalConfig()
|
|
17
|
-
|
|
18
|
-
config.oauthAccount = undefined
|
|
19
|
-
config.hasCompletedOnboarding = false
|
|
20
|
-
|
|
21
|
-
if (config.customApiKeyResponses?.approved) {
|
|
22
|
-
config.customApiKeyResponses.approved = []
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
saveGlobalConfig(config)
|
|
26
|
-
|
|
27
|
-
const message = (
|
|
28
|
-
<Text>Successfully logged out from your Anthropic account.</Text>
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
setTimeout(() => {
|
|
32
|
-
process.exit(0)
|
|
33
|
-
}, 200)
|
|
34
|
-
|
|
35
|
-
return message
|
|
36
|
-
},
|
|
37
|
-
userFacingName() {
|
|
38
|
-
return 'logout'
|
|
39
|
-
},
|
|
40
|
-
} satisfies Command
|
package/src/commands/mcp.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import type { Command } from '../commands'
|
|
2
|
-
import { listMCPServers, getClients } from '../services/mcpClient'
|
|
3
|
-
import { PRODUCT_COMMAND } from '../constants/product'
|
|
4
|
-
import chalk from 'chalk'
|
|
5
|
-
import { getTheme } from '../utils/theme'
|
|
6
|
-
|
|
7
|
-
const mcp = {
|
|
8
|
-
type: 'local',
|
|
9
|
-
name: 'mcp',
|
|
10
|
-
description: 'Show MCP server connection status',
|
|
11
|
-
isEnabled: true,
|
|
12
|
-
isHidden: false,
|
|
13
|
-
async call() {
|
|
14
|
-
const servers = listMCPServers()
|
|
15
|
-
const clients = await getClients()
|
|
16
|
-
const theme = getTheme()
|
|
17
|
-
|
|
18
|
-
if (Object.keys(servers).length === 0) {
|
|
19
|
-
return `⎿ No MCP servers configured. Run \`${PRODUCT_COMMAND} mcp\` to learn about how to configure MCP servers.`
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Sort servers by name and format status with colors
|
|
23
|
-
const serverStatusLines = clients
|
|
24
|
-
.sort((a, b) => a.name.localeCompare(b.name))
|
|
25
|
-
.map(client => {
|
|
26
|
-
const isConnected = client.type === 'connected'
|
|
27
|
-
const status = isConnected ? 'connected' : 'disconnected'
|
|
28
|
-
const coloredStatus = isConnected
|
|
29
|
-
? chalk.hex(theme.success)(status)
|
|
30
|
-
: chalk.hex(theme.error)(status)
|
|
31
|
-
return `⎿ • ${client.name}: ${coloredStatus}`
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
return ['⎿ MCP Server Status', ...serverStatusLines].join('\n')
|
|
35
|
-
},
|
|
36
|
-
userFacingName() {
|
|
37
|
-
return 'mcp'
|
|
38
|
-
},
|
|
39
|
-
} satisfies Command
|
|
40
|
-
|
|
41
|
-
export default mcp
|
package/src/commands/model.tsx
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import { render } from 'ink'
|
|
3
|
-
import { ModelConfig } from '../components/ModelConfig'
|
|
4
|
-
import { enableConfigs } from '../utils/config'
|
|
5
|
-
import { triggerModelConfigChange } from '../messages'
|
|
6
|
-
|
|
7
|
-
export const help = 'Change your AI provider and model settings'
|
|
8
|
-
export const description = 'Change your AI provider and model settings'
|
|
9
|
-
export const isEnabled = true
|
|
10
|
-
export const isHidden = false
|
|
11
|
-
export const name = 'model'
|
|
12
|
-
export const type = 'local-jsx'
|
|
13
|
-
|
|
14
|
-
export function userFacingName(): string {
|
|
15
|
-
return name
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export async function call(
|
|
19
|
-
onDone: (result?: string) => void,
|
|
20
|
-
context: any,
|
|
21
|
-
): Promise<React.ReactNode> {
|
|
22
|
-
const { abortController } = context
|
|
23
|
-
enableConfigs()
|
|
24
|
-
abortController?.abort?.()
|
|
25
|
-
return (
|
|
26
|
-
<ModelConfig
|
|
27
|
-
onClose={() => {
|
|
28
|
-
// Force ModelManager reload to ensure UI sync - wait for completion before closing
|
|
29
|
-
import('../utils/model').then(({ reloadModelManager }) => {
|
|
30
|
-
reloadModelManager()
|
|
31
|
-
// 🔧 Critical fix: Trigger global UI refresh after model config changes
|
|
32
|
-
// This ensures PromptInput component detects ModelManager singleton state changes
|
|
33
|
-
triggerModelConfigChange()
|
|
34
|
-
// Only close after reload is complete to ensure UI synchronization
|
|
35
|
-
onDone()
|
|
36
|
-
})
|
|
37
|
-
}}
|
|
38
|
-
/>
|
|
39
|
-
)
|
|
40
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import React from 'react'
|
|
2
|
-
import type { Command } from '../commands'
|
|
3
|
-
import { ModelStatusDisplay } from '../components/ModelStatusDisplay'
|
|
4
|
-
|
|
5
|
-
const modelstatus: Command = {
|
|
6
|
-
name: 'modelstatus',
|
|
7
|
-
description: 'Display current model configuration and status',
|
|
8
|
-
aliases: ['ms', 'model-status'],
|
|
9
|
-
isEnabled: true,
|
|
10
|
-
isHidden: false,
|
|
11
|
-
userFacingName() {
|
|
12
|
-
return 'modelstatus'
|
|
13
|
-
},
|
|
14
|
-
type: 'local-jsx',
|
|
15
|
-
call(onDone) {
|
|
16
|
-
return Promise.resolve(<ModelStatusDisplay onClose={onDone} />)
|
|
17
|
-
},
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export default modelstatus
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import type { Command } from '../commands'
|
|
3
|
-
import { Onboarding } from '../components/Onboarding'
|
|
4
|
-
import { clearTerminal } from '../utils/terminal'
|
|
5
|
-
import { getGlobalConfig, saveGlobalConfig } from '../utils/config'
|
|
6
|
-
import { clearConversation } from './clear'
|
|
7
|
-
|
|
8
|
-
export default {
|
|
9
|
-
type: 'local-jsx',
|
|
10
|
-
name: 'onboarding',
|
|
11
|
-
description: 'Run through the onboarding flow',
|
|
12
|
-
isEnabled: true,
|
|
13
|
-
isHidden: false,
|
|
14
|
-
async call(onDone, context) {
|
|
15
|
-
await clearTerminal()
|
|
16
|
-
const config = getGlobalConfig()
|
|
17
|
-
saveGlobalConfig({
|
|
18
|
-
...config,
|
|
19
|
-
theme: 'dark',
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<Onboarding
|
|
24
|
-
onDone={async () => {
|
|
25
|
-
clearConversation(context)
|
|
26
|
-
onDone()
|
|
27
|
-
}}
|
|
28
|
-
/>
|
|
29
|
-
)
|
|
30
|
-
},
|
|
31
|
-
userFacingName() {
|
|
32
|
-
return 'onboarding'
|
|
33
|
-
},
|
|
34
|
-
} satisfies Command
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { Command } from '../commands'
|
|
2
|
-
|
|
3
|
-
export default {
|
|
4
|
-
type: 'prompt',
|
|
5
|
-
name: 'pr-comments',
|
|
6
|
-
description: 'Get comments from a GitHub pull request',
|
|
7
|
-
progressMessage: 'fetching PR comments',
|
|
8
|
-
isEnabled: true,
|
|
9
|
-
isHidden: false,
|
|
10
|
-
userFacingName() {
|
|
11
|
-
return 'pr-comments'
|
|
12
|
-
},
|
|
13
|
-
async getPromptForCommand(args: string) {
|
|
14
|
-
return [
|
|
15
|
-
{
|
|
16
|
-
role: 'user',
|
|
17
|
-
content: [
|
|
18
|
-
{
|
|
19
|
-
type: 'text',
|
|
20
|
-
text: `You are an AI assistant integrated into a git-based version control system. Your task is to fetch and display comments from a GitHub pull request.
|
|
21
|
-
|
|
22
|
-
Follow these steps:
|
|
23
|
-
|
|
24
|
-
1. Use \`gh pr view --json number,headRepository\` to get the PR number and repository info
|
|
25
|
-
2. Use \`gh api /repos/{owner}/{repo}/issues/{number}/comments\` to get PR-level comments
|
|
26
|
-
3. Use \`gh api /repos/{owner}/{repo}/pulls/{number}/comments\` to get review comments. Pay particular attention to the following fields: \`body\`, \`diff_hunk\`, \`path\`, \`line\`, etc. If the comment references some code, consider fetching it using eg \`gh api /repos/{owner}/{repo}/contents/{path}?ref={branch} | jq .content -r | base64 -d\`
|
|
27
|
-
4. Parse and format all comments in a readable way
|
|
28
|
-
5. Return ONLY the formatted comments, with no additional text
|
|
29
|
-
|
|
30
|
-
Format the comments as:
|
|
31
|
-
|
|
32
|
-
## Comments
|
|
33
|
-
|
|
34
|
-
[For each comment thread:]
|
|
35
|
-
- @author file.ts#line:
|
|
36
|
-
\`\`\`diff
|
|
37
|
-
[diff_hunk from the API response]
|
|
38
|
-
\`\`\`
|
|
39
|
-
> quoted comment text
|
|
40
|
-
|
|
41
|
-
[any replies indented]
|
|
42
|
-
|
|
43
|
-
If there are no comments, return "No comments found."
|
|
44
|
-
|
|
45
|
-
Remember:
|
|
46
|
-
1. Only show the actual comments, no explanatory text
|
|
47
|
-
2. Include both PR-level and code review comments
|
|
48
|
-
3. Preserve the threading/nesting of comment replies
|
|
49
|
-
4. Show the file and line number context for code review comments
|
|
50
|
-
5. Use jq to parse the JSON responses from the GitHub API
|
|
51
|
-
|
|
52
|
-
${args ? 'Additional user input: ' + args : ''}
|
|
53
|
-
`,
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
|
-
},
|
|
57
|
-
]
|
|
58
|
-
},
|
|
59
|
-
} satisfies Command
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { Command } from '../commands'
|
|
2
|
-
import { reloadCustomCommands } from '../services/customCommands'
|
|
3
|
-
import { getCommands } from '../commands'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Refresh Commands - Reload custom commands from filesystem
|
|
7
|
-
*
|
|
8
|
-
* This command provides a runtime mechanism to refresh the custom commands
|
|
9
|
-
* cache without restarting the application. It's particularly useful during
|
|
10
|
-
* development or when users are actively creating/modifying custom commands.
|
|
11
|
-
*
|
|
12
|
-
* The command follows the standard local command pattern used throughout
|
|
13
|
-
* the project and provides detailed feedback about the refresh operation.
|
|
14
|
-
*/
|
|
15
|
-
const refreshCommands = {
|
|
16
|
-
type: 'local',
|
|
17
|
-
name: 'refresh-commands',
|
|
18
|
-
description: 'Reload custom commands from filesystem',
|
|
19
|
-
isEnabled: true,
|
|
20
|
-
isHidden: false,
|
|
21
|
-
async call(_, context) {
|
|
22
|
-
try {
|
|
23
|
-
// Clear custom commands cache to force filesystem rescan
|
|
24
|
-
reloadCustomCommands()
|
|
25
|
-
|
|
26
|
-
// Clear the main commands cache to ensure full reload
|
|
27
|
-
// This ensures that changes to custom commands are reflected in the main command list
|
|
28
|
-
getCommands.cache.clear?.()
|
|
29
|
-
|
|
30
|
-
// Reload commands to get updated count and validate the refresh
|
|
31
|
-
const commands = await getCommands()
|
|
32
|
-
const customCommands = commands.filter(
|
|
33
|
-
cmd => cmd.name.startsWith('project:') || cmd.name.startsWith('user:'),
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
// Provide detailed feedback about the refresh operation
|
|
37
|
-
return `✅ Commands refreshed successfully!
|
|
38
|
-
|
|
39
|
-
Custom commands reloaded: ${customCommands.length}
|
|
40
|
-
- Project commands: ${customCommands.filter(cmd => cmd.name.startsWith('project:')).length}
|
|
41
|
-
- User commands: ${customCommands.filter(cmd => cmd.name.startsWith('user:')).length}
|
|
42
|
-
|
|
43
|
-
Use /help to see updated command list.`
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.error('Failed to refresh commands:', error)
|
|
46
|
-
return '❌ Failed to refresh commands. Check console for details.'
|
|
47
|
-
}
|
|
48
|
-
},
|
|
49
|
-
userFacingName() {
|
|
50
|
-
return 'refresh-commands'
|
|
51
|
-
},
|
|
52
|
-
} satisfies Command
|
|
53
|
-
|
|
54
|
-
export default refreshCommands
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { MACRO } from '../constants/macros.js'
|
|
2
|
-
import type { Command } from '../commands'
|
|
3
|
-
import { RELEASE_NOTES } from '../constants/releaseNotes'
|
|
4
|
-
|
|
5
|
-
const releaseNotes: Command = {
|
|
6
|
-
description: 'Show release notes for the current or specified version',
|
|
7
|
-
isEnabled: false,
|
|
8
|
-
isHidden: false,
|
|
9
|
-
name: 'release-notes',
|
|
10
|
-
userFacingName() {
|
|
11
|
-
return 'release-notes'
|
|
12
|
-
},
|
|
13
|
-
type: 'local',
|
|
14
|
-
async call(args) {
|
|
15
|
-
const currentVersion = MACRO.VERSION
|
|
16
|
-
|
|
17
|
-
// If a specific version is requested, show that version's notes
|
|
18
|
-
const requestedVersion = args ? args.trim() : currentVersion
|
|
19
|
-
|
|
20
|
-
// Get the requested version's notes
|
|
21
|
-
const notes = RELEASE_NOTES[requestedVersion]
|
|
22
|
-
|
|
23
|
-
if (!notes || notes.length === 0) {
|
|
24
|
-
return `No release notes available for version ${requestedVersion}.`
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const header = `Release notes for version ${requestedVersion}:`
|
|
28
|
-
const formattedNotes = notes.map(note => `• ${note}`).join('\n')
|
|
29
|
-
|
|
30
|
-
return `${header}\n\n${formattedNotes}`
|
|
31
|
-
},
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export default releaseNotes
|
package/src/commands/resume.tsx
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import type { Command } from '../commands'
|
|
3
|
-
import { ResumeConversation } from '../screens/ResumeConversation'
|
|
4
|
-
import { render } from 'ink'
|
|
5
|
-
import { CACHE_PATHS, loadLogList } from '../utils/log'
|
|
6
|
-
|
|
7
|
-
export default {
|
|
8
|
-
type: 'local-jsx',
|
|
9
|
-
name: 'resume',
|
|
10
|
-
description: 'Resume a previous conversation',
|
|
11
|
-
isEnabled: true,
|
|
12
|
-
isHidden: false,
|
|
13
|
-
userFacingName() {
|
|
14
|
-
return 'resume'
|
|
15
|
-
},
|
|
16
|
-
async call(onDone, context) {
|
|
17
|
-
const { commands = [], tools = [], verbose = false } = context.options || {}
|
|
18
|
-
const logs = await loadLogList(CACHE_PATHS.messages())
|
|
19
|
-
render(
|
|
20
|
-
<ResumeConversation
|
|
21
|
-
commands={commands}
|
|
22
|
-
context={{ unmount: onDone }}
|
|
23
|
-
logs={logs}
|
|
24
|
-
tools={tools}
|
|
25
|
-
verbose={verbose}
|
|
26
|
-
/>,
|
|
27
|
-
)
|
|
28
|
-
// This return is here for type only
|
|
29
|
-
return null
|
|
30
|
-
},
|
|
31
|
-
} satisfies Command
|
package/src/commands/review.ts
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { Command } from '../commands'
|
|
2
|
-
import { BashTool } from '../tools/BashTool/BashTool'
|
|
3
|
-
|
|
4
|
-
export default {
|
|
5
|
-
type: 'prompt',
|
|
6
|
-
name: 'review',
|
|
7
|
-
description: 'Review a pull request',
|
|
8
|
-
isEnabled: true,
|
|
9
|
-
isHidden: false,
|
|
10
|
-
progressMessage: 'reviewing pull request',
|
|
11
|
-
userFacingName() {
|
|
12
|
-
return 'review'
|
|
13
|
-
},
|
|
14
|
-
async getPromptForCommand(args) {
|
|
15
|
-
return [
|
|
16
|
-
{
|
|
17
|
-
role: 'user',
|
|
18
|
-
content: [
|
|
19
|
-
{
|
|
20
|
-
type: 'text',
|
|
21
|
-
text: `
|
|
22
|
-
You are an expert code reviewer. Follow these steps:
|
|
23
|
-
|
|
24
|
-
1. If no PR number is provided in the args, use ${BashTool.name}("gh pr list") to show open PRs
|
|
25
|
-
2. If a PR number is provided, use ${BashTool.name}("gh pr view <number>") to get PR details
|
|
26
|
-
3. Use ${BashTool.name}("gh pr diff <number>") to get the diff
|
|
27
|
-
4. Analyze the changes and provide a thorough code review that includes:
|
|
28
|
-
- Overview of what the PR does
|
|
29
|
-
- Analysis of code quality and style
|
|
30
|
-
- Specific suggestions for improvements
|
|
31
|
-
- Any potential issues or risks
|
|
32
|
-
|
|
33
|
-
Keep your review concise but thorough. Focus on:
|
|
34
|
-
- Code correctness
|
|
35
|
-
- Following project conventions
|
|
36
|
-
- Performance implications
|
|
37
|
-
- Test coverage
|
|
38
|
-
- Security considerations
|
|
39
|
-
|
|
40
|
-
Format your review with clear sections and bullet points.
|
|
41
|
-
|
|
42
|
-
PR number: ${args}
|
|
43
|
-
`,
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
},
|
|
47
|
-
]
|
|
48
|
-
},
|
|
49
|
-
} satisfies Command
|
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
import { Command } from '../commands'
|
|
2
|
-
import { EOL, platform, homedir } from 'os'
|
|
3
|
-
import { execFileNoThrow } from '../utils/execFileNoThrow'
|
|
4
|
-
import chalk from 'chalk'
|
|
5
|
-
import { getTheme } from '../utils/theme'
|
|
6
|
-
import { env } from '../utils/env'
|
|
7
|
-
import { getGlobalConfig, saveGlobalConfig } from '../utils/config'
|
|
8
|
-
import { markProjectOnboardingComplete } from '../ProjectOnboarding'
|
|
9
|
-
import { readFileSync, writeFileSync } from 'fs'
|
|
10
|
-
import { join } from 'path'
|
|
11
|
-
import { safeParseJSON } from '../utils/json'
|
|
12
|
-
import { logError } from '../utils/log'
|
|
13
|
-
|
|
14
|
-
const terminalSetup: Command = {
|
|
15
|
-
type: 'local',
|
|
16
|
-
name: 'terminal-setup',
|
|
17
|
-
userFacingName() {
|
|
18
|
-
return 'terminal-setup'
|
|
19
|
-
},
|
|
20
|
-
description:
|
|
21
|
-
'Install Shift+Enter key binding for newlines (iTerm2 and VSCode only)',
|
|
22
|
-
isEnabled:
|
|
23
|
-
(platform() === 'darwin' && env.terminal === 'iTerm.app') ||
|
|
24
|
-
env.terminal === 'vscode',
|
|
25
|
-
isHidden: false,
|
|
26
|
-
async call() {
|
|
27
|
-
let result = ''
|
|
28
|
-
|
|
29
|
-
switch (env.terminal) {
|
|
30
|
-
case 'iTerm.app':
|
|
31
|
-
result = await installBindingsForITerm2()
|
|
32
|
-
break
|
|
33
|
-
case 'vscode':
|
|
34
|
-
result = installBindingsForVSCodeTerminal()
|
|
35
|
-
break
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Update global config to indicate Shift+Enter key binding is installed
|
|
39
|
-
const config = getGlobalConfig()
|
|
40
|
-
config.shiftEnterKeyBindingInstalled = true
|
|
41
|
-
saveGlobalConfig(config)
|
|
42
|
-
|
|
43
|
-
// Mark onboarding as complete
|
|
44
|
-
markProjectOnboardingComplete()
|
|
45
|
-
|
|
46
|
-
return result
|
|
47
|
-
},
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function isShiftEnterKeyBindingInstalled(): boolean {
|
|
51
|
-
return getGlobalConfig().shiftEnterKeyBindingInstalled === true
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function handleHashCommand(interpreted: string): void {
|
|
55
|
-
// Appends the AI-interpreted content to both AGENTS.md and CLAUDE.md (if exists)
|
|
56
|
-
try {
|
|
57
|
-
const cwd = process.cwd()
|
|
58
|
-
const codeContextPath = join(cwd, 'AGENTS.md')
|
|
59
|
-
const claudePath = join(cwd, 'CLAUDE.md')
|
|
60
|
-
|
|
61
|
-
// Check which files exist and update them
|
|
62
|
-
const filesToUpdate = []
|
|
63
|
-
|
|
64
|
-
// Always try to update AGENTS.md (create if not exists)
|
|
65
|
-
filesToUpdate.push({ path: codeContextPath, name: 'AGENTS.md' })
|
|
66
|
-
|
|
67
|
-
// Update CLAUDE.md only if it exists
|
|
68
|
-
try {
|
|
69
|
-
readFileSync(claudePath, 'utf-8')
|
|
70
|
-
filesToUpdate.push({ path: claudePath, name: 'CLAUDE.md' })
|
|
71
|
-
} catch {
|
|
72
|
-
// CLAUDE.md doesn't exist, skip it
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const now = new Date()
|
|
76
|
-
const timezoneMatch = now.toString().match(/\(([A-Z]+)\)/)
|
|
77
|
-
const timezone = timezoneMatch
|
|
78
|
-
? timezoneMatch[1]
|
|
79
|
-
: now
|
|
80
|
-
.toLocaleTimeString('en-us', { timeZoneName: 'short' })
|
|
81
|
-
.split(' ')
|
|
82
|
-
.pop()
|
|
83
|
-
|
|
84
|
-
const timestamp = interpreted.includes(now.getFullYear().toString())
|
|
85
|
-
? ''
|
|
86
|
-
: `\n\n_Added on ${now.toLocaleString()} ${timezone}_`
|
|
87
|
-
|
|
88
|
-
const updatedFiles = []
|
|
89
|
-
|
|
90
|
-
for (const file of filesToUpdate) {
|
|
91
|
-
try {
|
|
92
|
-
// Check if file exists, if not create it
|
|
93
|
-
let existingContent = ''
|
|
94
|
-
try {
|
|
95
|
-
existingContent = readFileSync(file.path, 'utf-8').trim()
|
|
96
|
-
} catch (error) {
|
|
97
|
-
// File doesn't exist yet, that's fine
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Add a separator if the file already has content
|
|
101
|
-
const separator = existingContent ? '\n\n' : ''
|
|
102
|
-
|
|
103
|
-
// Combine everything and write to file
|
|
104
|
-
const newContent = `${existingContent}${separator}${interpreted}${timestamp}`
|
|
105
|
-
writeFileSync(file.path, newContent, 'utf-8')
|
|
106
|
-
updatedFiles.push(file.name)
|
|
107
|
-
} catch (error) {
|
|
108
|
-
logError(error)
|
|
109
|
-
console.error(
|
|
110
|
-
chalk.hex(getTheme().error)(
|
|
111
|
-
`Failed to update ${file.name}: ${error.message}`,
|
|
112
|
-
),
|
|
113
|
-
)
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (updatedFiles.length > 0) {
|
|
118
|
-
console.log(
|
|
119
|
-
chalk.hex(getTheme().success)(
|
|
120
|
-
`Added note to ${updatedFiles.join(' and ')}`,
|
|
121
|
-
),
|
|
122
|
-
)
|
|
123
|
-
}
|
|
124
|
-
} catch (e) {
|
|
125
|
-
logError(e)
|
|
126
|
-
console.error(
|
|
127
|
-
chalk.hex(getTheme().error)(`Failed to add note: ${e.message}`),
|
|
128
|
-
)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
export default terminalSetup
|
|
133
|
-
|
|
134
|
-
async function installBindingsForITerm2(): Promise<string> {
|
|
135
|
-
const { code } = await execFileNoThrow('defaults', [
|
|
136
|
-
'write',
|
|
137
|
-
'com.googlecode.iterm2',
|
|
138
|
-
'GlobalKeyMap',
|
|
139
|
-
'-dict-add',
|
|
140
|
-
'0xd-0x20000-0x24',
|
|
141
|
-
`<dict>
|
|
142
|
-
<key>Text</key>
|
|
143
|
-
<string>\\n</string>
|
|
144
|
-
<key>Action</key>
|
|
145
|
-
<integer>12</integer>
|
|
146
|
-
<key>Version</key>
|
|
147
|
-
<integer>1</integer>
|
|
148
|
-
<key>Keycode</key>
|
|
149
|
-
<integer>13</integer>
|
|
150
|
-
<key>Modifiers</key>
|
|
151
|
-
<integer>131072</integer>
|
|
152
|
-
</dict>`,
|
|
153
|
-
])
|
|
154
|
-
|
|
155
|
-
if (code !== 0) {
|
|
156
|
-
throw new Error('Failed to install iTerm2 Shift+Enter key binding')
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
return `${chalk.hex(getTheme().success)(
|
|
160
|
-
'Installed iTerm2 Shift+Enter key binding',
|
|
161
|
-
)}${EOL}${chalk.dim('See iTerm2 → Preferences → Keys')}${EOL}`
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
type VSCodeKeybinding = {
|
|
165
|
-
key: string
|
|
166
|
-
command: string
|
|
167
|
-
args: { text: string }
|
|
168
|
-
when: string
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function installBindingsForVSCodeTerminal(): string {
|
|
172
|
-
const vscodeKeybindingsPath = join(
|
|
173
|
-
homedir(),
|
|
174
|
-
platform() === 'win32'
|
|
175
|
-
? join('AppData', 'Roaming', 'Code', 'User')
|
|
176
|
-
: platform() === 'darwin'
|
|
177
|
-
? join('Library', 'Application Support', 'Code', 'User')
|
|
178
|
-
: join('.config', 'Code', 'User'),
|
|
179
|
-
'keybindings.json',
|
|
180
|
-
)
|
|
181
|
-
|
|
182
|
-
try {
|
|
183
|
-
const content = readFileSync(vscodeKeybindingsPath, 'utf-8')
|
|
184
|
-
const keybindings: VSCodeKeybinding[] =
|
|
185
|
-
(safeParseJSON(content) as VSCodeKeybinding[]) ?? []
|
|
186
|
-
|
|
187
|
-
// Check if keybinding already exists
|
|
188
|
-
const existingBinding = keybindings.find(
|
|
189
|
-
binding =>
|
|
190
|
-
binding.key === 'shift+enter' &&
|
|
191
|
-
binding.command === 'workbench.action.terminal.sendSequence' &&
|
|
192
|
-
binding.when === 'terminalFocus',
|
|
193
|
-
)
|
|
194
|
-
if (existingBinding) {
|
|
195
|
-
return `${chalk.hex(getTheme().warning)(
|
|
196
|
-
'Found existing VSCode terminal Shift+Enter key binding. Remove it to continue.',
|
|
197
|
-
)}${EOL}${chalk.dim(`See ${vscodeKeybindingsPath}`)}${EOL}`
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Add the keybinding
|
|
201
|
-
keybindings.push({
|
|
202
|
-
key: 'shift+enter',
|
|
203
|
-
command: 'workbench.action.terminal.sendSequence',
|
|
204
|
-
args: { text: '\\\r\n' },
|
|
205
|
-
when: 'terminalFocus',
|
|
206
|
-
})
|
|
207
|
-
|
|
208
|
-
writeFileSync(
|
|
209
|
-
vscodeKeybindingsPath,
|
|
210
|
-
JSON.stringify(keybindings, null, 4),
|
|
211
|
-
'utf-8',
|
|
212
|
-
)
|
|
213
|
-
|
|
214
|
-
return `${chalk.hex(getTheme().success)(
|
|
215
|
-
'Installed VSCode terminal Shift+Enter key binding',
|
|
216
|
-
)}${EOL}${chalk.dim(`See ${vscodeKeybindingsPath}`)}${EOL}`
|
|
217
|
-
} catch (e) {
|
|
218
|
-
logError(e)
|
|
219
|
-
throw new Error('Failed to install VSCode terminal Shift+Enter key binding')
|
|
220
|
-
}
|
|
221
|
-
}
|