dsh-mcmp 2.2.1 → 2.2.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 CHANGED
@@ -43,6 +43,7 @@ DeepSeek Harness **持久化 Cordis 插件**:面向全国大学生数学建模
43
43
  - `/loopbegin` —— 默认 1 轮
44
44
  - `/loopbegin --round=3` —— 3 轮外循环(上限 10)
45
45
  - `/loopbegin --from 题目.txt` —— 从文件读取赛题(支持含空格/中文的文件名,如 `--from 2024 年高教社杯全国大学生数学建模竞赛题目.md`,也可用 `--from=文件` 形式)
46
+ - `/loopbegin --model glm-vision/glm-4.7-Flash` —— 可选显式覆盖(也可用 `--provider 提供商 --model 模型` 分拆形式)。**默认不需要此参数**:流水线子任务的模型**强制跟随你在对话右下角选择的模型**(每次启动时读取当前选择);若无法读取(未安装默认模型服务),兜底使用 `deepseek-official/deepseek-v4-flash`(high 推理由 deepseek 提供商默认提供)
46
47
  3. **查看进度**:右下角浮动面板(百分比、步骤打点、日志、文件)+ 聊天区工作流卡片。
47
48
 
48
49
  辅助命令:`/loopstatus`(查看进度)、`/loopabort`(中止,已产出成果保留)、`/loopreset`(清空状态与断点续跑记录,下次 `/loopbegin` 从头全新开始;等价于面板「重置(全新开始)」按钮)。
