@twinsearth/dsh-master 3.3.5 → 3.3.6
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/client.js +1 -1
- package/dist-host/engine/health-probe.js +7 -3
- package/dist-host/kernel.js +1 -1
- package/dist-host/plugins/cost-optimizer.js +3 -3
- package/docs/CHANGELOG.md +7 -2
- package/package.json +1 -1
- package/src/engine/health-probe.ts +6 -2
- package/src/kernel.ts +1 -1
- package/src/plugins/cost-optimizer.ts +3 -3
package/client.js
CHANGED
|
@@ -397,7 +397,7 @@ window.__ModuleLoader__.load({
|
|
|
397
397
|
return h('div', { style: S.card, 'data-dsh-master': 'cost-block' },
|
|
398
398
|
h('div', { style: S.row },
|
|
399
399
|
h('span', { style: S.name }, '成本(只读)'),
|
|
400
|
-
tag(block ? '3.3.
|
|
400
|
+
tag(block ? '3.3.6' : '未启用', block ? undefined : '#B45309')),
|
|
401
401
|
failed ? h('div', { style: S.error }, '成本接口不可达') : null,
|
|
402
402
|
!block && !failed ? h('div', { style: S.desc }, '成本系统未装配(cost-optimizer 未启用或角色不匹配)') : null,
|
|
403
403
|
columns ? h('div', { style: S.desc },
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
const DEFAULT_INTERVAL_MS = 1_000;
|
|
13
13
|
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
14
14
|
const DEFAULT_MAX_ATTEMPTS = 30;
|
|
15
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 5_000;
|
|
15
16
|
function positiveInt(value, fallback) {
|
|
16
17
|
const n = Number(value);
|
|
17
18
|
return Number.isFinite(n) && n > 0 ? Math.floor(n) : fallback;
|
|
@@ -43,6 +44,8 @@ export async function probeHealth(input = {}) {
|
|
|
43
44
|
: (status) => status >= 200 && status < 300;
|
|
44
45
|
const startedAt = now();
|
|
45
46
|
const deadline = startedAt + timeoutMs;
|
|
47
|
+
// 单次请求超时必须与轮询间隔分开:拿 intervalMs 当请求超时会把「慢但有响应」误判成 probe-failed
|
|
48
|
+
const requestTimeoutMs = positiveInt(input.requestTimeoutMs, DEFAULT_REQUEST_TIMEOUT_MS);
|
|
46
49
|
let attempts = 0;
|
|
47
50
|
let lastStatus = null;
|
|
48
51
|
let lastError = null;
|
|
@@ -52,7 +55,7 @@ export async function probeHealth(input = {}) {
|
|
|
52
55
|
attempts += 1;
|
|
53
56
|
try {
|
|
54
57
|
const controller = typeof AbortController === 'function' ? new AbortController() : null;
|
|
55
|
-
const timer = controller ? setTimeout(() => controller.abort(), Math.max(1, Math.min(
|
|
58
|
+
const timer = controller ? setTimeout(() => controller.abort(), Math.max(1, Math.min(requestTimeoutMs, 30_000))) : null;
|
|
56
59
|
if (timer && typeof timer.unref === 'function')
|
|
57
60
|
timer.unref();
|
|
58
61
|
let response = null;
|
|
@@ -78,9 +81,10 @@ export async function probeHealth(input = {}) {
|
|
|
78
81
|
await wait(intervalMs);
|
|
79
82
|
}
|
|
80
83
|
const elapsedMs = Math.max(0, now() - startedAt);
|
|
81
|
-
|
|
82
|
-
return { ok: false, code: 'probe-failed', error: lastError, status: lastStatus, attempts, elapsedMs, url };
|
|
84
|
+
// 只要拿到过响应,就以状态码为准——不能因为某次连接失败把「服务返回 503」改写成 probe-failed
|
|
83
85
|
if (lastStatus !== null)
|
|
84
86
|
return { ok: false, code: 'unhealthy-status', status: lastStatus, attempts, elapsedMs, url };
|
|
87
|
+
if (lastError)
|
|
88
|
+
return { ok: false, code: 'probe-failed', error: lastError, status: lastStatus, attempts, elapsedMs, url };
|
|
85
89
|
return { ok: false, code: 'probe-timeout', attempts, elapsedMs, url };
|
|
86
90
|
}
|
package/dist-host/kernel.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* 与瓮城 dsh-Fang 的协作只走 DSH 服务键,不 import fang 代码。
|
|
8
8
|
*/
|
|
9
9
|
import crypto from 'node:crypto';
|
|
10
|
-
export const MASTER_VERSION = '3.3.
|
|
10
|
+
export const MASTER_VERSION = '3.3.6';
|
|
11
11
|
export const FANG_CONTRACT_MIN = '3.1.14';
|
|
12
12
|
export const SERVICE = Object.freeze({
|
|
13
13
|
master: 'dshMaster',
|
|
@@ -108,7 +108,7 @@ export function apply(ctx, config = {}) {
|
|
|
108
108
|
};
|
|
109
109
|
const service = {
|
|
110
110
|
id: SERVICE.cost,
|
|
111
|
-
version: '3.3.
|
|
111
|
+
version: '3.3.6',
|
|
112
112
|
role,
|
|
113
113
|
get mode() {
|
|
114
114
|
return system.policy.describe().mode;
|
|
@@ -354,7 +354,7 @@ export function apply(ctx, config = {}) {
|
|
|
354
354
|
return {
|
|
355
355
|
ok: true,
|
|
356
356
|
id: 'cost-optimizer',
|
|
357
|
-
version: '3.3.
|
|
357
|
+
version: '3.3.6',
|
|
358
358
|
role,
|
|
359
359
|
mode: current.mode,
|
|
360
360
|
requestedMode: current.requestedMode,
|
|
@@ -396,7 +396,7 @@ export function apply(ctx, config = {}) {
|
|
|
396
396
|
doubleCountGuard: report.doubleCountGuard,
|
|
397
397
|
};
|
|
398
398
|
})(),
|
|
399
|
-
note: '3.3.
|
|
399
|
+
note: '3.3.6:系统层记账/预算/灰度/审计 + A1 工具输出紧凑化(默认 shadow)+ 瓮城回流出口(contract 1.1.1 真实投递,回执计数修复);工具面 A2–A3 与决策复用 B1–B4 已接入(shadow 默认);3.3.3 起角色矩阵母体全开、分身挂双主管;3.3.4 起内置 PM/PJM 两个智能体 preset;3.3.5 起补齐引擎原语、可中断 LLM 流、WS 通道与流式管线。',
|
|
400
400
|
};
|
|
401
401
|
},
|
|
402
402
|
};
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
## 3.3.
|
|
1
|
+
## 3.3.6(2026-11-14 已发布)
|
|
2
2
|
|
|
3
|
-
> 三方发布:annotated tag `v3.3.
|
|
3
|
+
> 三方发布:annotated tag `v3.3.6` + GitHub Release + npm `@twinsearth/dsh-master@3.3.6`。
|
|
4
|
+
> **为什么有 3.3.6**:3.3.5 的 tag 与 GitHub Release 已建,但 npm 侧发布返回
|
|
5
|
+
> `E409 VERSION_EXISTS`(该版本号被 registry 占位,`npm view` 却 404),导致 3.3.5 无法从 npm 交付。
|
|
6
|
+
> 3.3.6 与 3.3.5 的代码内容一致,是**npm 可达的交付版本**;3.3.5 的 GitHub Release 已加注说明。
|
|
4
7
|
> 接口包无变化(仍 `@twinsearth/dsh-fang-contract@1.1.1`)。
|
|
5
8
|
|
|
6
9
|
**主题:宿主侧引擎原语 + PM/PJM 闭环 + 面板/通道/流式管线。**
|
|
7
10
|
|
|
11
|
+
## 3.3.5(GitHub-only · npm 发布被 E409 阻塞)
|
|
12
|
+
|
|
8
13
|
- **闭环第一步 · PM 交接**:`pm_handoff_to_pjm` 生成交接包;**验收标准为空、或仍有未决问题/冲突时不给 `ready`**(`needs-clarification` + 具名原因),PJM 不允许接单。
|
|
9
14
|
- **闭环第二步 · PJM 接单与自反馈**:`pjm_take_handoff` / `pjm_create_plan({handoffId})` 接单(重复接单被拒);`pjm_report` 支持执行中随时汇报(`blocked` 必须写 blocker);全部步骤完成后 `pjm_submit_feedback` 提交交付/偏差/遗留/测试与实测用时。
|
|
10
15
|
- **闭环第三步 · PM 复核/复盘/总结**:`pm_review_feedback` 逐条验收(`met` 必须是布尔 + 证据),写 `kept/improve/lessons` 复盘与总结;**结论必须与验收一致**(有未达标却判 accepted、或全达标却判 changes-requested,都直接拒收);`accepted` 把计划标记为 `pmReview.accepted`,`changes-requested` 保持闭环打开。
|
package/package.json
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
const DEFAULT_INTERVAL_MS = 1_000
|
|
15
15
|
const DEFAULT_TIMEOUT_MS = 30_000
|
|
16
16
|
const DEFAULT_MAX_ATTEMPTS = 30
|
|
17
|
+
const DEFAULT_REQUEST_TIMEOUT_MS = 5_000
|
|
17
18
|
|
|
18
19
|
function positiveInt(value, fallback) {
|
|
19
20
|
const n = Number(value)
|
|
@@ -48,6 +49,8 @@ export async function probeHealth(input = {}) {
|
|
|
48
49
|
|
|
49
50
|
const startedAt = now()
|
|
50
51
|
const deadline = startedAt + timeoutMs
|
|
52
|
+
// 单次请求超时必须与轮询间隔分开:拿 intervalMs 当请求超时会把「慢但有响应」误判成 probe-failed
|
|
53
|
+
const requestTimeoutMs = positiveInt(input.requestTimeoutMs, DEFAULT_REQUEST_TIMEOUT_MS)
|
|
51
54
|
let attempts = 0
|
|
52
55
|
let lastStatus = null
|
|
53
56
|
let lastError = null
|
|
@@ -57,7 +60,7 @@ export async function probeHealth(input = {}) {
|
|
|
57
60
|
attempts += 1
|
|
58
61
|
try {
|
|
59
62
|
const controller = typeof AbortController === 'function' ? new AbortController() : null
|
|
60
|
-
const timer = controller ? setTimeout(() => controller.abort(), Math.max(1, Math.min(
|
|
63
|
+
const timer = controller ? setTimeout(() => controller.abort(), Math.max(1, Math.min(requestTimeoutMs, 30_000))) : null
|
|
61
64
|
if (timer && typeof timer.unref === 'function') timer.unref()
|
|
62
65
|
let response = null
|
|
63
66
|
try {
|
|
@@ -78,7 +81,8 @@ export async function probeHealth(input = {}) {
|
|
|
78
81
|
}
|
|
79
82
|
|
|
80
83
|
const elapsedMs = Math.max(0, now() - startedAt)
|
|
81
|
-
|
|
84
|
+
// 只要拿到过响应,就以状态码为准——不能因为某次连接失败把「服务返回 503」改写成 probe-failed
|
|
82
85
|
if (lastStatus !== null) return { ok: false, code: 'unhealthy-status', status: lastStatus, attempts, elapsedMs, url }
|
|
86
|
+
if (lastError) return { ok: false, code: 'probe-failed', error: lastError, status: lastStatus, attempts, elapsedMs, url }
|
|
83
87
|
return { ok: false, code: 'probe-timeout', attempts, elapsedMs, url }
|
|
84
88
|
}
|
package/src/kernel.ts
CHANGED
|
@@ -117,7 +117,7 @@ export function apply(ctx, config = {}) {
|
|
|
117
117
|
|
|
118
118
|
const service = {
|
|
119
119
|
id: SERVICE.cost,
|
|
120
|
-
version: '3.3.
|
|
120
|
+
version: '3.3.6',
|
|
121
121
|
role,
|
|
122
122
|
get mode() {
|
|
123
123
|
return system.policy.describe().mode
|
|
@@ -354,7 +354,7 @@ export function apply(ctx, config = {}) {
|
|
|
354
354
|
return {
|
|
355
355
|
ok: true,
|
|
356
356
|
id: 'cost-optimizer',
|
|
357
|
-
version: '3.3.
|
|
357
|
+
version: '3.3.6',
|
|
358
358
|
role,
|
|
359
359
|
mode: current.mode,
|
|
360
360
|
requestedMode: current.requestedMode,
|
|
@@ -396,7 +396,7 @@ export function apply(ctx, config = {}) {
|
|
|
396
396
|
doubleCountGuard: report.doubleCountGuard,
|
|
397
397
|
}
|
|
398
398
|
})(),
|
|
399
|
-
note: '3.3.
|
|
399
|
+
note: '3.3.6:系统层记账/预算/灰度/审计 + A1 工具输出紧凑化(默认 shadow)+ 瓮城回流出口(contract 1.1.1 真实投递,回执计数修复);工具面 A2–A3 与决策复用 B1–B4 已接入(shadow 默认);3.3.3 起角色矩阵母体全开、分身挂双主管;3.3.4 起内置 PM/PJM 两个智能体 preset;3.3.5 起补齐引擎原语、可中断 LLM 流、WS 通道与流式管线。',
|
|
400
400
|
}
|
|
401
401
|
},
|
|
402
402
|
}
|