dominds 0.3.2 → 0.3.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/dist/dialog-instance-registry.js +40 -1
- package/dist/dialog.js +2 -2
- package/dist/docs/dialog-system.md +6 -0
- package/dist/docs/dialog-system.zh.md +6 -0
- package/dist/docs/dominds-terminology.md +18 -0
- package/dist/docs/keep-going.zh.md +162 -0
- package/dist/llm/driver.js +66 -9
- package/dist/llm/gen/codex.js +11 -0
- package/dist/persistence.js +8 -4
- package/dist/server/api-routes.js +19 -1
- package/dist/server/setup-routes.js +2 -0
- package/dist/server/websocket-handler.js +18 -0
- package/dist/shared/utils/inter-dialog-format.js +7 -8
- package/dist/snippets/README.en.md +3 -0
- package/dist/static/assets/{_baseUniq-SokIVT_l.js → _baseUniq-mRW6pj4A.js} +2 -2
- package/dist/static/assets/{_baseUniq-SokIVT_l.js.map → _baseUniq-mRW6pj4A.js.map} +1 -1
- package/dist/static/assets/{arc-kjR8x1Ck.js → arc-QuaW82W7.js} +2 -2
- package/dist/static/assets/{arc-kjR8x1Ck.js.map → arc-QuaW82W7.js.map} +1 -1
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-Dqg6NBDR.js → architectureDiagram-VXUJARFQ-DnVRLy2e.js} +6 -6
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-Dqg6NBDR.js.map → architectureDiagram-VXUJARFQ-DnVRLy2e.js.map} +1 -1
- package/dist/static/assets/{blockDiagram-VD42YOAC-B-BQL_cY.js → blockDiagram-VD42YOAC-oj3riBZV.js} +7 -7
- package/dist/static/assets/{blockDiagram-VD42YOAC-B-BQL_cY.js.map → blockDiagram-VD42YOAC-oj3riBZV.js.map} +1 -1
- package/dist/static/assets/{c4Diagram-YG6GDRKO-Bzr91V4Y.js → c4Diagram-YG6GDRKO-D4aghgki.js} +3 -3
- package/dist/static/assets/{c4Diagram-YG6GDRKO-Bzr91V4Y.js.map → c4Diagram-YG6GDRKO-D4aghgki.js.map} +1 -1
- package/dist/static/assets/{channel-r5ULc-CH.js → channel-CO8pOP10.js} +2 -2
- package/dist/static/assets/{channel-r5ULc-CH.js.map → channel-CO8pOP10.js.map} +1 -1
- package/dist/static/assets/{chunk-4BX2VUAB-DbPnZ3jR.js → chunk-4BX2VUAB-wUTrHXKr.js} +2 -2
- package/dist/static/assets/{chunk-4BX2VUAB-DbPnZ3jR.js.map → chunk-4BX2VUAB-wUTrHXKr.js.map} +1 -1
- package/dist/static/assets/{chunk-55IACEB6-jRbyNM-u.js → chunk-55IACEB6-DuCJC-29.js} +2 -2
- package/dist/static/assets/{chunk-55IACEB6-jRbyNM-u.js.map → chunk-55IACEB6-DuCJC-29.js.map} +1 -1
- package/dist/static/assets/{chunk-B4BG7PRW-_roYgl4_.js → chunk-B4BG7PRW-BDM_YTnz.js} +5 -5
- package/dist/static/assets/{chunk-B4BG7PRW-_roYgl4_.js.map → chunk-B4BG7PRW-BDM_YTnz.js.map} +1 -1
- package/dist/static/assets/{chunk-DI55MBZ5-65DWu0ny.js → chunk-DI55MBZ5-Xyqh4xSb.js} +4 -4
- package/dist/static/assets/{chunk-DI55MBZ5-65DWu0ny.js.map → chunk-DI55MBZ5-Xyqh4xSb.js.map} +1 -1
- package/dist/static/assets/{chunk-FMBD7UC4-suO96TII.js → chunk-FMBD7UC4-Dh2eumwL.js} +2 -2
- package/dist/static/assets/{chunk-FMBD7UC4-suO96TII.js.map → chunk-FMBD7UC4-Dh2eumwL.js.map} +1 -1
- package/dist/static/assets/{chunk-QN33PNHL-CSWxSU4j.js → chunk-QN33PNHL-ozUUvqW2.js} +2 -2
- package/dist/static/assets/{chunk-QN33PNHL-CSWxSU4j.js.map → chunk-QN33PNHL-ozUUvqW2.js.map} +1 -1
- package/dist/static/assets/{chunk-QZHKN3VN-uzgBslqF.js → chunk-QZHKN3VN-DSB7FsZ7.js} +2 -2
- package/dist/static/assets/{chunk-QZHKN3VN-uzgBslqF.js.map → chunk-QZHKN3VN-DSB7FsZ7.js.map} +1 -1
- package/dist/static/assets/{chunk-TZMSLE5B-Bs3-ioaP.js → chunk-TZMSLE5B-CPAaVWZK.js} +2 -2
- package/dist/static/assets/{chunk-TZMSLE5B-Bs3-ioaP.js.map → chunk-TZMSLE5B-CPAaVWZK.js.map} +1 -1
- package/dist/static/assets/{classDiagram-2ON5EDUG-BwRTuVYR.js → classDiagram-2ON5EDUG-C-sqbbO5.js} +6 -6
- package/dist/static/assets/{classDiagram-2ON5EDUG-BwRTuVYR.js.map → classDiagram-2ON5EDUG-C-sqbbO5.js.map} +1 -1
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-BwRTuVYR.js → classDiagram-v2-WZHVMYZB-C-sqbbO5.js} +6 -6
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-BwRTuVYR.js.map → classDiagram-v2-WZHVMYZB-C-sqbbO5.js.map} +1 -1
- package/dist/static/assets/{clone-DTU0L3GE.js → clone-By5ScCya.js} +2 -2
- package/dist/static/assets/{clone-DTU0L3GE.js.map → clone-By5ScCya.js.map} +1 -1
- package/dist/static/assets/{cose-bilkent-S5V4N54A-DFN-M43c.js → cose-bilkent-S5V4N54A-C4NGA9He.js} +2 -2
- package/dist/static/assets/{cose-bilkent-S5V4N54A-DFN-M43c.js.map → cose-bilkent-S5V4N54A-C4NGA9He.js.map} +1 -1
- package/dist/static/assets/{dagre-6UL2VRFP-Db2QO3fw.js → dagre-6UL2VRFP-BkWOYnuR.js} +7 -7
- package/dist/static/assets/{dagre-6UL2VRFP-Db2QO3fw.js.map → dagre-6UL2VRFP-BkWOYnuR.js.map} +1 -1
- package/dist/static/assets/{diagram-PSM6KHXK-KdgI-gRF.js → diagram-PSM6KHXK-BzrBbXJK.js} +7 -7
- package/dist/static/assets/{diagram-PSM6KHXK-KdgI-gRF.js.map → diagram-PSM6KHXK-BzrBbXJK.js.map} +1 -1
- package/dist/static/assets/{diagram-QEK2KX5R-xH-jYUSp.js → diagram-QEK2KX5R-B0MnvOMb.js} +6 -6
- package/dist/static/assets/{diagram-QEK2KX5R-xH-jYUSp.js.map → diagram-QEK2KX5R-B0MnvOMb.js.map} +1 -1
- package/dist/static/assets/{diagram-S2PKOQOG-xaw91UrD.js → diagram-S2PKOQOG-BcO1Dh4d.js} +6 -6
- package/dist/static/assets/{diagram-S2PKOQOG-xaw91UrD.js.map → diagram-S2PKOQOG-BcO1Dh4d.js.map} +1 -1
- package/dist/static/assets/{erDiagram-Q2GNP2WA-BBxSVxZ2.js → erDiagram-Q2GNP2WA-DhJ57Zr6.js} +5 -5
- package/dist/static/assets/{erDiagram-Q2GNP2WA-BBxSVxZ2.js.map → erDiagram-Q2GNP2WA-DhJ57Zr6.js.map} +1 -1
- package/dist/static/assets/{flowDiagram-NV44I4VS-yzYTEiMx.js → flowDiagram-NV44I4VS-DE2_JdPY.js} +6 -6
- package/dist/static/assets/{flowDiagram-NV44I4VS-yzYTEiMx.js.map → flowDiagram-NV44I4VS-DE2_JdPY.js.map} +1 -1
- package/dist/static/assets/{ganttDiagram-JELNMOA3-CfOHq8RS.js → ganttDiagram-JELNMOA3-DkBsTv2T.js} +3 -3
- package/dist/static/assets/{ganttDiagram-JELNMOA3-CfOHq8RS.js.map → ganttDiagram-JELNMOA3-DkBsTv2T.js.map} +1 -1
- package/dist/static/assets/{gitGraphDiagram-NY62KEGX-DeZv5Du8.js → gitGraphDiagram-NY62KEGX-DV3eZqmy.js} +7 -7
- package/dist/static/assets/{gitGraphDiagram-NY62KEGX-DeZv5Du8.js.map → gitGraphDiagram-NY62KEGX-DV3eZqmy.js.map} +1 -1
- package/dist/static/assets/{graph-CDFIwKM1.js → graph-Dzw1schx.js} +3 -3
- package/dist/static/assets/{graph-CDFIwKM1.js.map → graph-Dzw1schx.js.map} +1 -1
- package/dist/static/assets/{index-BW6RWfVV.js → index-smy5Hge5.js} +84 -46
- package/dist/static/assets/{index-BW6RWfVV.js.map → index-smy5Hge5.js.map} +1 -1
- package/dist/static/assets/{infoDiagram-WHAUD3N6-DDDknjUc.js → infoDiagram-WHAUD3N6-BYQkShzE.js} +5 -5
- package/dist/static/assets/{infoDiagram-WHAUD3N6-DDDknjUc.js.map → infoDiagram-WHAUD3N6-BYQkShzE.js.map} +1 -1
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Bj6kqefO.js → journeyDiagram-XKPGCS4Q-B2Ofj4oX.js} +5 -5
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Bj6kqefO.js.map → journeyDiagram-XKPGCS4Q-B2Ofj4oX.js.map} +1 -1
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-DyIxtovg.js → kanban-definition-3W4ZIXB7-Be4yiLP0.js} +3 -3
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-DyIxtovg.js.map → kanban-definition-3W4ZIXB7-Be4yiLP0.js.map} +1 -1
- package/dist/static/assets/{layout-CenW9Lg4.js → layout-omu98FP8.js} +5 -5
- package/dist/static/assets/{layout-CenW9Lg4.js.map → layout-omu98FP8.js.map} +1 -1
- package/dist/static/assets/{linear-CIqoXI1R.js → linear-Csyd8pXl.js} +2 -2
- package/dist/static/assets/{linear-CIqoXI1R.js.map → linear-Csyd8pXl.js.map} +1 -1
- package/dist/static/assets/{min-PhMlVnVp.js → min-CdkxEeTW.js} +3 -3
- package/dist/static/assets/{min-PhMlVnVp.js.map → min-CdkxEeTW.js.map} +1 -1
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-BEc0C731.js → mindmap-definition-VGOIOE7T-nc4RuImy.js} +4 -4
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-BEc0C731.js.map → mindmap-definition-VGOIOE7T-nc4RuImy.js.map} +1 -1
- package/dist/static/assets/{pieDiagram-ADFJNKIX-Y9g6QrPu.js → pieDiagram-ADFJNKIX-D9-0_cv2.js} +7 -7
- package/dist/static/assets/{pieDiagram-ADFJNKIX-Y9g6QrPu.js.map → pieDiagram-ADFJNKIX-D9-0_cv2.js.map} +1 -1
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-0flyaoAo.js → quadrantDiagram-AYHSOK5B-C2fbgOCn.js} +3 -3
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-0flyaoAo.js.map → quadrantDiagram-AYHSOK5B-C2fbgOCn.js.map} +1 -1
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-F46cCDfo.js → requirementDiagram-UZGBJVZJ-DTesSf61.js} +4 -4
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-F46cCDfo.js.map → requirementDiagram-UZGBJVZJ-DTesSf61.js.map} +1 -1
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-B56j3BkK.js → sankeyDiagram-TZEHDZUN-ZWNntzxe.js} +2 -2
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-B56j3BkK.js.map → sankeyDiagram-TZEHDZUN-ZWNntzxe.js.map} +1 -1
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-DzQxEivA.js → sequenceDiagram-WL72ISMW-Ci-51cqk.js} +4 -4
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-DzQxEivA.js.map → sequenceDiagram-WL72ISMW-Ci-51cqk.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-8zkC6mTh.js → stateDiagram-FKZM4ZOC-EPKqXOfY.js} +9 -9
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-8zkC6mTh.js.map → stateDiagram-FKZM4ZOC-EPKqXOfY.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-CwSo5ElY.js → stateDiagram-v2-4FDKWEC3-CQHvPi94.js} +5 -5
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-CwSo5ElY.js.map → stateDiagram-v2-4FDKWEC3-CQHvPi94.js.map} +1 -1
- package/dist/static/assets/{timeline-definition-IT6M3QCI-ZlRniSmj.js → timeline-definition-IT6M3QCI-ByNrm0qi.js} +3 -3
- package/dist/static/assets/{timeline-definition-IT6M3QCI-ZlRniSmj.js.map → timeline-definition-IT6M3QCI-ByNrm0qi.js.map} +1 -1
- package/dist/static/assets/{treemap-KMMF4GRG-D1jARXF5.js → treemap-KMMF4GRG-CoEvR_zQ.js} +4 -4
- package/dist/static/assets/{treemap-KMMF4GRG-D1jARXF5.js.map → treemap-KMMF4GRG-CoEvR_zQ.js.map} +1 -1
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-BPX1HHsI.js → xychartDiagram-PRI3JC2R-Dex1o_-m.js} +3 -3
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-BPX1HHsI.js.map → xychartDiagram-PRI3JC2R-Dex1o_-m.js.map} +1 -1
- package/dist/static/index.html +1 -1
- package/dist/team-config-updates.js +180 -0
- package/dist/team.js +82 -3
- package/dist/tellask.js +11 -3
- package/dist/tools/context-health.js +7 -7
- package/dist/tools/diag.js +2 -2
- package/dist/tools/team-mgmt.js +2 -2
- package/dist/utils/task-doc.js +16 -16
- package/package.json +1 -1
- package/dist/minds/builtin/cmdr/persona.md +0 -3
- package/dist/minds/builtin/dijiang/knowledge.md +0 -287
- package/dist/minds/builtin/dijiang/persona.md +0 -7
|
@@ -5,6 +5,25 @@ exports.ensureDialogLoaded = ensureDialogLoaded;
|
|
|
5
5
|
const dialog_1 = require("./dialog");
|
|
6
6
|
const dialog_global_registry_1 = require("./dialog-global-registry");
|
|
7
7
|
const persistence_1 = require("./persistence");
|
|
8
|
+
const diligence_1 = require("./shared/diligence");
|
|
9
|
+
const team_1 = require("./team");
|
|
10
|
+
function resolveMemberDiligencePushMax(team, agentId) {
|
|
11
|
+
const member = team.getMember(agentId);
|
|
12
|
+
if (member && member.diligence_push_max !== undefined) {
|
|
13
|
+
return member.diligence_push_max;
|
|
14
|
+
}
|
|
15
|
+
return diligence_1.DEFAULT_DILIGENCE_PUSH_MAX;
|
|
16
|
+
}
|
|
17
|
+
function normalizeDiligencePushMax(value) {
|
|
18
|
+
if (!Number.isFinite(value))
|
|
19
|
+
return 0;
|
|
20
|
+
return Math.floor(value);
|
|
21
|
+
}
|
|
22
|
+
function clampNonNegativeFiniteInt(value, fallback) {
|
|
23
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
24
|
+
return fallback;
|
|
25
|
+
return Math.max(0, Math.floor(value));
|
|
26
|
+
}
|
|
8
27
|
async function getOrRestoreRootDialog(rootId, status) {
|
|
9
28
|
const existing = dialog_global_registry_1.globalDialogRegistry.get(rootId);
|
|
10
29
|
if (existing) {
|
|
@@ -18,6 +37,15 @@ async function getOrRestoreRootDialog(rootId, status) {
|
|
|
18
37
|
if (!rootState)
|
|
19
38
|
return undefined;
|
|
20
39
|
const latest = await persistence_1.DialogPersistence.loadDialogLatest(rootDialogId, status);
|
|
40
|
+
let diligencePushMax = diligence_1.DEFAULT_DILIGENCE_PUSH_MAX;
|
|
41
|
+
try {
|
|
42
|
+
const team = await team_1.Team.load();
|
|
43
|
+
diligencePushMax = normalizeDiligencePushMax(resolveMemberDiligencePushMax(team, rootState.metadata.agentId));
|
|
44
|
+
}
|
|
45
|
+
catch (_err) {
|
|
46
|
+
diligencePushMax = diligence_1.DEFAULT_DILIGENCE_PUSH_MAX;
|
|
47
|
+
}
|
|
48
|
+
const defaultDisableDiligencePush = diligencePushMax <= 0;
|
|
21
49
|
const rootStore = new persistence_1.DiskFileDialogStore(rootDialogId);
|
|
22
50
|
const rootDialog = new dialog_1.RootDialog(rootStore, rootState.metadata.taskDocPath, rootDialogId, rootState.metadata.agentId, {
|
|
23
51
|
messages: rootState.messages,
|
|
@@ -25,7 +53,18 @@ async function getOrRestoreRootDialog(rootId, status) {
|
|
|
25
53
|
currentCourse: rootState.currentCourse,
|
|
26
54
|
contextHealth: rootState.contextHealth,
|
|
27
55
|
});
|
|
28
|
-
|
|
56
|
+
const persistedDisableDiligencePush = latest && typeof latest.disableDiligencePush === 'boolean'
|
|
57
|
+
? latest.disableDiligencePush
|
|
58
|
+
: defaultDisableDiligencePush;
|
|
59
|
+
rootDialog.disableDiligencePush = persistedDisableDiligencePush;
|
|
60
|
+
const persistedRemainingBudget = latest && typeof latest.diligencePushRemainingBudget === 'number'
|
|
61
|
+
? latest.diligencePushRemainingBudget
|
|
62
|
+
: undefined;
|
|
63
|
+
const normalizedRemainingBudget = clampNonNegativeFiniteInt(persistedRemainingBudget, diligencePushMax > 0 ? diligencePushMax : 0);
|
|
64
|
+
rootDialog.diligencePushRemainingBudget =
|
|
65
|
+
diligencePushMax > 0
|
|
66
|
+
? Math.min(normalizedRemainingBudget, diligencePushMax)
|
|
67
|
+
: normalizedRemainingBudget;
|
|
29
68
|
rootDialog.setPersistenceStatus(status);
|
|
30
69
|
dialog_global_registry_1.globalDialogRegistry.register(rootDialog);
|
|
31
70
|
// Keep the in-memory root dialog fully hydrated regardless of persistence status
|
package/dist/dialog.js
CHANGED
|
@@ -96,8 +96,8 @@ class Dialog {
|
|
|
96
96
|
// Phase 11: Suspension state for Type A subdialog mechanism
|
|
97
97
|
// Tracks whether this dialog is in normal state, suspended, or resuming from suspension
|
|
98
98
|
this._suspensionState = 'active';
|
|
99
|
-
// Diligence Push (diligence auto-continue) budget counter (
|
|
100
|
-
//
|
|
99
|
+
// Diligence Push (diligence auto-continue) budget counter (root-dialog state).
|
|
100
|
+
// Persisted via latest.yaml so restarts and UI navigation can restore correct remaining budget.
|
|
101
101
|
this.diligencePushRemainingBudget = 0;
|
|
102
102
|
// Diligence Push disable switch (persisted via latest.yaml; default = false).
|
|
103
103
|
this.disableDiligencePush = false;
|
|
@@ -64,6 +64,12 @@ The **subdialog registry** is a root dialog-scoped Map that maintains persistent
|
|
|
64
64
|
|
|
65
65
|
A **teammate Tellask** is a Dominds specific syntax that triggers communication with another agent as subdialog. Teammate Tellasks have three distinct patterns with different semantics (see Section 3).
|
|
66
66
|
|
|
67
|
+
**Tellask block structure** (see also `dominds/docs/dominds-terminology.md`):
|
|
68
|
+
|
|
69
|
+
- **Tellask headline**: the first line `!?@<name> ...` (additional `!?@...` lines in the same block are appended to the headline).
|
|
70
|
+
- **Tellask body**: subsequent lines that start with `!?` but not `!?@`.
|
|
71
|
+
- Structured directives like `!tellaskSession <slug>` MUST be in the headline.
|
|
72
|
+
|
|
67
73
|
---
|
|
68
74
|
|
|
69
75
|
## Backend-Driven Architecture
|
|
@@ -64,6 +64,12 @@
|
|
|
64
64
|
|
|
65
65
|
**队友 Tellask** 是 Dominds 特定的语法,触发与另一个作为子对话的代理的通信。队友 Tellask 有三种不同模式,具有不同语义(见第 3 节)。
|
|
66
66
|
|
|
67
|
+
**诉请块结构**(另见 `dominds/docs/dominds-terminology.md`):
|
|
68
|
+
|
|
69
|
+
- **诉请头(Tellask headline)**:诉请块第一行 `!?@<name> ...`(同一诉请块内,后续以 `!?@...` 开头的行会并入诉请头)。
|
|
70
|
+
- **诉请内容(Tellask body)**:后续以 `!?` 开头但不以 `!?@` 开头的行。
|
|
71
|
+
- `!tellaskSession <slug>` 等结构化指令必须写在诉请头中。
|
|
72
|
+
|
|
67
73
|
---
|
|
68
74
|
|
|
69
75
|
## 后端驱动架构
|
|
@@ -156,6 +156,8 @@
|
|
|
156
156
|
### 快速对照(Quick Glossary)
|
|
157
157
|
|
|
158
158
|
- EN: `Tellask` | ZH: `诉请`
|
|
159
|
+
- EN: `Tellask headline` | ZH: `诉请头`
|
|
160
|
+
- EN: `Tellask body` | ZH: `诉请内容`
|
|
159
161
|
- EN: `TellaskBack` | ZH: `回问诉请`
|
|
160
162
|
- EN: `Tellask Session` | ZH: `长线诉请`
|
|
161
163
|
- EN: `Fresh Tellask` | ZH: `一次性诉请`
|
|
@@ -171,6 +173,22 @@
|
|
|
171
173
|
- EN: A Tellask is not casual chat; it is a collaboration action that Dominds can drive, route, and coordinate (including suspend/resume).
|
|
172
174
|
- ZH: Tellask 不是随意聊天,而是一种可被 Dominds 驱动、路由、并由系统协调(包括挂起/恢复)的协作动作。
|
|
173
175
|
|
|
176
|
+
#### Tellask headline(诉请头)
|
|
177
|
+
|
|
178
|
+
- EN: The first line of a Tellask block, starting with `!?@<name> ...`.
|
|
179
|
+
- ZH: 诉请块的第一行,以 `!?@<name> ...` 开头。
|
|
180
|
+
|
|
181
|
+
- EN: Additional lines starting with `!?@...` in the same block are appended to the headline (they do not start a new Tellask).
|
|
182
|
+
- ZH: 同一诉请块内,后续以 `!?@...` 开头的行会被并入诉请头(不会开启新的诉请)。
|
|
183
|
+
|
|
184
|
+
- EN: Put structured directives such as `!tellaskSession <slug>` in the headline.
|
|
185
|
+
- ZH: 结构化指令(例如 `!tellaskSession <slug>`)必须放在诉请头中。
|
|
186
|
+
|
|
187
|
+
#### Tellask body(诉请内容)
|
|
188
|
+
|
|
189
|
+
- EN: Lines in the Tellask block that start with `!?` but do not start with `!?@`. They carry the request context (steps, constraints, acceptance criteria, etc.).
|
|
190
|
+
- ZH: 诉请块内以 `!?` 开头但不以 `!?@` 开头的行,用于承载诉请内容(步骤、上下文、约束、验收标准等)。
|
|
191
|
+
|
|
174
192
|
### 3 种诉请形态(Three Tellask Modes)
|
|
175
193
|
|
|
176
194
|
- EN: These names are intended to replace implementation-heavy labels like “Type A/B/C” in user-facing prompts.
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Keep-Going(鞭策)— 设计文档
|
|
2
|
+
|
|
3
|
+
## 概述
|
|
4
|
+
|
|
5
|
+
Dominds 根对话旨在长期运行。根对话"停止"(变为空闲)通常不是操作员想要的:他们希望智能体持续推进,直到:
|
|
6
|
+
|
|
7
|
+
- 合法地暂停等待人类决策(Q4H),或
|
|
8
|
+
- 合法地暂停等待子对话(tellask/backfill)。
|
|
9
|
+
|
|
10
|
+
本文档指定了一个运行时机制("keep-going"),仅针对**根/主对话**,防止对话停止:每当驱动程序即将停止时,它会自动发送一个简短的鞭策语(渲染为正常的用户气泡)并继续生成,除非对话处于合法暂停状态(Q4H 或待处理的子对话)。
|
|
11
|
+
|
|
12
|
+
## 目标
|
|
13
|
+
|
|
14
|
+
- 防止根对话停止,除非处于合法暂停状态(Q4H / 子对话)。
|
|
15
|
+
- 保持行为可预测和有界(无无限循环)。
|
|
16
|
+
- 使鞭策语文本可按工作区(rtws)和语言配置。
|
|
17
|
+
- 提供清晰的用户控制的"禁用"机制。
|
|
18
|
+
|
|
19
|
+
## 非目标
|
|
20
|
+
|
|
21
|
+
- 自动完成/自动将对话标记为完成。
|
|
22
|
+
- 将此行为应用于子对话(子对话保持范围,应向其调用者报告)。
|
|
23
|
+
|
|
24
|
+
## 定义
|
|
25
|
+
|
|
26
|
+
- **根/主对话**:`RootDialog`(`dlg.id.rootId === dlg.id.selfId`),主要对话线程。
|
|
27
|
+
- **子对话**:`SubDialog`,为 tellask / 作用域工作创建。
|
|
28
|
+
- **Q4H**:"Questions for Human",通过 `!?@human` 发起,暂停对话进度直到人类响应。
|
|
29
|
+
|
|
30
|
+
## 预期的"正常"完成路径(推荐)
|
|
31
|
+
|
|
32
|
+
当智能体需要人类决策来结束时(例如,确认选择或决定是否将对话标记为完成),正确的路径是:
|
|
33
|
+
|
|
34
|
+
1. 智能体发出 Q4H(`!?@human`)并提供必要的上下文和明确的决策请求。
|
|
35
|
+
2. WebUI 清楚地呈现 Q4H。
|
|
36
|
+
3. 人类决定并:
|
|
37
|
+
- 手动将根对话标记为"完成",或
|
|
38
|
+
- 提供请求的信息以便对话继续。
|
|
39
|
+
|
|
40
|
+
这是"受控收敛"路径。keep-going 机制不应覆盖合法的暂停状态。
|
|
41
|
+
|
|
42
|
+
## Keep-Going 行为("自动继续"回退)
|
|
43
|
+
|
|
44
|
+
### 触发条件(必须全部满足)
|
|
45
|
+
|
|
46
|
+
- 对话是**根/主对话**(绝不会是子对话)。
|
|
47
|
+
- 对话**未暂停**:
|
|
48
|
+
- 没有待处理的 Q4H,并且
|
|
49
|
+
- 没有待处理的子对话(等待回填)。
|
|
50
|
+
- 驱动程序即将停止生成循环(即没有工具/函数输出需要另一次迭代)。
|
|
51
|
+
|
|
52
|
+
### 操作
|
|
53
|
+
|
|
54
|
+
运行时自动发送一个鞭策语(渲染为正常的用户气泡)并运行另一次生成迭代。
|
|
55
|
+
|
|
56
|
+
### 有界性
|
|
57
|
+
|
|
58
|
+
为避免无限循环,keep-going 有一个按对话的预算(每个成员的 `diligence-push-max`),控制对于给定对话在运行时强制 Q4H 暂停之前可以注入多少个自动继续的鞭策语。
|
|
59
|
+
|
|
60
|
+
- 默认值:**3**
|
|
61
|
+
- 如果 `< 1`,则该成员的 keep-going 有效禁用
|
|
62
|
+
- 可通过 `.minds/team.yaml` 中的 `diligence-push-max` 按成员配置
|
|
63
|
+
|
|
64
|
+
### Q4H 时重置
|
|
65
|
+
|
|
66
|
+
当对话因待处理的 Q4H(Questions for Human)而暂停时,keep-going 注入计数器会被重置。这确保在人类回答 Q4H 并恢复对话后,对话会获得新的 keep-going 预算。
|
|
67
|
+
|
|
68
|
+
### 预算耗尽 → 强制 Q4H
|
|
69
|
+
|
|
70
|
+
当 keep-going 预算耗尽时,运行时会创建一个 Q4H 条目,询问人类是否继续或停止。这将"有界性"转换为合法的暂停点,并避免无限自动继续循环。
|
|
71
|
+
|
|
72
|
+
### 禁用开关
|
|
73
|
+
|
|
74
|
+
可以通过以下任一方式按 rtws 禁用 keep-going:
|
|
75
|
+
|
|
76
|
+
- 如果选中的鞭策语文件存在但其内容为空/仅空白,则禁用 keep-going(不注入)。
|
|
77
|
+
|
|
78
|
+
可以通过以下任一方式按成员禁用 keep-going:
|
|
79
|
+
|
|
80
|
+
- 如果 `diligence-push-max < 1`,则该成员的 keep-going 被禁用(不注入)。
|
|
81
|
+
|
|
82
|
+
## 鞭策语解析
|
|
83
|
+
|
|
84
|
+
让 `<rtws>` 为当前运行时工作区(即 `process.cwd()`)。
|
|
85
|
+
|
|
86
|
+
解析顺序:
|
|
87
|
+
|
|
88
|
+
1. `<rtws>/.minds/diligence.<work-lang-id>.md`(例如,`diligence.zh.md`)
|
|
89
|
+
2. `<rtws>/.minds/diligence.md`(语言无关的回退)
|
|
90
|
+
3. 内置回退文本(硬编码的 i18n;`zh` 是规范的并嵌入在源代码中)
|
|
91
|
+
|
|
92
|
+
如果上述顺序中第一个存在的文件具有空/空白内容,则**禁用** keep-going。
|
|
93
|
+
|
|
94
|
+
注意:鞭策语文件中的 YAML frontmatter 会被运行时忽略。如果存在,它被视为非内容元数据并从提示正文中剥离。
|
|
95
|
+
|
|
96
|
+
### 团队成员上限:`diligence-push-max`
|
|
97
|
+
|
|
98
|
+
每个团队成员可以选择通过 `.minds/team.yaml` 限制 keep-going:
|
|
99
|
+
|
|
100
|
+
```yaml
|
|
101
|
+
members:
|
|
102
|
+
alice:
|
|
103
|
+
diligence-push-max: 10
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
规则:
|
|
107
|
+
|
|
108
|
+
- 如果缺失,`diligence-push-max` 对于该成员默认为 **3**。
|
|
109
|
+
- 如果 `diligence-push-max < 1`,则该成员的 keep-going 被禁用(不注入),即使鞭策语文件存在。
|
|
110
|
+
- 内置影子成员 `fuxi` 和 `pangu` 默认为 `diligence-push-max: 0`,除非在 team.yaml 中显式覆盖。
|
|
111
|
+
|
|
112
|
+
## UX 备注
|
|
113
|
+
|
|
114
|
+
- Keep-going 是一个仅运行时的提示,但它应该是**可见的**:鞭策语渲染为正常的用户消息气泡(由运行时自动发送),以便操作员理解为什么会出现额外的迭代。
|
|
115
|
+
- 用户应该观察到智能体在仅工具操作后继续简短的跟进。
|
|
116
|
+
- 当智能体真正需要用户干预时,它应该使用 Q4H。Keep-going 不应试图"假装"完成。
|
|
117
|
+
|
|
118
|
+
## 实现(后端)
|
|
119
|
+
|
|
120
|
+
### 位置
|
|
121
|
+
|
|
122
|
+
在 LLM 驱动程序循环中实现(`dominds/main/llm/driver.ts`),作为迭代后的小检查:
|
|
123
|
+
|
|
124
|
+
1. 如果 `suspendForHuman` 为 true,则停止(Q4H / 子对话待处理)。
|
|
125
|
+
2. 如果有任何工具反馈,则正常继续。
|
|
126
|
+
3. 否则(仅限根),尝试 keep-going 自动继续:
|
|
127
|
+
- 如果禁用 → 正常停止。
|
|
128
|
+
- 如果预算耗尽 → 创建 Q4H 并停止。
|
|
129
|
+
- 否则 → 自动发送鞭策语并继续。
|
|
130
|
+
|
|
131
|
+
### 消息类型
|
|
132
|
+
|
|
133
|
+
我们将鞭策语作为自动发送的用户消息注入:
|
|
134
|
+
|
|
135
|
+
- 类型为 `prompting_msg`、角色为 `'user'` 的 `ChatMessage`
|
|
136
|
+
|
|
137
|
+
这确保了:
|
|
138
|
+
|
|
139
|
+
- 它存在于模型上下文中
|
|
140
|
+
- 它作为人类消息记录持久化
|
|
141
|
+
- 它在聊天时间线中渲染为正常的用户气泡(像任何其他用户消息一样)
|
|
142
|
+
|
|
143
|
+
## 可观察性
|
|
144
|
+
|
|
145
|
+
建议的后续步骤(初始实现不需要):
|
|
146
|
+
|
|
147
|
+
- 当触发 keep-going 时添加结构化日志行,包括:
|
|
148
|
+
- 对话 id
|
|
149
|
+
- 语言
|
|
150
|
+
- 使用的鞭策语来源(语言特定/通用/内置/禁用)
|
|
151
|
+
- 为"keep-going 触发"和"keep-going 因空文件禁用"添加可选的指标计数器。
|
|
152
|
+
|
|
153
|
+
## 测试
|
|
154
|
+
|
|
155
|
+
回归测试应覆盖:
|
|
156
|
+
|
|
157
|
+
- 根对话:仅工具输出 → 鞭策语注入 → 继续响应
|
|
158
|
+
- 根对话:空助手输出 → 鞭策语注入 → 继续响应
|
|
159
|
+
- 子对话:无鞭策语注入
|
|
160
|
+
- 工作区配置:
|
|
161
|
+
- 当语言特定文件缺失时,`.minds/diligence.md` 被遵守
|
|
162
|
+
- 空的鞭策语文件禁用 keep-going
|
package/dist/llm/driver.js
CHANGED
|
@@ -754,8 +754,8 @@ function createSayingEventsReceiver(dlg) {
|
|
|
754
754
|
callBodyFinish: async () => {
|
|
755
755
|
await dlg.callingBodyFinish();
|
|
756
756
|
},
|
|
757
|
-
callFinish: async (
|
|
758
|
-
await dlg.callingFinish(callId);
|
|
757
|
+
callFinish: async (call, _upstreamEndOffset) => {
|
|
758
|
+
await dlg.callingFinish(call.callId);
|
|
759
759
|
},
|
|
760
760
|
};
|
|
761
761
|
}
|
|
@@ -908,8 +908,6 @@ async function runBackendDriver() {
|
|
|
908
908
|
for (const rootDialog of dialogsToDrive) {
|
|
909
909
|
try {
|
|
910
910
|
if (!(await rootDialog.canDrive())) {
|
|
911
|
-
dialog_global_registry_1.globalDialogRegistry.markNotNeedingDrive(rootDialog.id.rootId);
|
|
912
|
-
await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, false, rootDialog.status);
|
|
913
911
|
continue;
|
|
914
912
|
}
|
|
915
913
|
const release = await rootDialog.acquire();
|
|
@@ -919,7 +917,9 @@ async function runBackendDriver() {
|
|
|
919
917
|
finally {
|
|
920
918
|
release();
|
|
921
919
|
}
|
|
922
|
-
|
|
920
|
+
const status = await rootDialog.getSuspensionStatus();
|
|
921
|
+
const shouldStayQueued = rootDialog.hasUpNext() || !status.canDrive;
|
|
922
|
+
if (shouldStayQueued) {
|
|
923
923
|
dialog_global_registry_1.globalDialogRegistry.markNeedsDrive(rootDialog.id.rootId);
|
|
924
924
|
await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, true, rootDialog.status);
|
|
925
925
|
}
|
|
@@ -927,7 +927,6 @@ async function runBackendDriver() {
|
|
|
927
927
|
dialog_global_registry_1.globalDialogRegistry.markNotNeedingDrive(rootDialog.id.rootId);
|
|
928
928
|
await persistence_1.DialogPersistence.setNeedsDrive(rootDialog.id, false, rootDialog.status);
|
|
929
929
|
}
|
|
930
|
-
const status = await rootDialog.getSuspensionStatus();
|
|
931
930
|
if (status.subdialogs) {
|
|
932
931
|
log_1.log.info(`Dialog ${rootDialog.id.rootId} suspended, waiting for subdialogs`);
|
|
933
932
|
}
|
|
@@ -1067,6 +1066,46 @@ async function _driveDialogStream(dlg, humanPrompt) {
|
|
|
1067
1066
|
log_1.log.warn(`Provider not found for agent ${dlg.agentId}`, error);
|
|
1068
1067
|
throw error;
|
|
1069
1068
|
}
|
|
1069
|
+
const modelsUnknown = providerCfg.models;
|
|
1070
|
+
const models = typeof modelsUnknown === 'object' && modelsUnknown !== null && !Array.isArray(modelsUnknown)
|
|
1071
|
+
? modelsUnknown
|
|
1072
|
+
: undefined;
|
|
1073
|
+
const modelInfo = models ? models[model] : undefined;
|
|
1074
|
+
if (!modelInfo) {
|
|
1075
|
+
const uiLanguage = dlg.getUiLanguage();
|
|
1076
|
+
const msg = uiLanguage === 'zh'
|
|
1077
|
+
? [
|
|
1078
|
+
'配置错误:当前成员的模型配置无效。',
|
|
1079
|
+
'',
|
|
1080
|
+
`- member: ${agent.name} (${dlg.agentId})`,
|
|
1081
|
+
`- provider: ${provider}`,
|
|
1082
|
+
`- model: ${model}(这是 model key;在该 provider 的 models 列表中不存在,或该 provider 缺少 models 配置)`,
|
|
1083
|
+
'',
|
|
1084
|
+
'请联系团队管理者修复:',
|
|
1085
|
+
`- 在 .minds/team.yaml 中把该成员的 provider/model 改成有效 key;或`,
|
|
1086
|
+
`- 在 .minds/llm.yaml 的 providers.${provider}.models 下补齐该 model key。`,
|
|
1087
|
+
'',
|
|
1088
|
+
'提示:你也可以打开 WebUI 的 `/setup` 查看当前工作区可用的 provider/model 列表。',
|
|
1089
|
+
'',
|
|
1090
|
+
'团队管理者修复后建议运行:`team_mgmt_validate_team_cfg({})`。',
|
|
1091
|
+
].join('\n')
|
|
1092
|
+
: [
|
|
1093
|
+
'Configuration error: invalid model selection for this member.',
|
|
1094
|
+
'',
|
|
1095
|
+
`- member: ${agent.name} (${dlg.agentId})`,
|
|
1096
|
+
`- provider: ${provider}`,
|
|
1097
|
+
`- model: ${model} (this is a model key; not found under this provider's models list, or the provider has no models configured)`,
|
|
1098
|
+
'',
|
|
1099
|
+
'Please contact your team manager to fix:',
|
|
1100
|
+
`- Update the member's provider/model keys in .minds/team.yaml, or`,
|
|
1101
|
+
`- Add the model key under .minds/llm.yaml providers.${provider}.models.`,
|
|
1102
|
+
'',
|
|
1103
|
+
'Tip: you can also open the WebUI `/setup` page to see available provider/model keys for this workspace.',
|
|
1104
|
+
'',
|
|
1105
|
+
'After the fix, the team manager should run: `team_mgmt_validate_team_cfg({})`.',
|
|
1106
|
+
].join('\n');
|
|
1107
|
+
throw new Error(msg);
|
|
1108
|
+
}
|
|
1070
1109
|
const llmGen = (0, registry_1.getLlmGenerator)(providerCfg.apiType);
|
|
1071
1110
|
if (!llmGen) {
|
|
1072
1111
|
const error = new Error(`LLM generator not found: API type '${providerCfg.apiType}' for provider '${provider}' in agent '${dlg.agentId}'. Please check .minds/llm.yaml configuration.`);
|
|
@@ -1471,6 +1510,10 @@ async function _driveDialogStream(dlg, humanPrompt) {
|
|
|
1471
1510
|
else {
|
|
1472
1511
|
dlg.diligencePushRemainingBudget = Math.max(0, Math.floor(dlg.diligencePushRemainingBudget));
|
|
1473
1512
|
}
|
|
1513
|
+
void persistence_1.DialogPersistence.mutateDialogLatest(dlg.id, () => ({
|
|
1514
|
+
kind: 'patch',
|
|
1515
|
+
patch: { diligencePushRemainingBudget: dlg.diligencePushRemainingBudget },
|
|
1516
|
+
}));
|
|
1474
1517
|
}
|
|
1475
1518
|
}
|
|
1476
1519
|
catch (err) {
|
|
@@ -1500,6 +1543,10 @@ async function _driveDialogStream(dlg, humanPrompt) {
|
|
|
1500
1543
|
else {
|
|
1501
1544
|
dlg.diligencePushRemainingBudget = Math.max(0, Math.floor(dlg.diligencePushRemainingBudget));
|
|
1502
1545
|
}
|
|
1546
|
+
void persistence_1.DialogPersistence.mutateDialogLatest(dlg.id, () => ({
|
|
1547
|
+
kind: 'patch',
|
|
1548
|
+
patch: { diligencePushRemainingBudget: dlg.diligencePushRemainingBudget },
|
|
1549
|
+
}));
|
|
1503
1550
|
}
|
|
1504
1551
|
break;
|
|
1505
1552
|
}
|
|
@@ -1510,6 +1557,10 @@ async function _driveDialogStream(dlg, humanPrompt) {
|
|
|
1510
1557
|
diligencePushMax: resolveMemberDiligencePushMax(team, dlg.agentId),
|
|
1511
1558
|
});
|
|
1512
1559
|
dlg.diligencePushRemainingBudget = prepared.nextRemainingBudget;
|
|
1560
|
+
void persistence_1.DialogPersistence.mutateDialogLatest(dlg.id, () => ({
|
|
1561
|
+
kind: 'patch',
|
|
1562
|
+
patch: { diligencePushRemainingBudget: dlg.diligencePushRemainingBudget },
|
|
1563
|
+
}));
|
|
1513
1564
|
if (prepared.kind !== 'disabled') {
|
|
1514
1565
|
(0, evt_registry_1.postDialogEvent)(dlg, {
|
|
1515
1566
|
type: 'diligence_budget_evt',
|
|
@@ -1880,6 +1931,10 @@ async function _driveDialogStream(dlg, humanPrompt) {
|
|
|
1880
1931
|
else {
|
|
1881
1932
|
dlg.diligencePushRemainingBudget = Math.max(0, Math.floor(dlg.diligencePushRemainingBudget));
|
|
1882
1933
|
}
|
|
1934
|
+
void persistence_1.DialogPersistence.mutateDialogLatest(dlg.id, () => ({
|
|
1935
|
+
kind: 'patch',
|
|
1936
|
+
patch: { diligencePushRemainingBudget: dlg.diligencePushRemainingBudget },
|
|
1937
|
+
}));
|
|
1883
1938
|
}
|
|
1884
1939
|
break;
|
|
1885
1940
|
}
|
|
@@ -1890,6 +1945,10 @@ async function _driveDialogStream(dlg, humanPrompt) {
|
|
|
1890
1945
|
diligencePushMax: resolveMemberDiligencePushMax(team, dlg.agentId),
|
|
1891
1946
|
});
|
|
1892
1947
|
dlg.diligencePushRemainingBudget = prepared.nextRemainingBudget;
|
|
1948
|
+
void persistence_1.DialogPersistence.mutateDialogLatest(dlg.id, () => ({
|
|
1949
|
+
kind: 'patch',
|
|
1950
|
+
patch: { diligencePushRemainingBudget: dlg.diligencePushRemainingBudget },
|
|
1951
|
+
}));
|
|
1893
1952
|
if (prepared.kind !== 'disabled') {
|
|
1894
1953
|
(0, evt_registry_1.postDialogEvent)(dlg, {
|
|
1895
1954
|
type: 'diligence_budget_evt',
|
|
@@ -2457,9 +2516,7 @@ async function supplyResponseToSupdialog(parentDialog, subdialogId, responseText
|
|
|
2457
2516
|
if (parentDialog instanceof dialog_1.RootDialog) {
|
|
2458
2517
|
dialog_global_registry_1.globalDialogRegistry.markNeedsDrive(parentDialog.id.rootId);
|
|
2459
2518
|
}
|
|
2460
|
-
|
|
2461
|
-
void driveDialogStream(parentDialog, undefined, true);
|
|
2462
|
-
}
|
|
2519
|
+
void driveDialogStream(parentDialog, undefined, true);
|
|
2463
2520
|
}
|
|
2464
2521
|
}
|
|
2465
2522
|
catch (error) {
|
package/dist/llm/gen/codex.js
CHANGED
|
@@ -395,6 +395,17 @@ class CodexGen {
|
|
|
395
395
|
}
|
|
396
396
|
return;
|
|
397
397
|
}
|
|
398
|
+
case 'response.reasoning_summary_text.done':
|
|
399
|
+
case 'response.reasoning_text.done':
|
|
400
|
+
case 'response.reasoning_summary_part.done': {
|
|
401
|
+
if (thinkingStarted) {
|
|
402
|
+
await receiver.thinkingFinish();
|
|
403
|
+
thinkingStarted = false;
|
|
404
|
+
if (activeStream === 'thinking')
|
|
405
|
+
activeStream = 'idle';
|
|
406
|
+
}
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
398
409
|
case 'response.output_item.added':
|
|
399
410
|
return;
|
|
400
411
|
case 'response.output_item.done': {
|
package/dist/persistence.js
CHANGED
|
@@ -138,6 +138,9 @@ function parseDialogLatestFile(value) {
|
|
|
138
138
|
return null;
|
|
139
139
|
if (value.disableDiligencePush !== undefined && typeof value.disableDiligencePush !== 'boolean')
|
|
140
140
|
return null;
|
|
141
|
+
if (value.diligencePushRemainingBudget !== undefined &&
|
|
142
|
+
typeof value.diligencePushRemainingBudget !== 'number')
|
|
143
|
+
return null;
|
|
141
144
|
if (value.messageCount !== undefined && typeof value.messageCount !== 'number')
|
|
142
145
|
return null;
|
|
143
146
|
if (value.functionCallCount !== undefined && typeof value.functionCallCount !== 'number')
|
|
@@ -224,6 +227,7 @@ function parseDialogLatestFile(value) {
|
|
|
224
227
|
needsDrive: value.needsDrive,
|
|
225
228
|
runState,
|
|
226
229
|
disableDiligencePush: value.disableDiligencePush,
|
|
230
|
+
diligencePushRemainingBudget: value.diligencePushRemainingBudget,
|
|
227
231
|
};
|
|
228
232
|
}
|
|
229
233
|
function isSubdialogResponseRecord(value) {
|
|
@@ -1100,11 +1104,11 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
|
|
|
1100
1104
|
}));
|
|
1101
1105
|
}
|
|
1102
1106
|
},
|
|
1103
|
-
callFinish: async (
|
|
1107
|
+
callFinish: async (call) => {
|
|
1104
1108
|
if (ws.readyState === 1) {
|
|
1105
1109
|
ws.send(JSON.stringify({
|
|
1106
1110
|
type: 'tool_call_finish_evt',
|
|
1107
|
-
callId:
|
|
1111
|
+
callId: call.callId,
|
|
1108
1112
|
course,
|
|
1109
1113
|
genseq,
|
|
1110
1114
|
dialog: { selfId: dialog.id.selfId, rootId: dialog.id.rootId },
|
|
@@ -1402,11 +1406,11 @@ class DiskFileDialogStore extends dialog_1.DialogStore {
|
|
|
1402
1406
|
}));
|
|
1403
1407
|
}
|
|
1404
1408
|
},
|
|
1405
|
-
callFinish: async (
|
|
1409
|
+
callFinish: async (call) => {
|
|
1406
1410
|
if (ws.readyState === 1) {
|
|
1407
1411
|
ws.send(JSON.stringify({
|
|
1408
1412
|
type: 'tool_call_finish_evt',
|
|
1409
|
-
callId,
|
|
1413
|
+
callId: call.callId,
|
|
1410
1414
|
course,
|
|
1411
1415
|
genseq: event.genseq,
|
|
1412
1416
|
dialog: {
|
|
@@ -62,6 +62,18 @@ const snippets_routes_1 = require("./snippets-routes");
|
|
|
62
62
|
// Dialog lookup is performed via file-backed persistence; no in-memory registry
|
|
63
63
|
const log = (0, log_1.createLogger)('api-routes');
|
|
64
64
|
let cachedDomindsVersion;
|
|
65
|
+
function resolveMemberDiligencePushMax(team, agentId) {
|
|
66
|
+
const member = team.getMember(agentId);
|
|
67
|
+
if (member && member.diligence_push_max !== undefined) {
|
|
68
|
+
return member.diligence_push_max;
|
|
69
|
+
}
|
|
70
|
+
return diligence_1.DEFAULT_DILIGENCE_PUSH_MAX;
|
|
71
|
+
}
|
|
72
|
+
function normalizeDiligencePushMax(value) {
|
|
73
|
+
if (!Number.isFinite(value))
|
|
74
|
+
return 0;
|
|
75
|
+
return Math.floor(value);
|
|
76
|
+
}
|
|
65
77
|
async function readDomindsPackageVersion() {
|
|
66
78
|
if (cachedDomindsVersion !== undefined)
|
|
67
79
|
return cachedDomindsVersion;
|
|
@@ -800,6 +812,11 @@ async function handleCreateDialog(req, res, context) {
|
|
|
800
812
|
// Create RootDialog
|
|
801
813
|
const dialog = new dialog_1.RootDialog(dialogUI, taskDocPath, dialogId, agentId);
|
|
802
814
|
dialog_global_registry_1.globalDialogRegistry.register(dialog);
|
|
815
|
+
const team = await team_1.Team.load();
|
|
816
|
+
const diligencePushMax = normalizeDiligencePushMax(resolveMemberDiligencePushMax(team, agentId));
|
|
817
|
+
const defaultDisableDiligencePush = diligencePushMax <= 0;
|
|
818
|
+
dialog.disableDiligencePush = defaultDisableDiligencePush;
|
|
819
|
+
dialog.diligencePushRemainingBudget = diligencePushMax > 0 ? diligencePushMax : 0;
|
|
803
820
|
// Persist dialog metadata and latest.yaml (write-once pattern)
|
|
804
821
|
const metadata = {
|
|
805
822
|
id: dialogId.selfId,
|
|
@@ -819,7 +836,8 @@ async function handleCreateDialog(req, res, context) {
|
|
|
819
836
|
functionCallCount: 0,
|
|
820
837
|
subdialogCount: 0,
|
|
821
838
|
runState: { kind: 'idle_waiting_user' },
|
|
822
|
-
disableDiligencePush:
|
|
839
|
+
disableDiligencePush: defaultDisableDiligencePush,
|
|
840
|
+
diligencePushRemainingBudget: dialog.diligencePushRemainingBudget,
|
|
823
841
|
},
|
|
824
842
|
}));
|
|
825
843
|
// Dialog is registered with the global registry on creation
|
|
@@ -15,6 +15,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
15
15
|
const yaml_1 = __importDefault(require("yaml"));
|
|
16
16
|
const client_1 = require("../llm/client");
|
|
17
17
|
const log_1 = require("../log");
|
|
18
|
+
const team_config_updates_1 = require("../team-config-updates");
|
|
18
19
|
const log = (0, log_1.createLogger)('setup-routes');
|
|
19
20
|
const TEAM_YAML_PATH = path_1.default.join('.minds', 'team.yaml');
|
|
20
21
|
const WORKSPACE_LLM_YAML_PATH = path_1.default.join('.minds', 'llm.yaml');
|
|
@@ -165,6 +166,7 @@ async function handleWriteTeamYaml(rawBody) {
|
|
|
165
166
|
await promises_1.default.mkdir(path_1.default.dirname(outPath), { recursive: true });
|
|
166
167
|
const content = buildMinimalTeamYaml(req);
|
|
167
168
|
await promises_1.default.writeFile(outPath, content, 'utf-8');
|
|
169
|
+
(0, team_config_updates_1.notifyTeamConfigUpdated)(`setup.write_team_yaml/${exists ? 'overwritten' : 'created'}`);
|
|
168
170
|
return {
|
|
169
171
|
kind: 'ok',
|
|
170
172
|
response: {
|
|
@@ -19,6 +19,7 @@ const runtime_language_1 = require("../shared/runtime-language");
|
|
|
19
19
|
const language_1 = require("../shared/types/language");
|
|
20
20
|
const time_1 = require("../shared/utils/time");
|
|
21
21
|
const team_1 = require("../team");
|
|
22
|
+
const team_config_updates_1 = require("../team-config-updates");
|
|
22
23
|
const id_1 = require("../utils/id");
|
|
23
24
|
const task_package_1 = require("../utils/task-package");
|
|
24
25
|
const auth_1 = require("./auth");
|
|
@@ -305,6 +306,10 @@ async function handleRefillDiligencePushBudget(ws, packet) {
|
|
|
305
306
|
rootDialog.diligencePushRemainingBudget =
|
|
306
307
|
clampNonNegativeFiniteInt(rootDialog.diligencePushRemainingBudget, 0) + 3;
|
|
307
308
|
}
|
|
309
|
+
await persistence_1.DialogPersistence.mutateDialogLatest(rootDialogId, () => ({
|
|
310
|
+
kind: 'patch',
|
|
311
|
+
patch: { diligencePushRemainingBudget: rootDialog.diligencePushRemainingBudget },
|
|
312
|
+
}), foundStatus);
|
|
308
313
|
(0, evt_registry_1.postDialogEvent)(rootDialog, {
|
|
309
314
|
type: 'diligence_budget_evt',
|
|
310
315
|
maxInjectCount: configuredMax > 0 ? configuredMax : 0,
|
|
@@ -404,6 +409,7 @@ async function handleCreateDialog(ws, packet) {
|
|
|
404
409
|
subdialogCount: 0,
|
|
405
410
|
runState: { kind: 'idle_waiting_user' },
|
|
406
411
|
disableDiligencePush: defaultDisableDiligencePush,
|
|
412
|
+
diligencePushRemainingBudget: dialog.diligencePushRemainingBudget,
|
|
407
413
|
},
|
|
408
414
|
}));
|
|
409
415
|
// Send dialog_ready with full info so frontend can track the active dialog
|
|
@@ -417,6 +423,7 @@ async function handleCreateDialog(ws, packet) {
|
|
|
417
423
|
taskDocPath: taskDocPath,
|
|
418
424
|
disableDiligencePush: defaultDisableDiligencePush,
|
|
419
425
|
diligencePushMax,
|
|
426
|
+
diligencePushRemainingBudget: dialog.diligencePushRemainingBudget,
|
|
420
427
|
};
|
|
421
428
|
ws.send(JSON.stringify(response));
|
|
422
429
|
broadcastDialogsIndexMessage?.({
|
|
@@ -559,6 +566,7 @@ async function handleDisplayDialog(ws, packet) {
|
|
|
559
566
|
assignmentFromSup: metadata.assignmentFromSup,
|
|
560
567
|
disableDiligencePush: effectiveDisableDiligencePush,
|
|
561
568
|
diligencePushMax,
|
|
569
|
+
diligencePushRemainingBudget: clampNonNegativeFiniteInt(rootDialog.diligencePushRemainingBudget, diligencePushMax > 0 ? diligencePushMax : 0),
|
|
562
570
|
};
|
|
563
571
|
ws.send(JSON.stringify(dialogReadyResponse));
|
|
564
572
|
// Send authoritative run state for this dialog so the client can render Send↔Stop and Continue.
|
|
@@ -1026,6 +1034,16 @@ function setupWebSocketServer(httpServer, clients, auth, serverWorkLanguage) {
|
|
|
1026
1034
|
}
|
|
1027
1035
|
}
|
|
1028
1036
|
});
|
|
1037
|
+
// Broadcast `.minds/team.yaml` updates so multi-tab clients can refresh cached team config.
|
|
1038
|
+
(0, team_config_updates_1.setTeamConfigBroadcaster)((msg) => {
|
|
1039
|
+
const data = JSON.stringify(msg);
|
|
1040
|
+
for (const ws of clients) {
|
|
1041
|
+
if (ws.readyState === 1) {
|
|
1042
|
+
ws.send(data);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
});
|
|
1046
|
+
(0, team_config_updates_1.startTeamConfigWatcher)();
|
|
1029
1047
|
wss.on('connection', (ws, req) => {
|
|
1030
1048
|
const authCheck = (0, auth_1.getWebSocketAuthCheck)(req, auth);
|
|
1031
1049
|
if (authCheck.kind !== 'ok') {
|