@shareai-lab/kode 1.0.71 → 1.0.75

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 (108) hide show
  1. package/README.md +160 -1
  2. package/README.zh-CN.md +65 -1
  3. package/cli.js +5 -10
  4. package/package.json +6 -2
  5. package/src/ProjectOnboarding.tsx +47 -29
  6. package/src/Tool.ts +33 -4
  7. package/src/commands/agents.tsx +3401 -0
  8. package/src/commands/help.tsx +2 -2
  9. package/src/commands/resume.tsx +2 -1
  10. package/src/commands/terminalSetup.ts +4 -4
  11. package/src/commands.ts +3 -0
  12. package/src/components/ApproveApiKey.tsx +1 -1
  13. package/src/components/Config.tsx +10 -6
  14. package/src/components/ConsoleOAuthFlow.tsx +5 -4
  15. package/src/components/CustomSelect/select-option.tsx +28 -2
  16. package/src/components/CustomSelect/select.tsx +14 -5
  17. package/src/components/CustomSelect/theme.ts +45 -0
  18. package/src/components/Help.tsx +4 -4
  19. package/src/components/InvalidConfigDialog.tsx +1 -1
  20. package/src/components/LogSelector.tsx +1 -1
  21. package/src/components/MCPServerApprovalDialog.tsx +1 -1
  22. package/src/components/Message.tsx +2 -0
  23. package/src/components/ModelListManager.tsx +10 -6
  24. package/src/components/ModelSelector.tsx +201 -23
  25. package/src/components/ModelStatusDisplay.tsx +7 -5
  26. package/src/components/PromptInput.tsx +146 -96
  27. package/src/components/SentryErrorBoundary.ts +9 -3
  28. package/src/components/StickerRequestForm.tsx +16 -0
  29. package/src/components/StructuredDiff.tsx +36 -29
  30. package/src/components/TextInput.tsx +13 -0
  31. package/src/components/TodoItem.tsx +47 -0
  32. package/src/components/TrustDialog.tsx +1 -1
  33. package/src/components/messages/AssistantLocalCommandOutputMessage.tsx +5 -1
  34. package/src/components/messages/AssistantToolUseMessage.tsx +14 -4
  35. package/src/components/messages/TaskProgressMessage.tsx +32 -0
  36. package/src/components/messages/TaskToolMessage.tsx +58 -0
  37. package/src/components/permissions/FallbackPermissionRequest.tsx +2 -4
  38. package/src/components/permissions/FileEditPermissionRequest/FileEditPermissionRequest.tsx +1 -1
  39. package/src/components/permissions/FileEditPermissionRequest/FileEditToolDiff.tsx +5 -3
  40. package/src/components/permissions/FileWritePermissionRequest/FileWritePermissionRequest.tsx +1 -1
  41. package/src/components/permissions/FileWritePermissionRequest/FileWriteToolDiff.tsx +5 -3
  42. package/src/components/permissions/FilesystemPermissionRequest/FilesystemPermissionRequest.tsx +2 -4
  43. package/src/components/permissions/PermissionRequest.tsx +3 -5
  44. package/src/constants/macros.ts +2 -0
  45. package/src/constants/modelCapabilities.ts +179 -0
  46. package/src/constants/models.ts +90 -0
  47. package/src/constants/product.ts +1 -1
  48. package/src/context.ts +7 -7
  49. package/src/entrypoints/cli.tsx +23 -3
  50. package/src/entrypoints/mcp.ts +10 -10
  51. package/src/hooks/useCanUseTool.ts +1 -1
  52. package/src/hooks/useTextInput.ts +5 -2
  53. package/src/hooks/useUnifiedCompletion.ts +1405 -0
  54. package/src/messages.ts +1 -0
  55. package/src/query.ts +3 -0
  56. package/src/screens/ConfigureNpmPrefix.tsx +1 -1
  57. package/src/screens/Doctor.tsx +1 -1
  58. package/src/screens/REPL.tsx +11 -12
  59. package/src/services/adapters/base.ts +38 -0
  60. package/src/services/adapters/chatCompletions.ts +90 -0
  61. package/src/services/adapters/responsesAPI.ts +170 -0
  62. package/src/services/claude.ts +198 -62
  63. package/src/services/customCommands.ts +43 -22
  64. package/src/services/gpt5ConnectionTest.ts +340 -0
  65. package/src/services/mcpClient.ts +1 -1
  66. package/src/services/mentionProcessor.ts +273 -0
  67. package/src/services/modelAdapterFactory.ts +69 -0
  68. package/src/services/openai.ts +534 -14
  69. package/src/services/responseStateManager.ts +90 -0
  70. package/src/services/systemReminder.ts +113 -12
  71. package/src/test/testAdapters.ts +96 -0
  72. package/src/tools/AskExpertModelTool/AskExpertModelTool.tsx +120 -56
  73. package/src/tools/BashTool/BashTool.tsx +4 -31
  74. package/src/tools/BashTool/BashToolResultMessage.tsx +1 -1
  75. package/src/tools/BashTool/OutputLine.tsx +1 -0
  76. package/src/tools/FileEditTool/FileEditTool.tsx +4 -5
  77. package/src/tools/FileReadTool/FileReadTool.tsx +43 -10
  78. package/src/tools/MCPTool/MCPTool.tsx +2 -1
  79. package/src/tools/MultiEditTool/MultiEditTool.tsx +2 -2
  80. package/src/tools/NotebookReadTool/NotebookReadTool.tsx +15 -23
  81. package/src/tools/StickerRequestTool/StickerRequestTool.tsx +1 -1
  82. package/src/tools/TaskTool/TaskTool.tsx +170 -86
  83. package/src/tools/TaskTool/prompt.ts +61 -25
  84. package/src/tools/ThinkTool/ThinkTool.tsx +1 -3
  85. package/src/tools/TodoWriteTool/TodoWriteTool.tsx +65 -41
  86. package/src/tools/lsTool/lsTool.tsx +5 -2
  87. package/src/tools.ts +16 -16
  88. package/src/types/conversation.ts +51 -0
  89. package/src/types/logs.ts +58 -0
  90. package/src/types/modelCapabilities.ts +64 -0
  91. package/src/types/notebook.ts +87 -0
  92. package/src/utils/advancedFuzzyMatcher.ts +290 -0
  93. package/src/utils/agentLoader.ts +284 -0
  94. package/src/utils/ask.tsx +1 -0
  95. package/src/utils/commands.ts +1 -1
  96. package/src/utils/commonUnixCommands.ts +161 -0
  97. package/src/utils/config.ts +173 -2
  98. package/src/utils/conversationRecovery.ts +1 -0
  99. package/src/utils/debugLogger.ts +13 -13
  100. package/src/utils/exampleCommands.ts +1 -0
  101. package/src/utils/fuzzyMatcher.ts +328 -0
  102. package/src/utils/messages.tsx +6 -5
  103. package/src/utils/model.ts +120 -42
  104. package/src/utils/responseState.ts +23 -0
  105. package/src/utils/secureFile.ts +559 -0
  106. package/src/utils/terminal.ts +1 -0
  107. package/src/utils/theme.ts +11 -0
  108. package/src/hooks/useSlashCommandTypeahead.ts +0 -137
