@renxqoo/renx-code 0.0.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.
Files changed (215) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +278 -0
  3. package/dist/App.d.ts +2 -0
  4. package/dist/App.d.ts.map +1 -0
  5. package/dist/App.js +170 -0
  6. package/dist/App.js.map +1 -0
  7. package/dist/agent/prompts/system.d.ts +24 -0
  8. package/dist/agent/prompts/system.d.ts.map +1 -0
  9. package/dist/agent/prompts/system.js +222 -0
  10. package/dist/agent/prompts/system.js.map +1 -0
  11. package/dist/agent/runtime/event-format.d.ts +17 -0
  12. package/dist/agent/runtime/event-format.d.ts.map +1 -0
  13. package/dist/agent/runtime/event-format.js +194 -0
  14. package/dist/agent/runtime/event-format.js.map +1 -0
  15. package/dist/agent/runtime/model-types.d.ts +13 -0
  16. package/dist/agent/runtime/model-types.d.ts.map +1 -0
  17. package/dist/agent/runtime/model-types.js +1 -0
  18. package/dist/agent/runtime/model-types.js.map +1 -0
  19. package/dist/agent/runtime/runtime.d.ts +16 -0
  20. package/dist/agent/runtime/runtime.d.ts.map +1 -0
  21. package/dist/agent/runtime/runtime.js +691 -0
  22. package/dist/agent/runtime/runtime.js.map +1 -0
  23. package/dist/agent/runtime/source-modules.d.ts +176 -0
  24. package/dist/agent/runtime/source-modules.d.ts.map +1 -0
  25. package/dist/agent/runtime/source-modules.js +110 -0
  26. package/dist/agent/runtime/source-modules.js.map +1 -0
  27. package/dist/agent/runtime/tool-call-buffer.d.ts +12 -0
  28. package/dist/agent/runtime/tool-call-buffer.d.ts.map +1 -0
  29. package/dist/agent/runtime/tool-call-buffer.js +48 -0
  30. package/dist/agent/runtime/tool-call-buffer.js.map +1 -0
  31. package/dist/agent/runtime/tool-confirmation.d.ts +3 -0
  32. package/dist/agent/runtime/tool-confirmation.d.ts.map +1 -0
  33. package/dist/agent/runtime/tool-confirmation.js +9 -0
  34. package/dist/agent/runtime/tool-confirmation.js.map +1 -0
  35. package/dist/agent/runtime/types.d.ts +86 -0
  36. package/dist/agent/runtime/types.d.ts.map +1 -0
  37. package/dist/agent/runtime/types.js +1 -0
  38. package/dist/agent/runtime/types.js.map +1 -0
  39. package/dist/cli.d.ts +3 -0
  40. package/dist/cli.d.ts.map +1 -0
  41. package/dist/cli.js +43 -0
  42. package/dist/cli.js.map +1 -0
  43. package/dist/commands/slash-commands.d.ts +11 -0
  44. package/dist/commands/slash-commands.d.ts.map +1 -0
  45. package/dist/commands/slash-commands.js +48 -0
  46. package/dist/commands/slash-commands.js.map +1 -0
  47. package/dist/components/chat/assistant-reply.d.ts +13 -0
  48. package/dist/components/chat/assistant-reply.d.ts.map +1 -0
  49. package/dist/components/chat/assistant-reply.js +78 -0
  50. package/dist/components/chat/assistant-reply.js.map +1 -0
  51. package/dist/components/chat/assistant-segment.d.ts +8 -0
  52. package/dist/components/chat/assistant-segment.d.ts.map +1 -0
  53. package/dist/components/chat/assistant-segment.js +54 -0
  54. package/dist/components/chat/assistant-segment.js.map +1 -0
  55. package/dist/components/chat/assistant-tool-group.d.ts +7 -0
  56. package/dist/components/chat/assistant-tool-group.d.ts.map +1 -0
  57. package/dist/components/chat/assistant-tool-group.js +695 -0
  58. package/dist/components/chat/assistant-tool-group.js.map +1 -0
  59. package/dist/components/chat/code-block.d.ts +16 -0
  60. package/dist/components/chat/code-block.d.ts.map +1 -0
  61. package/dist/components/chat/code-block.js +194 -0
  62. package/dist/components/chat/code-block.js.map +1 -0
  63. package/dist/components/chat/prompt-card.d.ts +9 -0
  64. package/dist/components/chat/prompt-card.d.ts.map +1 -0
  65. package/dist/components/chat/prompt-card.js +18 -0
  66. package/dist/components/chat/prompt-card.js.map +1 -0
  67. package/dist/components/chat/segment-groups.d.ts +24 -0
  68. package/dist/components/chat/segment-groups.d.ts.map +1 -0
  69. package/dist/components/chat/segment-groups.js +69 -0
  70. package/dist/components/chat/segment-groups.js.map +1 -0
  71. package/dist/components/chat/turn-item.d.ts +9 -0
  72. package/dist/components/chat/turn-item.d.ts.map +1 -0
  73. package/dist/components/chat/turn-item.js +11 -0
  74. package/dist/components/chat/turn-item.js.map +1 -0
  75. package/dist/components/conversation-panel.d.ts +8 -0
  76. package/dist/components/conversation-panel.d.ts.map +1 -0
  77. package/dist/components/conversation-panel.js +8 -0
  78. package/dist/components/conversation-panel.js.map +1 -0
  79. package/dist/components/file-mention-menu.d.ts +11 -0
  80. package/dist/components/file-mention-menu.d.ts.map +1 -0
  81. package/dist/components/file-mention-menu.js +15 -0
  82. package/dist/components/file-mention-menu.js.map +1 -0
  83. package/dist/components/file-picker-dialog.d.ts +21 -0
  84. package/dist/components/file-picker-dialog.d.ts.map +1 -0
  85. package/dist/components/file-picker-dialog.js +48 -0
  86. package/dist/components/file-picker-dialog.js.map +1 -0
  87. package/dist/components/footer-hints.d.ts +7 -0
  88. package/dist/components/footer-hints.d.ts.map +1 -0
  89. package/dist/components/footer-hints.js +29 -0
  90. package/dist/components/footer-hints.js.map +1 -0
  91. package/dist/components/model-picker-dialog.d.ts +20 -0
  92. package/dist/components/model-picker-dialog.d.ts.map +1 -0
  93. package/dist/components/model-picker-dialog.js +72 -0
  94. package/dist/components/model-picker-dialog.js.map +1 -0
  95. package/dist/components/prompt.d.ts +18 -0
  96. package/dist/components/prompt.d.ts.map +1 -0
  97. package/dist/components/prompt.js +96 -0
  98. package/dist/components/prompt.js.map +1 -0
  99. package/dist/components/slash-command-menu.d.ts +9 -0
  100. package/dist/components/slash-command-menu.d.ts.map +1 -0
  101. package/dist/components/slash-command-menu.js +20 -0
  102. package/dist/components/slash-command-menu.js.map +1 -0
  103. package/dist/components/tool-confirm-dialog-content.d.ts +15 -0
  104. package/dist/components/tool-confirm-dialog-content.d.ts.map +1 -0
  105. package/dist/components/tool-confirm-dialog-content.js +143 -0
  106. package/dist/components/tool-confirm-dialog-content.js.map +1 -0
  107. package/dist/components/tool-confirm-dialog.d.ts +12 -0
  108. package/dist/components/tool-confirm-dialog.d.ts.map +1 -0
  109. package/dist/components/tool-confirm-dialog.js +21 -0
  110. package/dist/components/tool-confirm-dialog.js.map +1 -0
  111. package/dist/components/tool-display-config.d.ts +11 -0
  112. package/dist/components/tool-display-config.d.ts.map +1 -0
  113. package/dist/components/tool-display-config.js +94 -0
  114. package/dist/components/tool-display-config.js.map +1 -0
  115. package/dist/config/paths.d.ts +7 -0
  116. package/dist/config/paths.d.ts.map +1 -0
  117. package/dist/config/paths.js +24 -0
  118. package/dist/config/paths.js.map +1 -0
  119. package/dist/files/attachment-capabilities.d.ts +19 -0
  120. package/dist/files/attachment-capabilities.d.ts.map +1 -0
  121. package/dist/files/attachment-capabilities.js +26 -0
  122. package/dist/files/attachment-capabilities.js.map +1 -0
  123. package/dist/files/attachment-content.d.ts +5 -0
  124. package/dist/files/attachment-content.d.ts.map +1 -0
  125. package/dist/files/attachment-content.js +117 -0
  126. package/dist/files/attachment-content.js.map +1 -0
  127. package/dist/files/file-mention-query.d.ts +9 -0
  128. package/dist/files/file-mention-query.d.ts.map +1 -0
  129. package/dist/files/file-mention-query.js +23 -0
  130. package/dist/files/file-mention-query.js.map +1 -0
  131. package/dist/files/prompt-display.d.ts +3 -0
  132. package/dist/files/prompt-display.d.ts.map +1 -0
  133. package/dist/files/prompt-display.js +11 -0
  134. package/dist/files/prompt-display.js.map +1 -0
  135. package/dist/files/types.d.ts +6 -0
  136. package/dist/files/types.d.ts.map +1 -0
  137. package/dist/files/types.js +1 -0
  138. package/dist/files/types.js.map +1 -0
  139. package/dist/files/workspace-files.d.ts +3 -0
  140. package/dist/files/workspace-files.d.ts.map +1 -0
  141. package/dist/files/workspace-files.js +50 -0
  142. package/dist/files/workspace-files.js.map +1 -0
  143. package/dist/hooks/agent-event-handlers.d.ts +11 -0
  144. package/dist/hooks/agent-event-handlers.d.ts.map +1 -0
  145. package/dist/hooks/agent-event-handlers.js +137 -0
  146. package/dist/hooks/agent-event-handlers.js.map +1 -0
  147. package/dist/hooks/chat-local-replies.d.ts +9 -0
  148. package/dist/hooks/chat-local-replies.d.ts.map +1 -0
  149. package/dist/hooks/chat-local-replies.js +54 -0
  150. package/dist/hooks/chat-local-replies.js.map +1 -0
  151. package/dist/hooks/turn-updater.d.ts +9 -0
  152. package/dist/hooks/turn-updater.d.ts.map +1 -0
  153. package/dist/hooks/turn-updater.js +103 -0
  154. package/dist/hooks/turn-updater.js.map +1 -0
  155. package/dist/hooks/use-agent-chat.d.ts +29 -0
  156. package/dist/hooks/use-agent-chat.d.ts.map +1 -0
  157. package/dist/hooks/use-agent-chat.js +455 -0
  158. package/dist/hooks/use-agent-chat.js.map +1 -0
  159. package/dist/hooks/use-file-mention-menu.d.ts +22 -0
  160. package/dist/hooks/use-file-mention-menu.d.ts.map +1 -0
  161. package/dist/hooks/use-file-mention-menu.js +137 -0
  162. package/dist/hooks/use-file-mention-menu.js.map +1 -0
  163. package/dist/hooks/use-file-picker.d.ts +21 -0
  164. package/dist/hooks/use-file-picker.d.ts.map +1 -0
  165. package/dist/hooks/use-file-picker.js +145 -0
  166. package/dist/hooks/use-file-picker.js.map +1 -0
  167. package/dist/hooks/use-model-picker.d.ts +23 -0
  168. package/dist/hooks/use-model-picker.d.ts.map +1 -0
  169. package/dist/hooks/use-model-picker.js +151 -0
  170. package/dist/hooks/use-model-picker.js.map +1 -0
  171. package/dist/hooks/use-slash-command-menu.d.ts +19 -0
  172. package/dist/hooks/use-slash-command-menu.d.ts.map +1 -0
  173. package/dist/hooks/use-slash-command-menu.js +101 -0
  174. package/dist/hooks/use-slash-command-menu.js.map +1 -0
  175. package/dist/index.d.ts +2 -0
  176. package/dist/index.d.ts.map +1 -0
  177. package/dist/index.js +39 -0
  178. package/dist/index.js.map +1 -0
  179. package/dist/runtime/clipboard.d.ts +10 -0
  180. package/dist/runtime/clipboard.d.ts.map +1 -0
  181. package/dist/runtime/clipboard.js +64 -0
  182. package/dist/runtime/clipboard.js.map +1 -0
  183. package/dist/runtime/exit.d.ts +7 -0
  184. package/dist/runtime/exit.d.ts.map +1 -0
  185. package/dist/runtime/exit.js +85 -0
  186. package/dist/runtime/exit.js.map +1 -0
  187. package/dist/runtime/terminal-theme.d.ts +25 -0
  188. package/dist/runtime/terminal-theme.d.ts.map +1 -0
  189. package/dist/runtime/terminal-theme.js +148 -0
  190. package/dist/runtime/terminal-theme.js.map +1 -0
  191. package/dist/types/chat.d.ts +29 -0
  192. package/dist/types/chat.d.ts.map +1 -0
  193. package/dist/types/chat.js +1 -0
  194. package/dist/types/chat.js.map +1 -0
  195. package/dist/types/message-content.d.ts +38 -0
  196. package/dist/types/message-content.d.ts.map +1 -0
  197. package/dist/types/message-content.js +1 -0
  198. package/dist/types/message-content.js.map +1 -0
  199. package/dist/ui/open-code-theme.d.ts +58 -0
  200. package/dist/ui/open-code-theme.d.ts.map +1 -0
  201. package/dist/ui/open-code-theme.js +113 -0
  202. package/dist/ui/open-code-theme.js.map +1 -0
  203. package/dist/ui/opencode-markdown.d.ts +7 -0
  204. package/dist/ui/opencode-markdown.d.ts.map +1 -0
  205. package/dist/ui/opencode-markdown.js +169 -0
  206. package/dist/ui/opencode-markdown.js.map +1 -0
  207. package/dist/ui/theme.d.ts +68 -0
  208. package/dist/ui/theme.d.ts.map +1 -0
  209. package/dist/ui/theme.js +80 -0
  210. package/dist/ui/theme.js.map +1 -0
  211. package/dist/utils/time.d.ts +2 -0
  212. package/dist/utils/time.d.ts.map +1 -0
  213. package/dist/utils/time.js +7 -0
  214. package/dist/utils/time.js.map +1 -0
  215. package/package.json +128 -0
