@ebowwa/coder 0.7.64 → 0.7.66

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 (101) hide show
  1. package/dist/index.js +36233 -32
  2. package/dist/interfaces/ui/terminal/cli/index.js +34318 -158
  3. package/dist/interfaces/ui/terminal/native/README.md +53 -0
  4. package/dist/interfaces/ui/terminal/native/claude_code_native.darwin-x64.node +0 -0
  5. package/dist/interfaces/ui/terminal/native/claude_code_native.dylib +0 -0
  6. package/dist/interfaces/ui/terminal/native/index.d.ts +0 -0
  7. package/dist/interfaces/ui/terminal/native/index.darwin-arm64.node +0 -0
  8. package/dist/interfaces/ui/terminal/native/index.js +43 -0
  9. package/dist/interfaces/ui/terminal/native/index.node +0 -0
  10. package/dist/interfaces/ui/terminal/native/package.json +34 -0
  11. package/dist/native/README.md +53 -0
  12. package/dist/native/claude_code_native.darwin-x64.node +0 -0
  13. package/dist/native/claude_code_native.dylib +0 -0
  14. package/dist/native/index.d.ts +0 -480
  15. package/dist/native/index.darwin-arm64.node +0 -0
  16. package/dist/native/index.js +43 -1625
  17. package/dist/native/index.node +0 -0
  18. package/dist/native/package.json +34 -0
  19. package/native/index.darwin-arm64.node +0 -0
  20. package/native/index.js +33 -19
  21. package/package.json +3 -2
  22. package/packages/src/core/agent-loop/__tests__/compaction.test.ts +17 -14
  23. package/packages/src/core/agent-loop/compaction.ts +6 -2
  24. package/packages/src/core/agent-loop/index.ts +2 -0
  25. package/packages/src/core/agent-loop/loop-state.ts +1 -1
  26. package/packages/src/core/agent-loop/turn-executor.ts +4 -0
  27. package/packages/src/core/agent-loop/types.ts +4 -0
  28. package/packages/src/core/api-client-impl.ts +377 -176
  29. package/packages/src/core/cognitive-security/hooks.ts +2 -1
  30. package/packages/src/core/config/todo +7 -0
  31. package/packages/src/core/context/__tests__/integration.test.ts +334 -0
  32. package/packages/src/core/context/compaction.ts +170 -0
  33. package/packages/src/core/context/constants.ts +58 -0
  34. package/packages/src/core/context/extraction.ts +85 -0
  35. package/packages/src/core/context/index.ts +66 -0
  36. package/packages/src/core/context/summarization.ts +251 -0
  37. package/packages/src/core/context/token-estimation.ts +98 -0
  38. package/packages/src/core/context/types.ts +59 -0
  39. package/packages/src/core/models.ts +81 -4
  40. package/packages/src/core/normalizers/todo +5 -1
  41. package/packages/src/core/providers/README.md +230 -0
  42. package/packages/src/core/providers/__tests__/providers.test.ts +135 -0
  43. package/packages/src/core/providers/index.ts +419 -0
  44. package/packages/src/core/providers/types.ts +132 -0
  45. package/packages/src/core/retry.ts +10 -0
  46. package/packages/src/ecosystem/tools/index.ts +174 -0
  47. package/packages/src/index.ts +23 -2
  48. package/packages/src/interfaces/ui/index.ts +17 -20
  49. package/packages/src/interfaces/ui/spinner.ts +2 -2
  50. package/packages/src/interfaces/ui/terminal/bridge/index.ts +370 -0
  51. package/packages/src/interfaces/ui/terminal/bridge/ipc.ts +829 -0
  52. package/packages/src/interfaces/ui/terminal/bridge/screen-export.ts +968 -0
  53. package/packages/src/interfaces/ui/terminal/bridge/types.ts +226 -0
  54. package/packages/src/interfaces/ui/terminal/bridge/useBridge.ts +210 -0
  55. package/packages/src/interfaces/ui/terminal/cli/bootstrap.ts +132 -0
  56. package/packages/src/interfaces/ui/terminal/cli/index.ts +200 -13
  57. package/packages/src/interfaces/ui/terminal/cli/interactive/index.ts +110 -0
  58. package/packages/src/interfaces/ui/terminal/cli/interactive/input-handler.ts +402 -0
  59. package/packages/src/interfaces/ui/terminal/cli/interactive/interactive-runner.ts +820 -0
  60. package/packages/src/interfaces/ui/terminal/cli/interactive/message-store.ts +299 -0
  61. package/packages/src/interfaces/ui/terminal/cli/interactive/types.ts +274 -0
  62. package/packages/src/interfaces/ui/terminal/shared/index.ts +13 -0
  63. package/packages/src/interfaces/ui/terminal/shared/query.ts +9 -3
  64. package/packages/src/interfaces/ui/terminal/shared/setup.ts +5 -1
  65. package/packages/src/interfaces/ui/terminal/shared/spinner-frames.ts +73 -0
  66. package/packages/src/interfaces/ui/terminal/shared/status-line.ts +10 -2
  67. package/packages/src/native/index.ts +404 -27
  68. package/packages/src/native/tui_v2_types.ts +39 -0
  69. package/packages/src/teammates/coordination.test.ts +279 -0
  70. package/packages/src/teammates/coordination.ts +646 -0
  71. package/packages/src/teammates/index.ts +95 -25
  72. package/packages/src/teammates/integration.test.ts +272 -0
  73. package/packages/src/teammates/runner.test.ts +235 -0
  74. package/packages/src/teammates/runner.ts +750 -0
  75. package/packages/src/teammates/schemas.ts +673 -0
  76. package/packages/src/types/index.ts +1 -0
  77. package/packages/src/core/context-compaction.ts +0 -578
  78. package/packages/src/interfaces/ui/Screenshot 2026-03-02 at 9.23.10/342/200/257PM.png +0 -0
  79. package/packages/src/interfaces/ui/Screenshot 2026-03-03 at 10.55.11/342/200/257AM.png +0 -0
  80. package/packages/src/interfaces/ui/terminal/tui/HelpPanel.tsx +0 -262
  81. package/packages/src/interfaces/ui/terminal/tui/InputContext.tsx +0 -232
  82. package/packages/src/interfaces/ui/terminal/tui/InputField.tsx +0 -62
  83. package/packages/src/interfaces/ui/terminal/tui/InteractiveTUI.tsx +0 -537
  84. package/packages/src/interfaces/ui/terminal/tui/MessageArea.tsx +0 -107
  85. package/packages/src/interfaces/ui/terminal/tui/MessageStore.tsx +0 -240
  86. package/packages/src/interfaces/ui/terminal/tui/StatusBar.tsx +0 -54
  87. package/packages/src/interfaces/ui/terminal/tui/commands.ts +0 -438
  88. package/packages/src/interfaces/ui/terminal/tui/components/InteractiveElements.tsx +0 -584
  89. package/packages/src/interfaces/ui/terminal/tui/components/MultilineInput.tsx +0 -614
  90. package/packages/src/interfaces/ui/terminal/tui/components/PaneManager.tsx +0 -333
  91. package/packages/src/interfaces/ui/terminal/tui/components/Sidebar.tsx +0 -604
  92. package/packages/src/interfaces/ui/terminal/tui/components/index.ts +0 -118
  93. package/packages/src/interfaces/ui/terminal/tui/console.ts +0 -49
  94. package/packages/src/interfaces/ui/terminal/tui/index.ts +0 -90
  95. package/packages/src/interfaces/ui/terminal/tui/run.tsx +0 -42
  96. package/packages/src/interfaces/ui/terminal/tui/spinner.ts +0 -69
  97. package/packages/src/interfaces/ui/terminal/tui/tui-app.tsx +0 -390
  98. package/packages/src/interfaces/ui/terminal/tui/tui-footer.ts +0 -422
  99. package/packages/src/interfaces/ui/terminal/tui/types.ts +0 -186
  100. package/packages/src/interfaces/ui/terminal/tui/useInputHandler.ts +0 -104
  101. package/packages/src/interfaces/ui/terminal/tui/useNativeInput.ts +0 -239
