@bd7pil/reeve 0.1.8 → 0.1.10

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.
@@ -15,8 +15,8 @@
15
15
  },
16
16
  "providers": {
17
17
  "opencode": { "base_url": "https://opencode.ai/inference/openai/v1", "path": "/chat/completions", "key": "public", "lane": "passthrough", "models": ["*"] },
18
- "openrouter": { "base_url": "https://openrouter.ai/api/v1", "auth": ["openrouter"], "models": [] },
19
- "nvidia": { "base_url": "https://integrate.api.nvidia.com/v1", "auth": ["nvidia"], "models": [] },
18
+ "openrouter": { "base_url": "https://openrouter.ai/api/v1", "path": "/chat/completions", "auth": ["openrouter"], "models": [] },
19
+ "nvidia": { "base_url": "https://integrate.api.nvidia.com/v1", "path": "/chat/completions", "auth": ["nvidia"], "models": [] },
20
20
  "zhipuai-coding-plan": { "base_url": "https://open.bigmodel.cn", "path": "/api/coding/paas/v4/chat/completions", "auth": ["zhipuai-coding-plan"] },
21
21
  "xxyapi-deepseek": { "base_url": "https://www.xxyapi.com", "auth": ["xxyapi-deepseek"] },
22
22
  "lmuai": { "base_url": "https://api.lmuai.com", "auth": ["lmuai", "lmuai-glm"] },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bd7pil/reeve",
3
- "version": "0.1.8",
3
+ "version": "0.1.10",
4
4
  "description": "REEVE 编排层(opencode v2 插件):agent/skill 注册 + 子任务台账 + GATE 代理层(路由/回退/台账)+ 性能统计",
5
5
  "type": "module",
6
6
  "main": "index.js",
package/provision.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schema": 1,
3
3
  "name": "reeve",
4
- "version": "0.1.8",
4
+ "version": "0.1.10",
5
5
  "license": "MIT",
6
6
  "//": "REEVE 在 ocrc 实例里的装配说明。**没有二进制工件** —— 代理层是插件内的 GATE(纯 JS),不需要任何本地服务(Bifrost 时代已结束)。",
7
7
  "host": {
@@ -15,7 +15,7 @@
15
15
  ]
16
16
  },
