@luchenglong/cli-bridge 0.2.3 → 0.2.4

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/CHANGELOG.md CHANGED
@@ -9,6 +9,23 @@ GitHub Release(`scripts/verify.mjs` 在 CI 与 prepack 双重锁一致)。
9
9
  > - CodeBuddy 线:[docs/history/codebuddy/CHANGELOG.md](docs/history/codebuddy/CHANGELOG.md)(终版 1.6.2)
10
10
  > - MiMo 线:[docs/history/mimo/CHANGELOG.md](docs/history/mimo/CHANGELOG.md)(终版 1.2.9)
11
11
 
12
+ ## [0.2.4] - 2026-10-16
13
+
14
+ ### Fixed
15
+ - **任务完成后状态灯长时间不灭**:原先用单一 `PROJECT_TTL_MS`(10 分钟)判定项目
16
+ 陈旧,导致跑完的任务要让灯挂满 10 分钟才消失,用户感知是「灯不灭」。改为区分两态:
17
+ **已收口**(`running=0` 且已有 `lastStatus`)走 `PROJECT_DONE_TTL_MS`(60 秒)快速
18
+ 淡出;**未收口**(运行中/长时间无终态)仍走 10 分钟防抖,避免运行中闪灯。
19
+ 淡出只影响 pill 渲染与顶层聚合 —— stale 项目仍保留在列表里作弹窗历史,不丢数据。
20
+ - **MCP 工具面版本号与统一 server 不一致**:四个 provider 的 `meta.version` 与描述符
21
+ `mcp.version` 硬编码版本字面量(8 处),0.2.3 出现「server 报 0.2.3、provider 面报
22
+ 0.2.2」。新增 `mcp/version.mjs` 从 package.json 读一次作为单一来源(读不到抛错,
23
+ 绝不静默回落);测试改为断言 semver 形态而非钉字面量,发布不再需要改测试。
24
+
25
+ ### Changed
26
+ - `doneTtlMs` 缺省跟随显式传入的 `projectTtlMs`(仅生产默认值取更短的
27
+ `PROJECT_DONE_TTL_MS`)—— 否则「传了短 TTL 却不生效」会静默坑调用方。
28
+
12
29
  ## [0.2.3] - 2026-10-15
13
30
 
14
31
  ### Added
