@master0071/dsh-systemone 0.4.3 → 0.4.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/lib/auto.js +52 -5
- package/lib/index.d.ts +3 -0
- package/lib/provider.js +5 -1
- package/lib/tools.js +6 -3
- package/lib/volatile.js +4 -2
- package/package.json +1 -1
package/lib/auto.js
CHANGED
|
@@ -64,6 +64,8 @@ export function installAutoDecide(ctx, deps) {
|
|
|
64
64
|
if (!readBoolean(config, 'autoDecide', false)) return () => {}
|
|
65
65
|
|
|
66
66
|
const disposers = []
|
|
67
|
+
/** agentId → 该 agent 的 per-agent 清理函数;agent 销毁时一并调用并从表中移除,避免无界增长。 */
|
|
68
|
+
const agentDisposers = new Map()
|
|
67
69
|
/** agentId → { stateKey, text, scenarioId, source, headline, at }:供 context 通道渲染。 */
|
|
68
70
|
const perAgent = new Map()
|
|
69
71
|
/** agentId → 上次注入的决策文本:同一决策只注入一次,避免每步重复污染历史。 */
|
|
@@ -84,12 +86,23 @@ export function installAutoDecide(ctx, deps) {
|
|
|
84
86
|
}
|
|
85
87
|
}
|
|
86
88
|
|
|
87
|
-
// agent
|
|
89
|
+
// agent 销毁时清理状态与 per-agent 监听器,避免长会话内存泄漏
|
|
88
90
|
disposers.push(ctx.on('agent/disposed', (payload) => {
|
|
89
91
|
const id = payload?.agent?.id
|
|
90
92
|
if (id !== undefined) {
|
|
91
93
|
perAgent.delete(id)
|
|
92
94
|
lastInjected.delete(id)
|
|
95
|
+
const list = agentDisposers.get(id)
|
|
96
|
+
if (list) {
|
|
97
|
+
for (const dispose of list) {
|
|
98
|
+
try {
|
|
99
|
+
dispose()
|
|
100
|
+
} catch {
|
|
101
|
+
// 卸载竞态
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
agentDisposers.delete(id)
|
|
105
|
+
}
|
|
93
106
|
}
|
|
94
107
|
}))
|
|
95
108
|
|
|
@@ -101,10 +114,13 @@ export function installAutoDecide(ctx, deps) {
|
|
|
101
114
|
const agent = payload?.agent
|
|
102
115
|
const agentCtx = agent?.ctx
|
|
103
116
|
if (!agentCtx) return
|
|
117
|
+
const agentId = agent?.id
|
|
118
|
+
// 该 agent 的监听器与动态上下文注册统一记到这里,随 agent 销毁一起移除
|
|
119
|
+
const perAgentDisposers = []
|
|
104
120
|
// ① 消息一入箱就异步预计算,让决策尽可能在 assembly 之前就绪
|
|
105
121
|
if (typeof agentCtx.on === 'function') {
|
|
106
122
|
try {
|
|
107
|
-
|
|
123
|
+
const dispose = agentCtx.on('agent/inbox/inserted', (event) => {
|
|
108
124
|
if (readString(config, 'autoInject', 'message') !== 'context') return
|
|
109
125
|
const newText = extractUserText([event?.message])
|
|
110
126
|
if (!newText) return
|
|
@@ -112,7 +128,8 @@ export function installAutoDecide(ctx, deps) {
|
|
|
112
128
|
if (isTrivialInput(newText, readNumber(config, 'autoMinChars', AUTO_DEFAULTS.autoMinChars))) return
|
|
113
129
|
// 返回 promise 便于测试等待;宿主事件总线忽略返回值
|
|
114
130
|
return computeAndStore(agent, newText)
|
|
115
|
-
})
|
|
131
|
+
})
|
|
132
|
+
if (typeof dispose === 'function') perAgentDisposers.push(dispose)
|
|
116
133
|
} catch (error) {
|
|
117
134
|
log('warn', `注册入箱预计算失败:${messageOf(error)}`)
|
|
118
135
|
}
|
|
@@ -120,17 +137,36 @@ export function installAutoDecide(ctx, deps) {
|
|
|
120
137
|
// ② 把最新决策渲染进作用域动态上下文
|
|
121
138
|
if (agentCtx?.systemPrompt?.context) {
|
|
122
139
|
try {
|
|
123
|
-
|
|
140
|
+
const dispose = agentCtx.systemPrompt.context({
|
|
124
141
|
name: 'systemone-auto-decision',
|
|
125
142
|
order: 900,
|
|
126
143
|
text: () => (readString(config, 'autoInject', 'message') === 'context')
|
|
127
144
|
? (perAgent.get(agent?.id)?.text || '')
|
|
128
145
|
: '',
|
|
129
|
-
})
|
|
146
|
+
})
|
|
147
|
+
if (typeof dispose === 'function') perAgentDisposers.push(dispose)
|
|
130
148
|
} catch (error) {
|
|
131
149
|
log('warn', `注册动态上下文失败:${messageOf(error)}`)
|
|
132
150
|
}
|
|
133
151
|
}
|
|
152
|
+
// 记入 per-agent 表:agent 销毁时移除;同一 agent 重复创建时先清理旧条目。
|
|
153
|
+
// agentId 缺失时退回插件级 disposers,随插件卸载统一清理。
|
|
154
|
+
if (perAgentDisposers.length === 0) return
|
|
155
|
+
if (agentId === undefined) {
|
|
156
|
+
disposers.push(...perAgentDisposers)
|
|
157
|
+
return
|
|
158
|
+
}
|
|
159
|
+
const existing = agentDisposers.get(agentId)
|
|
160
|
+
if (existing) {
|
|
161
|
+
for (const dispose of existing) {
|
|
162
|
+
try {
|
|
163
|
+
dispose()
|
|
164
|
+
} catch {
|
|
165
|
+
// 重复创建竞态
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
agentDisposers.set(agentId, perAgentDisposers)
|
|
134
170
|
}))
|
|
135
171
|
|
|
136
172
|
// ── pre-step:同一步生效(仅 message 通道) ──
|
|
@@ -243,6 +279,17 @@ export function installAutoDecide(ctx, deps) {
|
|
|
243
279
|
// 卸载竞态
|
|
244
280
|
}
|
|
245
281
|
}
|
|
282
|
+
// 兜底:即使宿主未触发 agent/disposed,也清掉所有 per-agent 监听器
|
|
283
|
+
for (const list of agentDisposers.values()) {
|
|
284
|
+
for (const dispose of list) {
|
|
285
|
+
try {
|
|
286
|
+
dispose()
|
|
287
|
+
} catch {
|
|
288
|
+
// 卸载竞态
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
agentDisposers.clear()
|
|
246
293
|
perAgent.clear()
|
|
247
294
|
lastInjected.clear()
|
|
248
295
|
cache.clear()
|
package/lib/index.d.ts
CHANGED
package/lib/provider.js
CHANGED
|
@@ -84,7 +84,11 @@ export class HttpProvider {
|
|
|
84
84
|
timer.unref?.()
|
|
85
85
|
const onOuterAbort = () => controller.abort()
|
|
86
86
|
if (signal && typeof signal.addEventListener === 'function') {
|
|
87
|
-
signal.
|
|
87
|
+
if (signal.aborted) {
|
|
88
|
+
controller.abort()
|
|
89
|
+
} else {
|
|
90
|
+
signal.addEventListener('abort', onOuterAbort, { once: true })
|
|
91
|
+
}
|
|
88
92
|
}
|
|
89
93
|
|
|
90
94
|
try {
|
package/lib/tools.js
CHANGED
|
@@ -296,9 +296,12 @@ function applyParams(questions, params) {
|
|
|
296
296
|
// criteria 整体替换;addCriteria 在替换结果之上追加/覆盖单个选项
|
|
297
297
|
if (override.criteria) {
|
|
298
298
|
if (question.type === 'choice' && !Array.isArray(override.criteria)) {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
299
|
+
const entries = Object.entries(override.criteria)
|
|
300
|
+
if (entries.length < 2) {
|
|
301
|
+
ignored.push(`${qid}.criteria(choice 至少需要 2 个选项)`)
|
|
302
|
+
} else {
|
|
303
|
+
next.criteria = Object.fromEntries(entries.map(([k, v]) => [String(k), String(v)]))
|
|
304
|
+
}
|
|
302
305
|
} else if (question.type === 'score' && Array.isArray(override.criteria) && override.criteria.length >= 2) {
|
|
303
306
|
next.criteria = override.criteria.map((v) => String(v))
|
|
304
307
|
} else {
|
package/lib/volatile.js
CHANGED
|
@@ -36,9 +36,11 @@ export function readString(config, key, fallback = '') {
|
|
|
36
36
|
return text === '' ? fallback : text
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
/** 读取数值配置(去壳 +
|
|
39
|
+
/** 读取数值配置(去壳 + 空值/非法值兜底)。 */
|
|
40
40
|
export function readNumber(config, key, fallback) {
|
|
41
|
-
const
|
|
41
|
+
const raw = unwrap(config?.[key])
|
|
42
|
+
if (raw === undefined || raw === null || raw === '') return fallback
|
|
43
|
+
const value = Number(raw)
|
|
42
44
|
return Number.isFinite(value) ? value : fallback
|
|
43
45
|
}
|
|
44
46
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@master0071/dsh-systemone",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.4",
|
|
4
4
|
"description": "DeepSeek Harness 插件:将 SystemOne 决策模型(默认云知声 u2-decision,可切换提供商)接入软件开发、客服、内容审核、路由、销售线索、风控、招聘、数据治理、教育、需求变更等 10 大业务场景,为 Agent 返回带概率分布的决策与处置建议。",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|