@twinsearth/dsh-master 3.2.10 → 3.3.1

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.
Files changed (104) hide show
  1. package/README.md +4 -0
  2. package/client.js +50 -0
  3. package/dist-host/contract/client.js +7 -0
  4. package/dist-host/contract/constants.js +16 -2
  5. package/dist-host/contract/index.js +1 -0
  6. package/dist-host/contract/relay.js +239 -0
  7. package/dist-host/cost/attribution.js +183 -0
  8. package/dist-host/cost/audit.js +163 -0
  9. package/dist-host/cost/budget.js +211 -0
  10. package/dist-host/cost/bus.js +95 -0
  11. package/dist-host/cost/cert-chain.js +100 -0
  12. package/dist-host/cost/experiment.js +132 -0
  13. package/dist-host/cost/fang-relay.js +329 -0
  14. package/dist-host/cost/gate.js +189 -0
  15. package/dist-host/cost/host-surface.js +80 -0
  16. package/dist-host/cost/index.js +345 -0
  17. package/dist-host/cost/ledger-report.js +193 -0
  18. package/dist-host/cost/ledger.js +401 -0
  19. package/dist-host/cost/metrics.js +198 -0
  20. package/dist-host/cost/milestones.js +209 -0
  21. package/dist-host/cost/modules/index.js +5 -0
  22. package/dist-host/cost/modules/manifests.js +130 -0
  23. package/dist-host/cost/policy.js +276 -0
  24. package/dist-host/cost/report.js +156 -0
  25. package/dist-host/cost/reuse-report.js +128 -0
  26. package/dist-host/cost/rsi.js +367 -0
  27. package/dist-host/cost/toolface.js +147 -0
  28. package/dist-host/cost/types.js +31 -0
  29. package/dist-host/kernel.js +28 -2
  30. package/dist-host/plugins/cost-optimizer.js +329 -27
  31. package/dist-host/plugins/superagent-router.js +104 -1
  32. package/dist-host/superagent/types.js +8 -0
  33. package/dist-worker/agent-loop.js +449 -7
  34. package/dist-worker/baseline-fit.js +66 -0
  35. package/dist-worker/budget-guard.js +93 -0
  36. package/dist-worker/ccs.js +99 -0
  37. package/dist-worker/cost-hooks.js +115 -0
  38. package/dist-worker/cost-modules.js +330 -0
  39. package/dist-worker/cost-spi.js +3 -0
  40. package/dist-worker/edg.js +372 -0
  41. package/dist-worker/gdr.js +159 -0
  42. package/dist-worker/index.js +80 -2
  43. package/dist-worker/llm-http.js +20 -0
  44. package/dist-worker/sink-http.js +1 -0
  45. package/dist-worker/spill.js +115 -0
  46. package/dist-worker/tool-batch.js +66 -0
  47. package/dist-worker/tool-compact.js +275 -0
  48. package/dist-worker/tool-disclosure.js +90 -0
  49. package/dist-worker/tools.js +16 -0
  50. package/docs/ARCHITECTURE.md +24 -0
  51. package/docs/CHANGELOG.md +66 -0
  52. package/docs/DESIGN-v3.3.0-cost-optimization.md +1058 -0
  53. package/docs/EXPERIMENT-M5-fang-relay.md +117 -0
  54. package/docs/EXPERIMENT-M5-real-ab.md +87 -0
  55. package/docs/THIRD-PARTY.md +87 -0
  56. package/package.json +2 -2
  57. package/src/contract/client.js +7 -0
  58. package/src/contract/constants.js +17 -2
  59. package/src/contract/index.js +1 -0
  60. package/src/contract/relay.js +223 -0
  61. package/src/cost/attribution.ts +186 -0
  62. package/src/cost/audit.ts +170 -0
  63. package/src/cost/budget.ts +226 -0
  64. package/src/cost/bus.ts +97 -0
  65. package/src/cost/cert-chain.ts +102 -0
  66. package/src/cost/experiment.ts +136 -0
  67. package/src/cost/fang-relay.ts +318 -0
  68. package/src/cost/gate.ts +191 -0
  69. package/src/cost/host-surface.ts +97 -0
  70. package/src/cost/index.ts +348 -0
  71. package/src/cost/ledger-report.ts +186 -0
  72. package/src/cost/ledger.ts +385 -0
  73. package/src/cost/metrics.ts +193 -0
  74. package/src/cost/milestones.ts +206 -0
  75. package/src/cost/modules/index.ts +13 -0
  76. package/src/cost/modules/manifests.ts +129 -0
  77. package/src/cost/policy.ts +276 -0
  78. package/src/cost/report.ts +158 -0
  79. package/src/cost/reuse-report.ts +131 -0
  80. package/src/cost/rsi.ts +364 -0
  81. package/src/cost/toolface.ts +151 -0
  82. package/src/cost/types.ts +298 -0
  83. package/src/kernel.ts +27 -2
  84. package/src/plugins/cost-optimizer.ts +313 -26
  85. package/src/plugins/superagent-router.ts +96 -1
  86. package/src/superagent/types.ts +70 -0
  87. package/worker/agent-loop.ts +444 -7
  88. package/worker/baseline-fit.ts +80 -0
  89. package/worker/budget-guard.ts +156 -0
  90. package/worker/ccs.ts +202 -0
  91. package/worker/cost-hooks.ts +133 -0
  92. package/worker/cost-modules.ts +356 -0
  93. package/worker/cost-spi.ts +283 -0
  94. package/worker/edg.ts +424 -0
  95. package/worker/gdr.ts +233 -0
  96. package/worker/index.ts +84 -3
  97. package/worker/llm-http.ts +18 -0
  98. package/worker/sink-http.ts +5 -2
  99. package/worker/spill.ts +133 -0
  100. package/worker/tool-batch.ts +124 -0
  101. package/worker/tool-compact.ts +317 -0
  102. package/worker/tool-disclosure.ts +131 -0
  103. package/worker/tools.ts +553 -531
  104. package/worker/types.ts +191 -0