@@ -0,0 +1,230 @@
1
+ # Provider System
2
+
3
+ Multi-provider architecture for Coder CLI supporting multiple LLM backends.
4
+
5
+ ## Supported Providers
6
+
7
+ | Provider | Models | Format | Endpoint |
8
+ |----------|--------|--------|----------|
9
+ | **Zhipu (Z.AI)** | GLM-5, GLM-4.7, GLM-4.6, GLM-4.5V, GLM-4.5, GLM-4.5-air | OpenAI | `https://api.z.ai/api/coding/paas/v4` |
10
+ | **MiniMax** | MiniMax-M2.5 | Anthropic | `https://api.minimax.io/anthropic` |
11
+ | **OpenAI** | GPT-4, GPT-4-turbo | OpenAI | `https://api.openai.com/v1` |
12
+ | **Anthropic** | Claude Opus 4.6, Sonnet 4.6 | Anthropic | *Not implemented (stub)* |
13
+
14
+ ## Z.AI Endpoints
15
+
16
+ Z.AI provides **two different endpoints**:
17
+
18
+ | Endpoint | Format | Auth | Use Case |
19
+ |----------|--------|------|----------|
20
+ | `https://api.z.ai/api/coding/paas/v4` | OpenAI | `Z_AI_API_KEY` | **Coding plan** (default) |
21
+ | `https://api.z.ai/api/anthropic` | Anthropic | `ANTHROPIC_AUTH_TOKEN` | Anthropic-compatible |
22
+
23
+ Our implementation uses the **coding plan endpoint** with shared quotas.
24
+
25
+ ### GLM Models (Coding Plan - Shared Quota)
26
+
27
+ | Model | Context | Max Output | Vision | Thinking | Quota |
28
+ |-------|---------|------------|--------|----------|-------|
29
+ | **GLM-5** | 200K | 128K | Yes | Yes | 3x peak, 2x off-peak |
30
+ | **GLM-4.7** | 128K | 8K | Yes | Yes | 1x |
31
+ | **GLM-4.6** | 128K | 8K | Yes | Yes | 1x |
32
+ | **GLM-4.5V** | 128K | 4K | Yes | No | 1x |
33
+ | **GLM-4.5** | 128K | 4K | No | No | 1x |
34
+ | **GLM-4.5-Air** | 128K | 4K | No | No | 1x (fast/cheap) |
35
+
36
+ ## Configuration
37
+
38
+ ### Environment Variables
39
+
40
+ ```bash
41
+ # Z.AI / GLM (Coding Plan)
42
+ Z_AI_API_KEY=xxx # Single key
43
+ Z_AI_API_KEYS='["key1","key2"]' # Rolling keys (JSON array)
44
+ ZHIPU_BASE_URL=https://api.z.ai/api/coding/paas/v4 # Optional override
45
+
46
+ # MiniMax
47
+ MINIMAX_API_KEY=xxx
48
+ MINIMAX_BASE_URL=https://api.minimax.io/anthropic # Optional: use minimaxi.com for China
49
+
50
+ # OpenAI (Future)
51
+ OPENAI_API_KEY=xxx
52
+ ```
53
+
54
+ ### Doppler Configuration
55
+
56
+ Add keys to your Doppler project:
57
+
58
+ ```bash
59
+ doppler secrets set Z_AI_API_KEY=xxx
60
+ doppler secrets set Z_AI_API_KEYS='["key1","key2"]' # For rolling keys
61
+ doppler secrets set MINIMAX_API_KEY=xxx
62
+ ```
63
+
64
+ ## Usage
65
+
66
+ ### Model Selection
67
+
68
+ ```bash
69
+ # Use GLM-5 (Zhipu)
70
+ coder --model glm-5
71
+
72
+ # Use MiniMax M2.5
73
+ coder --model minimax-m2.5
74
+
75
+ # Use GLM-4.5-air (fast/cheap)
76
+ coder --model glm-4.5-air
77
+ ```
78
+
79
+ ### Model Aliases
80
+
81
+ ```typescript
82
+ // In code
83
+ import { MODEL_ALIASES } from "@ebowwa/coder";
84
+
85
+ MODEL_ALIASES.glm // → "glm-5"
86
+ MODEL_ALIASES.glm4 // → "glm-4.5-air"
87
+ MODEL_ALIASES.minimax // → "minimax-m2.5"
88
+ MODEL_ALIASES.m25 // → "minimax-m2.5"
89
+ MODEL_ALIASES.fast // → "glm-4.5-air"
90
+ ```
91
+
92
+ ### Provider Resolution
93
+
94
+ ```typescript
95
+ import { resolveProvider, getProviderForModel } from "@ebowwa/coder";
96
+
97
+ // Detect provider from model name
98
+ const provider = getProviderForModel("glm-5"); // → "zhipu"
99
+
100
+ // Resolve full provider info
101
+ const resolved = resolveProvider("glm-5");
102
+ // {
103
+ // config: ProviderConfig,
104
+ // apiKey: string,
105
+ // endpoint: string,
106
+ // model: string
107
+ // }
108
+ ```
109
+
110
+ ### Health Tracking
111
+
112
+ ```typescript
113
+ import {
114
+ isProviderHealthy,
115
+ getHealthyProviders,
116
+ recordProviderSuccess,
117
+ recordProviderFailure,
118
+ } from "@ebowwa/coder";
119
+
120
+ // Check if provider is healthy
121
+ if (isProviderHealthy("zhipu")) {
122
+ // Use zhipu
123
+ }
124
+
125
+ // Get all healthy providers
126
+ const healthy = getHealthyProviders(); // ["zhipu", "minimax"]
127
+
128
+ // Track success (auto-called by API client)
129
+ recordProviderSuccess("zhipu", 1500); // 1.5s latency
130
+
131
+ // Track failure (auto-called on retry)
132
+ recordProviderFailure("zhipu");
133
+ ```
134
+
135
+ ## Architecture
136
+
137
+ ```
138
+ ┌─────────────────────────────────────────────────────┐
139
+ │ Model Request │
140
+ │ (model: "glm-5") │
141
+ └─────────────────────────────────────────────────────┘
142
+
143
+
144
+ ┌─────────────────────────┐
145
+ │ resolveProvider() │
146
+ │ - Detect from name │
147
+ │ - Load API key │
148
+ │ - Build endpoint │
149
+ └─────────────────────────┘
150
+
151
+ ┌───────────┴───────────┐
152
+ │ │
153
+ ▼ ▼
154
+ ┌───────────────┐ ┌───────────────┐
155
+ │ Zhipu (Z.AI) │ │ MiniMax │
156
+ │ OpenAI format │ │ Anthropic fmt │
157
+ │ /chat/ │ │ /v1/messages │
158
+ │ completions │ │ │
159
+ └───────────────┘ └───────────────┘
160
+ │ │
161
+ └───────────┬───────────┘
162
+
163
+ ┌─────────────────────────┐
164
+ │ Health Tracking │
165
+ │ - Latency metrics │
166
+ │ - Failure backoff │
167
+ │ - Rolling key rotation │
168
+ └─────────────────────────┘
169
+ ```
170
+
171
+ ## Rolling Keys
172
+
173
+ The provider system supports multiple API keys with round-robin rotation:
174
+
175
+ ```bash
176
+ # Set multiple keys as JSON array
177
+ Z_AI_API_KEYS='["key1","key2","key3"]'
178
+ ```
179
+
180
+ Features:
181
+ - **Round-robin rotation** - Cycles through keys on each request
182
+ - **Exponential backoff** - Keys that fail are temporarily disabled
183
+ - **Health tracking** - Keys are tracked per-provider
184
+
185
+ ## Fallback Chain
186
+
187
+ Default fallback order:
188
+ 1. `zhipu` (Z.AI / GLM)
189
+ 2. `minimax` (MiniMax)
190
+
191
+ Configure via environment:
192
+ ```bash
193
+ MODEL_FALLBACK_CHAIN='["zhipu","minimax","openai"]'
194
+ ```
195
+
196
+ ## Adding New Providers
197
+
198
+ 1. Add provider config to `providers/index.ts`:
199
+ ```typescript
200
+ PROVIDERS.newprovider = {
201
+ name: "newprovider",
202
+ displayName: "New Provider",
203
+ endpoint: "https://api.newprovider.com/v1",
204
+ authHeader: "Authorization",
205
+ apiKeyEnv: ["NEWPROVIDER_API_KEY"],
206
+ format: "openai", // or "anthropic"
207
+ defaultModel: "newprovider-1",
208
+ models: ["newprovider-1", "newprovider-2"],
209
+ supportsStreaming: true,
210
+ supportsToolCalling: true,
211
+ supportsVision: true,
212
+ supportsThinking: false,
213
+ };
214
+ ```
215
+
216
+ 2. Add model to `models.ts`:
217
+ ```typescript
218
+ "newprovider-1": {
219
+ id: "newprovider-1",
220
+ name: "NP-1",
221
+ fullName: "NewProvider 1",
222
+ provider: "newprovider",
223
+ // ...
224
+ }
225
+ ```
226
+
227
+ 3. Add to fallback chain (optional):
228
+ ```typescript
229
+ DEFAULT_ROUTING_CONFIG.fallbackChain.push("newprovider");
230
+ ```
@@ -0,0 +1,135 @@
1
+ import { describe, test, expect } from "bun:test";
2
+ import {
3
+ getProvider,
4
+ getProviderForModel,
5
+ resolveProvider,
6
+ isProviderHealthy,
7
+ getHealthyProviders,
8
+ getNextHealthyProvider,
9
+ PROVIDERS,
10
+ type ProviderName,
11
+ } from "../index.js";
12
+
13
+ describe("Provider Registry", () => {
14
+ describe("getProvider", () => {
15
+ test("returns zhipu provider config", () => {
16
+ const provider = getProvider("zhipu");
17
+ expect(provider).toBeDefined();
18
+ expect(provider?.name).toBe("zhipu");
19
+ expect(provider?.displayName).toBe("Z.AI (GLM)");
20
+ expect(provider?.format).toBe("openai");
21
+ });
22
+
23
+ test("returns minimax provider config", () => {
24
+ const provider = getProvider("minimax");
25
+ expect(provider).toBeDefined();
26
+ expect(provider?.name).toBe("minimax");
27
+ expect(provider?.displayName).toBe("MiniMax");
28
+ expect(provider?.format).toBe("anthropic");
29
+ });
30
+
31
+ test("returns undefined for unknown provider", () => {
32
+ const provider = getProvider("unknown" as any);
33
+ expect(provider).toBeUndefined();
34
+ });
35
+ });
36
+
37
+ describe("getProviderForModel", () => {
38
+ test("detects zhipu from glm-5", () => {
39
+ expect(getProviderForModel("glm-5")).toBe("zhipu");
40
+ });
41
+
42
+ test("detects zhipu from GLM-4.7 (case insensitive)", () => {
43
+ expect(getProviderForModel("GLM-4.7")).toBe("zhipu");
44
+ });
45
+
46
+ test("detects minimax from minimax-m2.5", () => {
47
+ expect(getProviderForModel("minimax-m2.5")).toBe("minimax");
48
+ });
49
+
50
+ test("detects minimax from MiniMax-M2.5 (case insensitive)", () => {
51
+ expect(getProviderForModel("MiniMax-M2.5")).toBe("minimax");
52
+ });
53
+
54
+ test("defaults to zhipu for unknown models", () => {
55
+ expect(getProviderForModel("unknown-model")).toBe("zhipu");
56
+ });
57
+ });
58
+
59
+ describe("isProviderHealthy", () => {
60
+ test("zhipu starts healthy", () => {
61
+ expect(isProviderHealthy("zhipu")).toBe(true);
62
+ });
63
+
64
+ test("minimax starts healthy", () => {
65
+ expect(isProviderHealthy("minimax")).toBe(true);
66
+ });
67
+
68
+ test("anthropic is marked unhealthy (not implemented)", () => {
69
+ expect(isProviderHealthy("anthropic")).toBe(false);
70
+ });
71
+ });
72
+
73
+ describe("getHealthyProviders", () => {
74
+ test("returns list of healthy providers", () => {
75
+ const healthy = getHealthyProviders();
76
+ expect(healthy).toContain("zhipu");
77
+ expect(healthy).toContain("minimax");
78
+ expect(healthy).not.toContain("anthropic");
79
+ });
80
+ });
81
+
82
+ describe("getNextHealthyProvider", () => {
83
+ test("returns first healthy provider from fallback chain", () => {
84
+ const provider = getNextHealthyProvider();
85
+ expect(provider).toBe("zhipu");
86
+ });
87
+
88
+ test("can exclude provider", () => {
89
+ const provider = getNextHealthyProvider("zhipu");
90
+ expect(provider).toBe("minimax");
91
+ });
92
+ });
93
+
94
+ describe("resolveProvider", () => {
95
+ test("returns null when no API key configured", () => {
96
+ // Clear env for this test
97
+ const originalKey = process.env.Z_AI_API_KEY;
98
+ delete process.env.Z_AI_API_KEY;
99
+
100
+ const result = resolveProvider("glm-5");
101
+ // May return null or use fallback
102
+ // This depends on whether keys are loaded
103
+
104
+ // Restore
105
+ if (originalKey) {
106
+ process.env.Z_AI_API_KEY = originalKey;
107
+ }
108
+ });
109
+ });
110
+ });
111
+
112
+ describe("Provider Configuration", () => {
113
+ test("zhipu uses OpenAI format", () => {
114
+ expect(PROVIDERS.zhipu.format).toBe("openai");
115
+ expect(PROVIDERS.zhipu.endpoint).toContain("z.ai");
116
+ });
117
+
118
+ test("minimax uses Anthropic format", () => {
119
+ expect(PROVIDERS.minimax.format).toBe("anthropic");
120
+ expect(PROVIDERS.minimax.endpoint).toContain("minimax");
121
+ });
122
+
123
+ test("providers have required fields", () => {
124
+ for (const name of Object.keys(PROVIDERS) as ProviderName[]) {
125
+ const config = PROVIDERS[name];
126
+ expect(config.name).toBe(name);
127
+ expect(config.displayName).toBeTruthy();
128
+ expect(config.endpoint).toBeTruthy();
129
+ expect(config.apiKeyEnv).toBeInstanceOf(Array);
130
+ expect(config.apiKeyEnv.length).toBeGreaterThan(0);
131
+ expect(config.defaultModel).toBeTruthy();
132
+ expect(config.models).toBeInstanceOf(Array);
133
+ }
134
+ });
135
+ });