package/lib/index.js CHANGED
@@ -35,6 +35,26 @@ export function apply(ctx) {
35
35
  // 全流水线缺陷台账:跨步骤错误登记、裁决与向上修复的唯一权威文件
36
36
  const LEDGER = '00_缺陷与裁决台账.md'
37
37
 
38
+ // 子任务模型路由解析:
39
+ // 1) 显式 --model 覆盖(优先级最高)
40
+ // 2) 父对话当前选择的模型(右下角模型选择器 → agent-default-model 设置)
41
+ // 3) 兜底:DeepSeek V4 Flash(high 推理由 deepseek 提供商默认提供)
42
+ // 无论哪种情况,都强制把 agentOptions 传给每个子任务,
43
+ // 避免子任务继承父会话"创建时固化"的模型选项(聊天里切换模型不生效的老问题)。
44
+ const FALLBACK_MODEL = { provider: 'deepseek-official', model: 'deepseek-v4-flash' }
45
+ function resolveForcedModel() {
46
+ try {
47
+ const adm = ctx.get('agentDefaultModel')
48
+ if (adm && typeof adm.currentSelection === 'function') {
49
+ const sel = adm.currentSelection()
50
+ if (sel && typeof sel.provider === 'string' && sel.provider && typeof sel.model === 'string' && sel.model) {
51
+ return { provider: sel.provider, model: sel.model }
52
+ }
53
+ }
54
+ } catch (err) { /* ignore */ }
55
+ return { ...FALLBACK_MODEL }
56
+ }
57
+
38
58
  // ---------- 识图能力探测(宿主侧,仅供参考;以子智能体自检为准) ----------
39
59
  function detectVision() {
40
60
  // 1) 宿主服务:常见的识图服务键
@@ -426,7 +446,8 @@ export function apply(ctx) {
426
446
  }
427
447
 
428
448
  // 启动一个子智能体并返回 { ok, text, outcome }
429
- async function runChild(provider, session, agent, controller, label, promptText, onStarted) {
449
+ // agentOptions:可选 { provider, model } —— 强制子任务使用指定模型路由(覆盖父会话的固化选项)
450
+ async function runChild(provider, session, agent, controller, label, promptText, onStarted, agentOptions) {
430
451
  let child = null
431
452
  try {
432
453
  const parent = (agents && agents.get(session.id)) || agent
@@ -435,6 +456,7 @@ export function apply(ctx) {
435
456
  prompt: [{ type: 'text', text: promptText }],
436
457
  parent,
437
458
  signal: controller.signal,
459
+ ...(agentOptions && agentOptions.provider && agentOptions.model ? { agentOptions } : {}),
438
460
  })
439
461
  if (onStarted) { try { onStarted(child) } catch (err) { /* ignore */ } }
440
462
  const res = await child.result
@@ -479,7 +501,7 @@ export function apply(ctx) {
479
501
  const res = await runChild(provider, session, agent, controller, label, buildPrompt(r, f.s, f.i, s, it, args), (child) => {
480
502
  started = true
481
503
  appendRec(runId, session, 'tool-workflow/agent-start', { runId, seq: g + 1, label, phase: s.phase, childId: String(child.id) })
482
- })
504
+ }, args.agentOptions)
483
505
  outcome = res.outcome
484
506
  note = (res.text || '').trim().slice(0, 300)
485
507
  if (res.err) note = '执行异常: ' + String((res.err && res.err.message) || res.err).slice(0, 200)
@@ -506,7 +528,7 @@ export function apply(ctx) {
506
528
  if (controller.signal.aborted) { cancelled = true; break }
507
529
  if (failStreak >= 3) {
508
530
  stopReason = 'error'
509
- errorMsg = '连续 3 个子任务失败(每个失败迭代已含自动重试),流水线提前终止。常见原因:模型服务限流(429)/账户余额不足(402)/上下文过长/工作区文件问题;请排查后重新 /loopbegin 续跑,或 /loopreset 后重来。已有成果全部保留。'
531
+ errorMsg = '连续 3 个子任务失败,流水线提前终止。常见原因:模型服务限流(429)/账户余额不足(402)/上下文过长/工作区文件问题;可尝试 /loopbegin --model 提供商/模型 换用其他模型,或 /loopreset 后重来。已有成果全部保留。'
510
532
  break
511
533
  }
512
534
  }
@@ -521,7 +543,7 @@ export function apply(ctx) {
521
543
  // 否则面板「中止」与 /loopabort 只会 abort 已失效的主控制器,兜底定稿无法被中止
522
544
  if (active && active.runId === runId) active.controller = fresh
523
545
  const reason = stopReason === 'cancelled' ? '用户中止' : stopReason === 'error' ? errorMsg : '正常流程已结束但定稿步骤未完成'
524
- const fres = await runChild(provider, session, agent, fresh, '兜底·论文定稿(不论成败)', buildFinalizePrompt(args, reason))
546
+ const fres = await runChild(provider, session, agent, fresh, '兜底·论文定稿(不论成败)', buildFinalizePrompt(args, reason), undefined, args.agentOptions)
525
547
  if (fres.outcome === 'completed') {
526
548
  finalDone = true
527
549
  pushLog('兜底定稿完成: 论文定稿.md 已生成')
@@ -560,6 +582,27 @@ export function apply(ctx) {
560
582
  if (!Number.isSafeInteger(rounds) || rounds < 1) rounds = 1
561
583
  if (rounds > 10) return { kind: 'error', text: '--round 最大为 10。每轮 19 次迭代、每次迭代启动一个专家子智能体,轮数过大会非常耗时。' }
562
584
  const fresh = /(?:^|\s)--fresh\b/i.test(raw)
585
+ // 子任务模型:默认强制跟随父对话当前选择的模型(右下角模型选择器);
586
+ // 可选 --model 提供商/模型 显式覆盖;无法读取时兜底 DeepSeek V4 Flash。
587
+ let explicitAgentOptions = undefined
588
+ {
589
+ const mProvider = /(?:^|\s)--provider\s*[=:]?\s*([A-Za-z0-9._\-]+)/i.exec(raw)
590
+ const mModel = /(?:^|\s)--model\s*[=:]?\s*([A-Za-z0-9._\-]+(?:\/[A-Za-z0-9._\-]+)?)/i.exec(raw)
591
+ if (mModel) {
592
+ const rawModel = mModel[1]
593
+ const slash = rawModel.indexOf('/')
594
+ if (slash >= 0) {
595
+ explicitAgentOptions = { provider: rawModel.slice(0, slash), model: rawModel.slice(slash + 1) }
596
+ } else if (mProvider) {
597
+ explicitAgentOptions = { provider: mProvider[1], model: rawModel }
598
+ } else {
599
+ return { kind: 'error', text: '--model 需要指定提供商/模型,例如 --model glm-vision/glm-4.7-Flash;也可配合 --provider 提供商 --model 模型 使用。' }
600
+ }
601
+ } else if (mProvider) {
602
+ return { kind: 'error', text: '--provider 必须配合 --model 使用,例如 --provider glm-vision --model glm-4.7-Flash。' }
603
+ }
604
+ }
605
+ const agentOptions = explicitAgentOptions || resolveForcedModel()
563
606
  // --from 路径:允许含空格,遇到下一个 -- 标志或行尾即结束,避免吞掉后面的 --round/--fresh
564
607
  const mFrom = /(?:^|\s)--from(?:=)?\s*([^\r\n]+?)(?=\s+--|\r?$)/i.exec(raw)
565
608
  let problem = null
@@ -581,7 +624,7 @@ export function apply(ctx) {
581
624
  const problemPath = problem.kind === 'file' ? problem.path : wsDir + '/00_赛题原文.md'
582
625
  const title = problem.kind === 'text' ? problem.text.split(/\r?\n/).map((l) => l.trim()).filter((l) => l.length > 0)[0] : problem.path
583
626
  const vision = detectVision()
584
- const args = { rounds, wsDir, problemPath, problem, title: title ? title.slice(0, 40) : '赛题', vision }
627
+ const args = { rounds, wsDir, problemPath, problem, title: title ? title.slice(0, 40) : '赛题', vision, agentOptions }
585
628
  // 断点续跑:扫描本会话落盘的 v2 工作流记录,跳过已完成的迭代
586
629
  const resumeCount = fresh ? 0 : completedIterations(session)
587
630
  args.startIndex = resumeCount
@@ -613,6 +656,8 @@ export function apply(ctx) {
613
656
  pushLog('流水线已启动: ' + rounds + ' 轮 × 19 次迭代,输出目录 ' + wsDir + (resumeCount > 0 ? '(断点续跑:跳过已完成的 ' + resumeCount + ' 次迭代)' : '') + '(关闭本聊天窗口不影响后台执行)')
614
657
  if (vision) pushLog('识图能力探测: ' + (vision.source === 'service' ? '检测到识图服务 ' + vision.key : '检测到识图工具 ' + (vision.tools || []).join(',')) + '(S5 将自动调用)')
615
658
  else pushLog('识图能力探测:未检测到独立识图插件,S5 将让子智能体自检(无识图则走脚本分析)')
659
+ if (explicitAgentOptions) pushLog('子任务模型路由:强制 ' + agentOptions.provider + '/' + agentOptions.model + '(--model 显式覆盖)')
660
+ else pushLog('子任务模型路由:跟随父对话当前选择 ' + agentOptions.provider + '/' + agentOptions.model + ' (无法读取时兜底 deepseek-official/deepseek-v4-flash)')
616
661
  refreshFiles()
617
662
  void runPipeline(runId, session, agent, args, controller).catch((err) => {
618
663
  pushLog('流水线异常: ' + String((err && err.message) || err))
@@ -636,7 +681,7 @@ export function apply(ctx) {
636
681
  commands.register({
637
682
  name: 'loopbegin',
638
683
  description: '启动数学建模论文自动化流水线 v2(8 步骤:含图表视觉自检、评审修复闭环、论文定稿;每轮 19 次迭代、多轮外循环,成果全部落盘)',
639
- input: { hint: '--round=N 外循环轮数(默认 1);可选 --from 题目文件 指定赛题文件;--fresh 从头重跑' },
684
+ input: { hint: '--round=N 外循环轮数(默认 1);--model 提供商/模型 强制子任务模型(如 --model glm-vision/glm-4.7-Flash);可选 --from 题目文件 指定赛题文件;--fresh 从头重跑' },
640
685
  handler: (invocation) => startPipeline(invocation.agent, invocation.rawInput),
641
686
  })
642
687
  } catch (err) { console.warn('dsh-mcmp: loopbegin 注册失败(可能被其他实例占用): ' + String((err && err.message) || err)) }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-mcmp",
3
- "version": "2.2.1",
3
+ "version": "2.2.3",
4
4
  "description": "DeepSeek Harness 插件:数学建模论文自动化流水线 v2(8 步骤 × 19 迭代 × N 轮:图表视觉自检与修复、评审问题修复闭环、跨步骤缺陷台账与向上修复、论文兜底定稿、质疑驱动、断点续跑、进度面板)",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",