17
17
  "enginePlugin": {
18
- "spec": "@bd7pil/reeve@0.1.8",
18
+ "spec": "@bd7pil/reeve@0.1.10",
19
19
  "kind": "package",
20
20
  "entry": "~/.ocrc/components/reeve/node_modules/@bd7pil/reeve",
21
21
  "requiresPeer": []
package/src/index.js CHANGED
@@ -36,7 +36,7 @@ import { SUBAGENT_ROSTER, withRoster } from './roster.js'
36
36
  import { probeGate, startGate } from './gate/gate.js'
37
37
  import { defaultFallbackConfigPath } from './gate/config.js'
38
38
  import { REEVE_TIERS, BUILTINS_TO_HIDE, mergeTierModels, pickDefaultAgent, readEndpoint, resolveGateEndpoint } from './models.js'
39
- import { STATS_DEFAULTS, aggregateGateRows, aggregateLedger, buildStats, fetchGateFree, fetchGateModels, mergeModelCandidates, readLedgerTail } from './stats.js'
39
+ import { STATS_DEFAULTS, aggregateGateRows, aggregateLedger, buildStats, fetchGateFree, fetchGateModels, fetchGateVersion, mergeModelCandidates, readLedgerTail } from './stats.js'
40
40
  import { loadAgents, loadSkills } from './register.js'
41
41
  import { ensureProviderBlock, reeveProviderBlock } from './config-write.js'
42
42
 
@@ -285,6 +285,42 @@ export default {
285
285
  statsTimer.unref?.()
286
286
  logger.debug(`[reeve] 性能统计:每 ${Math.round(statsIntervalMs / 1000)}s 刷一次(台账尾 ${statsLimit} 行 / ${Math.round(statsWindowMs / 3600000)}h 窗口)`)
287
287
  }
288
+
289
+ // GATE 运行态独立刷新(2s):面板的"已生效"要看到 chain_targets/policy/free 真的变了。
290
+ // 统计是 60s 一轮(含台账聚合),拿它当"热更已完成"的信号会让面板在 30s 超时后误报"没生效"
291
+ // ——真宿主保存测试抓到的:GATE 已经换链,快照还停在 60s 前。这里只读进程内 snapshot / 环回
292
+ // /gate/version(都很便宜),且**只在签名变化时**刷快照,稳定时不写盘。
293
+ let gateStateTimer = null
294
+ const gateSignature = () =>
295
+ JSON.stringify({
296
+ port: gateState?.port ?? null,
297
+ error: gateState?.error ?? null,
298
+ chains: gateState?.chains ?? null,
299
+ ct: gateState?.chain_targets ?? null,
300
+ policy: gateState?.policy ?? null,
301
+ free: gateState?.free ?? null,
302
+ })
303
+ let lastGateSig = gateSignature()
304
+ const refreshGateState = async () => {
305
+ let next = null
306
+ if (gateHandle) next = gateHandle.snapshot()
307
+ else if (gateState?.port) {
308
+ const { doc } = await fetchGateVersion({ port: gateState.port, host: gateState.host ?? '127.0.0.1' })
309
+ if (doc?.name === 'reeve-gate') next = { ...doc, reused: true }
310
+ }
311
+ if (!next) return
312
+ gateState = next
313
+ const sig = gateSignature()
314
+ if (sig !== lastGateSig) {
315
+ lastGateSig = sig
316
+ snapshotFlush()
317
+ }
318
+ }
319
+
320
+ if (gateHandle || gateState?.port) {
321
+ gateStateTimer = setInterval(() => void refreshGateState(), 2000)
322
+ gateStateTimer.unref?.()
323
+ }
288
324
  const supervisor = new Supervisor({
289
325
  ledger,
290
326
  logger,
@@ -565,6 +601,7 @@ export default {
565
601
  abort.abort()
566
602
  supervisor.stopAll()
567
603
  if (statsTimer) clearInterval(statsTimer)
604
+ if (gateStateTimer) clearInterval(gateStateTimer)
568
605
  if (snapshot) {
569
606
  snapshot.cancel()
570
607
  void snapshot.flush().catch(() => {})
package/src/stats.js CHANGED
@@ -314,6 +314,18 @@ export async function fetchGateFree({ port, host = '127.0.0.1', fetchImpl = fetc
314
314
  }
315
315
  }
316
316
 
317
+ /** GATE 的运行态(/gate/version):开关快照轮询用。读不到返回 {doc:null,error},不抛。 */
318
+ export async function fetchGateVersion({ port, host = '127.0.0.1', fetchImpl = fetch, timeoutMs = STATS_DEFAULTS.timeoutMs } = {}) {
319
+ try {
320
+ const res = await fetchImpl(`http://${host}:${port}/gate/version`, { signal: AbortSignal.timeout(timeoutMs) })
321
+ if (res.status !== 200) return { doc: null, error: `HTTP ${res.status}` }
322
+ const doc = await res.json()
323
+ return { doc: doc && typeof doc === 'object' ? doc : null, error: null }
324
+ } catch (err) {
325
+ return { doc: null, error: String(err?.message ?? err).slice(0, 140) }
326
+ }
327
+ }
328
+
317
329
  /** GATE 自己的模型目录(`provider/model` ∪ 链名)—— 面板选择器的候选来源之一。 */
318
330
  export async function fetchGateModels({ port, host = '127.0.0.1', fetchImpl = fetch, timeoutMs = STATS_DEFAULTS.timeoutMs } = {}) {
319
331
  try {