@@ -0,0 +1,298 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ // Copyright (c) 2026 dsh-Master contributors — see LICENSE-CORE.
3
+
4
+ /**
5
+ * 3.3.0 成本优化系统层的共享类型(M1)。
6
+ *
7
+ * 只放类型与常量,不含运行时逻辑;host 侧 `src/cost/*` 与插件编排器共用。
8
+ * 对齐 `docs/DESIGN-v3.3.0-cost-optimization.md` §5(系统层)与 §9(安全不变量)。
9
+ */
10
+
11
+ /** 两本账:执行节省 vs 治理成本(HarnessMM 论文要求分开核算)。 */
12
+ export type CostAccount = 'execution' | 'governance'
13
+
14
+ /** 归因模块 id;a* = 工具面(dsh-ops 方向),b* = 决策复用(HarnessMM 方向)。 */
15
+ export type CostModuleId =
16
+ | 'a1-compact'
17
+ | 'a2-disclosure'
18
+ | 'a3-batch'
19
+ | 'b1-edg'
20
+ | 'b2-gdr'
21
+ | 'b3-ccs'
22
+ | 'b4-rsi'
23
+ | 'unattributed'
24
+
25
+ export type CostSource = 'model' | 'tool' | 'substitution' | 'retry' | 'authoring' | 'offline'
26
+
27
+ /** 事件相位(设计 §5.1):prompt / completion / tool / authoring / substitution。 */
28
+ export type CostPhase = 'prompt' | 'completion' | 'tool' | 'authoring' | 'substitution'
29
+
30
+ export const COST_PHASES: readonly CostPhase[] = Object.freeze(['prompt', 'completion', 'tool', 'authoring', 'substitution'])
31
+
32
+ /**
33
+ * 作用面(设计 §3.3):宿主会话工具面与 master Worker 工具面是**两个不同面板**,
34
+ * 节省必须分开记账,否则会把「装了别人的宿主插件」算成自己的收益。
35
+ * * `worker` —— 本项目 Worker 自带工具面(`worker/tools.ts`),A1–A3 在这里生效;
36
+ * * `host` —— 宿主会话工具面(dsh-ops 一类宿主插件生效的地方),本项目只做
37
+ * **可选适配器 + 归因**,不重写、不冒领。
38
+ */
39
+ export type CostSurface = 'worker' | 'host'
40
+
41
+ export interface CostTokens {
42
+ input: number
43
+ output: number
44
+ total: number
45
+ }
46
+
47
+ export interface CostEntryInput {
48
+ account: CostAccount
49
+ module?: CostModuleId
50
+ source?: CostSource
51
+ /** 相位;缺省由 source 推导(见 ledger.ts PHASE_OF_SOURCE)。 */
52
+ phase?: CostPhase
53
+ /** 作用面;缺省为 worker(本项目的自研模块都在这面)。 */
54
+ surface?: CostSurface
55
+ /** 外部适配器上报(如 dsh-ops 在宿主面的收益):只展示,永不计入本项目 executionSaved。 */
56
+ external?: boolean
57
+ taskId?: string
58
+ forkId?: string
59
+ sessionId?: string
60
+ /** 会话内轮次与循环步号(可回放定位)。 */
61
+ turn?: number
62
+ step?: number
63
+ provider?: string
64
+ model?: string
65
+ toolName?: string
66
+ ticketId?: string
67
+ inputTokens?: number
68
+ outputTokens?: number
69
+ cachedTokens?: number
70
+ totalTokens?: number
71
+ /** 对照组(observe)同任务基线;给出时才计算 saved。 */
72
+ baselineTokens?: number
73
+ /** 显式节省归因;给出时优先于 baseline 推导。 */
74
+ savedTokens?: number
75
+ /** provider 未返回 usage 时的兜底估算:报表与实测分开列,不混算。 */
76
+ estimated?: boolean
77
+ meta?: Record<string, unknown>
78
+ }
79
+
80
+ export interface CostEntry extends CostTokens {
81
+ id: string
82
+ at: number
83
+ account: CostAccount
84
+ module: CostModuleId
85
+ source: CostSource
86
+ phase: CostPhase
87
+ surface: CostSurface
88
+ external: boolean
89
+ taskId: string | null
90
+ forkId: string | null
91
+ sessionId: string | null
92
+ turn: number
93
+ step: number
94
+ provider: string | null
95
+ model: string | null
96
+ toolName: string | null
97
+ ticketId: string | null
98
+ cached: number
99
+ baselineTokens: number | null
100
+ savedTokens: number
101
+ estimated: boolean
102
+ meta: Record<string, unknown>
103
+ }
104
+
105
+ export interface CostBlock {
106
+ input: number
107
+ output: number
108
+ total: number
109
+ saved: number
110
+ entries: number
111
+ }
112
+
113
+ export interface CostSurfaceRow extends CostBlock {
114
+ surface: CostSurface
115
+ external: boolean
116
+ }
117
+
118
+ export interface CostTaskRow extends CostBlock {
119
+ key: string
120
+ }
121
+
122
+ export interface CostModuleRow extends CostBlock {
123
+ module: CostModuleId
124
+ }
125
+
126
+ export interface CostForkRow extends CostBlock {
127
+ forkId: string
128
+ }
129
+
130
+ /** 估算与实测必须分开列(设计 §5.1):总量各自累计,绝不相加。 */
131
+ export interface CostEstimateSplit {
132
+ measuredTokens: number
133
+ measuredEntries: number
134
+ estimatedTokens: number
135
+ estimatedEntries: number
136
+ /** 估算值占全部 token 的比例(0..1),用于报表标注可信度。 */
137
+ estimatedRatio: number
138
+ }
139
+
140
+ export interface CostLedgerSnapshot {
141
+ ok: true
142
+ count: number
143
+ dropped: number
144
+ execution: CostBlock
145
+ governance: CostBlock
146
+ netSaved: number
147
+ ownExecutionSaved: number
148
+ externalSaved: number
149
+ /** 按作用面拆分:本项目(worker)与外部适配器(host)永不相加。 */
150
+ bySurface: CostSurfaceRow[]
151
+ byModule: CostModuleRow[]
152
+ byTask: CostTaskRow[]
153
+ byFork: CostForkRow[]
154
+ /** 实测 vs 估算(不混算)。 */
155
+ tokens: CostEstimateSplit
156
+ persistence: { enabled: boolean; file: string | null; appended: number; failed: number }
157
+ }
158
+
159
+ export interface CostQuery {
160
+ taskId?: string
161
+ forkId?: string
162
+ sessionId?: string
163
+ ticketId?: string
164
+ module?: string
165
+ account?: CostAccount
166
+ phase?: CostPhase
167
+ surface?: CostSurface
168
+ external?: boolean
169
+ estimated?: boolean
170
+ /** 时间窗(含边界)。 */
171
+ from?: number
172
+ to?: number
173
+ limit?: number
174
+ }
175
+
176
+ export type BudgetUnit = 'task' | 'fork' | 'day'
177
+ export type BudgetExhaustAction = 'hard-stop' | 'degrade'
178
+
179
+ export interface BudgetRule {
180
+ unit: BudgetUnit
181
+ /** token 上限(> 0)。与 limitCost 至少给一个,否则规则无效(fail-closed)。 */
182
+ limitTokens?: number
183
+ /** 成本上限(同一货币单位;需要调用方在 authorize 时给 cost 才可判定)。 */
184
+ limitCost?: number
185
+ /** 超限策略;默认 hard-stop。 */
186
+ onExhaust?: BudgetExhaustAction
187
+ /** degrade 档目标模型;必须在 degradeModels 白名单内,否则自动退化为 hard-stop。 */
188
+ degradeTo?: string
189
+ }
190
+
191
+ /** @deprecated 使用 BudgetRule(保留别名以兼容早期调用)。 */
192
+ export type BudgetLimit = BudgetRule
193
+
194
+ export interface BudgetStateRow {
195
+ unit: BudgetUnit
196
+ key: string
197
+ consumedTokens: number
198
+ consumedCost: number
199
+ limitTokens: number | null
200
+ limitCost: number | null
201
+ remainingTokens: number | null
202
+ remainingCost: number | null
203
+ onExhaust: BudgetExhaustAction
204
+ }
205
+
206
+ export type PolicyMode = 'observe' | 'shadow' | 'enforce'
207
+
208
+ export interface EnforceEvidence {
209
+ /** shadow 期守卫准确率(0..1)。 */
210
+ accuracy?: number
211
+ /** shadow 期样本数。 */
212
+ samples?: number
213
+ /** shadow 期破坏性工具命中次数(必须为 0)。 */
214
+ destructiveHits?: number
215
+ }
216
+
217
+ export interface PolicyDescription {
218
+ mode: PolicyMode
219
+ requestedMode: PolicyMode
220
+ allowlist: string[]
221
+ gate: { minAccuracy: number; minSamples: number; allowlistRequired: true }
222
+ lastRefusal: { at: number; next: PolicyMode; reasons: string[] } | null
223
+ }
224
+
225
+ export interface AuditRecord {
226
+ seq: number
227
+ at: number
228
+ type: string
229
+ actor: string
230
+ payload: Record<string, unknown>
231
+ prevHash: string
232
+ hash: string
233
+ }
234
+
235
+ /**
236
+ * 替换证书(设计 §5.5):每一次「用已解决决策替换慢模型回调」都必须留下这张凭证。
237
+ * 与 ledger 事件用同一 `taskId + step` 关联,因此可回放「这一省是怎么来的」。
238
+ */
239
+ export interface SubstitutionCert {
240
+ /** 可执行决策图(B1)中的边标识。 */
241
+ edgeId: string
242
+ /** 被替换回调原本要调用的工具。 */
243
+ toolName: string
244
+ /** 工具 schema 的哈希:schema 变了,旧决策不得复用。 */
245
+ schemaHash: string
246
+ /** 守卫表达式(B2 判据),保留原文以便复核。 */
247
+ guardExpr: string
248
+ /** 命中时工具回执的摘要(B2 依据它判断守卫)。 */
249
+ receiptDigest: string
250
+ /** 被替换掉的模型回调标识(慢模型那一次)。 */
251
+ replacedCallbackId: string
252
+ /** 必须经 DSH 原生派发器执行:恒为 true(false 一律拒绝)。 */
253
+ viaNativeDispatcher: true
254
+ /** 关联键(与 ledger 事件一致)。 */
255
+ taskId: string
256
+ step: number
257
+ /** 本次替换的归因节省(token)。 */
258
+ savedTokens?: number
259
+ moduleId?: string
260
+ forkId?: string
261
+ sessionId?: string
262
+ ticketId?: string
263
+ at?: number
264
+ }
265
+
266
+ export const COST_MODULES: readonly CostModuleId[] = Object.freeze([
267
+ 'a1-compact',
268
+ 'a2-disclosure',
269
+ 'a3-batch',
270
+ 'b1-edg',
271
+ 'b2-gdr',
272
+ 'b3-ccs',
273
+ 'b4-rsi',
274
+ 'unattributed',
275
+ ])
276
+
277
+ export const COST_SOURCES: readonly CostSource[] = Object.freeze([
278
+ 'model',
279
+ 'tool',
280
+ 'substitution',
281
+ 'retry',
282
+ 'authoring',
283
+ 'offline',
284
+ ])
285
+
286
+ export const POLICY_MODES: readonly PolicyMode[] = Object.freeze(['observe', 'shadow', 'enforce'])
287
+
288
+ /** 两个作用面(设计 §3.3):不可合并统计。 */
289
+ export const COST_SURFACES: readonly CostSurface[] = Object.freeze(['worker', 'host'])
290
+
291
+ /** 默认预算:与 Worker 现有 maxTokens 对齐(task=50k),fork=500k。 */
292
+ export const DEFAULT_BUDGET_LIMITS: readonly BudgetLimit[] = Object.freeze([
293
+ Object.freeze({ unit: 'task' as BudgetUnit, limitTokens: 50_000, onExhaust: 'hard-stop' as BudgetExhaustAction }),
294
+ Object.freeze({ unit: 'fork' as BudgetUnit, limitTokens: 500_000, onExhaust: 'hard-stop' as BudgetExhaustAction }),
295
+ ])
296
+
297
+ /** enforce 门禁(设计 §13):准确率 ≥0.98、样本 ≥20、零破坏性命中、非空白名单。 */
298
+ export const ENFORCE_GATE = Object.freeze({ minAccuracy: 0.98, minSamples: 20 })
package/src/kernel.ts CHANGED
@@ -10,7 +10,7 @@
10
10
 
