@renxqoo/renx-code 0.0.4 → 0.0.6

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 (210) hide show
  1. package/README.md +82 -51
  2. package/bin/renx.cjs +16 -0
  3. package/package.json +2 -45
  4. package/src/agent/runtime/runtime.context-usage.test.ts +4 -5
  5. package/src/agent/runtime/runtime.error-handling.test.ts +4 -5
  6. package/src/agent/runtime/runtime.test.ts +7 -4
  7. package/src/agent/runtime/runtime.ts +3 -9
  8. package/src/agent/runtime/runtime.usage-forwarding.test.ts +4 -5
  9. package/src/agent/runtime/source-modules.test.ts +16 -35
  10. package/src/agent/runtime/source-modules.ts +17 -0
  11. package/vendor/agent-root/src/agent/ENTERPRISE_ACCEPTANCE_CHECKLIST.md +95 -0
  12. package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.html +1345 -0
  13. package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.md +1353 -0
  14. package/vendor/agent-root/src/agent/ERROR_CONTRACT.md +60 -0
  15. package/vendor/agent-root/src/agent/TEST_COVERAGE_ANALYSIS.md +278 -0
  16. package/vendor/agent-root/src/agent/__test__/error-contract.test.ts +72 -0
  17. package/vendor/agent-root/src/agent/__test__/types.test.ts +137 -0
  18. package/vendor/agent-root/src/agent/agent/__test__/abort-runtime.test.ts +83 -0
  19. package/vendor/agent-root/src/agent/agent/__test__/callback-safety.test.ts +34 -0
  20. package/vendor/agent-root/src/agent/agent/__test__/compaction.test.ts +323 -0
  21. package/vendor/agent-root/src/agent/agent/__test__/concurrency.test.ts +290 -0
  22. package/vendor/agent-root/src/agent/agent/__test__/error-normalizer.test.ts +377 -0
  23. package/vendor/agent-root/src/agent/agent/__test__/error.test.ts +212 -0
  24. package/vendor/agent-root/src/agent/agent/__test__/fault-injection.test.ts +295 -0
  25. package/vendor/agent-root/src/agent/agent/__test__/index.test.ts +3607 -0
  26. package/vendor/agent-root/src/agent/agent/__test__/logger.test.ts +35 -0
  27. package/vendor/agent-root/src/agent/agent/__test__/message-utils.test.ts +517 -0
  28. package/vendor/agent-root/src/agent/agent/__test__/telemetry.test.ts +97 -0
  29. package/vendor/agent-root/src/agent/agent/__test__/timeout-budget.test.ts +479 -0
  30. package/vendor/agent-root/src/agent/agent/__test__/tool-call-merge.test.ts +80 -0
  31. package/vendor/agent-root/src/agent/agent/__test__/tool-execution-ledger.test.ts +76 -0
  32. package/vendor/agent-root/src/agent/agent/__test__/write-buffer.test.ts +173 -0
  33. package/vendor/agent-root/src/agent/agent/__test__/write-file-session.test.ts +109 -0
  34. package/vendor/agent-root/src/agent/agent/abort-runtime.ts +71 -0
  35. package/vendor/agent-root/src/agent/agent/callback-safety.ts +33 -0
  36. package/vendor/agent-root/src/agent/agent/compaction.ts +291 -0
  37. package/vendor/agent-root/src/agent/agent/concurrency.ts +103 -0
  38. package/vendor/agent-root/src/agent/agent/error-normalizer.ts +190 -0
  39. package/vendor/agent-root/src/agent/agent/error.ts +198 -0
  40. package/vendor/agent-root/src/agent/agent/index.ts +1772 -0
  41. package/vendor/agent-root/src/agent/agent/logger.ts +65 -0
  42. package/vendor/agent-root/src/agent/agent/message-utils.ts +101 -0
  43. package/vendor/agent-root/src/agent/agent/stream-events.ts +61 -0
  44. package/vendor/agent-root/src/agent/agent/telemetry.ts +123 -0
  45. package/vendor/agent-root/src/agent/agent/timeout-budget.ts +227 -0
  46. package/vendor/agent-root/src/agent/agent/tool-call-merge.ts +111 -0
  47. package/vendor/agent-root/src/agent/agent/tool-execution-ledger.ts +164 -0
  48. package/vendor/agent-root/src/agent/agent/write-buffer.ts +188 -0
  49. package/vendor/agent-root/src/agent/agent/write-file-session.ts +238 -0
  50. package/vendor/agent-root/src/agent/app/__test__/agent-app-service.test.ts +1053 -0
  51. package/vendor/agent-root/src/agent/app/__test__/minimal-agent-application.test.ts +158 -0
  52. package/vendor/agent-root/src/agent/app/__test__/sqlite-agent-app-store.test.ts +437 -0
  53. package/vendor/agent-root/src/agent/app/agent-app-service.ts +748 -0
  54. package/vendor/agent-root/src/agent/app/contracts.ts +109 -0
  55. package/vendor/agent-root/src/agent/app/index.ts +5 -0
  56. package/vendor/agent-root/src/agent/app/minimal-agent-application.ts +151 -0
  57. package/vendor/agent-root/src/agent/app/ports.ts +72 -0
  58. package/vendor/agent-root/src/agent/app/sqlite-agent-app-store.ts +1182 -0
  59. package/vendor/agent-root/src/agent/app/sqlite-client.ts +177 -0
  60. package/vendor/agent-root/src/agent/docs/cli-app-layer/00-README.md +36 -0
  61. package/vendor/agent-root/src/agent/docs/cli-app-layer/01-scope-and-goals.md +33 -0
  62. package/vendor/agent-root/src/agent/docs/cli-app-layer/02-architecture-overview.md +40 -0
  63. package/vendor/agent-root/src/agent/docs/cli-app-layer/03-domain-model-and-contracts.md +91 -0
  64. package/vendor/agent-root/src/agent/docs/cli-app-layer/04-ports-and-interfaces.md +116 -0
  65. package/vendor/agent-root/src/agent/docs/cli-app-layer/05-run-orchestration-and-state-machine.md +52 -0
  66. package/vendor/agent-root/src/agent/docs/cli-app-layer/06-cli-commands-and-ux.md +53 -0
  67. package/vendor/agent-root/src/agent/docs/cli-app-layer/07-storage-design-local.md +52 -0
  68. package/vendor/agent-root/src/agent/docs/cli-app-layer/08-error-and-observability.md +40 -0
  69. package/vendor/agent-root/src/agent/docs/cli-app-layer/09-security-and-policy-boundary.md +19 -0
  70. package/vendor/agent-root/src/agent/docs/cli-app-layer/10-test-plan-and-acceptance.md +28 -0
  71. package/vendor/agent-root/src/agent/docs/cli-app-layer/11-implementation-phases.md +26 -0
  72. package/vendor/agent-root/src/agent/docs/cli-app-layer/12-open-questions-and-risks.md +30 -0
  73. package/vendor/agent-root/src/agent/docs/cli-app-layer/13-sqlite-schema-fields-and-rationale.md +567 -0
  74. package/vendor/agent-root/src/agent/docs/cli-app-layer/14-project-flow-mermaid.md +583 -0
  75. package/vendor/agent-root/src/agent/docs/cli-app-layer/15-openclaw-style-project-blueprint.md +972 -0
  76. package/vendor/agent-root/src/agent/error-contract.ts +154 -0
  77. package/vendor/agent-root/src/agent/prompts/system.ts +246 -0
  78. package/vendor/agent-root/src/agent/prompts/system1.ts +208 -0
  79. package/vendor/agent-root/src/agent/storage/__test__/file-history-store.test.ts +98 -0
  80. package/vendor/agent-root/src/agent/storage/file-history-store.ts +313 -0
  81. package/vendor/agent-root/src/agent/storage/file-storage-config.ts +94 -0
  82. package/vendor/agent-root/src/agent/storage/file-system.ts +31 -0
  83. package/vendor/agent-root/src/agent/storage/file-write-service.ts +21 -0
  84. package/vendor/agent-root/src/agent/tool/__test__/base-tool.test.ts +413 -0
  85. package/vendor/agent-root/src/agent/tool/__test__/bash-policy.test.ts +356 -0
  86. package/vendor/agent-root/src/agent/tool/__test__/bash.mocked-coverage.test.ts +375 -0
  87. package/vendor/agent-root/src/agent/tool/__test__/bash.test.ts +372 -0
  88. package/vendor/agent-root/src/agent/tool/__test__/error.test.ts +108 -0
  89. package/vendor/agent-root/src/agent/tool/__test__/file-edit-tool.test.ts +258 -0
  90. package/vendor/agent-root/src/agent/tool/__test__/file-history-tools.test.ts +121 -0
  91. package/vendor/agent-root/src/agent/tool/__test__/file-read-tool.test.ts +210 -0
  92. package/vendor/agent-root/src/agent/tool/__test__/glob.test.ts +139 -0
  93. package/vendor/agent-root/src/agent/tool/__test__/grep.mocked-coverage.test.ts +456 -0
  94. package/vendor/agent-root/src/agent/tool/__test__/grep.test.ts +192 -0
  95. package/vendor/agent-root/src/agent/tool/__test__/lsp.test.ts +300 -0
  96. package/vendor/agent-root/src/agent/tool/__test__/outside-workspace-confirmation.test.ts +214 -0
  97. package/vendor/agent-root/src/agent/tool/__test__/path-security.test.ts +336 -0
  98. package/vendor/agent-root/src/agent/tool/__test__/skill-loader.test.ts +494 -0
  99. package/vendor/agent-root/src/agent/tool/__test__/skill-parser.test.ts +543 -0
  100. package/vendor/agent-root/src/agent/tool/__test__/skill-tool.test.ts +172 -0
  101. package/vendor/agent-root/src/agent/tool/__test__/task-concurrency-and-version.test.ts +116 -0
  102. package/vendor/agent-root/src/agent/tool/__test__/task-create-get-list-update.test.ts +267 -0
  103. package/vendor/agent-root/src/agent/tool/__test__/task-create.test.ts +519 -0
  104. package/vendor/agent-root/src/agent/tool/__test__/task-errors.test.ts +225 -0
  105. package/vendor/agent-root/src/agent/tool/__test__/task-output-blocking.test.ts +223 -0
  106. package/vendor/agent-root/src/agent/tool/__test__/task-output.test.ts +184 -0
  107. package/vendor/agent-root/src/agent/tool/__test__/task-parent-abort.test.ts +287 -0
  108. package/vendor/agent-root/src/agent/tool/__test__/task-real-runner-adapter.test.ts +190 -0
  109. package/vendor/agent-root/src/agent/tool/__test__/task-run-lifecycle.test.ts +352 -0
  110. package/vendor/agent-root/src/agent/tool/__test__/task-store-runner-branches.test.ts +395 -0
  111. package/vendor/agent-root/src/agent/tool/__test__/task-store.test.ts +391 -0
  112. package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config-integration.test.ts +176 -0
  113. package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config.test.ts +68 -0
  114. package/vendor/agent-root/src/agent/tool/__test__/task-tools-core-edges.test.ts +630 -0
  115. package/vendor/agent-root/src/agent/tool/__test__/task-tools-runtime-edges.test.ts +732 -0
  116. package/vendor/agent-root/src/agent/tool/__test__/task-types.test.ts +494 -0
  117. package/vendor/agent-root/src/agent/tool/__test__/task-utils-branches.test.ts +175 -0
  118. package/vendor/agent-root/src/agent/tool/__test__/tool-manager.test.ts +505 -0
  119. package/vendor/agent-root/src/agent/tool/__test__/types.test.ts +55 -0
  120. package/vendor/agent-root/src/agent/tool/__test__/web-fetch.test.ts +244 -0
  121. package/vendor/agent-root/src/agent/tool/__test__/web-search.test.ts +290 -0
  122. package/vendor/agent-root/src/agent/tool/__test__/write-file.test.ts +368 -0
  123. package/vendor/agent-root/src/agent/tool/base-tool.ts +345 -0
  124. package/vendor/agent-root/src/agent/tool/bash-policy.ts +636 -0
  125. package/vendor/agent-root/src/agent/tool/bash.ts +688 -0
  126. package/vendor/agent-root/src/agent/tool/error.ts +131 -0
  127. package/vendor/agent-root/src/agent/tool/file-edit-tool.ts +264 -0
  128. package/vendor/agent-root/src/agent/tool/file-history-list.ts +103 -0
  129. package/vendor/agent-root/src/agent/tool/file-history-restore.ts +149 -0
  130. package/vendor/agent-root/src/agent/tool/file-read-tool.ts +211 -0
  131. package/vendor/agent-root/src/agent/tool/glob.ts +171 -0
  132. package/vendor/agent-root/src/agent/tool/grep.ts +496 -0
  133. package/vendor/agent-root/src/agent/tool/lsp.ts +481 -0
  134. package/vendor/agent-root/src/agent/tool/path-security.ts +117 -0
  135. package/vendor/agent-root/src/agent/tool/search/common.ts +153 -0
  136. package/vendor/agent-root/src/agent/tool/skill/index.ts +13 -0
  137. package/vendor/agent-root/src/agent/tool/skill/loader.ts +229 -0
  138. package/vendor/agent-root/src/agent/tool/skill/parser.ts +124 -0
  139. package/vendor/agent-root/src/agent/tool/skill/types.ts +27 -0
  140. package/vendor/agent-root/src/agent/tool/skill-tool.ts +143 -0
  141. package/vendor/agent-root/src/agent/tool/task-create.ts +186 -0
  142. package/vendor/agent-root/src/agent/tool/task-errors.ts +42 -0
  143. package/vendor/agent-root/src/agent/tool/task-get.ts +116 -0
  144. package/vendor/agent-root/src/agent/tool/task-graph.ts +78 -0
  145. package/vendor/agent-root/src/agent/tool/task-list.ts +141 -0
  146. package/vendor/agent-root/src/agent/tool/task-mock-runner-adapter.ts +232 -0
  147. package/vendor/agent-root/src/agent/tool/task-output.ts +223 -0
  148. package/vendor/agent-root/src/agent/tool/task-parent-abort.ts +115 -0
  149. package/vendor/agent-root/src/agent/tool/task-real-runner-adapter.ts +336 -0
  150. package/vendor/agent-root/src/agent/tool/task-runner-adapter.ts +55 -0
  151. package/vendor/agent-root/src/agent/tool/task-stop.ts +187 -0
  152. package/vendor/agent-root/src/agent/tool/task-store.ts +217 -0
  153. package/vendor/agent-root/src/agent/tool/task-subagent-config.ts +149 -0
  154. package/vendor/agent-root/src/agent/tool/task-types.ts +264 -0
  155. package/vendor/agent-root/src/agent/tool/task-update.ts +315 -0
  156. package/vendor/agent-root/src/agent/tool/task.ts +209 -0
  157. package/vendor/agent-root/src/agent/tool/tool-manager.ts +362 -0
  158. package/vendor/agent-root/src/agent/tool/tool-prompts.ts +242 -0
  159. package/vendor/agent-root/src/agent/tool/types.ts +116 -0
  160. package/vendor/agent-root/src/agent/tool/web-fetch.ts +227 -0
  161. package/vendor/agent-root/src/agent/tool/web-search.ts +208 -0
  162. package/vendor/agent-root/src/agent/tool/write-file.ts +497 -0
  163. package/vendor/agent-root/src/agent/types.ts +232 -0
  164. package/vendor/agent-root/src/agent/utils/__tests__/index.test.ts +18 -0
  165. package/vendor/agent-root/src/agent/utils/__tests__/message-utils.test.ts +610 -0
  166. package/vendor/agent-root/src/agent/utils/__tests__/message.test.ts +223 -0
  167. package/vendor/agent-root/src/agent/utils/__tests__/token.test.ts +42 -0
  168. package/vendor/agent-root/src/agent/utils/index.ts +16 -0
  169. package/vendor/agent-root/src/agent/utils/message.ts +171 -0
  170. package/vendor/agent-root/src/agent/utils/token.ts +28 -0
  171. package/vendor/agent-root/src/config/__tests__/load-config-to-env.test.ts +129 -0
  172. package/vendor/agent-root/src/config/__tests__/loader.test.ts +247 -0
  173. package/vendor/agent-root/src/config/__tests__/runtime.test.ts +88 -0
  174. package/vendor/agent-root/src/config/index.ts +54 -0
  175. package/vendor/agent-root/src/config/loader.ts +431 -0
  176. package/vendor/agent-root/src/config/paths.ts +30 -0
  177. package/vendor/agent-root/src/config/runtime.ts +163 -0
  178. package/vendor/agent-root/src/config/types.ts +70 -0
  179. package/vendor/agent-root/src/logger/index.ts +57 -0
  180. package/vendor/agent-root/src/logger/logger.ts +819 -0
  181. package/vendor/agent-root/src/logger/types.ts +150 -0
  182. package/vendor/agent-root/src/providers/__tests__/errors.test.ts +441 -0
  183. package/vendor/agent-root/src/providers/__tests__/index.test.ts +16 -0
  184. package/vendor/agent-root/src/providers/__tests__/openai-compatible.options.test.ts +318 -0
  185. package/vendor/agent-root/src/providers/__tests__/openai-compatible.test.ts +600 -0
  186. package/vendor/agent-root/src/providers/__tests__/registry.test.ts +449 -0
  187. package/vendor/agent-root/src/providers/__tests__/responses-adapter.test.ts +298 -0
  188. package/vendor/agent-root/src/providers/adapters/__tests__/anthropic.test.ts +354 -0
  189. package/vendor/agent-root/src/providers/adapters/__tests__/kimi.test.ts +58 -0
  190. package/vendor/agent-root/src/providers/adapters/__tests__/standard.test.ts +261 -0
  191. package/vendor/agent-root/src/providers/adapters/anthropic.ts +572 -0
  192. package/vendor/agent-root/src/providers/adapters/base.ts +131 -0
  193. package/vendor/agent-root/src/providers/adapters/kimi.ts +48 -0
  194. package/vendor/agent-root/src/providers/adapters/responses.ts +732 -0
  195. package/vendor/agent-root/src/providers/adapters/standard.ts +120 -0
  196. package/vendor/agent-root/src/providers/http/__tests__/client.timeout.test.ts +313 -0
  197. package/vendor/agent-root/src/providers/http/client.ts +289 -0
  198. package/vendor/agent-root/src/providers/http/stream-parser.ts +109 -0
  199. package/vendor/agent-root/src/providers/index.ts +76 -0
  200. package/vendor/agent-root/src/providers/kimi-headers.ts +177 -0
  201. package/vendor/agent-root/src/providers/openai-compatible.ts +387 -0
  202. package/vendor/agent-root/src/providers/registry/model-config.ts +230 -0
  203. package/vendor/agent-root/src/providers/registry/provider-factory.ts +123 -0
  204. package/vendor/agent-root/src/providers/registry.ts +135 -0
  205. package/vendor/agent-root/src/providers/types/api.ts +284 -0
  206. package/vendor/agent-root/src/providers/types/config.ts +58 -0
  207. package/vendor/agent-root/src/providers/types/errors.ts +323 -0
  208. package/vendor/agent-root/src/providers/types/index.ts +72 -0
  209. package/vendor/agent-root/src/providers/types/provider.ts +45 -0
  210. package/vendor/agent-root/src/providers/types/registry.ts +88 -0