@@ -30,7 +30,17 @@ import { settingsView, parseSettingsBody, readSettingsFile, writeSettingsFile, S
30
30
  import { declareBridgePresets } from './preset-declarations.mjs'
31
31
 
32
32
  export const PRESET_TTL_MS = 75000
33
+ /** 运行中/仍在活动的项目的新鲜期(防抖:短暂停顿不该让灯闪)。 */
33
34
  export const PROJECT_TTL_MS = 10 * 60 * 1000
35
+ /**
36
+ * 已完成(running=0 且已有 lastStatus)项目的新鲜期。
37
+ *
38
+ * 0.2.1 用单一 10 分钟 TTL 修「一次失败后灯永久挂着」—— 但 10 分钟对于「刚跑完、
39
+ * 想看到灯灭」来说太长:任务结束后灯要挂满 10 分钟才消失,用户感知是「灯不灭」。
40
+ * 区分两态:运行中(含短暂间隔)保持长 TTL 防抖;已收口的项目走短 TTL 快速淡出。
41
+ * 淡出只影响 pill 渲染(stale 项目仍在弹窗里作历史),不丢数据。
42
+ */
43
+ export const PROJECT_DONE_TTL_MS = 60 * 1000
34
44
  export const MAX_PROJECTS = 24
35
45
  export const MAX_SESSIONS = 64
36
46
 
@@ -50,6 +60,11 @@ export function createIndicatorState(opts) {
50
60
  const now = typeof o.now === 'function' ? o.now : Date.now
51
61
  const ttlMs = o.ttlMs != null ? o.ttlMs : PRESET_TTL_MS
52
62
  const projectTtlMs = o.projectTtlMs != null ? o.projectTtlMs : PROJECT_TTL_MS
63
+ // doneTtlMs 缺省跟随 projectTtlMs(显式传 projectTtlMs 的测试/调用方同时支配两态,
64
+ // 否则「传短 TTL 却不生效」会静默坑人);只有走生产默认值时才取更短的
65
+ // PROJECT_DONE_TTL_MS(已完成项目快速淡出)。
66
+ const doneTtlMs = o.doneTtlMs != null ? o.doneTtlMs
67
+ : (o.projectTtlMs != null ? projectTtlMs : PROJECT_DONE_TTL_MS)
53
68
  const staleMs = o.staleMs != null ? o.staleMs : MCP_BRIDGE_STALE_MS
54
69
  const ids = Array.isArray(o.ids) && o.ids.length ? o.ids.slice() : PROVIDER_IDS.slice()
55
70
  const listPresetSessions = typeof o.listPresetSessions === 'function' ? o.listPresetSessions : null
@@ -183,7 +198,11 @@ export function createIndicatorState(opts) {
183
198
  const isStale = (p) => {
184
199
  if (p.running > 0) return false
185
200
  const at = Number(p.updatedAt) || Number(p.lastAt) || 0
186
- return !!at && (t - at) > projectTtlMs
201
+ if (!at) return false
202
+ // 已收口(有终态)的项目走短 TTL → 完成后快速淡出;
203
+ // 仍无终态的(长时间运行中的间隔、或从未跑完)保持长 TTL 防抖。
204
+ const ttl = p.lastStatus ? doneTtlMs : projectTtlMs
205
+ return (t - at) > ttl
187
206
  }
188
207
  // 顶层聚合只看新鲜(未 stale)项目:陈旧历史不再决定灯色(0.2.1 修复「指示灯长期
189
208
  // 存在」的服务端半边 —— 客户端半边在 pill 过滤;无新鲜项目时顶层回落 idle)。
@@ -31,7 +31,7 @@ import * as mimoMcp from './providers/mimo.mjs'
31
31
  import * as opencodeMcp from './providers/opencode.mjs'
32
32
 
33
33
  const SERVER_NAME = 'cli-bridge-mcp'
34
- const SERVER_VERSION = '0.2.3'
34
+ const SERVER_VERSION = '0.2.4'
35
35
  const PROTOCOL = '2024-11-05'
36
36
 
37
37
  const PROVIDERS = [agyMcp, codebuddyMcp, mimoMcp, opencodeMcp]
@@ -18,8 +18,9 @@ import { fileURLToPath } from 'node:url'
18
18
 
19
19
  import defineProvider from '../../providers/agy.mjs'
20
20
  import { createStatusEngine, createLineStream, buildMcpBridgePayload, isLimited, renderStatus } from '../../core/bridge-kit.mjs'
21
+ import { packageVersion } from '../version.mjs'
21
22
 
22
- export const meta = { id: 'agy', label: 'AGY', version: '0.2.2' }
23
+ export const meta = { id: 'agy', label: 'AGY', version: packageVersion() }
23
24
 
24
25
  const QUOTA_SCRIPT_DEFAULT = fileURLToPath(new URL('../../bin/agy-quota.mjs', import.meta.url))
25
26
 
@@ -24,8 +24,9 @@ import { resolve as resolvePath, join as nodePathJoin } from 'node:path'
24
24
 
25
25
  import defineProvider from '../../providers/codebuddy.mjs'
26
26
  import { createStatusEngine, createLineStream, buildMcpBridgePayload, mcpBridgeFileName } from '../../core/bridge-kit.mjs'
27
+ import { packageVersion } from '../version.mjs'
27
28
 
28
- export const meta = { id: 'codebuddy', label: 'CODEBUDDY', version: '0.2.2' }
29
+ export const meta = { id: 'codebuddy', label: 'CODEBUDDY', version: packageVersion() }
29
30
 
30
31
  const provider = defineProvider({
31
32
  env: process.env,
@@ -26,8 +26,9 @@ import {
26
26
  createStatusEngine, createLineStream, buildMcpBridgePayload,
27
27
  fallbackResult, shortLabel, renderStatus
28
28
  } from '../../core/bridge-kit.mjs'
29
+ import { packageVersion } from '../version.mjs'
29
30
 
30
- export const meta = { id: 'mimo', label: 'MIMO', version: '0.2.2' }
31
+ export const meta = { id: 'mimo', label: 'MIMO', version: packageVersion() }
31
32
 
32
33
  const BACKEND_DESKTOP = 'mimo-desktop'
33
34
  const SETTINGS_FILE_NAME = 'cli-bridge-settings.json'
@@ -13,8 +13,9 @@ import { resolve as resolvePath } from 'node:path'
13
13
 
14
14
  import defineProvider, { resolveExePrefix } from '../../providers/opencode.mjs'
15
15
  import { createStatusEngine, createLineStream, buildMcpBridgePayload, isLimited, renderStatus } from '../../core/bridge-kit.mjs'
16
+ import { packageVersion } from '../version.mjs'
16
17
 
17
- export const meta = { id: 'opencode', label: 'OPENCODE', version: '0.2.2' }
18
+ export const meta = { id: 'opencode', label: 'OPENCODE', version: packageVersion() }
18
19
 
19
20
  const provider = defineProvider({
20
21
  env: process.env,
@@ -0,0 +1,26 @@
1
+ // mcp/version.mjs — MCP 工具面版本号单一来源。
2
+ //
3
+ // 历史问题:四个 provider 的 `meta.version` 与描述符的 `mcp.version` 各自硬编码
4
+ // 版本字面量(共 8 处),每次发布必须手工同步 —— 漏改一处就出现「统一 server 报
5
+ // 0.2.3、provider 面仍报 0.2.2」的自相矛盾输出(0.2.3 发布时即踩到)。
6
+ //
7
+ // 契约 §4 要求 provider version「独立跟随本包」—— 跟随 = 同源派生,不是各处抄写。
8
+ // 这里从包自身的 package.json 读一次,全包共用。失败时抛错而非静默回落:版本号
9
+ // 错误会误导排障,宁可大声失败(红线 7)。
10
+ import { readFileSync } from 'node:fs'
11
+ import { fileURLToPath } from 'node:url'
12
+
13
+ const pkgPath = fileURLToPath(new URL('../package.json', import.meta.url))
14
+ let cached = null
15
+
16
+ export function packageVersion() {
17
+ if (cached) return cached
18
+ let parsed
19
+ try { parsed = JSON.parse(readFileSync(pkgPath, 'utf8')) } catch (e) {
20
+ throw new Error('mcp/version: cannot read package.json (' + String(e && e.message || e) + ')')
21
+ }
22
+ const v = parsed && parsed.version
23
+ if (typeof v !== 'string' || !v) throw new Error('mcp/version: package.json has no version field')
24
+ cached = v
25
+ return v
26
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luchenglong/cli-bridge",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "CLI Bridge for DeepSeek Harness (DSH): one package bridging four local coding-CLI agents — agy (Google Antigravity CLI), Tencent CodeBuddy Code, Xiaomi MiMo (MiMoCode / MiMo Desktop), and OpenCode. Each provider keeps its own agent preset (cordis-agy / codebuddy-first / cordis-mimo / opencode-first), tools (agy_run / codebuddy_run / mimo_run / opencode_run + continue + status), rate-limit/network fallback dialog, and zero-dependency MCP server, unified under a single home-level status light, one settings file, and one bundle patch. Merges agy-first-bridge, codebuddy-first-bridge and mimo-first-bridge.",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
@@ -89,3 +89,4 @@
89
89
  "url": "https://github.com/new-256/cli-bridge/issues"
90
90
  }
91
91
  }
92
+