@ahoo-wang/godex 0.0.1 → 0.0.2
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.
- package/README.md +1 -0
- package/README.zh-CN.md +473 -0
- package/package.json +9 -8
package/README.md
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
OpenAI Responses API gateway — translates `/v1/responses` into upstream Chat Completions API calls, so **any LLM provider can drive Codex**.
|
|
4
4
|
|
|
5
|
+
[](https://codecov.io/gh/Ahoo-Wang/Godex)
|
|
5
6
|
[](https://bun.sh)
|
|
6
7
|
[](https://www.typescriptlang.org/)
|
|
7
8
|
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
# Godex
|
|
2
|
+
|
|
3
|
+
OpenAI Responses API 网关 — 将 `/v1/responses` 请求转换为上游 Chat Completions API 调用,让**任何 LLM 提供商都能驱动 Codex**。
|
|
4
|
+
|
|
5
|
+
[](https://codecov.io/gh/Ahoo-Wang/Godex)
|
|
6
|
+
[](https://bun.sh)
|
|
7
|
+
[](https://www.typescriptlang.org/)
|
|
8
|
+
|
|
9
|
+
## 架构
|
|
10
|
+
|
|
11
|
+
```mermaid
|
|
12
|
+
C4Context
|
|
13
|
+
title Godex — 系统上下文
|
|
14
|
+
|
|
15
|
+
Person(user, "开发者 / Codex CLI", "通过 OpenAI 兼容端点<br/>发送 Responses API 请求")
|
|
16
|
+
System(godex_svr, "Godex 服务器", "转换 Responses API → Chat Completions API<br/>基于 Bun HTTP 服务器,端口可配置")
|
|
17
|
+
SystemDb(sessions, "会话存储", "存储响应历史,用于<br/>previous_response_id 链式解析<br/>SQLite(持久化)或内存")
|
|
18
|
+
System_Ext(zhipu, "智谱 (Zhipu)", "Chat Completions API 提供商")
|
|
19
|
+
System_Ext(openai, "OpenAI", "Chat Completions API 提供商")
|
|
20
|
+
System_Ext(other, "自定义提供商", "任何 Chat Completions<br/>兼容后端")
|
|
21
|
+
|
|
22
|
+
Rel(user, godex_svr, "POST /v1/responses, GET /v1/models, GET /health", "HTTP/SSE")
|
|
23
|
+
Rel(godex_svr, sessions, "保存 / 解析链")
|
|
24
|
+
Rel(godex_svr, zhipu, "POST /chat/completions", "HTTPS")
|
|
25
|
+
Rel(godex_svr, openai, "POST /chat/completions", "HTTPS")
|
|
26
|
+
Rel(godex_svr, other, "POST /chat/completions", "HTTPS")
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 请求流程
|
|
30
|
+
|
|
31
|
+
```mermaid
|
|
32
|
+
sequenceDiagram
|
|
33
|
+
actor C as 客户端 (Codex CLI)
|
|
34
|
+
participant R as Router 路由
|
|
35
|
+
participant AC as ApplicationContext 应用上下文
|
|
36
|
+
participant RC as ResponsesContext 响应上下文
|
|
37
|
+
participant MR as ModelResolver 模型解析器
|
|
38
|
+
participant SS as SessionStore 会话存储
|
|
39
|
+
participant REG as Registrar 注册器
|
|
40
|
+
participant A as Adapter 适配器 (DefaultAdapter)
|
|
41
|
+
participant PM as ProviderMapper 提供商映射器
|
|
42
|
+
participant CC as ChatClient 聊天客户端
|
|
43
|
+
participant UP as 上游 API
|
|
44
|
+
|
|
45
|
+
C->>R: POST /v1/responses
|
|
46
|
+
R->>RC: ResponsesContext.create(app, body)
|
|
47
|
+
|
|
48
|
+
activate RC
|
|
49
|
+
RC->>MR: resolve(model)
|
|
50
|
+
MR-->>RC: { provider, model }
|
|
51
|
+
RC->>RC: 验证提供商配置
|
|
52
|
+
|
|
53
|
+
opt previous_response_id
|
|
54
|
+
RC->>SS: resolveChain(id)
|
|
55
|
+
SS-->>RC: 会话快照
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
RC->>REG: resolve(provider)
|
|
59
|
+
REG-->>RC: Provider 实例
|
|
60
|
+
deactivate RC
|
|
61
|
+
|
|
62
|
+
alt stream = true
|
|
63
|
+
R->>A: adapter.stream(ctx)
|
|
64
|
+
activate A
|
|
65
|
+
A->>PM: request.map(ctx)
|
|
66
|
+
PM-->>A: 上游请求
|
|
67
|
+
A->>CC: streamChat(req)
|
|
68
|
+
CC->>UP: POST (SSE)
|
|
69
|
+
UP-->>CC: SSE 数据块
|
|
70
|
+
CC-->>A: ReadableStream<SSE>
|
|
71
|
+
A->>A: pipeTransform → ProviderEventToResponseTransformer
|
|
72
|
+
A->>A: pipeTransform → ResponseSessionPersistenceTransformer
|
|
73
|
+
A-->>R: ReadableStream<ResponseStreamEvent>
|
|
74
|
+
deactivate A
|
|
75
|
+
R->>R: pipeTransform → ResponseSseEncodeTransformer
|
|
76
|
+
R-->>C: SSE 字节流
|
|
77
|
+
else stream = false
|
|
78
|
+
R->>A: adapter.request(ctx)
|
|
79
|
+
activate A
|
|
80
|
+
A->>PM: request.map(ctx)
|
|
81
|
+
PM-->>A: 上游请求
|
|
82
|
+
A->>CC: chat(req)
|
|
83
|
+
CC->>UP: POST
|
|
84
|
+
UP-->>CC: JSON 响应
|
|
85
|
+
CC-->>A: 上游响应
|
|
86
|
+
A->>PM: response.map(ctx, res)
|
|
87
|
+
PM-->>A: ResponseObject
|
|
88
|
+
A->>SS: save(session)
|
|
89
|
+
A-->>R: ResponseObject
|
|
90
|
+
deactivate A
|
|
91
|
+
R-->>C: JSON 响应
|
|
92
|
+
end
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 组件模型
|
|
96
|
+
|
|
97
|
+
```mermaid
|
|
98
|
+
classDiagram
|
|
99
|
+
direction TB
|
|
100
|
+
|
|
101
|
+
class ApplicationContext {
|
|
102
|
+
+config: GodexConfig
|
|
103
|
+
+logger: Logger
|
|
104
|
+
+resolver: ModelResolver
|
|
105
|
+
+registrar: Registrar
|
|
106
|
+
+adapter: Adapter
|
|
107
|
+
+sessionStore: ResponseSessionStore
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
class ResponsesContext {
|
|
111
|
+
+app: ApplicationContext
|
|
112
|
+
+request: ResponseCreateRequest
|
|
113
|
+
+session: ResponseSessionSnapshot
|
|
114
|
+
+resolved: ResolvedModel
|
|
115
|
+
+provider: Provider
|
|
116
|
+
+responseId: string
|
|
117
|
+
+requestId: string
|
|
118
|
+
+logger: Logger
|
|
119
|
+
+create(app, body)$ Promise~ResponsesContext~
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
class ModelResolver {
|
|
123
|
+
-defaultProvider: string
|
|
124
|
+
-providerConfigs: Record
|
|
125
|
+
+resolve(model) ResolvedModel
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
class Registrar {
|
|
129
|
+
-factories: Map~string, ProviderFactory~
|
|
130
|
+
+registerFactory(name, factory)
|
|
131
|
+
+build(providers)
|
|
132
|
+
+resolve(name) Provider
|
|
133
|
+
+list() string[]
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
class Adapter {
|
|
137
|
+
<<interface>>
|
|
138
|
+
+request(ctx) Promise~ResponseObject~
|
|
139
|
+
+stream(ctx) Promise~ReadableStream~
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
class DefaultAdapter {
|
|
143
|
+
+request(ctx) Promise~ResponseObject~
|
|
144
|
+
+stream(ctx) Promise~ReadableStream~
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
class Provider {
|
|
148
|
+
<<interface>>
|
|
149
|
+
+name: string
|
|
150
|
+
+mapper: ProviderMapper
|
|
151
|
+
+chatClient: ChatClient
|
|
152
|
+
+capabilities: ProviderCapabilities
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
class ProviderMapper {
|
|
156
|
+
<<interface>>
|
|
157
|
+
+request: RequestMapper
|
|
158
|
+
+response: ResponseMapper
|
|
159
|
+
+stream: StreamMapper
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
class ChatClient {
|
|
163
|
+
<<interface>>
|
|
164
|
+
+chat(req) Promise~TRes~
|
|
165
|
+
+streamChat(req) Promise~ReadableStream~
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
class RequestMapper {
|
|
169
|
+
<<interface>>
|
|
170
|
+
+map(ctx) TReq
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
class ResponseMapper {
|
|
174
|
+
<<interface>>
|
|
175
|
+
+map(ctx, result) ResponseObject
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
class StreamMapper {
|
|
179
|
+
<<interface>>
|
|
180
|
+
+map(ctx, event) ResponseStreamEvent[]
|
|
181
|
+
+buildResponseObject(ctx, state) ResponseObject
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
class ResponseSessionStore {
|
|
185
|
+
<<interface>>
|
|
186
|
+
+get(id) StoredResponseSession
|
|
187
|
+
+save(session, opts)
|
|
188
|
+
+resolveChain(id, opts) ResponseSessionSnapshot
|
|
189
|
+
+delete(id)
|
|
190
|
+
+close()
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
class Router {
|
|
194
|
+
-routes: Route[]
|
|
195
|
+
+register(route)
|
|
196
|
+
+dispatch(req) Promise~Response~
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
ApplicationContext --> ResponsesContext : 创建
|
|
200
|
+
ApplicationContext --> ModelResolver
|
|
201
|
+
ApplicationContext --> Registrar
|
|
202
|
+
ApplicationContext --> Adapter
|
|
203
|
+
ApplicationContext --> ResponseSessionStore
|
|
204
|
+
ResponsesContext --> Provider : 使用
|
|
205
|
+
Provider --> ProviderMapper
|
|
206
|
+
Provider --> ChatClient
|
|
207
|
+
ProviderMapper --> RequestMapper
|
|
208
|
+
ProviderMapper --> ResponseMapper
|
|
209
|
+
ProviderMapper --> StreamMapper
|
|
210
|
+
Adapter <|.. DefaultAdapter
|
|
211
|
+
DefaultAdapter --> ProviderMapper : 调用
|
|
212
|
+
DefaultAdapter --> ChatClient : 调用
|
|
213
|
+
DefaultAdapter --> ResponseSessionStore : 保存
|
|
214
|
+
Router --> ResponsesContext : 分发至
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## 流式管道
|
|
218
|
+
|
|
219
|
+
```mermaid
|
|
220
|
+
flowchart LR
|
|
221
|
+
subgraph upstream["上游提供商"]
|
|
222
|
+
SSE["SSE 数据块<br/>(JsonServerSentEvent)"]
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
subgraph godex["Godex 流式管道"]
|
|
226
|
+
T1["ProviderEventTo<br/>ResponseTransformer"]
|
|
227
|
+
T2["ResponseSession<br/>PersistenceTransformer"]
|
|
228
|
+
T3["ResponseSse<br/>EncodeTransformer"]
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
subgraph client["客户端"]
|
|
232
|
+
BYTES["SSE 字节流<br/>(text/event-stream)"]
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
SSE -->|"pipeThrough(TransformStream)"| T1
|
|
236
|
+
T1 -->|"逐事件 map()<br/>SSE 数据块 → ResponseStreamEvent[]"| T2
|
|
237
|
+
T2 -->|"累积 StreamState<br/>拦截终止事件<br/>buildResponseObject()<br/>保存会话"| T3
|
|
238
|
+
T3 -->|"序列化为 SSE 传输格式<br/>event: xxx\ndata: {...}\n\n"| BYTES
|
|
239
|
+
|
|
240
|
+
style upstream fill:#1a1a2e,stroke:#16213e,color:#e0e0e0
|
|
241
|
+
style godex fill:#0f3460,stroke:#16213e,color:#e0e0e0
|
|
242
|
+
style client fill:#1a1a2e,stroke:#16213e,color:#e0e0e0
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Transformer 职责
|
|
246
|
+
|
|
247
|
+
| 阶段 | Transformer | 输入 | 输出 | 副作用 |
|
|
248
|
+
|------|------------|------|------|--------|
|
|
249
|
+
| 1 | `ProviderEventToResponseTransformer` | `JsonServerSentEvent<TChunk>` | `ResponseStreamEvent` | 逐事件调用 `StreamMapper.map()` |
|
|
250
|
+
| 2 | `ResponseSessionPersistenceTransformer` | `ResponseStreamEvent` | `ResponseStreamEvent` | 累积 `StreamState`,终止事件时调用 `buildResponseObject()` 并保存会话(`store=false` 时跳过) |
|
|
251
|
+
| 3 | `ResponseSseEncodeTransformer` | `ResponseStreamEvent` | `Uint8Array`(SSE 传输格式) | 序列化为 `event:` / `data:` 行 |
|
|
252
|
+
|
|
253
|
+
## 错误体系
|
|
254
|
+
|
|
255
|
+
```mermaid
|
|
256
|
+
classDiagram
|
|
257
|
+
direction TB
|
|
258
|
+
|
|
259
|
+
class GodexError {
|
|
260
|
+
+name: string
|
|
261
|
+
+code: string
|
|
262
|
+
+status: number
|
|
263
|
+
+context: object
|
|
264
|
+
+toLogEntry() object
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
class ServerError {
|
|
268
|
+
+status: 400-499
|
|
269
|
+
+context: object
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
class AdapterError {
|
|
273
|
+
+status: 400-499
|
|
274
|
+
+context: 不支持的参数 / 工具 / 输入项
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
class ProviderError {
|
|
278
|
+
+status: 502
|
|
279
|
+
+context: 上游状态码 / 响应体 / 响应头
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
class SessionError {
|
|
283
|
+
+status: 400-409
|
|
284
|
+
+context: 链元数据
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
GodexError <|-- ServerError
|
|
288
|
+
GodexError <|-- AdapterError
|
|
289
|
+
GodexError <|-- ProviderError
|
|
290
|
+
GodexError <|-- SessionError
|
|
291
|
+
|
|
292
|
+
note for GodexError "基础错误,支持结构化日志。<br/>所有错误携带领域编码(如 server.request.invalid_json)。"
|
|
293
|
+
note for ProviderError "包装上游 HTTP 失败:<br/>速率限制、超时、5xx。"
|
|
294
|
+
note for SessionError "链式解析失败:<br/>未找到、循环、深度超限。"
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
## 项目结构
|
|
298
|
+
|
|
299
|
+
```
|
|
300
|
+
src/
|
|
301
|
+
├── cli/ Commander CLI(serve、配置检查、初始化)
|
|
302
|
+
├── config/ godex.yaml 配置模式、环境变量插值、默认值
|
|
303
|
+
├── context/ ApplicationContext(DI 容器)、ResponsesContext(每请求)
|
|
304
|
+
├── adapter/ Adapter 接口、DefaultAdapter、流式 Transformer
|
|
305
|
+
│ ├── mapper/ RequestMapper / ResponseMapper / StreamMapper 契约
|
|
306
|
+
│ └── transformers/ ProviderEvent → Response → SSE 编码管道
|
|
307
|
+
├── providers/ Provider 注册表 + 内置工厂
|
|
308
|
+
│ └── zhipu/ 参考提供商实现:映射器、聊天客户端、工具、消息
|
|
309
|
+
├── resolver/ ModelResolver(模型选择器 → 提供商 + 模型)
|
|
310
|
+
├── server/ Bun HTTP 服务器、Router、路由(/v1/responses、/health、/v1/models)
|
|
311
|
+
├── session/ ResponseSessionStore(内存 + SQLite)、链式解析
|
|
312
|
+
├── error/ GodexError 错误体系及领域编码
|
|
313
|
+
├── protocol/openai/ OpenAI 兼容类型定义
|
|
314
|
+
├── logger/ 结构化 JSON 日志
|
|
315
|
+
└── e2e/ 模拟上游的端到端测试
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## 快速开始
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
# 安装依赖
|
|
322
|
+
bun install
|
|
323
|
+
|
|
324
|
+
# 构建独立二进制文件(当前平台)
|
|
325
|
+
bun run build
|
|
326
|
+
|
|
327
|
+
# 交互式创建配置
|
|
328
|
+
bun run start -- init
|
|
329
|
+
|
|
330
|
+
# 启动服务器(默认端口 5678)
|
|
331
|
+
bun run dev
|
|
332
|
+
|
|
333
|
+
# 或直接运行编译后的二进制文件
|
|
334
|
+
./platforms/darwin-arm64/bin/godex serve
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### godex.yaml
|
|
338
|
+
|
|
339
|
+
```yaml
|
|
340
|
+
server:
|
|
341
|
+
port: 5678
|
|
342
|
+
|
|
343
|
+
default_provider: zhipu
|
|
344
|
+
|
|
345
|
+
providers:
|
|
346
|
+
zhipu:
|
|
347
|
+
api_key: ${ZHIPU_API_KEY}
|
|
348
|
+
base_url: https://open.bigmodel.cn/api/paas/v4
|
|
349
|
+
models:
|
|
350
|
+
"gpt-4o": glm-4.7 # 模型名称映射
|
|
351
|
+
"*": glm-5.1 # 兜底映射
|
|
352
|
+
|
|
353
|
+
session:
|
|
354
|
+
backend: sqlite # 或 "memory"
|
|
355
|
+
sqlite:
|
|
356
|
+
path: ./data/sessions.db
|
|
357
|
+
|
|
358
|
+
logging:
|
|
359
|
+
level: info # trace | debug | info | warn | error
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### 添加提供商
|
|
363
|
+
|
|
364
|
+
在 `src/providers/<name>/` 中实现以下接口:
|
|
365
|
+
|
|
366
|
+
| 接口 | 用途 |
|
|
367
|
+
|------|------|
|
|
368
|
+
| `Provider<TReq, TRes, TChunk>` | 组合 mapper + chatClient + capabilities |
|
|
369
|
+
| `ProviderMapper<TReq, TRes, TChunk>` | request / response / stream 映射函数 |
|
|
370
|
+
| `ChatClient<TReq, TRes, TChunk>` | `chat()` 和 `streamChat()` HTTP 调用 |
|
|
371
|
+
|
|
372
|
+
在 `src/providers/builtin.ts` 中注册工厂:
|
|
373
|
+
|
|
374
|
+
```ts
|
|
375
|
+
registrar.registerFactory("myprovider", (config) =>
|
|
376
|
+
createMyProvider(config) as Provider<unknown, unknown, unknown>
|
|
377
|
+
);
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
## 使用
|
|
381
|
+
|
|
382
|
+
```bash
|
|
383
|
+
# 安装 — 运行时无需 Bun
|
|
384
|
+
npm install -g @ahoo-wang/godex
|
|
385
|
+
|
|
386
|
+
# 交互式创建配置
|
|
387
|
+
godex init
|
|
388
|
+
|
|
389
|
+
# 启动网关
|
|
390
|
+
godex serve
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
Godex 以**独立原生二进制文件**发布,零运行时依赖。npm 的 `postinstall` 脚本自动为您的平台选择正确的二进制文件。唯一前置条件是 Node.js >= 18(仅在 `npm install` 期间需要)。
|
|
394
|
+
|
|
395
|
+
Godex 在 `http://localhost:5678` 暴露**与 OpenAI 兼容的 Responses API**(端口可配置)。将任何使用 OpenAI 协议的工具指向此端点即可:
|
|
396
|
+
|
|
397
|
+
### 搭配 Codex CLI
|
|
398
|
+
|
|
399
|
+
```bash
|
|
400
|
+
export OPENAI_BASE_URL=http://localhost:5678/v1
|
|
401
|
+
export OPENAI_API_KEY=any-value # Godex 不验证此值,但必须设置
|
|
402
|
+
codex
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### 搭配 OpenAI SDK
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
import OpenAI from "openai";
|
|
409
|
+
|
|
410
|
+
const client = new OpenAI({
|
|
411
|
+
baseURL: "http://localhost:5678/v1",
|
|
412
|
+
apiKey: "any-value", // 透传,不验证
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
const response = await client.responses.create({
|
|
416
|
+
model: "gpt-4o", // 通过 godex.yaml 的 models 表映射为 glm-4.7
|
|
417
|
+
input: "Hello!",
|
|
418
|
+
});
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
### 模型选择
|
|
422
|
+
|
|
423
|
+
```
|
|
424
|
+
model: "gpt-4o" → 通过 default_provider 的模型映射解析
|
|
425
|
+
model: "zhipu/glm-4.7" → 显式指定 provider/model 选择器
|
|
426
|
+
model: "openai/gpt-4o" → 路由到已配置的 openai 提供商
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
`godex.yaml` 中的 `models` 映射表可将标准模型名称转换为提供商原生名称 — 客户端无需修改代码。
|
|
430
|
+
|
|
431
|
+
### 健康检查
|
|
432
|
+
|
|
433
|
+
```bash
|
|
434
|
+
curl http://localhost:5678/health
|
|
435
|
+
# {"status":"ok","providers":["zhipu"],"unsupported_providers":[]}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
## 发布
|
|
439
|
+
|
|
440
|
+
主包 `@ahoo-wang/godex` 是一个轻量外壳。原生二进制文件以平台特定的可选依赖发布:
|
|
441
|
+
|
|
442
|
+
```
|
|
443
|
+
@ahoo-wang/godex(包装包,0 运行时依赖)
|
|
444
|
+
├── engines: { node: ">=18.0.0" } ← 仅用于 postinstall
|
|
445
|
+
├── postinstall: scripts/install.cjs ← 检测平台,链接二进制文件
|
|
446
|
+
└── optionalDependencies:
|
|
447
|
+
├── @ahoo-wang/godex-darwin-arm64 ← macOS Apple Silicon
|
|
448
|
+
├── @ahoo-wang/godex-darwin-x64 ← macOS Intel
|
|
449
|
+
├── @ahoo-wang/godex-linux-x64 ← Linux x86_64
|
|
450
|
+
├── @ahoo-wang/godex-linux-arm64 ← Linux ARM64
|
|
451
|
+
├── @ahoo-wang/godex-win32-x64 ← Windows x86_64
|
|
452
|
+
└── @ahoo-wang/godex-win32-arm64 ← Windows ARM64
|
|
453
|
+
|
|
454
|
+
# 发布流程:
|
|
455
|
+
# 1. 将 GitHub 仓库设为公开,配置 NPM_TOKEN,然后推送发布提交。
|
|
456
|
+
# 2. 创建标签为 vX.Y.Z 的 GitHub Release。
|
|
457
|
+
# 3. Release 工作流构建所有平台二进制文件。
|
|
458
|
+
# 4. Release 工作流上传二进制压缩包和 SHA256SUMS 到 Release Assets。
|
|
459
|
+
# 5. Release 工作流先发布平台包,再发布 @ahoo-wang/godex。
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
## 命令
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
bun run dev # 热重载开发服务器,端口 13145
|
|
466
|
+
bun run build # 为当前平台编译原生二进制
|
|
467
|
+
bun run compile:all # 本地交叉编译全部 6 个平台
|
|
468
|
+
bun run test # 单元 + 集成测试
|
|
469
|
+
bun run test:e2e # 模拟上游的端到端测试
|
|
470
|
+
bun run typecheck # tsc --noEmit
|
|
471
|
+
bun run lint # Biome 检查
|
|
472
|
+
bun run ci # 完整 CI 流水线
|
|
473
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ahoo-wang/godex",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Make every model a Codex engine through an OpenAI-compatible Responses API gateway",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -38,18 +38,19 @@
|
|
|
38
38
|
"test:coverage": "bun test --path-ignore-patterns 'src/e2e/**' --coverage",
|
|
39
39
|
"check": "bun run typecheck && bun run lint && bun run test",
|
|
40
40
|
"ci": "bun run typecheck && biome ci src && bun run test && bun run test:e2e",
|
|
41
|
+
"version": "bun run scripts/version.ts",
|
|
41
42
|
"postinstall": "node scripts/install.cjs"
|
|
42
43
|
},
|
|
43
44
|
"engines": {
|
|
44
45
|
"node": ">=18.0.0"
|
|
45
46
|
},
|
|
46
47
|
"optionalDependencies": {
|
|
47
|
-
"@ahoo-wang/godex-darwin-arm64": "0.0.
|
|
48
|
-
"@ahoo-wang/godex-darwin-x64": "0.0.
|
|
49
|
-
"@ahoo-wang/godex-linux-x64": "0.0.
|
|
50
|
-
"@ahoo-wang/godex-linux-arm64": "0.0.
|
|
51
|
-
"@ahoo-wang/godex-win32-x64": "0.0.
|
|
52
|
-
"@ahoo-wang/godex-win32-arm64": "0.0.
|
|
48
|
+
"@ahoo-wang/godex-darwin-arm64": "0.0.2",
|
|
49
|
+
"@ahoo-wang/godex-darwin-x64": "0.0.2",
|
|
50
|
+
"@ahoo-wang/godex-linux-x64": "0.0.2",
|
|
51
|
+
"@ahoo-wang/godex-linux-arm64": "0.0.2",
|
|
52
|
+
"@ahoo-wang/godex-win32-x64": "0.0.2",
|
|
53
|
+
"@ahoo-wang/godex-win32-arm64": "0.0.2"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
56
|
"@biomejs/biome": "^2.4.15",
|
|
@@ -62,6 +63,6 @@
|
|
|
62
63
|
"commander": "^14.0.3",
|
|
63
64
|
"js-yaml": "^4.1.1",
|
|
64
65
|
"nanoid": "^5.1.11",
|
|
65
|
-
"typescript": "^
|
|
66
|
+
"typescript": "^6"
|
|
66
67
|
}
|
|
67
68
|
}
|