@@ -0,0 +1,449 @@
1
+ /**
2
+ * Provider Registry 测试
3
+ */
4
+
5
+ import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
6
+ import { ProviderRegistry, MODEL_CONFIGS, ModelId, Models } from '../registry';
7
+ import { OpenAICompatibleProvider } from '../openai-compatible';
8
+ import { StandardAdapter } from '../adapters/standard';
9
+ import { ResponsesAdapter } from '../adapters/responses';
10
+
11
+ // Mock process.env
12
+ const originalEnv = process.env;
13
+
14
+ describe('ProviderRegistry', () => {
15
+ beforeEach(() => {
16
+ vi.resetModules();
17
+ process.env = { ...originalEnv };
18
+ });
19
+
20
+ afterEach(() => {
21
+ process.env = originalEnv;
22
+ });
23
+
24
+ describe('MODEL_CONFIGS', () => {
25
+ it('should have all model configurations', () => {
26
+ const modelIds = Object.keys(MODEL_CONFIGS) as ModelId[];
27
+
28
+ modelIds.forEach((id) => {
29
+ expect(MODEL_CONFIGS[id]).toBeDefined();
30
+ expect(MODEL_CONFIGS[id].id).toBe(id);
31
+ });
32
+ });
33
+
34
+ it('should have required properties for each model', () => {
35
+ Object.values(MODEL_CONFIGS).forEach((config) => {
36
+ expect(config).toHaveProperty('id');
37
+ expect(config).toHaveProperty('provider');
38
+ expect(config).toHaveProperty('name');
39
+ expect(config).toHaveProperty('baseURL');
40
+ expect(config).toHaveProperty('endpointPath');
41
+ expect(config).toHaveProperty('envApiKey');
42
+ expect(config).toHaveProperty('envBaseURL');
43
+ expect(config).toHaveProperty('model');
44
+ expect(config).toHaveProperty('max_tokens');
45
+ expect(config).toHaveProperty('LLMMAX_TOKENS');
46
+ expect(config).toHaveProperty('features');
47
+ expect(Array.isArray(config.features)).toBe(true);
48
+ });
49
+ });
50
+
51
+ it('should have valid provider types', () => {
52
+ const validProviders = [
53
+ 'anthropic',
54
+ 'kimi',
55
+ 'deepseek',
56
+ 'glm',
57
+ 'minimax',
58
+ 'openai',
59
+ 'openrouter',
60
+ 'qwen',
61
+ ];
62
+
63
+ Object.values(MODEL_CONFIGS).forEach((config) => {
64
+ expect(validProviders).toContain(config.provider);
65
+ });
66
+ });
67
+
68
+ it('should use Anthropic messages endpoint for claude-opus-4.6', () => {
69
+ expect(MODEL_CONFIGS['claude-opus-4.6'].endpointPath).toBe('/v1/messages');
70
+ });
71
+
72
+ it('should use responses endpoint for gpt-5.3 compatibility gateway', () => {
73
+ expect(MODEL_CONFIGS['gpt-5.3'].baseURL).toBe('https://gmncode.cn/v1');
74
+ expect(MODEL_CONFIGS['gpt-5.3'].endpointPath).toBe('/responses');
75
+ expect(MODEL_CONFIGS['gpt-5.3'].model).toBe('gpt-5.3-codex');
76
+ expect(MODEL_CONFIGS['gpt-5.3'].max_tokens).toBe(128 * 1000);
77
+ expect(MODEL_CONFIGS['gpt-5.3'].LLMMAX_TOKENS).toBe(400 * 1000);
78
+ expect(MODEL_CONFIGS['gpt-5.3'].features).toContain('reasoning');
79
+ });
80
+ });
81
+
82
+ describe('createFromEnv', () => {
83
+ it('should create provider for glm-4.7', () => {
84
+ process.env.GLM_API_KEY = 'test-glm-key';
85
+
86
+ const provider = ProviderRegistry.createFromEnv('glm-4.7');
87
+
88
+ expect(provider).toBeInstanceOf(OpenAICompatibleProvider);
89
+ expect(provider.config.apiKey).toBe('test-glm-key');
90
+ });
91
+
92
+ it('should create provider for minimax-2.5', () => {
93
+ process.env.MINIMAX_API_KEY = 'test-minimax-key';
94
+
95
+ const provider = ProviderRegistry.createFromEnv('minimax-2.5');
96
+
97
+ expect(provider).toBeInstanceOf(OpenAICompatibleProvider);
98
+ expect(provider.config.apiKey).toBe('test-minimax-key');
99
+ });
100
+
101
+ it('should create provider for kimi-k2.5', () => {
102
+ process.env.KIMI_API_KEY = 'test-kimi-key';
103
+
104
+ const provider = ProviderRegistry.createFromEnv('kimi-k2.5');
105
+
106
+ expect(provider).toBeInstanceOf(OpenAICompatibleProvider);
107
+ expect(provider.config.apiKey).toBe('test-kimi-key');
108
+ });
109
+
110
+ it('should create provider for deepseek-reasoner', () => {
111
+ process.env.DEEPSEEK_API_KEY = 'test-deepseek-key';
112
+
113
+ const provider = ProviderRegistry.createFromEnv('deepseek-reasoner');
114
+
115
+ expect(provider).toBeInstanceOf(OpenAICompatibleProvider);
116
+ expect(provider.config.apiKey).toBe('test-deepseek-key');
117
+ });
118
+
119
+ it('should create provider for qwen3.5-plus with QWEN env vars', () => {
120
+ process.env.QWEN_API_KEY = 'test-qwen-key';
121
+
122
+ const provider = ProviderRegistry.createFromEnv('qwen3.5-plus');
123
+
124
+ expect(provider).toBeInstanceOf(OpenAICompatibleProvider);
125
+ expect(provider.config.apiKey).toBe('test-qwen-key');
126
+ });
127
+
128
+ it('should use StandardAdapter for glm-5', () => {
129
+ process.env.GLM_API_KEY = 'test-glm5-key';
130
+
131
+ const provider = ProviderRegistry.createFromEnv('glm-5');
132
+ expect(provider.adapter).toBeInstanceOf(StandardAdapter);
133
+ });
134
+
135
+ it('should create gpt-5.3 provider with gmn-compatible defaults', () => {
136
+ process.env.OPENAI_API_KEY = 'test-openai-key';
137
+ delete process.env.OPENAI_API_BASE;
138
+
139
+ const provider = ProviderRegistry.createFromEnv('gpt-5.3');
140
+
141
+ expect(provider.config.apiKey).toBe('test-openai-key');
142
+ expect(provider.config.baseURL).toBe('https://gmncode.cn/v1');
143
+ expect(provider.config.model).toBe('gpt-5.3-codex');
144
+ expect(provider.config.max_tokens).toBe(128 * 1000);
145
+ expect(provider.config.LLMMAX_TOKENS).toBe(400 * 1000);
146
+ expect(provider.adapter).toBeInstanceOf(ResponsesAdapter);
147
+ });
148
+
149
+ it('should use default baseURL when env var not set', () => {
150
+ process.env.GLM_API_KEY = 'test-key';
151
+ delete process.env.GLM_API_BASE;
152
+
153
+ const provider = ProviderRegistry.createFromEnv('glm-4.7');
154
+
155
+ expect(provider.config.baseURL).toBe('https://open.bigmodel.cn/api/paas/v4');
156
+ });
157
+
158
+ it('should use custom baseURL from env var', () => {
159
+ process.env.GLM_API_KEY = 'test-key';
160
+ process.env.GLM_API_BASE = 'https://custom.example.com';
161
+
162
+ const provider = ProviderRegistry.createFromEnv('glm-4.7');
163
+
164
+ expect(provider.config.baseURL).toBe('https://custom.example.com');
165
+ });
166
+
167
+ it('should accept config overrides', () => {
168
+ process.env.GLM_API_KEY = 'test-key';
169
+
170
+ const provider = ProviderRegistry.createFromEnv('glm-4.7', {
171
+ temperature: 0.8,
172
+ apiKey: 'override-key',
173
+ });
174
+
175
+ expect(provider.config.temperature).toBe(0.8);
176
+ expect(provider.config.apiKey).toBe('override-key');
177
+ });
178
+
179
+ it('should accept tool_stream override', () => {
180
+ process.env.GLM_API_KEY = 'test-key';
181
+
182
+ const provider = ProviderRegistry.createFromEnv('glm-4.7', {
183
+ temperature: 0.1,
184
+ tool_stream: true,
185
+ });
186
+
187
+ expect(provider.config.temperature).toBe(0.1);
188
+ expect(provider.config.tool_stream).toBe(true);
189
+ });
190
+
191
+ it('should use model default model_reasoning_effort', () => {
192
+ process.env.OPENAI_API_KEY = 'test-openai-key';
193
+
194
+ const provider = ProviderRegistry.createFromEnv('gpt-5.3');
195
+
196
+ expect(provider.config.model_reasoning_effort).toBe('high');
197
+ });
198
+
199
+ it('should accept model_reasoning_effort override', () => {
200
+ process.env.OPENAI_API_KEY = 'test-openai-key';
201
+
202
+ const provider = ProviderRegistry.createFromEnv('gpt-5.3', {
203
+ model_reasoning_effort: 'medium',
204
+ });
205
+
206
+ expect(provider.config.model_reasoning_effort).toBe('medium');
207
+ });
208
+
209
+ it('should allow max_tokens and LLMMAX_TOKENS overrides', () => {
210
+ process.env.GLM_API_KEY = 'test-key';
211
+
212
+ const provider = ProviderRegistry.createFromEnv('glm-4.7', {
213
+ max_tokens: 1234,
214
+ LLMMAX_TOKENS: 5678,
215
+ });
216
+
217
+ expect(provider.config.max_tokens).toBe(1234);
218
+ expect(provider.config.LLMMAX_TOKENS).toBe(5678);
219
+ });
220
+
221
+ it('should not leak unrelated override fields into provider config', () => {
222
+ process.env.GLM_API_KEY = 'test-key';
223
+
224
+ const provider = ProviderRegistry.createFromEnv('glm-4.7', {
225
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
226
+ ...({ id: 'should-not-be-in-runtime-config' } as any),
227
+ });
228
+
229
+ expect((provider.config as Record<string, unknown>).id).toBeUndefined();
230
+ });
231
+
232
+ it('should throw error for unknown modelId', () => {
233
+ expect(() => {
234
+ ProviderRegistry.createFromEnv('unknown-model' as ModelId);
235
+ }).toThrow('Unknown model: unknown-model');
236
+ });
237
+
238
+ it('should throw error for undefined modelId', () => {
239
+ expect(() => {
240
+ ProviderRegistry.createFromEnv(undefined as unknown as ModelId);
241
+ }).toThrow('ModelId is required');
242
+ });
243
+
244
+ it('should handle empty API key', () => {
245
+ delete process.env.GLM_API_KEY;
246
+
247
+ const provider = ProviderRegistry.createFromEnv('glm-4.7');
248
+
249
+ expect(provider.config.apiKey).toBe('');
250
+ });
251
+ });
252
+
253
+ describe('create', () => {
254
+ it('should create provider with custom config', () => {
255
+ const config = {
256
+ apiKey: 'custom-key',
257
+ baseURL: 'https://custom.api.com',
258
+ model: 'custom-model',
259
+ temperature: 0.5,
260
+ max_tokens: 2000,
261
+ LLMMAX_TOKENS: 8000,
262
+ };
263
+
264
+ const provider = ProviderRegistry.create('glm-4.7', config);
265
+
266
+ expect(provider).toBeInstanceOf(OpenAICompatibleProvider);
267
+ expect(provider.config.apiKey).toBe('custom-key');
268
+ expect(provider.config.baseURL).toBe('https://custom.api.com');
269
+ expect(provider.config.model).toBe('custom-model');
270
+ });
271
+
272
+ it('should throw error for unknown model', () => {
273
+ const config = {
274
+ apiKey: 'key',
275
+ baseURL: 'https://api.com',
276
+ model: 'model',
277
+ temperature: 0.5,
278
+ max_tokens: 2000,
279
+ LLMMAX_TOKENS: 8000,
280
+ };
281
+
282
+ expect(() => {
283
+ ProviderRegistry.create('unknown' as ModelId, config);
284
+ }).toThrow('Unknown model: unknown');
285
+ });
286
+ });
287
+
288
+ describe('listModels', () => {
289
+ it('should return all model configs', () => {
290
+ const models = ProviderRegistry.listModels();
291
+
292
+ expect(models).toHaveLength(Object.keys(MODEL_CONFIGS).length);
293
+ expect(models.every((m) => m.id in MODEL_CONFIGS)).toBe(true);
294
+ });
295
+
296
+ it('should return array of ModelConfig', () => {
297
+ const models = ProviderRegistry.listModels();
298
+
299
+ models.forEach((model) => {
300
+ expect(model).toHaveProperty('id');
301
+ expect(model).toHaveProperty('provider');
302
+ expect(model).toHaveProperty('name');
303
+ expect(model).toHaveProperty('features');
304
+ });
305
+ });
306
+ });
307
+
308
+ describe('listModelsByProvider', () => {
309
+ it('should return models for glm provider', () => {
310
+ const models = ProviderRegistry.listModelsByProvider('glm');
311
+
312
+ expect(models).toHaveLength(2);
313
+ expect(models.map((m) => m.id)).toContain('glm-4.7');
314
+ expect(models.map((m) => m.id)).toContain('glm-5');
315
+ });
316
+
317
+ it('should return models for deepseek provider', () => {
318
+ const models = ProviderRegistry.listModelsByProvider('deepseek');
319
+
320
+ expect(models).toHaveLength(1);
321
+ expect(models[0].id).toBe('deepseek-reasoner');
322
+ });
323
+
324
+ it('should return models for kimi provider', () => {
325
+ const models = ProviderRegistry.listModelsByProvider('kimi');
326
+
327
+ expect(models).toHaveLength(1);
328
+ expect(models[0].id).toBe('kimi-k2.5');
329
+ });
330
+
331
+ it('should return models for minimax provider', () => {
332
+ const models = ProviderRegistry.listModelsByProvider('minimax');
333
+
334
+ expect(models).toHaveLength(1);
335
+ expect(models[0].id).toBe('minimax-2.5');
336
+ });
337
+
338
+ it('should return empty array for provider with no models', () => {
339
+ // 使用类型断言测试边缘情况:传入一个不在当前配置中的 provider
340
+ const models = ProviderRegistry.listModelsByProvider('nonexistent-provider' as never);
341
+
342
+ expect(models).toEqual([]);
343
+ });
344
+ });
345
+
346
+ describe('getModelIds', () => {
347
+ it('should return all model IDs', () => {
348
+ const ids = ProviderRegistry.getModelIds();
349
+
350
+ expect(ids).toEqual(Object.keys(MODEL_CONFIGS));
351
+ });
352
+
353
+ it('should return type ModelId[]', () => {
354
+ const ids = ProviderRegistry.getModelIds();
355
+
356
+ expect(Array.isArray(ids)).toBe(true);
357
+ });
358
+ });
359
+
360
+ describe('getModelConfig', () => {
361
+ it('should return config for glm-4.7', () => {
362
+ const config = ProviderRegistry.getModelConfig('glm-4.7');
363
+
364
+ expect(config.id).toBe('glm-4.7');
365
+ expect(config.provider).toBe('glm');
366
+ expect(config.name).toBe('GLM-4.7');
367
+ });
368
+
369
+ it('should return config for deepseek-reasoner', () => {
370
+ const config = ProviderRegistry.getModelConfig('deepseek-reasoner');
371
+
372
+ expect(config.id).toBe('deepseek-reasoner');
373
+ expect(config.provider).toBe('deepseek');
374
+ expect(config.name).toBe('DeepSeek Reasoner');
375
+ });
376
+
377
+ it('should throw error for unknown model', () => {
378
+ expect(() => {
379
+ ProviderRegistry.getModelConfig('unknown' as ModelId);
380
+ }).toThrow('Unknown model: unknown');
381
+ });
382
+ });
383
+
384
+ describe('getModelName', () => {
385
+ it('should return display name for glm-4.7', () => {
386
+ const name = ProviderRegistry.getModelName('glm-4.7');
387
+ expect(name).toBe('GLM-4.7');
388
+ });
389
+
390
+ it('should return display name for minimax-2.5', () => {
391
+ const name = ProviderRegistry.getModelName('minimax-2.5');
392
+ expect(name).toBe('MiniMax-2.5');
393
+ });
394
+
395
+ it('should return display name for kimi-k2.5', () => {
396
+ const name = ProviderRegistry.getModelName('kimi-k2.5');
397
+ expect(name).toBe('Kimi K2.5');
398
+ });
399
+
400
+ it('should return display name for deepseek-reasoner', () => {
401
+ const name = ProviderRegistry.getModelName('deepseek-reasoner');
402
+ expect(name).toBe('DeepSeek Reasoner');
403
+ });
404
+
405
+ it('should return modelId for unknown model', () => {
406
+ const name = ProviderRegistry.getModelName('unknown' as ModelId);
407
+ expect(name).toBe('unknown');
408
+ });
409
+ });
410
+
411
+ describe('getProviders', () => {
412
+ it('should return unique provider types', () => {
413
+ const providers = ProviderRegistry.getProviders();
414
+
415
+ expect(providers).toContain('glm');
416
+ expect(providers).toContain('deepseek');
417
+ expect(providers).toContain('kimi');
418
+ expect(providers).toContain('minimax');
419
+ });
420
+
421
+ it('should return array', () => {
422
+ const providers = ProviderRegistry.getProviders();
423
+
424
+ expect(Array.isArray(providers)).toBe(true);
425
+ });
426
+ });
427
+
428
+ describe('Models accessor', () => {
429
+ it('should have glm47 accessor', () => {
430
+ expect(Models.glm47).toEqual(MODEL_CONFIGS['glm-4.7']);
431
+ expect(Models.glm47.apiKey).toBeUndefined();
432
+ });
433
+
434
+ it('should have minimax25 accessor', () => {
435
+ expect(Models.minimax25).toEqual(MODEL_CONFIGS['minimax-2.5']);
436
+ expect(Models.minimax25.apiKey).toBeUndefined();
437
+ });
438
+
439
+ it('should have kimiK25 accessor', () => {
440
+ expect(Models.kimiK25).toEqual(MODEL_CONFIGS['kimi-k2.5']);
441
+ expect(Models.kimiK25.apiKey).toBeUndefined();
442
+ });
443
+
444
+ it('should have deepseekReasoner accessor', () => {
445
+ expect(Models.deepseekReasoner).toEqual(MODEL_CONFIGS['deepseek-reasoner']);
446
+ expect(Models.deepseekReasoner.apiKey).toBeUndefined();
447
+ });
448
+ });
449
+ });