@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
package/src/messages.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import React from 'react'
1
2
  import type { Message } from './query'
2
3
 
3
4
  let getMessages: () => Message[] = () => []
package/src/query.ts CHANGED
@@ -80,6 +80,7 @@ export type AssistantMessage = {
80
80
  type: 'assistant'
81
81
  uuid: UUID
82
82
  isApiErrorMessage?: boolean
83
+ responseId?: string // For GPT-5 Responses API state management
83
84
  }
84
85
 
85
86
  export type BinaryFeedbackResult =
@@ -230,6 +231,7 @@ export async function* query(
230
231
  safeMode: toolUseContext.options.safeMode ?? false,
231
232
  model: toolUseContext.options.model || 'main',
232
233
  prependCLISysprompt: true,
234
+ toolUseContext: toolUseContext,
233
235
  },
234
236
  )
235
237
  }
@@ -408,6 +410,7 @@ export async function* runToolUse(
408
410
  currentRequest?.id,
409
411
  )
410
412
 
413
+
411
414
  logEvent('tengu_tool_use_start', {
412
415
  toolName: toolUse.name,
413
416
  toolUseID: toolUse.id,
@@ -1,6 +1,6 @@
1
1
  import React, { useState } from 'react'
2
2
  import { Box, Text } from 'ink'
3
- import { Select } from '@inkjs/ui'
3
+ import { Select } from '../components/CustomSelect/select'
4
4
  import TextInput from '../components/TextInput'
5
5
  import { SimpleSpinner } from '../components/Spinner'
6
6
  import { getTheme } from '../utils/theme'
@@ -1,6 +1,6 @@
1
1
  import React, { useCallback, useEffect, useState } from 'react'
2
2
  import { Box, Text, useInput } from 'ink'
3
- import { Select } from '@inkjs/ui'
3
+ import { Select } from '../components/CustomSelect/select'
4
4
  import { getTheme } from '../utils/theme'
5
5
  import { ConfigureNpmPrefix } from './ConfigureNpmPrefix.tsx'
6
6
  import { platform } from 'process'
@@ -171,17 +171,15 @@ export function REPL({
171
171
  }>({})
172
172
 
173
173
  const { status: apiKeyStatus, reverify } = useApiKeyVerification()
174
- // 🔧 FIXED: Simple cancellation logic matching original claude-code
175
174
  function onCancel() {
176
175
  if (!isLoading) {
177
176
  return
178
177
  }
179
178
  setIsLoading(false)
180
179
  if (toolUseConfirm) {
181
- // Tool use confirm handles the abort signal itself
182
180
  toolUseConfirm.onAbort()
183
- } else {
184
- abortController?.abort()
181
+ } else if (abortController && !abortController.signal.aborted) {
182
+ abortController.abort()
185
183
  }
186
184
  }
187
185
 
@@ -392,7 +390,7 @@ export function REPL({
392
390
  }
393
391
 
394
392
  // If this was a Koding request and we got an assistant message back,
395
- // save it to KODE.md (and CLAUDE.md if exists)
393
+ // save it to AGENTS.md (and CLAUDE.md if exists)
396
394
  if (
397
395
  isKodingRequest &&
398
396
  lastAssistantMessage &&
@@ -407,7 +405,7 @@ export function REPL({
407
405
  .map(block => (block.type === 'text' ? block.text : ''))
408
406
  .join('\n')
409
407
 
410
- // Add the content to KODE.md (and CLAUDE.md if exists)
408
+ // Add the content to AGENTS.md (and CLAUDE.md if exists)
411
409
  if (content && content.trim().length > 0) {
412
410
  handleHashCommand(content)
413
411
  }
@@ -605,12 +603,13 @@ export function REPL({
605
603
  return (
606
604
  <PermissionProvider isBypassPermissionsModeAvailable={!safeMode}>
607
605
  <ModeIndicator />
608
- <Static
609
- key={`static-messages-${forkNumber}`}
610
- items={messagesJSX.filter(_ => _.type === 'static')}
611
- >
612
- {_ => _.jsx}
613
- </Static>
606
+ <React.Fragment key={`static-messages-${forkNumber}`}>
607
+ <Static
608
+ items={messagesJSX.filter(_ => _.type === 'static')}
609
+ >
610
+ {_ => _.jsx}
611
+ </Static>
612
+ </React.Fragment>
614
613
  {messagesJSX.filter(_ => _.type === 'transient').map(_ => _.jsx)}
615
614
  <Box
616
615
  borderColor="red"
@@ -0,0 +1,38 @@
1
+ import { ModelCapabilities, UnifiedRequestParams, UnifiedResponse } from '../../types/modelCapabilities'
2
+ import { ModelProfile } from '../../utils/config'
3
+ import { Tool } from '../../Tool'
4
+
5
+ export abstract class ModelAPIAdapter {
6
+ constructor(
7
+ protected capabilities: ModelCapabilities,
8
+ protected modelProfile: ModelProfile
9
+ ) {}
10
+
11
+ // Subclasses must implement these methods
12
+ abstract createRequest(params: UnifiedRequestParams): any
13
+ abstract parseResponse(response: any): UnifiedResponse
14
+ abstract buildTools(tools: Tool[]): any
15
+
16
+ // Shared utility methods
17
+ protected getMaxTokensParam(): string {
18
+ return this.capabilities.parameters.maxTokensField
19
+ }
20
+
21
+ protected getTemperature(): number {
22
+ if (this.capabilities.parameters.temperatureMode === 'fixed_one') {
23
+ return 1
24
+ }
25
+ if (this.capabilities.parameters.temperatureMode === 'restricted') {
26
+ return Math.min(1, 0.7)
27
+ }
28
+ return 0.7
29
+ }
30
+
31
+ protected shouldIncludeReasoningEffort(): boolean {
32
+ return this.capabilities.parameters.supportsReasoningEffort
33
+ }
34
+
35
+ protected shouldIncludeVerbosity(): boolean {
36
+ return this.capabilities.parameters.supportsVerbosity
37
+ }
38
+ }
@@ -0,0 +1,90 @@
1
+ import { ModelAPIAdapter } from './base'
2
+ import { UnifiedRequestParams, UnifiedResponse } from '../../types/modelCapabilities'
3
+ import { Tool } from '../../Tool'
4
+ import { zodToJsonSchema } from 'zod-to-json-schema'
5
+
6
+ export class ChatCompletionsAdapter extends ModelAPIAdapter {
7
+ createRequest(params: UnifiedRequestParams): any {
8
+ const { messages, systemPrompt, tools, maxTokens, stream } = params
9
+
10
+ // Build complete message list (including system prompts)
11
+ const fullMessages = this.buildMessages(systemPrompt, messages)
12
+
13
+ // Build request
14
+ const request: any = {
15
+ model: this.modelProfile.modelName,
16
+ messages: fullMessages,
17
+ [this.getMaxTokensParam()]: maxTokens,
18
+ temperature: this.getTemperature()
19
+ }
20
+
21
+ // Add tools
22
+ if (tools && tools.length > 0) {
23
+ request.tools = this.buildTools(tools)
24
+ request.tool_choice = 'auto'
25
+ }
26
+
27
+ // Add reasoning effort for GPT-5 via Chat Completions
28
+ if (this.shouldIncludeReasoningEffort() && params.reasoningEffort) {
29
+ request.reasoning_effort = params.reasoningEffort // Chat Completions format
30
+ }
31
+
32
+ // Add verbosity for GPT-5 via Chat Completions
33
+ if (this.shouldIncludeVerbosity() && params.verbosity) {
34
+ request.verbosity = params.verbosity // Chat Completions format
35
+ }
36
+
37
+ // Add streaming options
38
+ if (stream) {
39
+ request.stream = true
40
+ request.stream_options = {
41
+ include_usage: true
42
+ }
43
+ }
44
+
45
+ // O1 model special handling
46
+ if (this.modelProfile.modelName.startsWith('o1')) {
47
+ delete request.temperature // O1 doesn't support temperature
48
+ delete request.stream // O1 doesn't support streaming
49
+ delete request.stream_options
50
+ }
51
+
52
+ return request
53
+ }
54
+
55
+ buildTools(tools: Tool[]): any[] {
56
+ // Chat Completions only supports traditional function calling
57
+ return tools.map(tool => ({
58
+ type: 'function',
59
+ function: {
60
+ name: tool.name,
61
+ description: tool.description || '',
62
+ parameters: tool.inputJSONSchema || zodToJsonSchema(tool.inputSchema)
63
+ }
64
+ }))
65
+ }
66
+
67
+ parseResponse(response: any): UnifiedResponse {
68
+ const choice = response.choices?.[0]
69
+
70
+ return {
71
+ id: response.id || `chatcmpl_${Date.now()}`,
72
+ content: choice?.message?.content || '',
73
+ toolCalls: choice?.message?.tool_calls || [],
74
+ usage: {
75
+ promptTokens: response.usage?.prompt_tokens || 0,
76
+ completionTokens: response.usage?.completion_tokens || 0
77
+ }
78
+ }
79
+ }
80
+
81
+ private buildMessages(systemPrompt: string[], messages: any[]): any[] {
82
+ // Merge system prompts and messages
83
+ const systemMessages = systemPrompt.map(prompt => ({
84
+ role: 'system',
85
+ content: prompt
86
+ }))
87
+
88
+ return [...systemMessages, ...messages]
89
+ }
90
+ }
@@ -0,0 +1,170 @@
1
+ import { ModelAPIAdapter } from './base'
2
+ import { UnifiedRequestParams, UnifiedResponse } from '../../types/modelCapabilities'
3
+ import { Tool } from '../../Tool'
4
+ import { zodToJsonSchema } from 'zod-to-json-schema'
5
+
6
+ export class ResponsesAPIAdapter extends ModelAPIAdapter {
7
+ createRequest(params: UnifiedRequestParams): any {
8
+ const { messages, systemPrompt, tools, maxTokens } = params
9
+
10
+ // Separate system messages and user messages
11
+ const systemMessages = messages.filter(m => m.role === 'system')
12
+ const nonSystemMessages = messages.filter(m => m.role !== 'system')
13
+
14
+ // Build base request
15
+ const request: any = {
16
+ model: this.modelProfile.modelName,
17
+ input: this.convertMessagesToInput(nonSystemMessages),
18
+ instructions: this.buildInstructions(systemPrompt, systemMessages)
19
+ }
20
+
21
+ // Add token limit
22
+ request[this.getMaxTokensParam()] = maxTokens
23
+
24
+ // Add temperature (GPT-5 only supports 1)
25
+ if (this.getTemperature() === 1) {
26
+ request.temperature = 1
27
+ }
28
+
29
+ // Add reasoning control - correct format for Responses API
30
+ if (this.shouldIncludeReasoningEffort()) {
31
+ request.reasoning = {
32
+ effort: params.reasoningEffort || this.modelProfile.reasoningEffort || 'medium'
33
+ }
34
+ }
35
+
36
+ // Add verbosity control - correct format for Responses API
37
+ if (this.shouldIncludeVerbosity()) {
38
+ request.text = {
39
+ verbosity: params.verbosity || 'high' // High verbosity for coding tasks
40
+ }
41
+ }
42
+
43
+ // Add tools
44
+ if (tools && tools.length > 0) {
45
+ request.tools = this.buildTools(tools)
46
+
47
+ // Handle allowed_tools
48
+ if (params.allowedTools && this.capabilities.toolCalling.supportsAllowedTools) {
49
+ request.tool_choice = {
50
+ type: 'allowed_tools',
51
+ mode: 'auto',
52
+ tools: params.allowedTools
53
+ }
54
+ }
55
+ }
56
+
57
+ // Add state management
58
+ if (params.previousResponseId && this.capabilities.stateManagement.supportsPreviousResponseId) {
59
+ request.previous_response_id = params.previousResponseId
60
+ }
61
+
62
+ return request
63
+ }
64
+
65
+ buildTools(tools: Tool[]): any[] {
66
+ // If freeform not supported, use traditional format
67
+ if (!this.capabilities.toolCalling.supportsFreeform) {
68
+ return tools.map(tool => ({
69
+ type: 'function',
70
+ function: {
71
+ name: tool.name,
72
+ description: tool.description || '',
73
+ parameters: tool.inputJSONSchema || zodToJsonSchema(tool.inputSchema)
74
+ }
75
+ }))
76
+ }
77
+
78
+ // Custom tools format (GPT-5 feature)
79
+ return tools.map(tool => {
80
+ const hasSchema = tool.inputJSONSchema || tool.inputSchema
81
+ const isCustom = !hasSchema
82
+
83
+ if (isCustom) {
84
+ // Custom tool format
85
+ return {
86
+ type: 'custom',
87
+ name: tool.name,
88
+ description: tool.description || ''
89
+ }
90
+ } else {
91
+ // Traditional function format
92
+ return {
93
+ type: 'function',
94
+ function: {
95
+ name: tool.name,
96
+ description: tool.description || '',
97
+ parameters: tool.inputJSONSchema || zodToJsonSchema(tool.inputSchema)
98
+ }
99
+ }
100
+ }
101
+ })
102
+ }
103
+
104
+ parseResponse(response: any): UnifiedResponse {
105
+ // Process basic text output
106
+ let content = response.output_text || ''
107
+
108
+ // Process structured output
109
+ if (response.output && Array.isArray(response.output)) {
110
+ const messageItems = response.output.filter(item => item.type === 'message')
111
+ if (messageItems.length > 0) {
112
+ content = messageItems
113
+ .map(item => {
114
+ if (item.content && Array.isArray(item.content)) {
115
+ return item.content
116
+ .filter(c => c.type === 'text')
117
+ .map(c => c.text)
118
+ .join('\n')
119
+ }
120
+ return item.content || ''
121
+ })
122
+ .filter(Boolean)
123
+ .join('\n\n')
124
+ }
125
+ }
126
+
127
+ // Parse tool calls
128
+ const toolCalls = this.parseToolCalls(response)
129
+
130
+ // Build unified response
131
+ return {
132
+ id: response.id || `resp_${Date.now()}`,
133
+ content,
134
+ toolCalls,
135
+ usage: {
136
+ promptTokens: response.usage?.input_tokens || 0,
137
+ completionTokens: response.usage?.output_tokens || 0,
138
+ reasoningTokens: response.usage?.output_tokens_details?.reasoning_tokens
139
+ },
140
+ responseId: response.id // Save for state management
141
+ }
142
+ }
143
+
144
+ private convertMessagesToInput(messages: any[]): any {
145
+ // Convert messages to Responses API input format
146
+ // May need adjustment based on actual API specification
147
+ return messages
148
+ }
149
+
150
+ private buildInstructions(systemPrompt: string[], systemMessages: any[]): string {
151
+ const systemContent = systemMessages.map(m => m.content).join('\n\n')
152
+ const promptContent = systemPrompt.join('\n\n')
153
+ return [systemContent, promptContent].filter(Boolean).join('\n\n')
154
+ }
155
+
156
+ private parseToolCalls(response: any): any[] {
157
+ if (!response.output || !Array.isArray(response.output)) {
158
+ return []
159
+ }
160
+
161
+ return response.output
162
+ .filter(item => item.type === 'tool_call')
163
+ .map(item => ({
164
+ id: item.id || `tool_${Date.now()}`,
165
+ type: 'tool_call',
166
+ name: item.name,
167
+ arguments: item.arguments // Can be text or JSON
168
+ }))
169
+ }
170
+ }