dsh-vibe-math 0.3.2 → 0.3.3
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/README.md +13 -4
- package/package.json +1 -1
- package/vibe-math-v1/preset.yml +1 -1
- package/vibe-math-v1/vibe-math.js +14 -9
- package/vibe-math-v2/vibe-math-v2.js +31 -17
package/README.md
CHANGED
|
@@ -96,7 +96,7 @@ dsh plugin --profile <你的 profile> add github:ChongCyrus/Vibe-Mathematics
|
|
|
96
96
|
|
|
97
97
|
> 静态 PNG 预览 + 可编辑 Mermaid 图源(GitHub 原生渲染);完整流程说明见 [docs/架构图.md](docs/架构图.md)。
|
|
98
98
|
|
|
99
|
-

|
|
100
100
|
|
|
101
101
|
```mermaid
|
|
102
102
|
flowchart TB
|
|
@@ -153,6 +153,10 @@ flowchart TB
|
|
|
153
153
|
|
|
154
154
|
## 🧩 架构图 · v2(新架构 · 概率驱动)
|
|
155
155
|
|
|
156
|
+
> 静态 PNG 预览 + 可编辑 Mermaid 图源(GitHub 原生渲染);生成脚本见 [docs/generate_framework_diagram_v2.py](docs/generate_framework_diagram_v2.py)。
|
|
157
|
+
|
|
158
|
+

|
|
159
|
+
|
|
156
160
|
```mermaid
|
|
157
161
|
flowchart TB
|
|
158
162
|
subgraph L1["👤 交互层"]
|
|
@@ -399,7 +403,9 @@ flowchart TB
|
|
|
399
403
|
| `solverToolAllow` / `solverToolDeny` | `[]` | 求解器允许/禁止的工具(硬性 toolFilter) |
|
|
400
404
|
| `verifierToolAllow` / `verifierToolDeny` | `[]` | 验证器允许/禁止的工具 |
|
|
401
405
|
| `solverMaxToolCalls` / `verifierMaxToolCalls` | 0 | 每轮外部工具调用上限(0=不限,软性) |
|
|
402
|
-
| `reportIntervalMs` |
|
|
406
|
+
| `reportIntervalMs` | 0 | 0 = 仅事件驱动(有代理状态更新等事件才写报告);>0 = 定时自动写(毫秒) |
|
|
407
|
+
| `tickIntervalMs` | 2000 | 调度器心跳间隔(毫秒) |
|
|
408
|
+
| `activityLogCap` | 100 | 活动日志保留条数(report 最多显示 30 条) |
|
|
403
409
|
|
|
404
410
|
### v2(新架构)默认值
|
|
405
411
|
|
|
@@ -419,7 +425,10 @@ flowchart TB
|
|
|
419
425
|
| `solverToolAllow` / `solverToolDeny` | `[]` | 求解器允许/禁止的工具 |
|
|
420
426
|
| `verifierToolAllow` / `verifierToolDeny` | `[]` | 验证器允许/禁止的工具 |
|
|
421
427
|
| `solverMaxToolCalls` / `verifierMaxToolCalls` | 0 | 每轮外部工具调用上限(0=不限) |
|
|
422
|
-
| `reportIntervalMs` |
|
|
428
|
+
| `reportIntervalMs` | 0 | 0 = 仅事件驱动(有状态更新才写/推);>0 = 定时自动汇报(毫秒) |
|
|
429
|
+
| `tickIntervalMs` | 2000 | 调度器心跳间隔(毫秒) |
|
|
430
|
+
| `activityLogCap` | 100 | 活动日志保留条数(report 最多显示 30 条) |
|
|
431
|
+
| `maxExplorerRetries` | 3 | explorer 拆方向失败的重派生上限 |
|
|
423
432
|
|
|
424
433
|
---
|
|
425
434
|
|
|
@@ -427,7 +436,7 @@ flowchart TB
|
|
|
427
436
|
|
|
428
437
|
- **断点续跑**:所有状态落盘到 `VibeMath_State/*.json`,每个子代理都是 DSH 的 **continuable 持久会话**(对话由 DSH 自动保存)。重启后新开会话 → `vibe_math_resume` 即可续跑。v2 额外用**进程纪元**区分"同进程暂停→恢复"(保留存活子代理继续)与"跨进程重启"(清理陈旧任务)。
|
|
429
438
|
- **中途人工干预**:`manual` 模式在关键节点(v1:brainstorm/solver 派发、验证裁决、晋升 Verified;v2:explorer/solver 派发、验证裁决)挂起决策;可随时 `set_mode auto` 切回自动;可对任意子代理 `message_agent` / `interrupt_agent`。
|
|
430
|
-
-
|
|
439
|
+
- **进度汇报**:默认**事件驱动** —— 只有代理状态更新等事件发生时才会写 `Progress_Logs/report.json`(v2 的 `reportMode` 可 `file`/`push`/`both`,`push` 通过 `rootAgent.followup()` 唤醒主代理主动汇报);只有把 `reportIntervalMs` 设为 >0 才启动定时自动汇报(间隔毫秒)。
|
|
431
440
|
|
|
432
441
|
---
|
|
433
442
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-vibe-math",
|
|
3
3
|
"description": "Multi-agent mathematical problem-solving & verification frameworks for DeepSeek Harness — TWO agent presets in one install: vibe-math-v1 (classic pipeline: brainstorm → solver iteration → multi-verifier debate → Verified) and vibe-math-v2 (new probability-driven architecture: qs.json + Propos knowledge base + explorer→solver→review/debate verdict). Installing this bundle auto-installs both presets into the DSH preset root.",
|
|
4
|
-
"version": "0.3.
|
|
4
|
+
"version": "0.3.3",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "installer.js",
|
|
7
7
|
"exports": {
|
package/vibe-math-v1/preset.yml
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
name: Vibe Math
|
|
1
|
+
name: Vibe Math V1
|
|
2
2
|
description: 多代理数学问题求解与验证框架(广度探索 → 深度迭代 → 交叉验证 → 知识沉淀)。具备标准模式的全部能力,并提供 vibe_math_* 工具集(20 个)与 /vibe 斜杠命令,用于数学问题的自动求解、多代理交叉验证、按项目隔离、断点续跑与人工/自动干预。
|
|
@@ -69,7 +69,9 @@ export function apply(ctx) {
|
|
|
69
69
|
verifierToolDeny: [],
|
|
70
70
|
solverMaxToolCalls: 0,
|
|
71
71
|
verifierMaxToolCalls: 0,
|
|
72
|
-
reportIntervalMs:
|
|
72
|
+
reportIntervalMs: 0, // 0 = 仅事件驱动(有代理状态更新等事件才写报告);>0 = 定时自动写(毫秒)
|
|
73
|
+
tickIntervalMs: 2000, // 调度器心跳间隔(毫秒):多久扫描一次状态并推进
|
|
74
|
+
activityLogCap: 100, // 活动日志保留条数(report.recentActivity 最多显示 30 条)
|
|
73
75
|
}
|
|
74
76
|
let params = Object.assign({}, DEFAULT_PARAMS)
|
|
75
77
|
let scheduler = { running: false, activeCount: 0, startedAt: 0, lastCheckpoint: 0, gate: null }
|
|
@@ -152,7 +154,9 @@ export function apply(ctx) {
|
|
|
152
154
|
{ name: 'verifierToolDeny', type: 'string[]', description: '验证器禁止的工具名列表', suggestion: [] },
|
|
153
155
|
{ name: 'solverMaxToolCalls', type: 'integer', description: '求解器每轮外部工具调用上限(0 = 不限)', suggestion: 0 },
|
|
154
156
|
{ name: 'verifierMaxToolCalls', type: 'integer', description: '验证器每轮外部工具调用上限(0 = 不限)', suggestion: 0 },
|
|
155
|
-
{ name: 'reportIntervalMs', type: 'integer', description: '
|
|
157
|
+
{ name: 'reportIntervalMs', type: 'integer', description: '进度汇报间隔(毫秒):0 = 仅事件驱动(有代理状态更新等事件才写 report.json);>0 = 定时自动汇报', suggestion: 0 },
|
|
158
|
+
{ name: 'tickIntervalMs', type: 'integer', description: '调度器心跳间隔(毫秒):多久扫描一次子代理状态并推进(越小越灵敏、越大越省资源)', suggestion: 2000 },
|
|
159
|
+
{ name: 'activityLogCap', type: 'integer', description: '活动日志保留条数(影响 report.recentActivity 的细节量,报告最多显示 30 条)', suggestion: 100 },
|
|
156
160
|
]
|
|
157
161
|
|
|
158
162
|
// ================= fs =================
|
|
@@ -178,7 +182,7 @@ export function apply(ctx) {
|
|
|
178
182
|
// ================= settings file (JSONC) =================
|
|
179
183
|
function sanitizeParams(obj) {
|
|
180
184
|
const out = {}
|
|
181
|
-
const intFields = ['maxParallelThreshold', 'solverMaxRounds', 'verifierCount', 'debateMaxRounds', 'solverMaxToolCalls', 'verifierMaxToolCalls', 'reportIntervalMs']
|
|
185
|
+
const intFields = ['maxParallelThreshold', 'solverMaxRounds', 'verifierCount', 'debateMaxRounds', 'solverMaxToolCalls', 'verifierMaxToolCalls', 'reportIntervalMs', 'tickIntervalMs', 'activityLogCap']
|
|
182
186
|
const arrayFields = ['solverToolAllow', 'solverToolDeny', 'verifierToolAllow', 'verifierToolDeny']
|
|
183
187
|
for (const k of Object.keys(DEFAULT_PARAMS)) {
|
|
184
188
|
if (!(k in obj)) continue
|
|
@@ -231,7 +235,7 @@ export function apply(ctx) {
|
|
|
231
235
|
async function saveAll() { await writeJson('VibeMath_State/params.json', params); await writeJson('VibeMath_State/scheduler_state.json', scheduler); await writeJson('VibeMath_State/agent_registry.json', agentRegistry); await writeJson('VibeMath_State/dependencies.json', dependencies); await writeJson('VibeMath_State/decision_queue.json', decisionQueue); await writeJson('VibeMath_State/tasks.json', tasks); await writeJson('VibeMath_State/solved_by_verified.json', solvedByVerified); await writeJson('VibeMath_State/promotion_queue.json', promotionQueue); await writeJson('VibeMath_State/verifier_accuracy.json', verifierAccuracy); scheduler.lastCheckpoint = now() }
|
|
232
236
|
|
|
233
237
|
// ================= activity log / report =================
|
|
234
|
-
function logActivity(event, detail) { activityLog.push({ at: now(), event: event, detail: String(detail || '') }); if (activityLog.length >
|
|
238
|
+
function logActivity(event, detail) { activityLog.push({ at: now(), event: event, detail: String(detail || '') }); const cap = Number(params.activityLogCap) || 100; if (activityLog.length > cap) activityLog.shift(); reportDirty = true }
|
|
235
239
|
function buildReport() {
|
|
236
240
|
const openTasks = Object.keys(tasks).filter(function (k) { const t = tasks[k]; return t.status === 'spawning' || t.status === 'debating' || t.status === 'awaiting-verdict' })
|
|
237
241
|
return {
|
|
@@ -246,13 +250,14 @@ export function apply(ctx) {
|
|
|
246
250
|
pendingDecisions: decisionQueue.filter(function (d) { return d.status === 'pending' }).map(function (d) { return { id: d.id, node: d.node, context: d.context } }),
|
|
247
251
|
openTasks: openTasks.length,
|
|
248
252
|
registeredAgents: Object.keys(agentRegistry).length,
|
|
249
|
-
recentActivity: activityLog.slice(-30),
|
|
253
|
+
recentActivity: activityLog.slice(-Math.min(30, Number(params.activityLogCap) || 100)),
|
|
250
254
|
params: params,
|
|
251
255
|
}
|
|
252
256
|
}
|
|
253
257
|
async function maybeWriteReport(force) {
|
|
254
|
-
|
|
255
|
-
if (!force && (now() - lastReportWrite) <
|
|
258
|
+
const interval = Number(params.reportIntervalMs) || 0
|
|
259
|
+
if (!force && interval > 0 && (now() - lastReportWrite) < interval) return
|
|
260
|
+
if (!force && interval <= 0 && !reportDirty) return
|
|
256
261
|
await writeJson('Progress_Logs/report.json', buildReport())
|
|
257
262
|
lastReportWrite = now()
|
|
258
263
|
reportDirty = false
|
|
@@ -458,7 +463,7 @@ export function apply(ctx) {
|
|
|
458
463
|
|
|
459
464
|
// ================= events / timer =================
|
|
460
465
|
ctx.on('subagent/end', function (info) { onChildEnd(info).catch(function (e) { console.error('vibe-math onChildEnd reject: ' + String((e && e.stack) || e)) }) })
|
|
461
|
-
ctx.effect(() => { const t = setInterval(function () { scheduleTick() }, 2000); return () => clearInterval(t) })
|
|
466
|
+
ctx.effect(() => { const t = setInterval(function () { scheduleTick() }, Math.max(200, Number(params.tickIntervalMs) || 2000)); return () => clearInterval(t) })
|
|
462
467
|
|
|
463
468
|
// ================= tools =================
|
|
464
469
|
function objParams(props, required) { return { type: 'object', properties: props, additionalProperties: false, required: required || [] } }
|
|
@@ -477,7 +482,7 @@ export function apply(ctx) {
|
|
|
477
482
|
registerTool('vibe_math_status', 'Show scheduler status, params, active agents, projects, and recent activity.', objParams({}), async function () { return await getStatus() })
|
|
478
483
|
registerTool('vibe_math_report', 'Return the full progress report (status + recent activity + params) and write it to Progress_Logs/report.json.', objParams({}), async function () { await maybeWriteReport(true); return buildReport() })
|
|
479
484
|
registerTool('vibe_math_set_mode', 'Switch between manual and auto (preset) mode.', objParams({ mode: { type: 'string', enum: ['manual', 'auto'] } }, ['mode']), async function (args) { params.mode = args.mode; await saveAll(); return { ok: true, mode: params.mode } })
|
|
480
|
-
registerTool('vibe_math_set_params', 'Update scheduler parameters (partial).', objParams({ maxParallelThreshold: { type: 'integer' }, solverMaxRounds: { type: 'integer' }, verifierCount: { type: 'integer' }, debateMaxRounds: { type: 'integer' }, verdictMode: { type: 'string', enum: ['direct-veto', 'weighted-vote'] }, provider: { type: 'string' }, model: { type: 'string' }, solverPersona: { type: 'string' }, verifierPersona: { type: 'string' }, solverToolAllow: { type: 'array', items: { type: 'string' } }, solverToolDeny: { type: 'array', items: { type: 'string' } }, verifierToolAllow: { type: 'array', items: { type: 'string' } }, verifierToolDeny: { type: 'array', items: { type: 'string' } }, solverMaxToolCalls: { type: 'integer' }, verifierMaxToolCalls: { type: 'integer' }, reportIntervalMs: { type: 'integer' } }), async function (args) { params = Object.assign({}, params, args); await saveAll(); return { ok: true, params: params } })
|
|
485
|
+
registerTool('vibe_math_set_params', 'Update scheduler parameters (partial).', objParams({ maxParallelThreshold: { type: 'integer' }, solverMaxRounds: { type: 'integer' }, verifierCount: { type: 'integer' }, debateMaxRounds: { type: 'integer' }, verdictMode: { type: 'string', enum: ['direct-veto', 'weighted-vote'] }, provider: { type: 'string' }, model: { type: 'string' }, solverPersona: { type: 'string' }, verifierPersona: { type: 'string' }, solverToolAllow: { type: 'array', items: { type: 'string' } }, solverToolDeny: { type: 'array', items: { type: 'string' } }, verifierToolAllow: { type: 'array', items: { type: 'string' } }, verifierToolDeny: { type: 'array', items: { type: 'string' } }, solverMaxToolCalls: { type: 'integer' }, verifierMaxToolCalls: { type: 'integer' }, reportIntervalMs: { type: 'integer' }, tickIntervalMs: { type: 'integer' }, activityLogCap: { type: 'integer' } }), async function (args) { params = Object.assign({}, params, args); await saveAll(); return { ok: true, params: params } })
|
|
481
486
|
registerTool('vibe_math_setup', 'Return the interactive parameter schema (each param: name, type, current, default, description, options, suggestion) for guided configuration.', objParams({}), async function () { const list = PARAM_SCHEMA.map(function (p) { const out = Object.assign({}, p); out.current = params[p.name]; out.default = DEFAULT_PARAMS[p.name]; return out }); return { ok: true, parameters: list, saveTo: frameworkRoot() + '/vibe_math_setting.json' } })
|
|
482
487
|
registerTool('vibe_math_save_settings', 'Write the current params to vibe_math_setting.json (JSON with comments) as new defaults.', objParams({}), async function () { return await saveSettings() })
|
|
483
488
|
registerTool('vibe_math_template', 'Create a fresh vibe_math_setting.json template (with defaults + comments) in the workspace (global) or current project folder.', objParams({ where: { type: 'string', enum: ['global', 'project'] } }), async function (args) { return await createTemplate((args && args.where) || 'global') })
|
|
@@ -47,10 +47,13 @@ export function apply(ctx) {
|
|
|
47
47
|
verifierToolDeny: [],
|
|
48
48
|
solverMaxToolCalls: 0,
|
|
49
49
|
verifierMaxToolCalls: 0,
|
|
50
|
-
reportIntervalMs:
|
|
50
|
+
reportIntervalMs: 0, // 0 = 仅事件驱动(有代理状态更新等事件才写/推报告);>0 = 定时自动汇报(毫秒)
|
|
51
51
|
reportMode: 'file', // file | push | both
|
|
52
52
|
promoteValueThreshold: 0.7, // Propos → qs auto-promotion threshold (价值/关键性)
|
|
53
53
|
priorityAdjust: 'none', // none | deadend-deprioritize | survival-map
|
|
54
|
+
tickIntervalMs: 2000, // 调度器心跳间隔(毫秒)
|
|
55
|
+
activityLogCap: 100, // 活动日志保留条数(report.recentActivity 最多显示 30 条)
|
|
56
|
+
maxExplorerRetries: 3, // explorer 重派生上限(拆方向失败重试次数)
|
|
54
57
|
}
|
|
55
58
|
let params = Object.assign({}, DEFAULT_PARAMS)
|
|
56
59
|
let scheduler = { running: false, activeCount: 0, startedAt: 0, lastCheckpoint: 0, gate: null }
|
|
@@ -128,10 +131,13 @@ export function apply(ctx) {
|
|
|
128
131
|
{ name: 'verifierToolDeny', type: 'string[]', description: '验证器禁止的工具名列表', suggestion: [] },
|
|
129
132
|
{ name: 'solverMaxToolCalls', type: 'integer', description: '求解器每轮外部工具调用上限(0 = 不限)', suggestion: 0 },
|
|
130
133
|
{ name: 'verifierMaxToolCalls', type: 'integer', description: '验证器每轮外部工具调用上限(0 = 不限)', suggestion: 0 },
|
|
131
|
-
{ name: 'reportIntervalMs', type: 'integer', description: '
|
|
134
|
+
{ name: 'reportIntervalMs', type: 'integer', description: '进度汇报间隔(毫秒):0 = 仅事件驱动(有代理状态更新等事件才写/推报告);>0 = 同时按该间隔定时自动汇报', suggestion: 0 },
|
|
132
135
|
{ name: 'reportMode', type: 'enum', options: ['file', 'push', 'both'], description: 'file = 写报告文件;push = 推送消息让主代理主动汇报;both = 两者都做', suggestion: 'file' },
|
|
133
136
|
{ name: 'promoteValueThreshold', type: 'number', description: 'Propos 中「价值/关键性」≥ 该值且未决(0,1) 的命题自动加入 qs.json', suggestion: 0.7 },
|
|
134
137
|
{ name: 'priorityAdjust', type: 'enum', options: ['none', 'deadend-deprioritize', 'survival-map'], description: '优先级动态调整策略:none=不自动调;deadend-deprioritize=方向全死路时降优先级;survival-map=按最高方向存活率重算(存活率高越优先)', suggestion: 'none' },
|
|
138
|
+
{ name: 'tickIntervalMs', type: 'integer', description: '调度器心跳间隔(毫秒):多久扫描一次子代理状态并推进(越小越灵敏、越大越省资源)', suggestion: 2000 },
|
|
139
|
+
{ name: 'activityLogCap', type: 'integer', description: '活动日志保留条数(影响 report.recentActivity 的细节量,报告最多显示 30 条)', suggestion: 100 },
|
|
140
|
+
{ name: 'maxExplorerRetries', type: 'integer', description: 'explorer 拆方向失败的重派生上限(达到后该问题标记为方向耗尽)', suggestion: 3 },
|
|
135
141
|
]
|
|
136
142
|
|
|
137
143
|
// ================= fs =================
|
|
@@ -156,7 +162,7 @@ export function apply(ctx) {
|
|
|
156
162
|
// ================= settings =================
|
|
157
163
|
function sanitizeParams(obj) {
|
|
158
164
|
const out = {}
|
|
159
|
-
const intFields = ['maxParallelThreshold', 'solverMaxRounds', 'verifierCount', 'debateMaxRounds', 'solverMaxToolCalls', 'verifierMaxToolCalls', 'reportIntervalMs']
|
|
165
|
+
const intFields = ['maxParallelThreshold', 'solverMaxRounds', 'verifierCount', 'debateMaxRounds', 'solverMaxToolCalls', 'verifierMaxToolCalls', 'reportIntervalMs', 'tickIntervalMs', 'activityLogCap', 'maxExplorerRetries']
|
|
160
166
|
const numFields = ['promoteValueThreshold']
|
|
161
167
|
const arrayFields = ['solverToolAllow', 'solverToolDeny', 'verifierToolAllow', 'verifierToolDeny']
|
|
162
168
|
for (const k of Object.keys(DEFAULT_PARAMS)) {
|
|
@@ -275,7 +281,7 @@ export function apply(ctx) {
|
|
|
275
281
|
async function reliableFiles() { return await listFiles('Reliable') }
|
|
276
282
|
|
|
277
283
|
// ================= reporting =================
|
|
278
|
-
function logActivity(event, detail) { activityLog.push({ at: now(), event: event, detail: String(detail || '') }); if (activityLog.length >
|
|
284
|
+
function logActivity(event, detail) { activityLog.push({ at: now(), event: event, detail: String(detail || '') }); const cap = Number(params.activityLogCap) || 100; if (activityLog.length > cap) activityLog.shift(); reportDirty = true }
|
|
279
285
|
async function buildReport() {
|
|
280
286
|
const qs = await getQs()
|
|
281
287
|
const propos = await getPropos()
|
|
@@ -287,21 +293,28 @@ export function apply(ctx) {
|
|
|
287
293
|
propositions: { total: propos.length, resolved: propos.filter(function (p) { return p.布尔估计 === 1 || p.布尔估计 === 0 }).length },
|
|
288
294
|
pendingDecisions: decisionQueue.filter(function (d) { return d.status === 'pending' }).map(function (d) { return { id: d.id, node: d.node, context: d.context } }),
|
|
289
295
|
registeredAgents: Object.keys(agentRegistry).length,
|
|
290
|
-
recentActivity: activityLog.slice(-30),
|
|
296
|
+
recentActivity: activityLog.slice(-Math.min(30, Number(params.activityLogCap) || 100)),
|
|
291
297
|
params: params,
|
|
292
298
|
}
|
|
293
299
|
}
|
|
294
300
|
async function maybeWriteReport(force) {
|
|
295
|
-
|
|
296
|
-
if (!force && (now() - lastReportWrite) <
|
|
301
|
+
const interval = Number(params.reportIntervalMs) || 0
|
|
302
|
+
if (!force && interval > 0 && (now() - lastReportWrite) < interval) return
|
|
303
|
+
if (!force && interval <= 0 && !reportDirty) return
|
|
297
304
|
await writeJson('Progress_Logs/report.json', await buildReport())
|
|
298
305
|
lastReportWrite = now(); reportDirty = false
|
|
299
306
|
}
|
|
300
307
|
async function maybePushReport(force) {
|
|
301
308
|
const mode = params.reportMode || 'file'
|
|
302
309
|
if (mode !== 'push' && mode !== 'both') return
|
|
303
|
-
|
|
304
|
-
if (
|
|
310
|
+
const interval = Number(params.reportIntervalMs) || 0
|
|
311
|
+
if (interval > 0) {
|
|
312
|
+
// heartbeat: push on interval (or force), independent of reportDirty so 'both' mode works
|
|
313
|
+
if (!force && (now() - lastPushReport) < interval) return
|
|
314
|
+
} else if (!force && !reportDirty) {
|
|
315
|
+
// event-driven: only push when an event happened since the last report
|
|
316
|
+
return
|
|
317
|
+
}
|
|
305
318
|
if (!rootAgent || typeof rootAgent.followup !== 'function') return
|
|
306
319
|
try {
|
|
307
320
|
const report = await buildReport()
|
|
@@ -310,7 +323,7 @@ export function apply(ctx) {
|
|
|
310
323
|
'活跃代理轮数=' + report.activeCount + ',待人工决策=' + report.pendingDecisions.length + '。' +
|
|
311
324
|
'请调用 vibe_math_report 汇总当前进展及各代理状态,并用人话简要汇报(不打断用户,简短即可)。'
|
|
312
325
|
rootAgent.followup({ id: uuid(), role: 'user', content: [textBlock(text)], source: { kind: 'plugin', plugin: 'vibe-math-v2' } })
|
|
313
|
-
lastPushReport = now()
|
|
326
|
+
lastPushReport = now()
|
|
314
327
|
} catch (e) {
|
|
315
328
|
console.error('vibe-math-v2: push report failed: ' + String((e && e.message) || e))
|
|
316
329
|
}
|
|
@@ -455,8 +468,8 @@ export function apply(ctx) {
|
|
|
455
468
|
await processVerify()
|
|
456
469
|
await reconcileVerify()
|
|
457
470
|
await processSolve()
|
|
458
|
-
await maybeWriteReport(false)
|
|
459
471
|
await maybePushReport(false)
|
|
472
|
+
await maybeWriteReport(false)
|
|
460
473
|
const qs = await getQs()
|
|
461
474
|
const unsolved = qs.filter(function (q) { return !q.已解决 && q.优先级 !== 'never' })
|
|
462
475
|
if (unsolved.length === 0 && Object.keys(agentRegistry).length === 0 && Object.keys(tasks).length === 0) {
|
|
@@ -469,7 +482,7 @@ export function apply(ctx) {
|
|
|
469
482
|
const prog = parseProgress(unsolved[i])
|
|
470
483
|
const exhaustedAll = prog.directions.length > 0 && prog.directions.every(function (d) { return d.status === 'dead-end' || d.status === 'success' })
|
|
471
484
|
const hasActive = prog.directions.some(function (d) { return d.status === 'active' })
|
|
472
|
-
const blocked = (prog.directions.length === 0 || exhaustedAll) && (explorerRetries[unsolved[i].id] || 0) >= 3
|
|
485
|
+
const blocked = (prog.directions.length === 0 || exhaustedAll) && (explorerRetries[unsolved[i].id] || 0) >= (Number(params.maxExplorerRetries) || 3)
|
|
473
486
|
if (hasActive || !blocked) { allBlocked = false; break }
|
|
474
487
|
}
|
|
475
488
|
if (allBlocked) {
|
|
@@ -623,10 +636,11 @@ export function apply(ctx) {
|
|
|
623
636
|
const prog = parseProgress(q)
|
|
624
637
|
const allExhausted = prog.directions.length > 0 && prog.directions.every(function (d) { return d.status === 'dead-end' || d.status === 'success' })
|
|
625
638
|
if (prog.directions.length === 0 || allExhausted) {
|
|
626
|
-
|
|
627
|
-
|
|
639
|
+
const explorerCap = Number(params.maxExplorerRetries) || 3
|
|
640
|
+
if ((explorerRetries[q.id] || 0) >= explorerCap) {
|
|
641
|
+
if (prog.directions.length === 0) prog.directions.push({ id: 'd_' + shortId(), title: 'explorer 失败', method: '', core_assumption: '', feasibility: 0, status: 'dead-end', round: 0, survival: 0, routes: [], blockers: [], dead_end_reason: 'explorer 连续 ' + explorerCap + ' 次未产出方向' })
|
|
628
642
|
await saveProgress(q.id, prog)
|
|
629
|
-
logActivity('explorer', 'problem ' + q.id + ' explorer exhausted (
|
|
643
|
+
logActivity('explorer', 'problem ' + q.id + ' explorer exhausted (' + explorerCap + ' failed attempts)')
|
|
630
644
|
continue
|
|
631
645
|
}
|
|
632
646
|
explorerRetries[q.id] = (explorerRetries[q.id] || 0) + 1
|
|
@@ -995,7 +1009,7 @@ export function apply(ctx) {
|
|
|
995
1009
|
|
|
996
1010
|
// ================= events / timer =================
|
|
997
1011
|
ctx.on('subagent/end', function (info) { onChildEnd(info).catch(function (e) { console.error('vibe-math-v2 onChildEnd reject: ' + String((e && e.stack) || e)) }) })
|
|
998
|
-
ctx.effect(() => { const t = setInterval(function () { scheduleTick() }, 2000); return () => clearInterval(t) })
|
|
1012
|
+
ctx.effect(() => { const t = setInterval(function () { scheduleTick() }, Math.max(200, Number(params.tickIntervalMs) || 2000)); return () => clearInterval(t) })
|
|
999
1013
|
|
|
1000
1014
|
// ================= tools =================
|
|
1001
1015
|
function objParams(props, required) { return { type: 'object', properties: props, additionalProperties: false, required: required || [] } }
|
|
@@ -1013,7 +1027,7 @@ export function apply(ctx) {
|
|
|
1013
1027
|
registerTool('vibe_math_status', 'Show scheduler status, params, active agents, projects, and recent activity.', objParams({}), async function () { return await getStatus() })
|
|
1014
1028
|
registerTool('vibe_math_report', 'Return the full progress report and write it to Progress_Logs/report.json.', objParams({}), async function () { await maybeWriteReport(true); return await buildReport() })
|
|
1015
1029
|
registerTool('vibe_math_set_mode', 'Switch between manual and auto (preset) mode.', objParams({ mode: { type: 'string', enum: ['manual', 'auto'] } }, ['mode']), async function (args) { params.mode = args.mode; await saveAll(); return { ok: true, mode: params.mode } })
|
|
1016
|
-
registerTool('vibe_math_set_params', 'Update scheduler parameters (partial).', objParams({ maxParallelThreshold: { type: 'integer' }, solverMaxRounds: { type: 'integer' }, verifierCount: { type: 'integer' }, debateMaxRounds: { type: 'integer' }, verdictMode: { type: 'string', enum: ['flat', 'forced'] }, reportMode: { type: 'string', enum: ['file', 'push', 'both'] }, promoteValueThreshold: { type: 'number' }, priorityAdjust: { type: 'string', enum: ['none', 'deadend-deprioritize', 'survival-map'] }, provider: { type: 'string' }, model: { type: 'string' }, solverPersona: { type: 'string' }, verifierPersona: { type: 'string' }, solverToolAllow: { type: 'array', items: { type: 'string' } }, solverToolDeny: { type: 'array', items: { type: 'string' } }, verifierToolAllow: { type: 'array', items: { type: 'string' } }, verifierToolDeny: { type: 'array', items: { type: 'string' } }, solverMaxToolCalls: { type: 'integer' }, verifierMaxToolCalls: { type: 'integer' }, reportIntervalMs: { type: 'integer' } }), async function (args) { params = Object.assign({}, params, sanitizeParams(args)); await saveAll(); return { ok: true, params: params } })
|
|
1030
|
+
registerTool('vibe_math_set_params', 'Update scheduler parameters (partial).', objParams({ maxParallelThreshold: { type: 'integer' }, solverMaxRounds: { type: 'integer' }, verifierCount: { type: 'integer' }, debateMaxRounds: { type: 'integer' }, verdictMode: { type: 'string', enum: ['flat', 'forced'] }, reportMode: { type: 'string', enum: ['file', 'push', 'both'] }, promoteValueThreshold: { type: 'number' }, priorityAdjust: { type: 'string', enum: ['none', 'deadend-deprioritize', 'survival-map'] }, provider: { type: 'string' }, model: { type: 'string' }, solverPersona: { type: 'string' }, verifierPersona: { type: 'string' }, solverToolAllow: { type: 'array', items: { type: 'string' } }, solverToolDeny: { type: 'array', items: { type: 'string' } }, verifierToolAllow: { type: 'array', items: { type: 'string' } }, verifierToolDeny: { type: 'array', items: { type: 'string' } }, solverMaxToolCalls: { type: 'integer' }, verifierMaxToolCalls: { type: 'integer' }, reportIntervalMs: { type: 'integer' }, tickIntervalMs: { type: 'integer' }, activityLogCap: { type: 'integer' }, maxExplorerRetries: { type: 'integer' } }), async function (args) { params = Object.assign({}, params, sanitizeParams(args)); await saveAll(); return { ok: true, params: params } })
|
|
1017
1031
|
registerTool('vibe_math_setup', 'Return the interactive parameter schema for guided configuration.', objParams({}), async function () { const list = PARAM_SCHEMA.map(function (p) { const out = Object.assign({}, p); out.current = params[p.name]; out.default = DEFAULT_PARAMS[p.name]; return out }); return { ok: true, parameters: list, saveTo: frameworkRoot() + '/vibe_math_setting.json' } })
|
|
1018
1032
|
registerTool('vibe_math_save_settings', 'Write the current params to vibe_math_setting.json (JSON with comments) as new defaults.', objParams({}), async function () { return await saveSettings() })
|
|
1019
1033
|
registerTool('vibe_math_template', 'Create a fresh vibe_math_setting.json template (with defaults + comments) in the workspace (global) or current project folder.', objParams({ where: { type: 'string', enum: ['global', 'project'] } }), async function (args) { return await createTemplate((args && args.where) || 'global') })
|