11
11
  import crypto from 'node:crypto'
12
12
 
13
- export const MASTER_VERSION = '3.2.10'
13
+ export const MASTER_VERSION = '3.3.1'
14
14
  export const FANG_CONTRACT_MIN = '3.1.14'
15
15
 
16
16
  export const SERVICE = Object.freeze({
@@ -21,6 +21,31 @@ export const SERVICE = Object.freeze({
21
21
  dual: 'dshMasterDual',
22
22
  })
23
23
 
24
+ /**
25
+ * 3.3.0 §11:成本系统的**可选子服务**。
26
+ *
27
+ * 主服务 `SERVICE.cost` 的形态不变(向后兼容);子服务由 cost-optimizer 在能力允许时
28
+ * 额外 `provide`,消费方必须用 `probeOptionalServices(ctx)` **探测**而不是假定存在 ——
29
+ * 缺了就是缺了,不能假装拿到空壳对象。
30
+ */
31
+ export const OPTIONAL_SERVICE = Object.freeze({
32
+ costLedger: 'dshMasterCostLedger',
33
+ costBudget: 'dshMasterCostBudget',
34
+ costPolicy: 'dshMasterCostPolicy',
35
+ costAudit: 'dshMasterCostAudit',
36
+ })
37
+
38
+ /** 探测可选子服务是否就位(只读、无副作用)。 */
39
+ export function probeOptionalServices(ctx) {
40
+ const present = {}
41
+ for (const [key, name] of Object.entries(OPTIONAL_SERVICE)) {
42
+ try {
43
+ present[key] = typeof ctx?.get === 'function' ? Boolean(ctx.get(name)) : false
44
+ } catch { present[key] = false }
45
+ }
46
+ return present
47
+ }
48
+
24
49
  export const FANG_SERVICE = Object.freeze({
25
50
  orchestrator: 'fang',
26
51
  forker: 'fangForker',
@@ -41,7 +66,7 @@ export const ROW = Object.freeze({
41
66
  export const ROLE = Object.freeze({ mother: 'mother', essence: 'essence', fork: 'fork' })
42
67
 
43
68
  /**
44
- * 角色矩阵(3.2.10):
69
+ * 角色矩阵:
45
70
  * * Router 在 essence 与 mother 激活:只评估/建票/派发,不执行代码;fork 不注册。
46
71
  * * Worker / Worker Agent Loop 在 fork 与 essence 激活:原身可直接执行工单,
47
72
  * 分身仍是默认执行体;mother 不执行。