@lqc123qwe/car-runtime 1.4.0 → 1.5.0
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/.github/workflows/ci.yml +12 -0
- package/README.md +16 -1
- package/package.json +4 -1
- package/src/cli.ts +32 -15
- package/src/dx/doctor.ts +9 -7
- package/src/load/config.ts +205 -137
- package/src/mcp/httpClient.ts +176 -0
- package/src/runtime-core/chatStep.ts +9 -3
- package/src/runtime-core/credentials.ts +6 -1
- package/src/runtime-core/llm.ts +289 -75
- package/test/s33-anthropic-adapter.spec.ts +354 -0
- package/test/s34-mcp-remote-transport.spec.ts +250 -0
- package/test/s35-config-ts-zod.spec.ts +145 -0
package/.github/workflows/ci.yml
CHANGED
|
@@ -66,6 +66,8 @@ jobs:
|
|
|
66
66
|
- uses: actions/checkout@v4
|
|
67
67
|
- uses: actions/setup-node@v4
|
|
68
68
|
with: { node-version: '22.19' }
|
|
69
|
+
# 1.5 起 zod 为常规运行时依赖(D-22)——CLI/doctor 传递加载,测试 job 需 node_modules
|
|
70
|
+
- run: npm install
|
|
69
71
|
- run: node -p "'G-06 node ' + process.version"
|
|
70
72
|
- run: node --experimental-sqlite --experimental-transform-types --test "test/*.spec.ts"
|
|
71
73
|
|
|
@@ -77,6 +79,8 @@ jobs:
|
|
|
77
79
|
- uses: actions/checkout@v4
|
|
78
80
|
- uses: actions/setup-node@v4
|
|
79
81
|
with: { node-version: '22.19' }
|
|
82
|
+
# 1.5 起 zod 为常规运行时依赖(D-22)——CLI/doctor 传递加载,测试 job 需 node_modules
|
|
83
|
+
- run: npm install
|
|
80
84
|
- run: node -p "'G-06 node ' + process.version"
|
|
81
85
|
- run: node --experimental-sqlite --experimental-transform-types --test "test/*.spec.ts"
|
|
82
86
|
|
|
@@ -88,6 +92,8 @@ jobs:
|
|
|
88
92
|
- uses: actions/checkout@v4
|
|
89
93
|
- uses: actions/setup-node@v4
|
|
90
94
|
with: { node-version: '22.19' }
|
|
95
|
+
# 1.5 起 zod 为常规运行时依赖(D-22)——CLI/doctor 传递加载,测试 job 需 node_modules
|
|
96
|
+
- run: npm install
|
|
91
97
|
- run: node -p "'G-06 node ' + process.version"
|
|
92
98
|
- run: node --experimental-sqlite --experimental-transform-types --test "test/*.spec.ts"
|
|
93
99
|
|
|
@@ -163,6 +169,8 @@ jobs:
|
|
|
163
169
|
- uses: actions/checkout@v4
|
|
164
170
|
- uses: actions/setup-node@v4
|
|
165
171
|
with: { node-version: '22.19' }
|
|
172
|
+
# 1.5 起 zod 为常规运行时依赖(D-22)——cli.ts 传递加载,dx-smoke 需 node_modules
|
|
173
|
+
- run: npm install
|
|
166
174
|
- run: node --experimental-transform-types src/cli.ts doctor
|
|
167
175
|
- run: node --experimental-transform-types src/cli.ts reload test/fixtures/hello-plugin.ts
|
|
168
176
|
|
|
@@ -174,6 +182,8 @@ jobs:
|
|
|
174
182
|
- uses: actions/checkout@v4
|
|
175
183
|
- uses: actions/setup-node@v4
|
|
176
184
|
with: { node-version: '22.19' }
|
|
185
|
+
# 1.5 起 zod 为常规运行时依赖(D-22)——cli.ts 传递加载,dx-smoke 需 node_modules
|
|
186
|
+
- run: npm install
|
|
177
187
|
- run: node --experimental-transform-types src/cli.ts doctor
|
|
178
188
|
- run: node --experimental-transform-types src/cli.ts reload test/fixtures/hello-plugin.ts
|
|
179
189
|
|
|
@@ -185,6 +195,8 @@ jobs:
|
|
|
185
195
|
- uses: actions/checkout@v4
|
|
186
196
|
- uses: actions/setup-node@v4
|
|
187
197
|
with: { node-version: '22.19' }
|
|
198
|
+
# 1.5 起 zod 为常规运行时依赖(D-22)——cli.ts 传递加载,dx-smoke 需 node_modules
|
|
199
|
+
- run: npm install
|
|
188
200
|
- run: node --experimental-transform-types src/cli.ts doctor
|
|
189
201
|
- run: node --experimental-transform-types src/cli.ts reload test/fixtures/hello-plugin.ts
|
|
190
202
|
|
package/README.md
CHANGED
|
@@ -184,9 +184,24 @@ node --experimental-transform-types --test test/*.spec.ts
|
|
|
184
184
|
- **1.3 发布资产自动化(W4,2026-09-27 收口)**:`scripts/release-artifacts.ts` 制品构建单一事实源(本地流水线/CI j16 双端复用;SHA256SUMS 裸字节自检 G-11 口径 + SBOM G-05 同构 + releaseAssetNames 五件套清单——G-10/CI/测试三方同源)+ release.yml 重构(构建 → cosign keyless 签名〔D-15 正式轨:OIDC+Rekor,CI 零 keypair 材料〕→ `gh release upload --clobber` 五件套 → npm publish 原步不动;**upload 先于 publish**)+ D-14 资产集迁移(car-release.pub 移出——keyless 验证锚 = bundle 证书 + Rekor)+ D-14 tag 形态统一(裸版本号)。s30 七测(构建/清单/同源/yml 结构与步骤序红线/**name 行冒号守卫**〔1.3-BUG-2 回归钉〕)。全量 **270(267 PASS + 3 skip / 0 fail)**。W1 三度延后登记 **1.4 头号候选**(设计账本 D-12a loopback 豁免 + D-13 --demo 保留)。规划:`car-docs/10-内核v1/1.3-迭代规划.md`;收口报告:`car-docs/10-内核v1/1.3-收口终验报告.md`。
|
|
185
185
|
- **1.3.0 正式发布(2026-09-27,S5 收官,W4 全自动首战兑现)**:Release `1.3.0`(tag 32dad29)→ **j16 run 36320604746 全步 success**(构建 → keyless 签名 → 自动上传五件套〔零人工拖拽〕→ npm publish)→ npm `@lqc123qwe/car-runtime@1.3.0` 在架,**dist-tags latest → 1.3.0、rc 保留 1.0.0-rc.1** + provenance。**post-publish 12 PASS / 1 DRY-RUN / 0 FAIL(G-09 实查)**;外部等价检查 **SHA256 MATCH(`70767c8d…`)+ cosign keyless Verified OK**(证书身份 + Rekor——D-15 正式轨兑现,pub 退役)。发布工程事件:首发受挫 1.3-BUG-2(workflow 步骤名未引号冒号 → YAML 解析失败 → startup failure 且 release 事件静默失效;**改 workflow 必须本地 PyYAML 复验**,post-publish 必须核对 release 事件 run 真实触发)。
|
|
186
186
|
|
|
187
|
+
## 1.4 状态(真实模型接入 W1 完整)
|
|
188
|
+
|
|
189
|
+
| `src/cli.ts` | 1.4-S5(D-13)car run 双路径:真路径(Context+RuntimeCore+bindContext→registerLlmAdapter 根作用域 effect → runTurn model 回调=chatStep;SIGINT 取消;SIGINT→signal)+ `--demo` 保留 stub(demo_tool 撞名边缘出清);无模型配置 exit 2 显式引导(CAR-E-LLM-CONFIG) | M8 §1「runTurn 消费接线」出清 |
|
|
190
|
+
| `src/load/config.ts` +2 | 1.4-S3(D-16)`llm.*` 键位(baseUrl/model/adapterId/maxTokens/allowEnvFallback——fail-visible)+ `mcp.servers.*` 键位(D-18;env 禁明文凭据由 gateway 强制检查)+ mergeLlmConfig(flag > env > config) | 1.4 W1-2 |
|
|
191
|
+
| `src/runtime-core/tools.ts` | 1.4-S1 toToolDefinitions(执行面 Map → 模型声明面;T-22 缺省 write 收口;执行面=声明面同一对象红线) | 1.4 W1-3 |
|
|
192
|
+
| `src/load/loader.ts` + `src/loop/stop.ts` | 1.4-S1 ToolReg/ToolDef 加 description/parameters/declaredSideEffect(加法);PluginApi.setSystemPrompt(pending 收集 → bindCore 冲刷,last-wins) | 1.4 W1-3/W1-4 |
|
|
193
|
+
| `src/session/log.ts` + `src/runtime-core/chatStep.ts` | 1.4-S2(D-17)EventKind 加 'system' + deriveMessages 投影 role:system + chatStep 角色映射 + golden 登记(contract-check 4/4);1.4-S4(D-19)**TurnAborted 全库首次实抛**(chunk 间隙 + finish 检查前序——assistant 未落链无半截) | §3.5.5 红线兑现 |
|
|
194
|
+
| `src/runtime-core/llm.ts` + `types.ts` | 1.4-S4:D-12a TLS loopback 豁免(http 仅 127.0.0.1/localhost/[::1]——1.4-BUG-3:URL.hostname IPv6 带方括号)+ LlmRequest.signal 透传三检查点(取消 ≠ 失败:不 retry 不 error chunk);**1.4-BUG-1 修复:出站 fetch 缺 method:'POST'(M8 潜伏——注入式 fetch 单测忽略 method,真 undici 暴露)** | 1.4 W1-5/W1-7 |
|
|
195
|
+
| `src/runtime-core/telemetry.ts` + `trace.ts` | 1.4-S6:startSpan trace 透传(traceId 复用 + parentSpanId)+ TelemetrySpan.spanId + TurnTracer(turn 根 → step 子层级;**挂点装配层**——loop 层零改动微调登记);**1.4-BUG-2 修复:出站默认 node:http(s)(win32 全局 fetch/undici + 进程退出 → libuv 断言崩溃 0xC0000409,Node 23.5 实测/22 不复现)** | M8 §4.4 遥测未入链出清 |
|
|
196
|
+
| `src/mcp/stdioClient.ts` + `src/ptc/runCode.ts` +2 | 1.4-S7(D-18)MCP stdio 客户端传输(spawn + JSON-RPC 行协议 + 30s 超时)+ `--mcp <serverId>` → gateway → 模型名 `mcp_<serverId>_<name>` + callTool 桥;makePtcToolDefinition 补 parameters + `--ptc` 桥(声明面=授权面同源快照)+ **renderSdkFromRegistry 首次生产调用点**(SDK 声明块独立 system 事件) | 1.4 MCP/PTC 块 |
|
|
197
|
+
| `test/s31-real-model-wiring.spec.ts` + `test/s32-telemetry-mcp-ptc.spec.ts` | 1.4 测试:s31 9 测(声明面/system/配置/loopback/取消/CarM8Error/多步真 E2E/spawn 全链/无配置 exit 2)+ s32 3 测(trace 透传/TurnTracer/**car run 全链:MCP 真进程+PTC worker 桥+SDK 出站+trace 父子链**) | 1.4-GO |
|
|
198
|
+
|
|
199
|
+
- **1.4 工程收口(2026-09-27)**:W1 完整四块兑现——**car run 首次真实调模型**(多步工具循环 E2E 全链),模型配置通道(llm.* + env + flags)、system prompt 落链(§3.5.5 红线兑现)、TurnAborted 首次实抛、CarM8Error 保形(A080001 引导文案可达)、TLS loopback 豁免(D-12a 兑现)、MCP/PTC 进真实 turn、遥测 turn/step span 出站。全量 **282(279 PASS + 3 能力门控 skip / 0 fail)** + tsc strict 0 + secrets-scan 105 文件 0 命中。**1.4-BUG-1(fetch 缺 POST)/BUG-2(win32 退出崩溃)/BUG-3(IPv6 方括号)均为生产接线暴露的真缺陷**。
|
|
200
|
+
- **1.4.0 正式发布(2026-09-27,S9 收官,全自动第二次实战)**:npm `@lqc123qwe/car-runtime@1.4.0` 在架——**dist-tags latest → 1.4.0、rc 保留指向 1.0.0-rc.1** + provenance。Release `1.4.0`(agent 经 GCM 凭据 API 创建)→ **j16 run 36328295548 全步 success**(构建/keyless 签名/自动上传五件套/npm publish)→ **post-publish 12 PASS / 1 DRY-RUN / 0 FAIL(G-09 实查)**;外部等价检查 **SHA256 MATCH(`55ce08fd…`)+ cosign keyless Verified OK**。
|
|
201
|
+
- **遗留登记**:anthropic 适配器(冻结);远程 MCP 传输(SSE/HTTP);写类工具双 toolResult 投影观察项;car.config.ts+zod;jiti。规划:`car-docs/10-内核v1/1.4-迭代规划.md`;收口报告:`car-docs/10-内核v1/1.4-收口终验报告.md`。
|
|
187
202
|
## 状态
|
|
188
203
|
|
|
189
|
-
- **版本主线**:S1-S4 48/48 | M2 89/89(v0.2.0)| M3 127/127(v0.3.0)| M4 139/139(**1.0.0-rc.1 已发布**)| M5 156/156(DEC-4 预埋项转正)| M6 179/179(2026-09-15 收口)| M7 全量 195(192 PASS + 3 能力门控 skip,2026-09-19 收口)| **M5-S28 装载签名门 全量 204(201 PASS + 3 skip,2026-09-26)** | **M8 运行时底座 全量 231(228 PASS + 3 skip,2026-09-26 收口,§3.2 八模块全部收口)** | **1.1 签名收尾最小集 全量 249(246 PASS + 3 skip,2026-09-27 收口,1.1.0 已发布,enforce 翻转准备就绪)** | **1.2 会话/遥测小项 全量 263(260 PASS + 3 skip,2026-09-27 收口,1.2.0 已发布)** | **1.3 发布资产自动化 全量 270(267 PASS + 3 skip,2026-09-27 收口,1.3.0 已发布,全链零人工拖拽兑现)**
|
|
204
|
+
- **版本主线**:S1-S4 48/48 | M2 89/89(v0.2.0)| M3 127/127(v0.3.0)| M4 139/139(**1.0.0-rc.1 已发布**)| M5 156/156(DEC-4 预埋项转正)| M6 179/179(2026-09-15 收口)| M7 全量 195(192 PASS + 3 能力门控 skip,2026-09-19 收口)| **M5-S28 装载签名门 全量 204(201 PASS + 3 skip,2026-09-26)** | **M8 运行时底座 全量 231(228 PASS + 3 skip,2026-09-26 收口,§3.2 八模块全部收口)** | **1.1 签名收尾最小集 全量 249(246 PASS + 3 skip,2026-09-27 收口,1.1.0 已发布,enforce 翻转准备就绪)** | **1.2 会话/遥测小项 全量 263(260 PASS + 3 skip,2026-09-27 收口,1.2.0 已发布)** | **1.3 发布资产自动化 全量 270(267 PASS + 3 skip,2026-09-27 收口,1.3.0 已发布,全链零人工拖拽兑现)** | **1.4 真实模型接入 全量 282(279 PASS + 3 skip,2026-09-27 收口,1.4.0 已发布)**
|
|
190
205
|
- **1.0.0 正式发布(2026-09-26,S29/S30)**:npm `@lqc123qwe/car-runtime@1.0.0` 在架——**dist-tag latest → 1.0.0,rc 保留指向 1.0.0-rc.1**(§1.1 口径);SLSA provenance(Actions OIDC,透明日志在案);GitHub Release v1.0.0 六资产(tgz/bundle/SHA256SUMS/SBOM/审计/公钥);**post-publish 全链 13 PASS / 0 DRY-RUN / 0 FAIL** + 外部验证者等价检查(Release 实下载件 SHA256 MATCH + cosign Verified OK)。**宽限期时钟:2026-09-26 起算,2026-12-25 到期 verifier 默认值 warn→enforce 翻转(计划内变更)**。终验报告:`car-docs/10-内核v1/M5-S30-1.0收口终验报告.md`。发布工程事件:j16 首跑 E403(npm 2FA 策略 vs granular token 无 bypass——清单预设回退路径兑现)→ bypass token re-run 绿;G-09 期望 tag 动态化(`4c84b17`)在真实发布兑现价值。
|
|
191
206
|
- **1.0.0-rc.1 已发布(2026-09-09)**:npm `@lqc123qwe/car-runtime@1.0.0-rc.1`(rc + latest 双 tag,SLSA provenance 在案)+ GitHub Release 6 制品;发布预演 **13 PASS / 0 DRY-RUN / 0 FAIL**(c762b72)。S22 GO 清单已全绿收口。
|
|
192
207
|
- **轨道 A 三项全部完成**:E-1 WSL2 逃逸矩阵 **20/20 PASS 零逃逸**(2026-09-07,G-07 转 PASS)| E-3 远端发布通道 **13/13 全门禁 PASS**(2026-09-09,G-08/09/10 转 PASS)| E-2 Windows koffi FFI **四判据双环境全 PASS**(S24/S25/S26,2026-09-09~10;本机非提权 + windows-latest 提权 runner 双绿,CI 门禁已接入)。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lqc123qwe/car-runtime",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Composable Agent Runtime (CAR) - microkernel plugin system with sandboxed PTC, append-only hashed session log, and MCP host bridge",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -24,5 +24,8 @@
|
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"@types/node": "^26.6.1"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"zod": "^3.25.76"
|
|
27
30
|
}
|
|
28
31
|
}
|
package/src/cli.ts
CHANGED
|
@@ -24,10 +24,10 @@ import { runTurn } from './loop/stop.ts'
|
|
|
24
24
|
import { Context } from './kernel/context.ts'
|
|
25
25
|
import { mountPlugin } from './load/loader.ts'
|
|
26
26
|
import { verifyPluginFile } from './load/sigGate.ts'
|
|
27
|
-
import { loadCarConfig, mergeSignatureGate, mergeLlmConfig } from './load/config.ts'
|
|
27
|
+
import { loadCarConfig, mergeSignatureGate, mergeLlmConfig, warmCarConfig } from './load/config.ts'
|
|
28
28
|
import { generateSigningKeypair, signPluginFile, resolveTrustRoot } from './load/sign.ts'
|
|
29
29
|
import { doctorCredentials, doctorConnectivity, doctorKeychain, doctorSignature, doctorModelReadiness } from './dx/doctor.ts'
|
|
30
|
-
import { RuntimeCore, createOpenAICompatAdapter } from './runtime-core/llm.ts'
|
|
30
|
+
import { RuntimeCore, createOpenAICompatAdapter, createAnthropicAdapter } from './runtime-core/llm.ts'
|
|
31
31
|
import { CredentialService } from './runtime-core/credentials.ts'
|
|
32
32
|
import { chatStep } from './runtime-core/chatStep.ts'
|
|
33
33
|
import { toToolDefinitions } from './runtime-core/tools.ts'
|
|
@@ -36,8 +36,11 @@ import { TurnTracer } from './runtime-core/trace.ts'
|
|
|
36
36
|
import type { CounterName, AllowedLabels } from './telemetry/metrics.ts'
|
|
37
37
|
|
|
38
38
|
const HELP = `用法: car <command> [args]
|
|
39
|
-
run <plugin.ts> [--sig-enforce] [--config <path>]
|
|
39
|
+
run <plugin.ts> [--sig-enforce] [--config <path>] [--adapter-id <id>]
|
|
40
40
|
装配并运行插件(快速上手流;装载前签名门 warn 缺省)
|
|
41
|
+
真路径:--prompt <text> + --base-url/--model(或 llm.* 配置);
|
|
42
|
+
--adapter-id anthropic = Messages API(凭据 ANTHROPIC_API_KEY);
|
|
43
|
+
--demo = stub 演示流
|
|
41
44
|
reload <file|dir> [--sig-enforce] [--config <path>]
|
|
42
45
|
热重载插件并打印六阶段加载报告(含 verify 签名门)
|
|
43
46
|
session verify <file> 哈希链完整性校验(撕裂尾显式报告)
|
|
@@ -49,6 +52,8 @@ const HELP = `用法: car <command> [args]
|
|
|
49
52
|
session verify/replay/export 均支持 --session <id> [--db <path>]
|
|
50
53
|
经 SQLite 索引定位会话(1.2;缺省 db = cwd sessions-index.db;索引未收录 = 显式报错)
|
|
51
54
|
doctor 环境自检
|
|
55
|
+
mcp-serve [--host <id>] [--plugin <file|dir>...] [--config <path>]
|
|
56
|
+
CAR-as-MCP-Server(宿主经 stdio JSON-RPC 接入)
|
|
52
57
|
plugin-sign keygen [--out <前缀>] [--force]
|
|
53
58
|
生成 ed25519 签名密钥对(<前缀>.priv PKCS8 DER / <前缀>.pub SPKI base64;缺省前缀 car-release)
|
|
54
59
|
plugin-sign sign <file...> [--key <priv>]
|
|
@@ -57,8 +62,10 @@ const HELP = `用法: car <command> [args]
|
|
|
57
62
|
验证签名(信任根序:--trust-root > CAR_TRUST_ROOT > ./car-release.pub;缺签/坏签均 FAIL)
|
|
58
63
|
签名门环境变量:CAR_SIG_ENFORCE=1 切 enforce;CAR_TRUST_ROOT=<ed25519 spki base64>;
|
|
59
64
|
CAR_UNSIGNED_ALLOW=1 显式声明豁免(warn 缺签路径计数 confirmed=yes,横幅保留)
|
|
60
|
-
配置文件通道(1.
|
|
61
|
-
sandbox.
|
|
65
|
+
配置文件通道(1.5 起双载体):cwd car.config.ts(export default {…};发现序 ts > json)或
|
|
66
|
+
car.config.json 或 --config <path>;键位 sandbox.unsigned.allow / sandbox.sig.enforce /
|
|
67
|
+
sandbox.sig.trustRoot / llm.* / mcp.servers.*(stdio: command/args/env;远程: url/headers,
|
|
68
|
+
\${ENV_VAR} 引用注入凭据);优先级 flag > env > 配置 > 缺省;未知键 fail-visible`
|
|
62
69
|
|
|
63
70
|
// 进程内热重载会话(ReloadManager 持有 epoch 与实例注册表;同进程连续 reload 语义完整)
|
|
64
71
|
let reloadMgrPromise: Promise<import('./load/report.ts').ReloadManager> | undefined
|
|
@@ -101,6 +108,8 @@ function resolveSigGate(argv: string[]): { options: import('./load/sigGate.ts').
|
|
|
101
108
|
|
|
102
109
|
async function main(): Promise<number> {
|
|
103
110
|
const [, , cmd, ...rest] = process.argv
|
|
111
|
+
// 1.5-S3(D-22):car.config.ts 载体统一预热(--config *.ts 或 cwd 发现序 ts>json;无 TS 载体 = no-op)
|
|
112
|
+
await warmCarConfig({ explicitPath: flagValue(rest, '--config') })
|
|
104
113
|
switch (cmd) {
|
|
105
114
|
case 'run': {
|
|
106
115
|
// 1.4-S5(D-13):缺省 = 真实模型路径(chatStep 经 openai-compat 适配器);--demo 保留 stub 演示流。
|
|
@@ -186,8 +195,9 @@ async function main(): Promise<number> {
|
|
|
186
195
|
const prompt = flagValue(rest, '--prompt')
|
|
187
196
|
if (!llm.baseUrl || !llm.model || prompt === undefined) {
|
|
188
197
|
console.error('CAR-E-LLM-CONFIG: 真实模型路径需要 baseUrl + model + --prompt——')
|
|
189
|
-
console.error(' 配置:car.config.json {"llm":{"baseUrl":"https://…","model":"…"}} / env CAR_LLM_BASE_URL+CAR_LLM_MODEL / flag --base-url --model --prompt')
|
|
190
|
-
console.error('
|
|
198
|
+
console.error(' 配置:car.config.ts(export default)或 car.config.json {"llm":{"baseUrl":"https://…","model":"…"}} / env CAR_LLM_BASE_URL+CAR_LLM_MODEL / flag --base-url --model --prompt')
|
|
199
|
+
console.error(' anthropic:llm.adapterId "anthropic"(或 --adapter-id anthropic)+ baseUrl https://api.anthropic.com;凭据 ANTHROPIC_API_KEY')
|
|
200
|
+
console.error(' 凭据:OPENAI_API_KEY / ANTHROPIC_API_KEY(env fallback 需 CAR_ALLOW_ENV_CREDENTIALS=1 或 llm.allowEnvFallback)或 keychain;诊断:car doctor')
|
|
191
201
|
console.error(' (无模型演示流:--demo)')
|
|
192
202
|
return 2
|
|
193
203
|
}
|
|
@@ -195,12 +205,15 @@ async function main(): Promise<number> {
|
|
|
195
205
|
const credService = new CredentialService()
|
|
196
206
|
const core = new RuntimeCore(credService)
|
|
197
207
|
core.bindContext(ctx)
|
|
198
|
-
// 适配器经根作用域 effect 可逆注册(bindContext 必须先于 register
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
credentials: credService,
|
|
202
|
-
|
|
203
|
-
|
|
208
|
+
// 适配器经根作用域 effect 可逆注册(bindContext 必须先于 register——否则走非可逆直注册分支);
|
|
209
|
+
// 1.5-S1(D-20):adapterId='anthropic' → anthropic 适配器(Messages API);缺省 openai-compat 不变
|
|
210
|
+
core.registerLlmAdapter(llm.adapterId === 'anthropic'
|
|
211
|
+
? createAnthropicAdapter({ baseUrl: llm.baseUrl, credentials: credService, provider: 'anthropic' })
|
|
212
|
+
: createOpenAICompatAdapter({
|
|
213
|
+
baseUrl: llm.baseUrl,
|
|
214
|
+
credentials: credService,
|
|
215
|
+
provider: 'openai-compat',
|
|
216
|
+
}), { default: true })
|
|
204
217
|
// MCP 工具进 turn(D-18):--mcp <serverId>(可重复;server 启动规格在 car.config.json mcp.servers 登记)
|
|
205
218
|
const mcpIds: string[] = []
|
|
206
219
|
for (let i = 0; i < rest.length; i++) {
|
|
@@ -214,11 +227,15 @@ async function main(): Promise<number> {
|
|
|
214
227
|
if (mcpIds.length) {
|
|
215
228
|
const { McpGateway } = await import('./mcp/gateway.ts')
|
|
216
229
|
const { createStdioClientTransport } = await import('./mcp/stdioClient.ts')
|
|
230
|
+
const { createHttpMcpTransport, resolveMcpHeaders } = await import('./mcp/httpClient.ts')
|
|
217
231
|
const gw = new McpGateway()
|
|
218
232
|
for (const id of mcpIds) {
|
|
219
233
|
const spec = cfgLlm.config.mcp?.servers?.[id]
|
|
220
|
-
if (!spec) { console.error(`CAR-E-MCP: server "${id}"
|
|
221
|
-
|
|
234
|
+
if (!spec) { console.error(`CAR-E-MCP: server "${id}" 未在配置 mcp.servers 登记`); return 2 }
|
|
235
|
+
// 1.5-S2(D-21):url = 远程 Streamable HTTP(懒 initialize + 会话头);command = stdio 本地进程
|
|
236
|
+
const transport = spec.url
|
|
237
|
+
? createHttpMcpTransport({ url: spec.url, headers: resolveMcpHeaders(spec.headers ?? {}) })
|
|
238
|
+
: createStdioClientTransport({ command: spec.command!, args: spec.args })
|
|
222
239
|
mcpTransports.push(transport)
|
|
223
240
|
const mcpTools = await gw.register({ serverId: id, transport, env: spec.env })
|
|
224
241
|
for (const t of mcpTools) {
|
package/src/dx/doctor.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* 门禁判定仍在 sigGate/verifier;公钥可打印、信任根值本身不打印
|
|
9
9
|
*/
|
|
10
10
|
import { createPublicKey } from 'node:crypto'
|
|
11
|
-
import { CredentialService } from '../runtime-core/credentials.ts'
|
|
11
|
+
import { CredentialService, providerEnvVars } from '../runtime-core/credentials.ts'
|
|
12
12
|
import { loadCarConfig, mergeSignatureGate, mergeLlmConfig } from '../load/config.ts'
|
|
13
13
|
|
|
14
14
|
export interface CredentialCheck {
|
|
@@ -106,24 +106,26 @@ export interface ModelReadinessCheck {
|
|
|
106
106
|
export function doctorModelReadiness(opts: { env?: NodeJS.ProcessEnv; cwd?: string; configPath?: string } = {}): ModelReadinessCheck {
|
|
107
107
|
const env = opts.env ?? process.env
|
|
108
108
|
const cfg = loadCarConfig({ explicitPath: opts.configPath, cwd: opts.cwd })
|
|
109
|
-
const { baseUrl, model, allowEnvFallback } = mergeLlmConfig(env, cfg.error ? {} : cfg.config)
|
|
109
|
+
const { baseUrl, model, adapterId, allowEnvFallback } = mergeLlmConfig(env, cfg.error ? {} : cfg.config)
|
|
110
|
+
// 1.5-S4(D-20 配套):adapterId → 凭据 provider 感知(anthropic → ANTHROPIC_API_KEY;缺省 openai-compat)
|
|
111
|
+
const provider = adapterId === 'anthropic' ? 'anthropic' : 'openai-compat'
|
|
110
112
|
const envFallback: ModelReadinessCheck['envFallback'] = allowEnvFallback ? 'on' : 'off'
|
|
111
113
|
let credential: ModelReadinessCheck['credential'] = 'not-found'
|
|
112
114
|
if (allowEnvFallback) {
|
|
113
|
-
// env fallback 显式开启:
|
|
114
|
-
if (
|
|
115
|
+
// env fallback 显式开启:provider 候选变量存在性(providerEnvVars;只探存在不取值)
|
|
116
|
+
if (providerEnvVars(provider).some(n => env[n])) credential = 'env'
|
|
115
117
|
}
|
|
116
118
|
if (credential === 'not-found') {
|
|
117
119
|
// keychain 通道存在性(resolve 探测,A080001 全落空即 not-found;值不打印)
|
|
118
120
|
try {
|
|
119
|
-
const ref = new CredentialService().resolve(
|
|
121
|
+
const ref = new CredentialService().resolve(provider, { env, allowEnvFallback })
|
|
120
122
|
credential = ref.source
|
|
121
123
|
} catch { /* 全落空 = not-found(登记口径,非错误) */ }
|
|
122
124
|
}
|
|
123
125
|
const configured = !!baseUrl && !!model
|
|
124
126
|
const parts = [
|
|
125
|
-
configured ? `baseUrl=${baseUrl} model=${model}` : 'baseUrl/model 未配置(car run 真路径需 llm.* 配置或 CAR_LLM_BASE_URL/CAR_LLM_MODEL——见 car doctor / 配置指南)',
|
|
126
|
-
credential === 'keychain' ?
|
|
127
|
+
configured ? `baseUrl=${baseUrl} model=${model}${adapterId ? ` adapter=${adapterId}` : ''}` : 'baseUrl/model 未配置(car run 真路径需 llm.* 配置或 CAR_LLM_BASE_URL/CAR_LLM_MODEL——见 car doctor / 配置指南)',
|
|
128
|
+
credential === 'keychain' ? `凭据=keychain 命中(car-runtime/${provider},值不打印)`
|
|
127
129
|
: credential === 'env' ? '凭据=env 命中(显式开启 fallback,值不打印)'
|
|
128
130
|
: '凭据未就绪(keychain 未命中且 env fallback 未开或变量缺席——A080001 会引导至此)',
|
|
129
131
|
`envFallback=${envFallback}`,
|