@@ -0,0 +1,691 @@
1
+ import { resolve as resolvePath } from 'node:path';
2
+ import { resolveToolConfirmDecision } from './tool-confirmation';
3
+ import { getSourceModules, resolveWorkspaceRoot, } from './source-modules';
4
+ import { ToolCallBuffer } from './tool-call-buffer';
5
+ import { buildSystemPrompt } from '../../agent/prompts/system';
6
+ import { resolveRenxDatabasePath, resolveRenxTaskDir } from '../../config/paths';
7
+ import { resolveAttachmentModelCapabilities } from '../../files/attachment-capabilities';
8
+ let runtimePromise = null;
9
+ let initializing = false;
10
+ const readPreferredModelIdFromEnv = () => {
11
+ return process.env.AGENT_MODEL?.trim() || undefined;
12
+ };
13
+ let preferredModelId = readPreferredModelIdFromEnv();
14
+ const DEFAULT_MODEL = 'qwen3.5-plus';
15
+ const DEFAULT_MAX_STEPS = 10000;
16
+ const DEFAULT_MAX_RETRY_COUNT = 10;
17
+ const PARENT_HIDDEN_TOOL_NAMES = new Set(['file_history_list', 'file_history_restore']);
18
+ const parsePositiveInt = (raw, fallback) => {
19
+ if (!raw || raw.trim().length === 0) {
20
+ return fallback;
21
+ }
22
+ const value = Number.parseInt(raw, 10);
23
+ if (!Number.isFinite(value) || value <= 0) {
24
+ return fallback;
25
+ }
26
+ return value;
27
+ };
28
+ const resolvePromptCacheConfig = (conversationId) => {
29
+ const rawPromptCacheKey = process.env.AGENT_PROMPT_CACHE_KEY?.trim();
30
+ const promptCacheRetention = process.env.AGENT_PROMPT_CACHE_RETENTION?.trim();
31
+ const promptCacheKey = rawPromptCacheKey?.replace(/\{conversationId\}/g, conversationId);
32
+ const config = {};
33
+ if (promptCacheKey) {
34
+ config.prompt_cache_key = promptCacheKey;
35
+ }
36
+ if (promptCacheRetention) {
37
+ config.prompt_cache_retention = promptCacheRetention;
38
+ }
39
+ return Object.keys(config).length > 0 ? config : undefined;
40
+ };
41
+ const resolveModelId = (modules, requested) => {
42
+ const ids = modules.ProviderRegistry.getModelIds();
43
+ const normalized = requested?.trim();
44
+ if (normalized && ids.includes(normalized)) {
45
+ return normalized;
46
+ }
47
+ if (ids.includes(DEFAULT_MODEL)) {
48
+ return DEFAULT_MODEL;
49
+ }
50
+ const fallback = ids[0];
51
+ if (!fallback) {
52
+ throw new Error('No models are registered in ProviderRegistry.');
53
+ }
54
+ return fallback;
55
+ };
56
+ const requireModelApiKey = (modules, modelId) => {
57
+ const modelConfig = modules.ProviderRegistry.getModelConfig(modelId);
58
+ if (!process.env[modelConfig.envApiKey]) {
59
+ throw new Error(`Missing env ${modelConfig.envApiKey} for model ${modelId}.`);
60
+ }
61
+ return modelConfig;
62
+ };
63
+ const resolveConversationId = () => {
64
+ const fromEnv = process.env.AGENT_CONVERSATION_ID?.trim() || process.env.AGENT_SESSION_ID?.trim();
65
+ if (fromEnv) {
66
+ return fromEnv;
67
+ }
68
+ return `opentui-${Date.now()}`;
69
+ };
70
+ const resolveDbPath = () => {
71
+ return resolveRenxDatabasePath(process.env);
72
+ };
73
+ const buildCliLoggerEnv = (env) => ({
74
+ ...env,
75
+ AGENT_LOG_CONSOLE: 'false',
76
+ });
77
+ const safeInvoke = (fn) => {
78
+ if (!fn) {
79
+ return;
80
+ }
81
+ try {
82
+ fn();
83
+ }
84
+ catch {
85
+ // Intentionally empty
86
+ }
87
+ };
88
+ const asRecord = (value) => {
89
+ return value && typeof value === 'object' ? value : {};
90
+ };
91
+ const readString = (value) => {
92
+ return typeof value === 'string' ? value : undefined;
93
+ };
94
+ const readNumber = (value) => {
95
+ return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
96
+ };
97
+ const readBoolean = (value) => {
98
+ return typeof value === 'boolean' ? value : undefined;
99
+ };
100
+ const toUsageEventFromApp = (usage) => {
101
+ return {
102
+ promptTokens: usage.usage.prompt_tokens,
103
+ completionTokens: usage.usage.completion_tokens,
104
+ totalTokens: usage.usage.total_tokens,
105
+ cumulativePromptTokens: usage.cumulativeUsage.prompt_tokens,
106
+ cumulativeCompletionTokens: usage.cumulativeUsage.completion_tokens,
107
+ cumulativeTotalTokens: usage.cumulativeUsage.total_tokens,
108
+ contextTokens: typeof usage.contextTokens === 'number' && Number.isFinite(usage.contextTokens)
109
+ ? Math.max(0, usage.contextTokens)
110
+ : undefined,
111
+ contextLimit: usage.contextLimitTokens,
112
+ contextUsagePercent: typeof usage.contextUsagePercent === 'number' && Number.isFinite(usage.contextUsagePercent)
113
+ ? Math.max(0, usage.contextUsagePercent)
114
+ : undefined,
115
+ };
116
+ };
117
+ const toContextUsageEventFromApp = (usage) => {
118
+ if (typeof usage.stepIndex !== 'number' ||
119
+ !Number.isFinite(usage.stepIndex) ||
120
+ typeof usage.messageCount !== 'number' ||
121
+ !Number.isFinite(usage.messageCount) ||
122
+ typeof usage.contextTokens !== 'number' ||
123
+ !Number.isFinite(usage.contextTokens) ||
124
+ typeof usage.contextLimitTokens !== 'number' ||
125
+ !Number.isFinite(usage.contextLimitTokens) ||
126
+ typeof usage.contextUsagePercent !== 'number' ||
127
+ !Number.isFinite(usage.contextUsagePercent)) {
128
+ return null;
129
+ }
130
+ return {
131
+ stepIndex: Math.max(0, usage.stepIndex),
132
+ messageCount: Math.max(0, usage.messageCount),
133
+ contextTokens: Math.max(0, usage.contextTokens),
134
+ contextLimit: Math.max(0, usage.contextLimitTokens),
135
+ contextUsagePercent: Math.max(0, usage.contextUsagePercent),
136
+ };
137
+ };
138
+ const toJsonString = (value) => {
139
+ if (typeof value === 'string') {
140
+ return value;
141
+ }
142
+ try {
143
+ return JSON.stringify(value);
144
+ }
145
+ catch {
146
+ return String(value);
147
+ }
148
+ };
149
+ const parseJsonObject = (raw) => {
150
+ try {
151
+ const parsed = JSON.parse(raw);
152
+ if (parsed && typeof parsed === 'object') {
153
+ return parsed;
154
+ }
155
+ return { value: parsed };
156
+ }
157
+ catch {
158
+ return { raw };
159
+ }
160
+ };
161
+ const toTextDeltaEvent = (payload, isReasoning) => {
162
+ return {
163
+ text: readString(payload.content) ?? readString(payload.reasoningContent) ?? '',
164
+ isReasoning,
165
+ };
166
+ };
167
+ const toStepEvent = (payload, finishReason, toolCallsCount = 0) => {
168
+ return {
169
+ stepIndex: readNumber(payload.stepIndex) ?? 0,
170
+ finishReason,
171
+ toolCallsCount,
172
+ };
173
+ };
174
+ const toLoopEvent = (stepIndex) => {
175
+ return {
176
+ loopIndex: stepIndex,
177
+ steps: stepIndex,
178
+ };
179
+ };
180
+ const toToolStreamEvent = (envelope, sequenceByToolCallId) => {
181
+ const payload = asRecord(envelope.data);
182
+ const toolCallId = readString(payload.toolCallId) ?? 'unknown';
183
+ const previousSequence = sequenceByToolCallId.get(toolCallId) ?? 0;
184
+ const sequence = previousSequence + 1;
185
+ sequenceByToolCallId.set(toolCallId, sequence);
186
+ return {
187
+ toolCallId,
188
+ toolName: readString(payload.toolName) ?? 'tool',
189
+ type: readString(payload.chunkType) ?? readString(payload.type) ?? 'stdout',
190
+ sequence,
191
+ timestamp: envelope.createdAt,
192
+ content: readString(payload.chunk) ?? readString(payload.content),
193
+ data: payload,
194
+ };
195
+ };
196
+ const toToolResultEvent = (payload, toolCallsById) => {
197
+ const toolCallId = readString(payload.tool_call_id) ?? readString(payload.toolCallId) ?? 'unknown';
198
+ const metadata = asRecord(payload.metadata);
199
+ const toolResult = asRecord(metadata.toolResult);
200
+ const error = asRecord(toolResult.error);
201
+ const summary = readString(toolResult.summary);
202
+ const explicitOutput = readString(toolResult.output);
203
+ const content = readString(payload.content);
204
+ const output = explicitOutput !== undefined ? explicitOutput : content !== summary ? content : undefined;
205
+ const toolCall = toolCallsById.get(toolCallId) ??
206
+ {
207
+ id: toolCallId,
208
+ function: { name: 'tool', arguments: '{}' },
209
+ };
210
+ return {
211
+ toolCall,
212
+ result: {
213
+ success: readBoolean(toolResult.success) ?? true,
214
+ error: readString(error.message),
215
+ data: {
216
+ ...(summary !== undefined ? { summary } : {}),
217
+ ...(output !== undefined ? { output } : {}),
218
+ ...(toolResult.payload !== undefined ? { payload: toolResult.payload } : {}),
219
+ ...(toolResult.metadata !== undefined ? { metadata: toolResult.metadata } : {}),
220
+ },
221
+ raw: payload,
222
+ },
223
+ };
224
+ };
225
+ const extractAssistantText = (result) => {
226
+ for (let i = result.messages.length - 1; i >= 0; i -= 1) {
227
+ const message = result.messages[i];
228
+ if (!message) {
229
+ continue;
230
+ }
231
+ if (message.role !== 'assistant') {
232
+ continue;
233
+ }
234
+ if (typeof message.content === 'string') {
235
+ return message.content;
236
+ }
237
+ return toJsonString(message.content);
238
+ }
239
+ return '';
240
+ };
241
+ const createRuntime = async () => {
242
+ const modules = await getSourceModules();
243
+ const workspaceRoot = resolveWorkspaceRoot();
244
+ await modules.loadEnvFiles(workspaceRoot);
245
+ modules.loadConfigToEnv({ projectRoot: workspaceRoot });
246
+ const conversationId = resolveConversationId();
247
+ const modelId = resolveModelId(modules, preferredModelId);
248
+ const modelConfig = requireModelApiKey(modules, modelId);
249
+ const maxSteps = parsePositiveInt(process.env.AGENT_MAX_STEPS, DEFAULT_MAX_STEPS);
250
+ const coreLogger = modules.createLoggerFromEnv(buildCliLoggerEnv(process.env), workspaceRoot);
251
+ const agentLogger = modules.createAgentLoggerAdapter(asRecord(coreLogger), {
252
+ runtime: 'renx-code',
253
+ });
254
+ const provider = modules.ProviderRegistry.createFromEnv(modelId, {
255
+ logger: asRecord(coreLogger),
256
+ });
257
+ const toolManager = new modules.DefaultToolManager();
258
+ const taskStore = new modules.TaskStore({
259
+ baseDir: resolveRenxTaskDir(process.env),
260
+ });
261
+ toolManager.registerTool(new modules.BashTool());
262
+ toolManager.registerTool(new modules.WriteFileTool({
263
+ allowedDirectories: [workspaceRoot],
264
+ }));
265
+ toolManager.registerTool(new modules.FileReadTool({
266
+ allowedDirectories: [workspaceRoot],
267
+ }));
268
+ toolManager.registerTool(new modules.FileEditTool({
269
+ allowedDirectories: [workspaceRoot],
270
+ }));
271
+ toolManager.registerTool(new modules.FileHistoryListTool({
272
+ allowedDirectories: [workspaceRoot],
273
+ }));
274
+ toolManager.registerTool(new modules.FileHistoryRestoreTool({
275
+ allowedDirectories: [workspaceRoot],
276
+ }));
277
+ toolManager.registerTool(new modules.GlobTool({
278
+ allowedDirectories: [workspaceRoot],
279
+ }));
280
+ toolManager.registerTool(new modules.GrepTool({
281
+ allowedDirectories: [workspaceRoot],
282
+ }));
283
+ toolManager.registerTool(new modules.SkillTool({
284
+ loaderOptions: {
285
+ workingDir: workspaceRoot,
286
+ },
287
+ }));
288
+ const agent = new modules.StatelessAgent(provider, toolManager, {
289
+ maxRetryCount: parsePositiveInt(process.env.AGENT_MAX_RETRY_COUNT, DEFAULT_MAX_RETRY_COUNT),
290
+ enableCompaction: true,
291
+ logger: agentLogger,
292
+ });
293
+ const appStore = modules.createSqliteAgentAppStore(resolveDbPath());
294
+ const preparableStore = appStore;
295
+ if (typeof preparableStore.prepare === 'function') {
296
+ await preparableStore.prepare();
297
+ }
298
+ const appService = new modules.AgentAppService({
299
+ agent,
300
+ executionStore: appStore,
301
+ eventStore: appStore,
302
+ messageStore: appStore,
303
+ });
304
+ const collectToolSchemas = () => toolManager
305
+ .getTools()
306
+ .map(tool => {
307
+ const schema = tool?.toToolSchema?.();
308
+ if (!schema || typeof schema !== 'object') {
309
+ return null;
310
+ }
311
+ return schema;
312
+ })
313
+ .filter((schema) => Boolean(schema));
314
+ const resolveToolSchemas = (allowedTools, hiddenToolNames) => {
315
+ const allSchemas = toolManager
316
+ ? collectToolSchemas().filter(schema => {
317
+ const name = schema.function?.name;
318
+ if (typeof name !== 'string') {
319
+ return false;
320
+ }
321
+ return !hiddenToolNames?.has(name);
322
+ })
323
+ : [];
324
+ if (!allowedTools || allowedTools.length === 0) {
325
+ return allSchemas;
326
+ }
327
+ const allowed = new Set(allowedTools);
328
+ return allSchemas.filter(schema => {
329
+ const name = schema.function?.name;
330
+ return typeof name === 'string' && allowed.has(name);
331
+ });
332
+ };
333
+ const resolveSubagentToolSchemas = (allowedTools) => resolveToolSchemas(allowedTools, undefined);
334
+ const taskRunner = new modules.RealSubagentRunnerAdapter({
335
+ store: taskStore,
336
+ appService,
337
+ resolveTools: resolveSubagentToolSchemas,
338
+ // Use provider-level model name (e.g. MiniMax-M2.5), not registry id (e.g. minimax-2.5),
339
+ // so subagent requests match the same backend model as parent agent.
340
+ resolveModelId: () => modelConfig.model || modelId,
341
+ });
342
+ toolManager.registerTool(new modules.TaskCreateTool({
343
+ store: taskStore,
344
+ defaultNamespace: conversationId,
345
+ }));
346
+ toolManager.registerTool(new modules.TaskGetTool({
347
+ store: taskStore,
348
+ defaultNamespace: conversationId,
349
+ }));
350
+ toolManager.registerTool(new modules.TaskListTool({
351
+ store: taskStore,
352
+ defaultNamespace: conversationId,
353
+ }));
354
+ toolManager.registerTool(new modules.TaskUpdateTool({
355
+ store: taskStore,
356
+ defaultNamespace: conversationId,
357
+ }));
358
+ toolManager.registerTool(new modules.TaskTool({
359
+ store: taskStore,
360
+ runner: taskRunner,
361
+ defaultNamespace: conversationId,
362
+ }));
363
+ toolManager.registerTool(new modules.TaskStopTool({
364
+ store: taskStore,
365
+ runner: taskRunner,
366
+ defaultNamespace: conversationId,
367
+ }));
368
+ toolManager.registerTool(new modules.TaskOutputTool({
369
+ store: taskStore,
370
+ runner: taskRunner,
371
+ defaultNamespace: conversationId,
372
+ }));
373
+ const parentTools = resolveToolSchemas(undefined, PARENT_HIDDEN_TOOL_NAMES);
374
+ return {
375
+ modules,
376
+ modelId,
377
+ modelLabel: modelConfig.name,
378
+ maxSteps,
379
+ conversationId,
380
+ workspaceRoot,
381
+ parentTools,
382
+ agent,
383
+ appService,
384
+ appStore,
385
+ logger: coreLogger && typeof coreLogger === 'object'
386
+ ? coreLogger
387
+ : undefined,
388
+ };
389
+ };
390
+ const getRuntime = async () => {
391
+ // 双重检查锁定模式
392
+ if (runtimePromise) {
393
+ return runtimePromise;
394
+ }
395
+ if (initializing) {
396
+ // 等待初始化完成
397
+ while (initializing) {
398
+ await new Promise(resolve => setTimeout(resolve, 10));
399
+ }
400
+ // 初始化完成后,runtimePromise应该已经设置
401
+ if (runtimePromise) {
402
+ return runtimePromise;
403
+ }
404
+ }
405
+ // 开始初始化
406
+ initializing = true;
407
+ try {
408
+ const promise = createRuntime();
409
+ runtimePromise = promise;
410
+ // 如果初始化失败,允许重新尝试
411
+ promise.catch(() => {
412
+ runtimePromise = null;
413
+ });
414
+ return promise;
415
+ }
416
+ finally {
417
+ initializing = false;
418
+ }
419
+ };
420
+ const disposeRuntimeInstance = async () => {
421
+ const runtime = await runtimePromise;
422
+ runtimePromise = null;
423
+ if (!runtime) {
424
+ return;
425
+ }
426
+ await runtime.logger?.close?.();
427
+ await runtime.appStore.close();
428
+ };
429
+ export const runAgentPrompt = async (prompt, handlers, options = {}) => {
430
+ const runtime = await getRuntime();
431
+ const startedAt = Date.now();
432
+ const streamedState = {
433
+ text: '',
434
+ latestErrorMessage: undefined,
435
+ stopEmitted: false,
436
+ lastLoopStep: 0,
437
+ };
438
+ const toolStreamSequenceById = new Map();
439
+ const toolCallsById = new Map();
440
+ const toolCallBuffer = new ToolCallBuffer();
441
+ let latestUsageEvent;
442
+ let currentAction = 'llm';
443
+ const onToolConfirm = (event) => {
444
+ const rawArgs = parseJsonObject(event.arguments);
445
+ const toolConfirmEvent = {
446
+ toolCallId: event.toolCallId,
447
+ toolName: event.toolName,
448
+ args: rawArgs,
449
+ rawArgs,
450
+ reason: readString(event.reason),
451
+ metadata: event.metadata,
452
+ };
453
+ safeInvoke(() => handlers.onToolConfirm?.(toolConfirmEvent));
454
+ void resolveToolConfirmDecision(toolConfirmEvent, handlers)
455
+ .then(decision => {
456
+ event.resolve(decision);
457
+ })
458
+ .catch(error => {
459
+ const message = error instanceof Error ? error.message : String(error);
460
+ event.resolve({
461
+ approved: false,
462
+ message: message || 'Tool confirmation failed.',
463
+ });
464
+ });
465
+ };
466
+ runtime.agent.on('tool_confirm', onToolConfirm);
467
+ let result;
468
+ try {
469
+ const historyMessages = await runtime.appService.listContextMessages(runtime.conversationId);
470
+ result = await runtime.appService.runForeground({
471
+ conversationId: runtime.conversationId,
472
+ userInput: prompt,
473
+ historyMessages: historyMessages,
474
+ systemPrompt: buildSystemPrompt({ directory: runtime.workspaceRoot }),
475
+ tools: runtime.parentTools,
476
+ config: resolvePromptCacheConfig(runtime.conversationId),
477
+ maxSteps: runtime.maxSteps,
478
+ abortSignal: options.abortSignal,
479
+ modelLabel: runtime.modelLabel,
480
+ }, {
481
+ onError: (error) => {
482
+ const message = error instanceof Error ? error.message : String(error);
483
+ if (message) {
484
+ streamedState.latestErrorMessage = message;
485
+ }
486
+ },
487
+ onContextUsage: usage => {
488
+ const contextUsageEvent = toContextUsageEventFromApp(usage);
489
+ if (!contextUsageEvent) {
490
+ return;
491
+ }
492
+ safeInvoke(() => handlers.onContextUsage?.(contextUsageEvent));
493
+ },
494
+ onUsage: usage => {
495
+ const usageEvent = toUsageEventFromApp(usage);
496
+ latestUsageEvent = usageEvent;
497
+ safeInvoke(() => handlers.onUsage?.(usageEvent));
498
+ },
499
+ onEvent: async (envelope) => {
500
+ const payload = asRecord(envelope.data);
501
+ switch (envelope.eventType) {
502
+ case 'chunk': {
503
+ const event = toTextDeltaEvent(payload, false);
504
+ if (event.text.length > 0) {
505
+ streamedState.text += event.text;
506
+ safeInvoke(() => handlers.onTextDelta?.(event));
507
+ }
508
+ break;
509
+ }
510
+ case 'reasoning_chunk': {
511
+ const event = toTextDeltaEvent(payload, true);
512
+ if (event.text.length > 0) {
513
+ safeInvoke(() => handlers.onTextDelta?.(event));
514
+ }
515
+ break;
516
+ }
517
+ case 'tool_stream': {
518
+ const toolStreamEvent = toToolStreamEvent(envelope, toolStreamSequenceById);
519
+ toolCallBuffer.ensureEmitted(toolStreamEvent.toolCallId, toolCall => {
520
+ safeInvoke(() => handlers.onToolUse?.(toolCall));
521
+ });
522
+ safeInvoke(() => handlers.onToolStream?.(toolStreamEvent));
523
+ break;
524
+ }
525
+ case 'tool_call': {
526
+ const rawToolCalls = payload.toolCalls;
527
+ if (Array.isArray(rawToolCalls) && rawToolCalls.length > 0) {
528
+ for (const item of rawToolCalls) {
529
+ const toolCall = asRecord(item);
530
+ const toolCallId = readString(asRecord(toolCall).id);
531
+ if (toolCallId) {
532
+ toolCallsById.set(toolCallId, toolCall);
533
+ }
534
+ toolCallBuffer.register(toolCall, event => {
535
+ safeInvoke(() => handlers.onToolUse?.(event));
536
+ }, currentAction === 'tool');
537
+ }
538
+ }
539
+ else {
540
+ const toolCall = payload;
541
+ const toolCallId = readString(asRecord(toolCall).id);
542
+ if (toolCallId) {
543
+ toolCallsById.set(toolCallId, toolCall);
544
+ }
545
+ toolCallBuffer.register(toolCall, event => {
546
+ safeInvoke(() => handlers.onToolUse?.(event));
547
+ }, currentAction === 'tool');
548
+ }
549
+ break;
550
+ }
551
+ case 'tool_result': {
552
+ const toolCallId = readString(payload.tool_call_id) ?? readString(payload.toolCallId);
553
+ toolCallBuffer.ensureEmitted(toolCallId, toolCall => {
554
+ safeInvoke(() => handlers.onToolUse?.(toolCall));
555
+ });
556
+ const toolResultEvent = toToolResultEvent(payload, toolCallsById);
557
+ safeInvoke(() => handlers.onToolResult?.(toolResultEvent));
558
+ break;
559
+ }
560
+ case 'progress': {
561
+ const nextAction = readString(payload.currentAction) ?? 'progress';
562
+ currentAction = nextAction;
563
+ const stepEvent = toStepEvent(payload, nextAction, 0);
564
+ safeInvoke(() => handlers.onStep?.(stepEvent));
565
+ if (nextAction === 'tool') {
566
+ toolCallBuffer.flush(toolCall => {
567
+ safeInvoke(() => handlers.onToolUse?.(toolCall));
568
+ });
569
+ }
570
+ if (nextAction === 'llm' && stepEvent.stepIndex > streamedState.lastLoopStep) {
571
+ streamedState.lastLoopStep = stepEvent.stepIndex;
572
+ const loopEvent = toLoopEvent(stepEvent.stepIndex);
573
+ safeInvoke(() => handlers.onLoop?.(loopEvent));
574
+ }
575
+ break;
576
+ }
577
+ case 'checkpoint': {
578
+ const stepEvent = toStepEvent(payload, 'checkpoint', 0);
579
+ safeInvoke(() => handlers.onStep?.(stepEvent));
580
+ break;
581
+ }
582
+ case 'done': {
583
+ safeInvoke(() => handlers.onTextComplete?.(streamedState.text));
584
+ const stopEvent = {
585
+ reason: readString(payload.finishReason) ?? 'stop',
586
+ };
587
+ safeInvoke(() => handlers.onStop?.(stopEvent));
588
+ streamedState.stopEmitted = true;
589
+ break;
590
+ }
591
+ case 'error': {
592
+ const message = readString(payload.message);
593
+ streamedState.latestErrorMessage = message;
594
+ break;
595
+ }
596
+ default:
597
+ break;
598
+ }
599
+ },
600
+ });
601
+ }
602
+ finally {
603
+ runtime.agent.off('tool_confirm', onToolConfirm);
604
+ }
605
+ if (!streamedState.stopEmitted) {
606
+ safeInvoke(() => handlers.onTextComplete?.(streamedState.text));
607
+ safeInvoke(() => handlers.onStop?.({
608
+ reason: result.finishReason,
609
+ message: result.finishReason === 'error' ? result.run.errorMessage : undefined,
610
+ }));
611
+ }
612
+ const finalText = streamedState.text || extractAssistantText(result);
613
+ const completionMessage = result.finishReason === 'error'
614
+ ? (streamedState.latestErrorMessage ?? result.run.errorMessage)
615
+ : undefined;
616
+ return {
617
+ text: finalText,
618
+ completionReason: result.finishReason,
619
+ completionMessage,
620
+ durationSeconds: (Date.now() - startedAt) / 1000,
621
+ modelLabel: runtime.modelLabel,
622
+ usage: latestUsageEvent,
623
+ };
624
+ };
625
+ export const getAgentModelLabel = async () => {
626
+ const runtime = await getRuntime();
627
+ return runtime.modelLabel;
628
+ };
629
+ export const getAgentModelAttachmentCapabilities = async () => {
630
+ const modules = await getSourceModules();
631
+ const modelId = await getAgentModelId();
632
+ const config = modules.ProviderRegistry.getModelConfig(modelId);
633
+ return resolveAttachmentModelCapabilities(config);
634
+ };
635
+ export const getAgentModelId = async () => {
636
+ if (runtimePromise) {
637
+ const runtime = await runtimePromise;
638
+ if (runtime) {
639
+ return runtime.modelId;
640
+ }
641
+ }
642
+ const modules = await getSourceModules();
643
+ return resolveModelId(modules, preferredModelId);
644
+ };
645
+ export const listAgentModels = async () => {
646
+ const modules = await getSourceModules();
647
+ const currentModelId = await getAgentModelId();
648
+ return modules.ProviderRegistry.getModelIds()
649
+ .map(id => {
650
+ const config = modules.ProviderRegistry.getModelConfig(id);
651
+ return {
652
+ id,
653
+ name: config.name,
654
+ provider: config.provider ?? 'other',
655
+ apiKeyEnv: config.envApiKey,
656
+ configured: Boolean(process.env[config.envApiKey]),
657
+ current: id === currentModelId,
658
+ };
659
+ })
660
+ .sort((a, b) => {
661
+ if (a.provider !== b.provider) {
662
+ return a.provider.localeCompare(b.provider);
663
+ }
664
+ if (a.current !== b.current) {
665
+ return a.current ? -1 : 1;
666
+ }
667
+ return a.name.localeCompare(b.name);
668
+ });
669
+ };
670
+ export const switchAgentModel = async (modelId) => {
671
+ const modules = await getSourceModules();
672
+ const available = modules.ProviderRegistry.getModelIds();
673
+ if (!available.includes(modelId)) {
674
+ throw new Error(`Unknown model: ${modelId}`);
675
+ }
676
+ const config = modules.ProviderRegistry.getModelConfig(modelId);
677
+ if (!process.env[config.envApiKey]) {
678
+ throw new Error(`Missing env ${config.envApiKey} for model ${modelId}.`);
679
+ }
680
+ preferredModelId = modelId;
681
+ await disposeRuntimeInstance();
682
+ return {
683
+ modelId,
684
+ modelLabel: config.name,
685
+ };
686
+ };
687
+ export const disposeAgentRuntime = async () => {
688
+ await disposeRuntimeInstance();
689
+ preferredModelId = readPreferredModelIdFromEnv();
690
+ };
691
+ //# sourceMappingURL=runtime.js.map