@@ -20,7 +20,11 @@ export function AssistantLocalCommandOutputMessage({
20
20
  ].filter(Boolean)
21
21
 
22
22
  if (insides.length === 0) {
23
- insides = [<Text key="0">(No output)</Text>]
23
+ insides = [
24
+ <React.Fragment key="0">
25
+ <Text>(No output)</Text>
26
+ </React.Fragment>
27
+ ]
24
28
  }
25
29
 
26
30
  return [
@@ -9,6 +9,7 @@ import { getTheme } from '../../utils/theme'
9
9
  import { BLACK_CIRCLE } from '../../constants/figures'
10
10
  import { ThinkTool } from '../../tools/ThinkTool/ThinkTool'
11
11
  import { AssistantThinkingMessage } from './AssistantThinkingMessage'
12
+ import { TaskToolMessage } from './TaskToolMessage'
12
13
 
13
14
  type Props = {
14
15
  param: ToolUseBlockParam
@@ -61,7 +62,7 @@ export function AssistantToolUseMessage({
61
62
  )
62
63
  }
63
64
 
64
- const userFacingToolName = tool.userFacingName(param.input as never)
65
+ const userFacingToolName = tool.userFacingName ? tool.userFacingName(param.input) : tool.name
65
66
  return (
66
67
  <Box
67
68
  flexDirection="row"
@@ -86,9 +87,18 @@ export function AssistantToolUseMessage({
86
87
  isError={erroredToolUseIDs.has(param.id)}
87
88
  />
88
89
  ))}
89
- <Text color={color} bold={!isQueued}>
90
- {userFacingToolName}
91
- </Text>
90
+ {tool.name === 'Task' && param.input ? (
91
+ <TaskToolMessage
92
+ agentType={(param.input as any).subagent_type || 'general-purpose'}
93
+ bold={!isQueued}
94
+ >
95
+ {userFacingToolName}
96
+ </TaskToolMessage>
97
+ ) : (
98
+ <Text color={color} bold={!isQueued}>
99
+ {userFacingToolName}
100
+ </Text>
101
+ )}
92
102
  </Box>
93
103
  <Box flexWrap="nowrap">
94
104
  {Object.keys(param.input as { [key: string]: unknown }).length > 0 &&
@@ -0,0 +1,32 @@
1
+ import React from 'react'
2
+ import { Box, Text } from 'ink'
3
+ import { getTheme } from '../../utils/theme'
4
+
5
+ interface Props {
6
+ agentType: string
7
+ status: string
8
+ toolCount?: number
9
+ }
10
+
11
+ export function TaskProgressMessage({ agentType, status, toolCount }: Props) {
12
+ const theme = getTheme()
13
+
14
+ return (
15
+ <Box flexDirection="column" marginTop={1}>
16
+ <Box flexDirection="row">
17
+ <Text color={theme.claude}>⎯ </Text>
18
+ <Text color={theme.text} bold>
19
+ [{agentType}]
20
+ </Text>
21
+ <Text color={theme.secondaryText}> {status}</Text>
22
+ </Box>
23
+ {toolCount && toolCount > 0 && (
24
+ <Box marginLeft={3}>
25
+ <Text color={theme.secondaryText}>
26
+ Tools used: {toolCount}
27
+ </Text>
28
+ </Box>
29
+ )}
30
+ </Box>
31
+ )
32
+ }
@@ -0,0 +1,58 @@
1
+ import React, { useEffect, useState, useMemo } from 'react'
2
+ import { Text } from 'ink'
3
+ import { getAgentByType } from '../../utils/agentLoader'
4
+ import { getTheme } from '../../utils/theme'
5
+
6
+ interface Props {
7
+ agentType: string
8
+ children: React.ReactNode
9
+ bold?: boolean
10
+ }
11
+
12
+ // Simple cache to prevent re-fetching agent configs
13
+ const agentConfigCache = new Map<string, any>()
14
+
15
+ export function TaskToolMessage({ agentType, children, bold = true }: Props) {
16
+ const theme = getTheme()
17
+ const [agentConfig, setAgentConfig] = useState<any>(() => {
18
+ // Return cached config immediately if available
19
+ return agentConfigCache.get(agentType) || null
20
+ })
21
+
22
+ useEffect(() => {
23
+ // Skip if already cached
24
+ if (agentConfigCache.has(agentType)) {
25
+ setAgentConfig(agentConfigCache.get(agentType))
26
+ return
27
+ }
28
+
29
+ // Load and cache agent configuration
30
+ let mounted = true
31
+ getAgentByType(agentType).then(config => {
32
+ if (mounted) {
33
+ agentConfigCache.set(agentType, config)
34
+ setAgentConfig(config)
35
+ }
36
+ }).catch(() => {
37
+ // Silently handle errors to prevent console noise
38
+ if (mounted) {
39
+ agentConfigCache.set(agentType, null)
40
+ }
41
+ })
42
+
43
+ return () => {
44
+ mounted = false
45
+ }
46
+ }, [agentType])
47
+
48
+ // Memoize color calculation to prevent unnecessary re-renders
49
+ const color = useMemo(() => {
50
+ return agentConfig?.color || theme.text
51
+ }, [agentConfig?.color, theme.text])
52
+
53
+ return (
54
+ <Text color={color} bold={bold}>
55
+ {children}
56
+ </Text>
57
+ )
58
+ }
@@ -1,6 +1,6 @@
1
1
  import { Box, Text } from 'ink'
2
2
  import React, { useMemo } from 'react'
3
- import { Select } from '@inkjs/ui'
3
+ import { Select } from '../CustomSelect/select'
4
4
  import { getTheme } from '../../utils/theme'
5
5
  import {
6
6
  PermissionRequestTitle,
@@ -34,9 +34,7 @@ export function FallbackPermissionRequest({
34
34
  const theme = getTheme()
35
35
 
36
36
  // TODO: Avoid these special cases
37
- const originalUserFacingName = toolUseConfirm.tool.userFacingName(
38
- toolUseConfirm.input as never,
39
- )
37
+ const originalUserFacingName = toolUseConfirm.tool.userFacingName()
40
38
  const userFacingName = originalUserFacingName.endsWith(' (MCP)')
41
39
  ? originalUserFacingName.slice(0, -6)
42
40
  : originalUserFacingName
@@ -1,4 +1,4 @@
1
- import { Select } from '@inkjs/ui'
1
+ import { Select } from '../../CustomSelect/select'
2
2
  import chalk from 'chalk'
3
3
  import { Box, Text } from 'ink'
4
4
  import { basename, extname } from 'path'
@@ -64,9 +64,11 @@ export function FileEditToolDiff({
64
64
  />
65
65
  )),
66
66
  i => (
67
- <Text color={getTheme().secondaryText} key={`ellipsis-${i}`}>
68
- ...
69
- </Text>
67
+ <React.Fragment key={`ellipsis-${i}`}>
68
+ <Text color={getTheme().secondaryText}>
69
+ ...
70
+ </Text>
71
+ </React.Fragment>
70
72
  ),
71
73
  )}
72
74
  </Box>
@@ -1,6 +1,6 @@
1
1
  import { Box, Text } from 'ink'
2
2
  import React, { useMemo } from 'react'
3
- import { Select } from '@inkjs/ui'
3
+ import { Select } from '../../CustomSelect/select'
4
4
  import { basename, extname } from 'path'
5
5
  import { getTheme } from '../../../utils/theme'
6
6
  import {
@@ -65,9 +65,11 @@ export function FileWriteToolDiff({
65
65
  />
66
66
  )),
67
67
  i => (
68
- <Text color={getTheme().secondaryText} key={`ellipsis-${i}`}>
69
- ...
70
- </Text>
68
+ <React.Fragment key={`ellipsis-${i}`}>
69
+ <Text color={getTheme().secondaryText}>
70
+ ...
71
+ </Text>
72
+ </React.Fragment>
71
73
  ),
72
74
  )
73
75
  ) : (
@@ -1,6 +1,6 @@
1
1
  import { Box, Text } from 'ink'
2
2
  import React, { useMemo } from 'react'
3
- import { Select } from '@inkjs/ui'
3
+ import { Select } from '../../CustomSelect/select'
4
4
  import { getTheme } from '../../../utils/theme'
5
5
  import {
6
6
  PermissionRequestTitle,
@@ -133,9 +133,7 @@ function FilesystemPermissionRequestImpl({
133
133
  onDone,
134
134
  verbose,
135
135
  }: Props): React.ReactNode {
136
- const userFacingName = toolUseConfirm.tool.userFacingName(
137
- toolUseConfirm.input as never,
138
- )
136
+ const userFacingName = toolUseConfirm.tool.userFacingName()
139
137
 
140
138
  const userFacingReadOrWrite = toolUseConfirm.tool.isReadOnly()
141
139
  ? 'Read'
@@ -51,8 +51,8 @@ export function toolUseConfirmGetPrefix(
51
51
  ): string | null {
52
52
  return (
53
53
  (toolUseConfirm.commandPrefix &&
54
- !toolUseConfirm.commandPrefix.commandInjectionDetected &&
55
- toolUseConfirm.commandPrefix.commandPrefix) ||
54
+ !(toolUseConfirm.commandPrefix as any).commandInjectionDetected &&
55
+ (toolUseConfirm.commandPrefix as any).commandPrefix) ||
56
56
  null
57
57
  )
58
58
  }
@@ -84,9 +84,7 @@ export function PermissionRequest({
84
84
  }
85
85
  })
86
86
 
87
- const toolName = toolUseConfirm.tool.userFacingName(
88
- toolUseConfirm.input as never,
89
- )
87
+ const toolName = toolUseConfirm.tool.userFacingName?.() || 'Tool'
90
88
  useNotifyAfterTimeout(
91
89
  `${PRODUCT_NAME} needs your permission to use ${toolName}`,
92
90
  )
@@ -3,4 +3,6 @@ import { version } from '../../package.json'
3
3
  export const MACRO = {
4
4
  VERSION: version,
5
5
  README_URL: 'https://docs.anthropic.com/s/claude-code',
6
+ PACKAGE_URL: '@shareai-lab/kode',
7
+ ISSUES_EXPLAINER: 'report the issue at https://github.com/shareAI-lab/kode/issues',
6
8
  }
@@ -0,0 +1,179 @@
1
+ import { ModelCapabilities } from '../types/modelCapabilities'
2
+
3
+ // GPT-5 standard capability definition
4
+ const GPT5_CAPABILITIES: ModelCapabilities = {
5
+ apiArchitecture: {
6
+ primary: 'responses_api',
7
+ fallback: 'chat_completions'
8
+ },
9
+ parameters: {
10
+ maxTokensField: 'max_completion_tokens',
11
+ supportsReasoningEffort: true,
12
+ supportsVerbosity: true,
13
+ temperatureMode: 'fixed_one'
14
+ },
15
+ toolCalling: {
16
+ mode: 'custom_tools',
17
+ supportsFreeform: true,
18
+ supportsAllowedTools: true,
19
+ supportsParallelCalls: true
20
+ },
21
+ stateManagement: {
22
+ supportsResponseId: true,
23
+ supportsConversationChaining: true,
24
+ supportsPreviousResponseId: true
25
+ },
26
+ streaming: {
27
+ supported: false, // Responses API doesn't support streaming yet
28
+ includesUsage: true
29
+ }
30
+ }
31
+
32
+ // Chat Completions standard capability definition
33
+ const CHAT_COMPLETIONS_CAPABILITIES: ModelCapabilities = {
34
+ apiArchitecture: {
35
+ primary: 'chat_completions'
36
+ },
37
+ parameters: {
38
+ maxTokensField: 'max_tokens',
39
+ supportsReasoningEffort: false,
40
+ supportsVerbosity: false,
41
+ temperatureMode: 'flexible'
42
+ },
43
+ toolCalling: {
44
+ mode: 'function_calling',
45
+ supportsFreeform: false,
46
+ supportsAllowedTools: false,
47
+ supportsParallelCalls: true
48
+ },
49
+ stateManagement: {
50
+ supportsResponseId: false,
51
+ supportsConversationChaining: false,
52
+ supportsPreviousResponseId: false
53
+ },
54
+ streaming: {
55
+ supported: true,
56
+ includesUsage: true
57
+ }
58
+ }
59
+
60
+ // Complete model capability mapping table
61
+ export const MODEL_CAPABILITIES_REGISTRY: Record<string, ModelCapabilities> = {
62
+ // GPT-5 series
63
+ 'gpt-5': GPT5_CAPABILITIES,
64
+ 'gpt-5-mini': GPT5_CAPABILITIES,
65
+ 'gpt-5-nano': GPT5_CAPABILITIES,
66
+ 'gpt-5-chat-latest': GPT5_CAPABILITIES,
67
+
68
+ // GPT-4 series
69
+ 'gpt-4o': CHAT_COMPLETIONS_CAPABILITIES,
70
+ 'gpt-4o-mini': CHAT_COMPLETIONS_CAPABILITIES,
71
+ 'gpt-4-turbo': CHAT_COMPLETIONS_CAPABILITIES,
72
+ 'gpt-4': CHAT_COMPLETIONS_CAPABILITIES,
73
+
74
+ // Claude series (supported through conversion layer)
75
+ 'claude-3-5-sonnet-20241022': CHAT_COMPLETIONS_CAPABILITIES,
76
+ 'claude-3-5-haiku-20241022': CHAT_COMPLETIONS_CAPABILITIES,
77
+ 'claude-3-opus-20240229': CHAT_COMPLETIONS_CAPABILITIES,
78
+
79
+ // O1 series (special reasoning models)
80
+ 'o1': {
81
+ ...CHAT_COMPLETIONS_CAPABILITIES,
82
+ parameters: {
83
+ ...CHAT_COMPLETIONS_CAPABILITIES.parameters,
84
+ maxTokensField: 'max_completion_tokens',
85
+ temperatureMode: 'fixed_one'
86
+ }
87
+ },
88
+ 'o1-mini': {
89
+ ...CHAT_COMPLETIONS_CAPABILITIES,
90
+ parameters: {
91
+ ...CHAT_COMPLETIONS_CAPABILITIES.parameters,
92
+ maxTokensField: 'max_completion_tokens',
93
+ temperatureMode: 'fixed_one'
94
+ }
95
+ },
96
+ 'o1-preview': {
97
+ ...CHAT_COMPLETIONS_CAPABILITIES,
98
+ parameters: {
99
+ ...CHAT_COMPLETIONS_CAPABILITIES.parameters,
100
+ maxTokensField: 'max_completion_tokens',
101
+ temperatureMode: 'fixed_one'
102
+ }
103
+ }
104
+ }
105
+
106
+ // Intelligently infer capabilities for unregistered models
107
+ export function inferModelCapabilities(modelName: string): ModelCapabilities | null {
108
+ if (!modelName) return null
109
+
110
+ const lowerName = modelName.toLowerCase()
111
+
112
+ // GPT-5 series
113
+ if (lowerName.includes('gpt-5') || lowerName.includes('gpt5')) {
114
+ return GPT5_CAPABILITIES
115
+ }
116
+
117
+ // GPT-6 series (reserved for future)
118
+ if (lowerName.includes('gpt-6') || lowerName.includes('gpt6')) {
119
+ return {
120
+ ...GPT5_CAPABILITIES,
121
+ streaming: { supported: true, includesUsage: true }
122
+ }
123
+ }
124
+
125
+ // GLM series
126
+ if (lowerName.includes('glm-5') || lowerName.includes('glm5')) {
127
+ return {
128
+ ...GPT5_CAPABILITIES,
129
+ toolCalling: {
130
+ ...GPT5_CAPABILITIES.toolCalling,
131
+ supportsAllowedTools: false // GLM might not support this
132
+ }
133
+ }
134
+ }
135
+
136
+ // O1 series
137
+ if (lowerName.startsWith('o1') || lowerName.includes('o1-')) {
138
+ return {
139
+ ...CHAT_COMPLETIONS_CAPABILITIES,
140
+ parameters: {
141
+ ...CHAT_COMPLETIONS_CAPABILITIES.parameters,
142
+ maxTokensField: 'max_completion_tokens',
143
+ temperatureMode: 'fixed_one'
144
+ }
145
+ }
146
+ }
147
+
148
+ // Default to null, let system use default behavior
149
+ return null
150
+ }
151
+
152
+ // Get model capabilities (with caching)
153
+ const capabilityCache = new Map<string, ModelCapabilities>()
154
+
155
+ export function getModelCapabilities(modelName: string): ModelCapabilities {
156
+ // Check cache
157
+ if (capabilityCache.has(modelName)) {
158
+ return capabilityCache.get(modelName)!
159
+ }
160
+
161
+ // Look up in registry
162
+ if (MODEL_CAPABILITIES_REGISTRY[modelName]) {
163
+ const capabilities = MODEL_CAPABILITIES_REGISTRY[modelName]
164
+ capabilityCache.set(modelName, capabilities)
165
+ return capabilities
166
+ }
167
+
168
+ // Try to infer
169
+ const inferred = inferModelCapabilities(modelName)
170
+ if (inferred) {
171
+ capabilityCache.set(modelName, inferred)
172
+ return inferred
173
+ }
174
+
175
+ // Default to Chat Completions
176
+ const defaultCapabilities = CHAT_COMPLETIONS_CAPABILITIES
177
+ capabilityCache.set(modelName, defaultCapabilities)
178
+ return defaultCapabilities
179
+ }
@@ -278,6 +278,96 @@ export default {
278
278
  supports_system_messages: true,
279
279
  supports_tool_choice: true,
280
280
  },
281
+ // GPT-5 Models
282
+ {
283
+ model: 'gpt-5',
284
+ max_tokens: 32768,
285
+ max_input_tokens: 200000,
286
+ max_output_tokens: 32768,
287
+ input_cost_per_token: 0.00001,
288
+ output_cost_per_token: 0.00005,
289
+ cache_read_input_token_cost: 0.000005,
290
+ provider: 'openai',
291
+ mode: 'chat',
292
+ supports_function_calling: true,
293
+ supports_parallel_function_calling: true,
294
+ supports_vision: true,
295
+ supports_prompt_caching: true,
296
+ supports_system_messages: true,
297
+ supports_tool_choice: true,
298
+ supports_reasoning_effort: true,
299
+ supports_responses_api: true,
300
+ supports_custom_tools: true,
301
+ supports_allowed_tools: true,
302
+ supports_verbosity_control: true,
303
+ },
304
+ {
305
+ model: 'gpt-5-mini',
306
+ max_tokens: 16384,
307
+ max_input_tokens: 128000,
308
+ max_output_tokens: 16384,
309
+ input_cost_per_token: 0.000001,
310
+ output_cost_per_token: 0.000005,
311
+ cache_read_input_token_cost: 0.0000005,
312
+ provider: 'openai',
313
+ mode: 'chat',
314
+ supports_function_calling: true,
315
+ supports_parallel_function_calling: true,
316
+ supports_vision: true,
317
+ supports_prompt_caching: true,
318
+ supports_system_messages: true,
319
+ supports_tool_choice: true,
320
+ supports_reasoning_effort: true,
321
+ supports_responses_api: true,
322
+ supports_custom_tools: true,
323
+ supports_allowed_tools: true,
324
+ supports_verbosity_control: true,
325
+ },
326
+ {
327
+ model: 'gpt-5-nano',
328
+ max_tokens: 8192,
329
+ max_input_tokens: 64000,
330
+ max_output_tokens: 8192,
331
+ input_cost_per_token: 0.0000005,
332
+ output_cost_per_token: 0.000002,
333
+ cache_read_input_token_cost: 0.00000025,
334
+ provider: 'openai',
335
+ mode: 'chat',
336
+ supports_function_calling: true,
337
+ supports_parallel_function_calling: true,
338
+ supports_vision: false,
339
+ supports_prompt_caching: true,
340
+ supports_system_messages: true,
341
+ supports_tool_choice: true,
342
+ supports_reasoning_effort: true,
343
+ supports_responses_api: true,
344
+ supports_custom_tools: true,
345
+ supports_allowed_tools: true,
346
+ supports_verbosity_control: true,
347
+ },
348
+ {
349
+ model: 'gpt-5-chat-latest',
350
+ max_tokens: 32768,
351
+ max_input_tokens: 200000,
352
+ max_output_tokens: 32768,
353
+ input_cost_per_token: 0.00001,
354
+ output_cost_per_token: 0.00005,
355
+ cache_read_input_token_cost: 0.000005,
356
+ provider: 'openai',
357
+ mode: 'chat',
358
+ supports_function_calling: true,
359
+ supports_parallel_function_calling: true,
360
+ supports_vision: true,
361
+ supports_prompt_caching: true,
362
+ supports_system_messages: true,
363
+ supports_tool_choice: true,
364
+ supports_reasoning_effort: true,
365
+ supports_responses_api: false,
366
+ supports_custom_tools: false,
367
+ supports_allowed_tools: false,
368
+ supports_verbosity_control: true,
369
+ requires_chat_completions: true,
370
+ },
281
371
  ],
282
372
  mistral: [
283
373
  {
@@ -1,6 +1,6 @@
1
1
  export const PRODUCT_NAME = 'Kode'
2
2
  export const PRODUCT_URL = 'https://github.com/shareAI-lab/Anykode'
3
- export const PROJECT_FILE = 'KODE.md'
3
+ export const PROJECT_FILE = 'AGENTS.md'
4
4
  export const PRODUCT_COMMAND = 'kode'
5
5
  export const CONFIG_BASE_DIR = '.kode'
6
6
  export const CONFIG_FILE = '.kode.json'
package/src/context.ts CHANGED
@@ -19,13 +19,13 @@ import { lastX } from './utils/generators'
19
19
  import { getGitEmail } from './utils/user'
20
20
  import { PROJECT_FILE } from './constants/product'
21
21
  /**
22
- * Find all KODE.md and CLAUDE.md files in the current working directory
22
+ * Find all AGENTS.md and CLAUDE.md files in the current working directory
23
23
  */
24
24
  export async function getClaudeFiles(): Promise<string | null> {
25
25
  const abortController = new AbortController()
26
26
  const timeout = setTimeout(() => abortController.abort(), 3000)
27
27
  try {
28
- // Search for both KODE.md and CLAUDE.md files
28
+ // Search for both AGENTS.md and CLAUDE.md files
29
29
  const [codeContextFiles, claudeFiles] = await Promise.all([
30
30
  ripGrep(
31
31
  ['--files', '--glob', join('**', '*', PROJECT_FILE)],
@@ -46,7 +46,7 @@ export async function getClaudeFiles(): Promise<string | null> {
46
46
 
47
47
  // Add instructions for additional project files
48
48
  const fileTypes = []
49
- if (codeContextFiles.length > 0) fileTypes.push('KODE.md')
49
+ if (codeContextFiles.length > 0) fileTypes.push('AGENTS.md')
50
50
  if (claudeFiles.length > 0) fileTypes.push('CLAUDE.md')
51
51
 
52
52
  return `NOTE: Additional project documentation files (${fileTypes.join(', ')}) were found. When working in these directories, make sure to read and follow the instructions in the corresponding files:\n${allFiles
@@ -97,21 +97,21 @@ export const getReadme = memoize(async (): Promise<string | null> => {
97
97
  })
98
98
 
99
99
  /**
100
- * Get project documentation content (KODE.md and CLAUDE.md)
100
+ * Get project documentation content (AGENTS.md and CLAUDE.md)
101
101
  */
102
102
  export const getProjectDocs = memoize(async (): Promise<string | null> => {
103
103
  try {
104
104
  const cwd = getCwd()
105
- const codeContextPath = join(cwd, 'KODE.md')
105
+ const codeContextPath = join(cwd, 'AGENTS.md')
106
106
  const claudePath = join(cwd, 'CLAUDE.md')
107
107
 
108
108
  const docs = []
109
109
 
110
- // Try to read KODE.md
110
+ // Try to read AGENTS.md
111
111
  if (existsSync(codeContextPath)) {
112
112
  try {
113
113
  const content = await readFile(codeContextPath, 'utf-8')
114
- docs.push(`# KODE.md\n\n${content}`)
114
+ docs.push(`# AGENTS.md\n\n${content}`)
115
115
  } catch (e) {
116
116
  logError(e)
117
117
  }
@@ -32,6 +32,7 @@ import {
32
32
  getConfigForCLI,
33
33
  listConfigForCLI,
34
34
  enableConfigs,
35
+ validateAndRepairAllGPT5Profiles,
35
36
  } from '../utils/config'
36
37
  import { cwd } from 'process'
37
38
  import { dateToFilename, logError, parseLogFilename } from '../utils/log'
@@ -40,7 +41,7 @@ import { Onboarding } from '../components/Onboarding'
40
41
  import { Doctor } from '../screens/Doctor'
41
42
  import { ApproveApiKey } from '../components/ApproveApiKey'
42
43
  import { TrustDialog } from '../components/TrustDialog'
43
- import { checkHasTrustDialogAccepted } from '../utils/config'
44
+ import { checkHasTrustDialogAccepted, McpServerConfig } from '../utils/config'
44
45
  import { isDefaultSlowAndCapableModel } from '../utils/model'
45
46
  import { LogList } from '../screens/LogList'
46
47
  import { ResumeConversation } from '../screens/ResumeConversation'
@@ -184,6 +185,13 @@ async function setup(cwd: string, safeMode?: boolean): Promise<void> {
184
185
 
185
186
  // Always grant read permissions for original working dir
186
187
  grantReadPermissionForOriginalDir()
188
+
189
+ // Start watching agent configuration files for changes
190
+ const { startAgentWatcher, clearAgentCache } = await import('../utils/agentLoader')
191
+ await startAgentWatcher(() => {
192
+ // Cache is already cleared in the watcher, just log
193
+ console.log('✅ Agent configurations hot-reloaded')
194
+ })
187
195
 
188
196
  // If --safe mode is enabled, prevent root/sudo usage for security
189
197
  if (safeMode) {
@@ -263,6 +271,17 @@ async function main() {
263
271
  // Validate configs are valid and enable configuration system
264
272
  try {
265
273
  enableConfigs()
274
+
275
+ // 🔧 Validate and auto-repair GPT-5 model profiles
276
+ try {
277
+ const repairResult = validateAndRepairAllGPT5Profiles()
278
+ if (repairResult.repaired > 0) {
279
+ console.log(`🔧 Auto-repaired ${repairResult.repaired} GPT-5 model configurations`)
280
+ }
281
+ } catch (repairError) {
282
+ // Don't block startup if GPT-5 validation fails
283
+ console.warn('⚠️ GPT-5 configuration validation failed:', repairError)
284
+ }
266
285
  } catch (error: unknown) {
267
286
  if (error instanceof ConfigParseError) {
268
287
  // Show the invalid config dialog with the error object
@@ -274,10 +293,11 @@ async function main() {
274
293
  let inputPrompt = ''
275
294
  let renderContext: RenderOptions | undefined = {
276
295
  exitOnCtrlC: false,
296
+ // @ts-expect-error - onFlicker not in RenderOptions interface
277
297
  onFlicker() {
278
298
  logEvent('tengu_flicker', {})
279
299
  },
280
- }
300
+ } as any
281
301
 
282
302
  if (
283
303
  !process.stdin.isTTY &&
@@ -484,7 +504,7 @@ ${commandList}`,
484
504
  .action(async ({ cwd, global }) => {
485
505
  await setup(cwd, false)
486
506
  console.log(
487
- JSON.stringify(listConfigForCLI((global as true) ?? false), null, 2),
507
+ JSON.stringify(listConfigForCLI(global ? (true as const) : (false as const)), null, 2),
488
508
  )
489
509
  process.exit(0)
490
510
  })